1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.ilrs;
18
19 import java.util.ArrayList;
20 import java.util.Collections;
21 import java.util.List;
22 import java.util.SortedSet;
23 import java.util.TreeSet;
24 import java.util.regex.Pattern;
25 import java.util.stream.Collectors;
26
27 import org.hipparchus.util.FastMath;
28 import org.orekit.annotation.DefaultDataContext;
29 import org.orekit.time.AbsoluteDate;
30 import org.orekit.time.ChronologicalComparator;
31 import org.orekit.time.TimeScalesFactory;
32 import org.orekit.time.TimeStamped;
33 import org.orekit.utils.ImmutableTimeStampedCache;
34
35
36
37
38
39
40
41
42 public class CRD {
43
44
45 public static final String STR_VALUE_NOT_AVAILABLE = "na";
46
47
48 public static final String STR_NAN = "NaN";
49
50
51 public static final Pattern PATTERN_NAN = Pattern.compile(STR_NAN);
52
53
54 private List<String> comments;
55
56
57 private List<CRDDataBlock> dataBlocks;
58
59
60
61
62 public CRD() {
63
64 this.comments = new ArrayList<>();
65 this.dataBlocks = new ArrayList<>();
66 }
67
68
69
70
71
72
73
74
75 public static String formatIntegerOrNaN(final int value, final int valueNotAvailable) {
76 return value == valueNotAvailable ? STR_VALUE_NOT_AVAILABLE : String.format("%d", value);
77 }
78
79
80
81
82
83
84
85 public static String handleNaN(final String crdString) {
86 return PATTERN_NAN.matcher(crdString).replaceAll(STR_VALUE_NOT_AVAILABLE);
87 }
88
89
90
91
92
93 public void addDataBlock(final CRDDataBlock dataBlock) {
94 dataBlocks.add(dataBlock);
95 }
96
97
98
99
100
101 public List<String> getComments() {
102 return comments;
103 }
104
105
106
107
108
109 public List<CRDDataBlock> getDataBlocks() {
110 return Collections.unmodifiableList(dataBlocks);
111 }
112
113
114
115
116
117
118
119
120 public static class CRDDataBlock {
121
122
123 private CRDHeader header;
124
125
126 private CRDConfiguration configurationRecords;
127
128
129 private List<RangeMeasurement> rangeData;
130
131
132 private final SortedSet<MeteorologicalMeasurement> meteoData;
133
134
135 private List<AnglesMeasurement> anglesData;
136
137
138 private List<RangeSupplement> rangeSupplementData;
139
140
141 private List<SessionStatistics> sessionStatisticsData;
142
143
144 private List<Calibration> calibrationData;
145
146
147 private List<CalibrationDetail> calibrationDetailData;
148
149
150
151
152 public CRDDataBlock() {
153
154 this.rangeData = new ArrayList<>();
155 this.meteoData = new TreeSet<>(new ChronologicalComparator());
156 this.anglesData = new ArrayList<>();
157 this.rangeSupplementData = new ArrayList<>();
158 this.sessionStatisticsData = new ArrayList<>();
159 this.calibrationData = new ArrayList<>();
160 this.calibrationDetailData = new ArrayList<>();
161 }
162
163
164
165
166
167 public CRDHeader getHeader() {
168 return header;
169 }
170
171
172
173
174
175 public void setHeader(final CRDHeader header) {
176 this.header = header;
177 }
178
179
180
181
182
183 public CRDConfiguration getConfigurationRecords() {
184 return configurationRecords;
185 }
186
187
188
189
190
191 public void setConfigurationRecords(final CRDConfiguration configurationRecords) {
192 this.configurationRecords = configurationRecords;
193 }
194
195
196
197
198
199 public void addRangeData(final RangeMeasurement range) {
200 rangeData.add(range);
201 }
202
203
204
205
206
207 public void addMeteoData(final MeteorologicalMeasurement meteorologicalMeasurement) {
208 meteoData.add(meteorologicalMeasurement);
209 }
210
211
212
213
214
215 public void addAnglesData(final AnglesMeasurement angles) {
216 anglesData.add(angles);
217 }
218
219
220
221
222
223 public List<RangeMeasurement> getRangeData() {
224 return Collections.unmodifiableList(rangeData);
225 }
226
227
228
229
230
231 public List<AnglesMeasurement> getAnglesData() {
232 return Collections.unmodifiableList(anglesData);
233 }
234
235
236
237
238
239 public Meteo getMeteoData() {
240 return new Meteo(meteoData);
241 }
242
243
244
245
246
247
248 public void addRangeSupplementData(final RangeSupplement rangeSupplement) {
249 rangeSupplementData.add(rangeSupplement);
250 }
251
252
253
254
255
256
257 public List<RangeSupplement> getRangeSupplementData() {
258 return Collections.unmodifiableList(rangeSupplementData);
259 }
260
261
262
263
264
265
266 public void addSessionStatisticsData(final SessionStatistics sessionStatistics) {
267 sessionStatisticsData.add(sessionStatistics);
268 }
269
270
271
272
273
274
275 public List<SessionStatistics> getSessionStatisticsData() {
276 return Collections.unmodifiableList(sessionStatisticsData);
277 }
278
279
280
281
282
283
284 public SessionStatistics getSessionStatisticsRecord() {
285 return getSessionStatisticsRecord(null);
286 }
287
288
289
290
291
292
293
294 public SessionStatistics getSessionStatisticsRecord(final String systemConfigurationId) {
295 if (sessionStatisticsData.isEmpty()) {
296 return null;
297 }
298
299 if (systemConfigurationId == null) {
300
301 return sessionStatisticsData.get(0);
302 }
303
304
305 for (SessionStatistics sessionStatistics : sessionStatisticsData) {
306 if (systemConfigurationId.equalsIgnoreCase(sessionStatistics.getSystemConfigurationId())) {
307 return sessionStatistics;
308 }
309 }
310
311 return null;
312 }
313
314
315
316
317
318
319 public void addCalibrationData(final Calibration cal) {
320 calibrationData.add(cal);
321 }
322
323
324
325
326
327
328 public List<Calibration> getCalibrationData() {
329 return Collections.unmodifiableList(calibrationData);
330 }
331
332
333
334
335
336
337 public List<Calibration> getCalibrationRecords() {
338 return getCalibrationRecords(null);
339 }
340
341
342
343
344
345
346
347 public List<Calibration> getCalibrationRecords(final String systemConfigurationId) {
348 if (calibrationData.isEmpty()) {
349 return null;
350 }
351
352 final String systemConfigId = systemConfigurationId == null ? getConfigurationRecords().getSystemRecord().getConfigurationId() : systemConfigurationId;
353
354 final List<Calibration> list = new ArrayList<Calibration>();
355
356 for (Calibration calibration : calibrationData) {
357 if (systemConfigId.equalsIgnoreCase(calibration.getSystemConfigurationId())) {
358 list.add(calibration);
359 }
360 }
361
362 return list;
363 }
364
365
366
367
368
369
370 public void addCalibrationDetailData(final CalibrationDetail cal) {
371 calibrationDetailData.add(cal);
372 }
373
374
375
376
377
378
379 public List<CalibrationDetail> getCalibrationDetailData() {
380 return Collections.unmodifiableList(calibrationDetailData);
381 }
382
383
384
385
386
387
388 public List<CalibrationDetail> getCalibrationDetailRecords() {
389 return getCalibrationDetailRecords(null);
390 }
391
392
393
394
395
396
397
398 public List<CalibrationDetail> getCalibrationDetailRecords(final String systemConfigurationId) {
399 if (calibrationDetailData.isEmpty()) {
400 return null;
401 }
402
403 final String systemConfigId = systemConfigurationId == null ? getConfigurationRecords().getSystemRecord().getConfigurationId() : systemConfigurationId;
404
405 final List<CalibrationDetail> list = new ArrayList<CalibrationDetail>();
406
407 for (CalibrationDetail calibration : calibrationDetailData) {
408 if (systemConfigId.equalsIgnoreCase(calibration.getSystemConfigurationId())) {
409 list.add(calibration);
410 }
411 }
412
413 return list;
414 }
415
416
417
418
419
420
421
422
423 public double getWavelength(final RangeMeasurement range) {
424 return getConfigurationRecords().getSystemRecord(range.getSystemConfigurationId()).getWavelength();
425 }
426
427 }
428
429
430 public static class RangeMeasurement implements TimeStamped {
431
432
433 private AbsoluteDate date;
434
435
436 private final double timeOfFlight;
437
438
439 private final String systemConfigurationId;
440
441
442
443
444
445
446
447
448
449
450
451 private final int epochEvent;
452
453
454 private final double snr;
455
456
457
458
459
460
461
462 public RangeMeasurement(final AbsoluteDate date,
463 final double timeOfFlight,
464 final int epochEvent) {
465 this(date, timeOfFlight, epochEvent, Double.NaN);
466 }
467
468
469
470
471
472
473
474
475 public RangeMeasurement(final AbsoluteDate date,
476 final double timeOfFlight,
477 final int epochEvent, final double snr) {
478 this(date, timeOfFlight, epochEvent, snr, null);
479 }
480
481
482
483
484
485
486
487
488
489
490 public RangeMeasurement(final AbsoluteDate date,
491 final double timeOfFlight, final int epochEvent,
492 final double snr,
493 final String systemConfigurationId) {
494 this.date = date;
495 this.timeOfFlight = timeOfFlight;
496 this.epochEvent = epochEvent;
497 this.snr = snr;
498 this.systemConfigurationId = systemConfigurationId;
499 }
500
501
502
503
504
505 public double getTimeOfFlight() {
506 return timeOfFlight;
507 }
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523 public int getEpochEvent() {
524 return epochEvent;
525 }
526
527
528
529
530
531 public double getSnr() {
532 return snr;
533 }
534
535
536 @Override
537 public AbsoluteDate getDate() {
538 return date;
539 }
540
541
542
543
544
545
546 public String getSystemConfigurationId() {
547 return systemConfigurationId;
548 }
549
550
551
552
553
554
555 public String toCrdString() {
556 return "00 not supported. use NptRangeMeasurement or FrRangeMeasurement instead.";
557 }
558 }
559
560
561
562
563
564 public static class FrRangeMeasurement extends RangeMeasurement {
565
566
567 private final int filterFlag;
568
569
570 private final int detectorChannel;
571
572
573 private final int stopNumber;
574
575
576 private final int receiveAmplitude;
577
578
579 private final int transmitAmplitude;
580
581
582
583
584
585
586
587
588
589
590
591
592
593 public FrRangeMeasurement(final AbsoluteDate date,
594 final double timeOfFlight,
595 final int epochEvent,
596 final String systemConfigurationId,
597 final int filterFlag,
598 final int detectorChannel,
599 final int stopNumber,
600 final int receiveAmplitude,
601 final int transmitAmplitude) {
602 super(date, timeOfFlight, epochEvent, Double.NaN, systemConfigurationId);
603 this.filterFlag = filterFlag;
604 this.detectorChannel = detectorChannel;
605 this.stopNumber = stopNumber;
606 this.receiveAmplitude = receiveAmplitude;
607 this.transmitAmplitude = transmitAmplitude;
608 }
609
610
611
612
613
614 public int getFilterFlag() {
615 return filterFlag;
616 }
617
618
619
620
621
622 public int getDetectorChannel() {
623 return detectorChannel;
624 }
625
626
627
628
629
630 public int getStopNumber() {
631 return stopNumber;
632 }
633
634
635
636
637
638 public int getReceiveAmplitude() {
639 return receiveAmplitude;
640 }
641
642
643
644
645
646 public int getTransmitAmplitude() {
647 return transmitAmplitude;
648 }
649
650
651 @Override
652 @DefaultDataContext
653 public String toCrdString() {
654 return String.format("10 %s", toString());
655 }
656
657 @Override
658 @DefaultDataContext
659 public String toString() {
660
661
662
663
664 final double sod = getDate()
665 .getComponents(TimeScalesFactory.getUTC()).getTime()
666 .getSecondsInLocalDay();
667
668 final String str = String.format(
669 "%18.12f %18.12f %4s %1d %1d %1d %1d %5s %5s", sod,
670 getTimeOfFlight(), getSystemConfigurationId(),
671 getEpochEvent(), filterFlag, detectorChannel, stopNumber,
672 formatIntegerOrNaN(receiveAmplitude, -1),
673 formatIntegerOrNaN(transmitAmplitude, -1));
674 return handleNaN(str).replace(',', '.');
675 }
676
677 }
678
679
680
681
682
683 public static class NptRangeMeasurement extends RangeMeasurement {
684
685
686 private final double windowLength;
687
688
689 private final int numberOfRawRanges;
690
691
692 private final double binRms;
693
694
695 private final double binSkew;
696
697
698 private final double binKurtosis;
699
700
701 private final double binPeakMinusMean;
702
703
704 private final double returnRate;
705
706
707 private final int detectorChannel;
708
709
710
711
712
713
714
715
716
717 public NptRangeMeasurement(final AbsoluteDate date,
718 final double timeOfFlight,
719 final int epochEvent, final double snr,
720 final String systemConfigurationId) {
721 this(date, timeOfFlight, epochEvent, snr, systemConfigurationId, -1,
722 -1, Double.NaN, Double.NaN, Double.NaN, Double.NaN,
723 Double.NaN, 0);
724 }
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742 public NptRangeMeasurement(final AbsoluteDate date,
743 final double timeOfFlight,
744 final int epochEvent, final double snr,
745 final String systemConfigurationId,
746 final double windowLength,
747 final int numberOfRawRanges,
748 final double binRms, final double binSkew,
749 final double binKurtosis,
750 final double binPeakMinusMean,
751 final double returnRate,
752 final int detectorChannel) {
753 super(date, timeOfFlight, epochEvent, snr, systemConfigurationId);
754
755 this.windowLength = windowLength;
756 this.numberOfRawRanges = numberOfRawRanges;
757 this.binSkew = binSkew;
758 this.binKurtosis = binKurtosis;
759 this.binPeakMinusMean = binPeakMinusMean;
760 this.detectorChannel = detectorChannel;
761 this.binRms = binRms == -1.0e-12 ? Double.NaN : binRms;
762 this.returnRate = returnRate == -1 ? Double.NaN : returnRate;
763 }
764
765
766
767
768
769 public double getWindowLength() {
770 return windowLength;
771 }
772
773
774
775
776
777 public int getNumberOfRawRanges() {
778 return numberOfRawRanges;
779 }
780
781
782
783
784
785 public double getBinRms() {
786 return binRms;
787 }
788
789
790
791
792
793 public double getBinSkew() {
794 return binSkew;
795 }
796
797
798
799
800
801 public double getBinKurtosis() {
802 return binKurtosis;
803 }
804
805
806
807
808
809 public double getBinPeakMinusMean() {
810 return binPeakMinusMean;
811 }
812
813
814
815
816
817 public double getReturnRate() {
818 return returnRate;
819 }
820
821
822
823
824
825 public int getDetectorChannel() {
826 return detectorChannel;
827 }
828
829
830 @Override
831 @DefaultDataContext
832 public String toCrdString() {
833 return String.format("11 %s", toString());
834 }
835
836 @Override
837 @DefaultDataContext
838 public String toString() {
839
840
841
842
843 final double sod = getDate()
844 .getComponents(TimeScalesFactory.getUTC()).getTime()
845 .getSecondsInLocalDay();
846
847 final String str = String.format(
848 "%18.12f %18.12f %4s %1d %6.1f %6d %9.1f %7.3f %7.3f %9.1f %5.2f %1d %5.1f",
849 sod, getTimeOfFlight(), getSystemConfigurationId(),
850 getEpochEvent(), windowLength, numberOfRawRanges,
851 binRms * 1e12, binSkew, binKurtosis,
852 binPeakMinusMean * 1e12, returnRate, detectorChannel,
853 getSnr());
854 return handleNaN(str).replace(',', '.');
855 }
856
857 }
858
859
860
861
862
863 public static class RangeSupplement implements TimeStamped {
864
865
866 private AbsoluteDate date;
867
868
869 private final String systemConfigurationId;
870
871
872 private final double troposphericRefractionCorrection;
873
874
875 private final double centerOfMassCorrection;
876
877
878 private final double ndFilterValue;
879
880
881 private final double timeBiasApplied;
882
883
884 private final double rangeRate;
885
886
887
888
889
890
891
892
893
894
895
896 public RangeSupplement(final AbsoluteDate date,
897 final String systemConfigurationId,
898 final double troposphericRefractionCorrection,
899 final double centerOfMassCorrection,
900 final double ndFilterValue,
901 final double timeBiasApplied,
902 final double rangeRate) {
903 this.date = date;
904 this.systemConfigurationId = systemConfigurationId;
905 this.troposphericRefractionCorrection = troposphericRefractionCorrection;
906 this.centerOfMassCorrection = centerOfMassCorrection;
907 this.ndFilterValue = ndFilterValue;
908 this.timeBiasApplied = timeBiasApplied;
909 this.rangeRate = rangeRate;
910 }
911
912 @Override
913 public AbsoluteDate getDate() {
914 return date;
915 }
916
917
918
919
920
921 public String getSystemConfigurationId() {
922 return systemConfigurationId;
923 }
924
925
926
927
928
929 public double getTroposphericRefractionCorrection() {
930 return troposphericRefractionCorrection;
931 }
932
933
934
935
936
937 public double getCenterOfMassCorrection() {
938 return centerOfMassCorrection;
939 }
940
941
942
943
944
945 public double getNdFilterValue() {
946 return ndFilterValue;
947 }
948
949
950
951
952
953 public double getTimeBiasApplied() {
954 return timeBiasApplied;
955 }
956
957
958
959
960
961 public double getRangeRate() {
962 return rangeRate;
963 }
964
965
966
967
968
969 @DefaultDataContext
970 public String toCrdString() {
971 return String.format("12 %s", toString());
972 }
973
974 @Override
975 @DefaultDataContext
976 public String toString() {
977
978
979
980
981 final double sod = getDate()
982 .getComponents(TimeScalesFactory.getUTC()).getTime()
983 .getSecondsInLocalDay();
984
985 final String str = String.format(
986 "%18.12f %4s %6.1f %6.4f %5.2f %8.4f %f", sod,
987 getSystemConfigurationId(),
988 troposphericRefractionCorrection * 1e12,
989 centerOfMassCorrection, ndFilterValue, timeBiasApplied,
990 rangeRate);
991 return handleNaN(str).replace(',', '.');
992 }
993
994 }
995
996
997 public static class MeteorologicalMeasurement implements TimeStamped {
998
999
1000 private AbsoluteDate date;
1001
1002
1003 private final double pressure;
1004
1005
1006 private final double temperature;
1007
1008
1009 private final double humidity;
1010
1011
1012
1013
1014 private final int originOfValues;
1015
1016
1017
1018
1019
1020
1021
1022
1023 public MeteorologicalMeasurement(final AbsoluteDate date,
1024 final double pressure, final double temperature,
1025 final double humidity) {
1026 this(date, pressure, temperature, humidity, 0);
1027 }
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037 public MeteorologicalMeasurement(final AbsoluteDate date, final double pressure, final double temperature,
1038 final double humidity, final int originOfValues) {
1039 this.date = date;
1040 this.pressure = pressure;
1041 this.temperature = temperature;
1042 this.humidity = humidity;
1043 this.originOfValues = originOfValues;
1044 }
1045
1046
1047
1048
1049
1050 public double getPressure() {
1051 return pressure;
1052 }
1053
1054
1055
1056
1057
1058 public double getTemperature() {
1059 return temperature;
1060 }
1061
1062
1063
1064
1065
1066 public double getHumidity() {
1067 return humidity;
1068 }
1069
1070
1071 @Override
1072 public AbsoluteDate getDate() {
1073 return date;
1074 }
1075
1076
1077
1078
1079
1080
1081
1082 public int getOriginOfValues() {
1083 return originOfValues;
1084 }
1085
1086
1087
1088
1089
1090
1091 @DefaultDataContext
1092 public String toCrdString() {
1093 return String.format("20 %s", toString());
1094 }
1095
1096 @Override
1097 @DefaultDataContext
1098 public String toString() {
1099
1100
1101
1102
1103 final double sod = getDate()
1104 .getComponents(TimeScalesFactory.getUTC()).getTime()
1105 .getSecondsInLocalDay();
1106
1107 final String str = String.format("%9.3f %7.2f %6.2f %4.0f %1d", sod,
1108 pressure * 1e3, temperature, humidity, originOfValues);
1109 return handleNaN(str).replace(',', '.');
1110 }
1111 }
1112
1113
1114 public static class AnglesMeasurement implements TimeStamped {
1115
1116
1117 private AbsoluteDate date;
1118
1119
1120 private final double azimuth;
1121
1122
1123 private final double elevation;
1124
1125
1126 private final int directionFlag;
1127
1128
1129
1130
1131
1132
1133
1134 private final int originIndicator;
1135
1136
1137 private final boolean refractionCorrected;
1138
1139
1140 private final double azimuthRate;
1141
1142
1143 private final double elevationRate;
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156 public AnglesMeasurement(final AbsoluteDate date, final double azimuth,
1157 final double elevation, final int directionFlag,
1158 final int originIndicator,
1159 final boolean refractionCorrected,
1160 final double azimuthRate, final double elevationRate) {
1161 this.date = date;
1162 this.azimuth = azimuth;
1163 this.elevation = elevation;
1164 this.directionFlag = directionFlag;
1165 this.originIndicator = originIndicator;
1166 this.refractionCorrected = refractionCorrected;
1167 this.azimuthRate = azimuthRate;
1168 this.elevationRate = elevationRate;
1169 }
1170
1171
1172
1173
1174
1175 public double getAzimuth() {
1176 return azimuth;
1177 }
1178
1179
1180
1181
1182
1183 public double getElevation() {
1184 return elevation;
1185 }
1186
1187
1188
1189
1190
1191 public int getDirectionFlag() {
1192 return directionFlag;
1193 }
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205 public int getOriginIndicator() {
1206 return originIndicator;
1207 }
1208
1209
1210
1211
1212
1213 public boolean isRefractionCorrected() {
1214 return refractionCorrected;
1215 }
1216
1217
1218
1219
1220
1221
1222
1223
1224 public double getAzimuthRate() {
1225 return azimuthRate;
1226 }
1227
1228
1229
1230
1231
1232
1233
1234
1235 public double getElevationRate() {
1236 return elevationRate;
1237 }
1238
1239
1240 @Override
1241 public AbsoluteDate getDate() {
1242 return date;
1243 }
1244
1245
1246
1247
1248
1249
1250 @DefaultDataContext
1251 public String toCrdString() {
1252 return String.format("30 %s", toString());
1253 }
1254
1255 @Override
1256 @DefaultDataContext
1257 public String toString() {
1258
1259
1260
1261
1262
1263 final double sod = getDate()
1264 .getComponents(TimeScalesFactory.getUTC()).getTime()
1265 .getSecondsInLocalDay();
1266
1267 final String str = String.format(
1268 "%9.3f %8.4f %8.4f %1d %1d %1d %10.7f %10.7f", sod,
1269 FastMath.toDegrees(azimuth), FastMath.toDegrees(elevation),
1270 directionFlag, originIndicator, refractionCorrected ? 1 : 0,
1271 FastMath.toDegrees(azimuthRate),
1272 FastMath.toDegrees(elevationRate));
1273 return handleNaN(str).replace(',', '.');
1274 }
1275 }
1276
1277
1278 public static class Meteo {
1279
1280
1281 private static final int N_NEIGHBORS = 2;
1282
1283
1284 private final AbsoluteDate firstDate;
1285
1286
1287 private final AbsoluteDate lastDate;
1288
1289
1290 private transient MeteorologicalMeasurement previousParam;
1291
1292
1293 private transient MeteorologicalMeasurement nextParam;
1294
1295
1296 private final transient ImmutableTimeStampedCache<MeteorologicalMeasurement> meteo;
1297
1298
1299
1300
1301
1302 public Meteo(final SortedSet<MeteorologicalMeasurement> meteoData) {
1303
1304
1305 final int neighborsSize = (meteoData.size() < 2) ? meteoData.size() : N_NEIGHBORS;
1306
1307
1308 if (neighborsSize == 0) {
1309
1310
1311 this.meteo = ImmutableTimeStampedCache.emptyCache();
1312
1313
1314 this.firstDate = null;
1315 this.lastDate = null;
1316
1317 } else {
1318
1319
1320 this.meteo = new ImmutableTimeStampedCache<MeteorologicalMeasurement>(neighborsSize, meteoData);
1321
1322
1323 this.firstDate = meteoData.first().getDate();
1324 this.lastDate = meteoData.last().getDate();
1325
1326 }
1327
1328 }
1329
1330
1331
1332
1333
1334 public List<MeteorologicalMeasurement> getData() {
1335 return meteo.getAll();
1336 }
1337
1338
1339
1340
1341
1342
1343
1344 public MeteorologicalMeasurement getMeteo(final AbsoluteDate date) {
1345
1346
1347 if (meteo.getMaxNeighborsSize() == 0) {
1348 return null;
1349 }
1350
1351
1352 bracketDate(date);
1353 if (date.durationFrom(firstDate) <= 0 || date.durationFrom(lastDate) > 0) {
1354
1355 return previousParam;
1356 } else {
1357
1358 final double pressure = getLinearInterpolation(date, previousParam.getPressure(), nextParam.getPressure());
1359 final double temperature = getLinearInterpolation(date, previousParam.getTemperature(), nextParam.getTemperature());
1360 final double humidity = getLinearInterpolation(date, previousParam.getHumidity(), nextParam.getHumidity());
1361 return new MeteorologicalMeasurement(date, pressure, temperature, humidity);
1362 }
1363
1364 }
1365
1366
1367
1368
1369
1370 private void bracketDate(final AbsoluteDate date) {
1371
1372
1373 if (previousParam != null &&
1374 date.durationFrom(previousParam.getDate()) > 0 &&
1375 date.durationFrom(nextParam.getDate()) <= 0) {
1376 return;
1377 }
1378
1379
1380 if (date.durationFrom(firstDate) <= 0) {
1381
1382 previousParam = meteo.getEarliest();
1383 nextParam = previousParam;
1384 } else if (date.durationFrom(lastDate) > 0) {
1385
1386 previousParam = meteo.getLatest();
1387 nextParam = previousParam;
1388 } else {
1389
1390 final List<MeteorologicalMeasurement> neighbors = meteo.getNeighbors(date).collect(Collectors.toList());
1391 previousParam = neighbors.get(0);
1392 nextParam = neighbors.get(1);
1393 }
1394
1395 }
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405 private double getLinearInterpolation(final AbsoluteDate date,
1406 final double previousValue,
1407 final double nextValue) {
1408
1409 final AbsoluteDate previousDate = previousParam.getDate();
1410 final AbsoluteDate currentDate = nextParam.getDate();
1411 final double dt = currentDate.durationFrom(previousDate);
1412 final double previousWeight = currentDate.durationFrom(date) / dt;
1413 final double nextWeight = date.durationFrom(previousDate) / dt;
1414
1415
1416 return previousValue * previousWeight + nextValue * nextWeight;
1417 }
1418
1419 }
1420
1421
1422
1423
1424
1425 public static class Calibration implements TimeStamped {
1426
1427
1428 private final AbsoluteDate date;
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440 private final int typeOfData;
1441
1442
1443 private final String systemConfigurationId;
1444
1445
1446 private final int numberOfPointsRecorded;
1447
1448
1449 private final int numberOfPointsUsed;
1450
1451
1452 private final double oneWayDistance;
1453
1454
1455 private final double systemDelay;
1456
1457
1458 private final double delayShift;
1459
1460
1461 private final double rms;
1462
1463
1464 private final double skew;
1465
1466
1467 private final double kurtosis;
1468
1469
1470 private final double peakMinusMean;
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483 private final int typeIndicator;
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494 private final int shiftTypeIndicator;
1495
1496
1497
1498
1499
1500
1501
1502 private final int detectorChannel;
1503
1504
1505
1506
1507
1508
1509
1510
1511
1512
1513 private final int span;
1514
1515
1516 private final double returnRate;
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
1534
1535
1536
1537
1538 public Calibration(final AbsoluteDate date, final int typeOfData,
1539 final String systemConfigurationId,
1540 final int numberOfPointsRecorded,
1541 final int numberOfPointsUsed,
1542 final double oneWayDistance,
1543 final double systemDelay, final double delayShift,
1544 final double rms, final double skew,
1545 final double kurtosis, final double peakMinusMean,
1546 final int typeIndicator, final int shiftTypeIndicator,
1547 final int detectorChannel, final int span,
1548 final double returnRate) {
1549 this.date = date;
1550 this.typeOfData = typeOfData;
1551 this.systemConfigurationId = systemConfigurationId;
1552 this.numberOfPointsRecorded = numberOfPointsRecorded;
1553 this.numberOfPointsUsed = numberOfPointsUsed;
1554 this.systemDelay = systemDelay;
1555 this.delayShift = delayShift;
1556 this.rms = rms;
1557 this.skew = skew;
1558 this.kurtosis = kurtosis;
1559 this.peakMinusMean = peakMinusMean;
1560 this.typeIndicator = typeIndicator;
1561 this.shiftTypeIndicator = shiftTypeIndicator;
1562 this.detectorChannel = detectorChannel;
1563 this.span = span;
1564 this.returnRate = returnRate;
1565 this.oneWayDistance = oneWayDistance == -1 ? Double.NaN : oneWayDistance;
1566 }
1567
1568 @Override
1569 public AbsoluteDate getDate() {
1570 return date;
1571 }
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584
1585
1586 public int getTypeOfData() {
1587 return typeOfData;
1588 }
1589
1590
1591
1592
1593
1594 public String getSystemConfigurationId() {
1595 return systemConfigurationId;
1596 }
1597
1598
1599
1600
1601
1602 public int getNumberOfPointsRecorded() {
1603 return numberOfPointsRecorded;
1604 }
1605
1606
1607
1608
1609
1610 public int getNumberOfPointsUsed() {
1611 return numberOfPointsUsed;
1612 }
1613
1614
1615
1616
1617
1618 public double getOneWayDistance() {
1619 return oneWayDistance;
1620 }
1621
1622
1623
1624
1625
1626 public double getSystemDelay() {
1627 return systemDelay;
1628 }
1629
1630
1631
1632
1633
1634 public double getDelayShift() {
1635 return delayShift;
1636 }
1637
1638
1639
1640
1641
1642 public double getRms() {
1643 return rms;
1644 }
1645
1646
1647
1648
1649
1650 public double getSkew() {
1651 return skew;
1652 }
1653
1654
1655
1656
1657
1658 public double getKurtosis() {
1659 return kurtosis;
1660 }
1661
1662
1663
1664
1665
1666 public double getPeakMinusMean() {
1667 return peakMinusMean;
1668 }
1669
1670
1671
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
1684 public int getTypeIndicator() {
1685 return typeIndicator;
1686 }
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700 public int getShiftTypeIndicator() {
1701 return shiftTypeIndicator;
1702 }
1703
1704
1705
1706
1707
1708
1709
1710
1711
1712
1713
1714 public int getDetectorChannel() {
1715 return detectorChannel;
1716 }
1717
1718
1719
1720
1721
1722
1723
1724
1725
1726
1727
1728
1729
1730 public int getSpan() {
1731 return span;
1732 }
1733
1734
1735
1736
1737
1738 public double getReturnRate() {
1739 return returnRate;
1740 }
1741
1742
1743
1744
1745
1746 @DefaultDataContext
1747 public String toCrdString() {
1748 return String.format("40 %s", toString());
1749 }
1750
1751 @Override
1752 @DefaultDataContext
1753 public String toString() {
1754
1755
1756
1757
1758
1759 final double sod = getDate()
1760 .getComponents(TimeScalesFactory.getUTC()).getTime()
1761 .getSecondsInLocalDay();
1762
1763 final String str = String.format(
1764 "%18.12f %1d %4s %8s %8s %8.4f %10.1f %8.1f %6.1f %7.3f %7.3f %6.1f %1d %1d %1d %1d %5.1f",
1765 sod, typeOfData, systemConfigurationId,
1766 formatIntegerOrNaN(numberOfPointsRecorded, -1),
1767 formatIntegerOrNaN(numberOfPointsUsed, -1), oneWayDistance,
1768 systemDelay * 1e12, delayShift * 1e12, rms * 1e12, skew,
1769 kurtosis, peakMinusMean * 1e12, typeIndicator,
1770 shiftTypeIndicator, detectorChannel, span, returnRate);
1771 return handleNaN(str).replace(',', '.');
1772 }
1773
1774 }
1775
1776
1777
1778
1779
1780 public static class CalibrationDetail extends Calibration {
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792
1793
1794
1795
1796
1797
1798
1799
1800
1801
1802
1803 public CalibrationDetail(final AbsoluteDate date, final int typeOfData,
1804 final String systemConfigurationId,
1805 final int numberOfPointsRecorded,
1806 final int numberOfPointsUsed, final double oneWayDistance,
1807 final double systemDelay, final double delayShift,
1808 final double rms, final double skew, final double kurtosis,
1809 final double peakMinusMean, final int typeIndicator,
1810 final int shiftTypeIndicator, final int detectorChannel,
1811 final int span, final double returnRate) {
1812 super(date, typeOfData, systemConfigurationId, numberOfPointsRecorded,
1813 numberOfPointsUsed, oneWayDistance, systemDelay, delayShift, rms, skew,
1814 kurtosis, peakMinusMean, typeIndicator, shiftTypeIndicator,
1815 detectorChannel, span, returnRate);
1816 }
1817
1818
1819
1820
1821
1822 @DefaultDataContext
1823 public String toCrdString() {
1824 return String.format("41 %s", toString());
1825 }
1826
1827 }
1828
1829
1830
1831
1832
1833 public static class SessionStatistics {
1834
1835
1836 private final String systemConfigurationId;
1837
1838
1839 private final double rms;
1840
1841
1842 private final double skewness;
1843
1844
1845 private final double kurtosis;
1846
1847
1848 private final double peakMinusMean;
1849
1850
1851
1852
1853
1854
1855
1856
1857
1858
1859
1860
1861
1862
1863 private final int dataQulityIndicator;
1864
1865
1866
1867
1868
1869
1870
1871
1872
1873
1874 public SessionStatistics(final String systemConfigurationId,
1875 final double rms, final double skewness,
1876 final double kurtosis,
1877 final double peakMinusMean,
1878 final int dataQulityIndicator) {
1879 this.systemConfigurationId = systemConfigurationId;
1880 this.rms = rms;
1881 this.skewness = skewness;
1882 this.kurtosis = kurtosis;
1883 this.peakMinusMean = peakMinusMean;
1884 this.dataQulityIndicator = dataQulityIndicator;
1885 }
1886
1887
1888
1889
1890
1891 public String getSystemConfigurationId() {
1892 return systemConfigurationId;
1893 }
1894
1895
1896
1897
1898
1899 public double getRms() {
1900 return rms;
1901 }
1902
1903
1904
1905
1906
1907 public double getSkewness() {
1908 return skewness;
1909 }
1910
1911
1912
1913
1914
1915 public double getKurtosis() {
1916 return kurtosis;
1917 }
1918
1919
1920
1921
1922
1923 public double getPeakMinusMean() {
1924 return peakMinusMean;
1925 }
1926
1927
1928
1929
1930
1931
1932
1933
1934
1935
1936
1937
1938
1939
1940
1941 public int getDataQulityIndicator() {
1942 return dataQulityIndicator;
1943 }
1944
1945
1946
1947
1948
1949 public String toCrdString() {
1950 return String.format("50 %s", toString());
1951 }
1952
1953 @Override
1954 public String toString() {
1955
1956
1957 final String str = String.format("%4s %6.1f %7.3f %7.3f %6.1f %1d",
1958 systemConfigurationId, rms * 1e12, skewness, kurtosis,
1959 peakMinusMean * 1e12, dataQulityIndicator);
1960 return handleNaN(str).replace(',', '.');
1961 }
1962
1963 }
1964
1965 }