1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.orekit.files.rinex.observation;
18 import java.io.BufferedReader;
19 import java.io.IOException;
20 import java.io.Reader;
21 import java.util.ArrayList;
22 import java.util.Arrays;
23 import java.util.Collections;
24 import java.util.List;
25 import java.util.function.Function;
26 import java.util.function.Predicate;
27
28 import org.hipparchus.exception.LocalizedCoreFormats;
29 import org.hipparchus.geometry.euclidean.threed.Vector3D;
30 import org.hipparchus.geometry.euclidean.twod.Vector2D;
31 import org.hipparchus.util.FastMath;
32 import org.orekit.annotation.DefaultDataContext;
33 import org.orekit.data.DataContext;
34 import org.orekit.data.DataSource;
35 import org.orekit.errors.OrekitException;
36 import org.orekit.errors.OrekitMessages;
37 import org.orekit.files.rinex.AppliedDCBS;
38 import org.orekit.files.rinex.AppliedPCVS;
39 import org.orekit.files.rinex.section.RinexLabels;
40 import org.orekit.files.rinex.utils.parsing.RinexUtils;
41 import org.orekit.gnss.ObservationTimeScale;
42 import org.orekit.gnss.ObservationType;
43 import org.orekit.gnss.SatInSystem;
44 import org.orekit.gnss.SatelliteSystem;
45 import org.orekit.time.AbsoluteDate;
46 import org.orekit.time.TimeScale;
47 import org.orekit.time.TimeScales;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public class RinexObservationParser {
69
70
71 public static final String DEFAULT_RINEX_2_NAMES = "^\\w{4}\\d{3}[0a-x](?:\\d{2})?\\.\\d{2}[oO]$";
72
73
74 public static final String DEFAULT_RINEX_3_NAMES = "^\\w{9}_\\w{1}_\\d{11}_\\d{2}\\w_\\d{2}\\w{1}_\\w{2}\\.rnx$";
75
76
77 private static final int MAX_SAT_PER_RINEX_2_LINE = 12;
78
79
80 private static final int MAX_OBS_PER_RINEX_2_LINE = 5;
81
82
83 private final TimeScales timeScales;
84
85
86
87
88
89
90 @DefaultDataContext
91 public RinexObservationParser() {
92 this(DataContext.getDefault().getTimeScales());
93 }
94
95
96
97
98
99
100 public RinexObservationParser(final TimeScales timeScales) {
101 this.timeScales = timeScales;
102 }
103
104
105
106
107
108
109 public RinexObservation parse(final DataSource source) {
110
111 Iterable<LineParser> candidateParsers = Collections.singleton(LineParser.VERSION);
112
113
114 final ParseInfo parseInfo = new ParseInfo(source.getName());
115
116 try (Reader reader = source.getOpener().openReaderOnce();
117 BufferedReader br = new BufferedReader(reader)) {
118 ++parseInfo.lineNumber;
119 nextLine:
120 for (String line = br.readLine(); line != null; line = br.readLine()) {
121 for (final LineParser candidate : candidateParsers) {
122 if (candidate.canHandle.test(line)) {
123 try {
124 candidate.parsingMethod.parse(line, parseInfo);
125 ++parseInfo.lineNumber;
126 candidateParsers = candidate.allowedNextProvider.apply(parseInfo);
127 continue nextLine;
128 } catch (StringIndexOutOfBoundsException | NumberFormatException e) {
129 throw new OrekitException(e,
130 OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
131 parseInfo.lineNumber, source.getName(), line);
132 }
133 }
134 }
135
136
137 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
138 parseInfo.lineNumber, source.getName(), line);
139
140 }
141
142 } catch (IOException ioe) {
143 throw new OrekitException(ioe, LocalizedCoreFormats.SIMPLE_MESSAGE, ioe.getLocalizedMessage());
144 }
145
146 return parseInfo.file;
147
148 }
149
150
151
152
153 private class ParseInfo {
154
155
156 private final String name;
157
158
159 private final TimeScales timeScales;
160
161
162 private int lineNumber;
163
164
165 private final RinexObservation file;
166
167
168 private AbsoluteDate tObs;
169
170
171 private boolean tFirstFixed;
172
173
174 private boolean tLastFixed;
175
176
177 private double rcvrClkOffset;
178
179
180 private TimeScale timeScale;
181
182
183 private int nbTypes;
184
185
186 private int nbSatObs;
187
188
189 private int nbObsScaleFactor;
190
191
192 private int indexObsSat;
193
194
195 private int nextObsStartLineNumber;
196
197
198 private SatelliteSystem currentSystem;
199
200
201 private int phaseShiftNbSat;
202
203
204 private int nbGlonass;
205
206
207 private final List<SatInSystem> satPhaseShift;
208
209
210 private ObservationType phaseShiftTypeObs;
211
212
213 private double corrPhaseShift;
214
215
216 private boolean headerCompleted;
217
218
219 private boolean specialRecord;
220
221
222 private boolean cycleSlip;
223
224
225 private int eventFlag;
226
227
228 private final List<ObservationType> typesObsScaleFactor;
229
230
231 private final List<ObservationType> typesObs;
232
233
234 private final List<ObservationData> observations;
235
236
237 private final List<SatInSystem> satObs;
238
239
240 private SatInSystem currentSat;
241
242
243
244
245 ParseInfo(final String name) {
246
247 this.name = name;
248 this.timeScales = RinexObservationParser.this.timeScales;
249 this.file = new RinexObservation();
250 this.lineNumber = 0;
251 this.tObs = AbsoluteDate.PAST_INFINITY;
252 this.tFirstFixed = false;
253 this.tLastFixed = false;
254 this.timeScale = null;
255 this.nbTypes = -1;
256 this.nbSatObs = -1;
257 this.nbGlonass = -1;
258 this.phaseShiftNbSat = -1;
259 this.nbObsScaleFactor = -1;
260 this.nextObsStartLineNumber = -1;
261 this.typesObs = new ArrayList<>();
262 this.observations = new ArrayList<>();
263 this.satPhaseShift = new ArrayList<>();
264 this.typesObsScaleFactor = new ArrayList<>();
265 this.satObs = new ArrayList<>();
266 }
267
268
269
270
271 private void setTObs(final AbsoluteDate rawDate) {
272 final RinexObservationHeader header = file.getHeader();
273 if (header.getClockOffsetApplied()) {
274
275 tObs = rawDate;
276 } else {
277
278
279 if (FastMath.abs(rawDate.durationFrom(header.getTFirstObs())) < 1.0e-6 &&
280 !tFirstFixed) {
281
282 header.setTFirstObs(header.getTFirstObs().shiftedBy(-rcvrClkOffset));
283 tFirstFixed = true;
284 }
285 if (FastMath.abs(rawDate.durationFrom(header.getTLastObs())) < 1.0e-6 &&
286 !tLastFixed) {
287
288 header.setTLastObs(header.getTLastObs().shiftedBy(-rcvrClkOffset));
289 tLastFixed = true;
290 }
291 tObs = rawDate.shiftedBy(-rcvrClkOffset);
292 }
293 }
294
295 }
296
297
298 private enum LineParser {
299
300
301 VERSION(line -> RinexLabels.VERSION.matches(RinexUtils.getLabel(line)),
302 (line, parseInfo) -> RinexUtils.parseVersionFileTypeSatelliteSystem(line, parseInfo.name, parseInfo.file.getHeader(),
303 2.00, 2.10, 2.11, 2.12, 2.20,
304 3.00, 3.01, 3.02, 3.03, 3.04, 3.05, 4.00),
305 LineParser::headerNext),
306
307
308 PROGRAM(line -> RinexLabels.PROGRAM.matches(RinexUtils.getLabel(line)),
309 (line, parseInfo) -> RinexUtils.parseProgramRunByDate(line, parseInfo.lineNumber, parseInfo.name,
310 parseInfo.timeScales, parseInfo.file.getHeader()),
311 LineParser::headerNext),
312
313
314 COMMENT(line -> RinexLabels.COMMENT.matches(RinexUtils.getLabel(line)),
315 (line, parseInfo) -> RinexUtils.parseComment(parseInfo.lineNumber, line, parseInfo.file),
316 LineParser::commentNext),
317
318
319 MARKER_NAME(line -> RinexLabels.MARKER_NAME.matches(RinexUtils.getLabel(line)),
320 (line, parseInfo) -> parseInfo.file.getHeader().setMarkerName(RinexUtils.parseString(line, 0, RinexUtils.LABEL_INDEX)),
321 LineParser::headerNext),
322
323
324 MARKER_NUMBER(line -> RinexLabels.MARKER_NUMBER.matches(RinexUtils.getLabel(line)),
325 (line, parseInfo) -> parseInfo.file.getHeader().setMarkerNumber(RinexUtils.parseString(line, 0, 20)),
326 LineParser::headerNext),
327
328
329 MARKER_TYPE(line -> RinexLabels.MARKER_TYPE.matches(RinexUtils.getLabel(line)),
330 (line, parseInfo) -> parseInfo.file.getHeader().setMarkerType(RinexUtils.parseString(line, 0, 20)),
331 LineParser::headerNext),
332
333
334 OBSERVER_AGENCY(line -> RinexLabels.OBSERVER_AGENCY.matches(RinexUtils.getLabel(line)),
335 (line, parseInfo) -> {
336 parseInfo.file.getHeader().setObserverName(RinexUtils.parseString(line, 0, 20));
337 parseInfo.file.getHeader().setAgencyName(RinexUtils.parseString(line, 20, 40));
338 },
339 LineParser::headerNext),
340
341
342 REC_NB_TYPE_VERS(line -> RinexLabels.REC_NB_TYPE_VERS.matches(RinexUtils.getLabel(line)),
343 (line, parseInfo) -> {
344 parseInfo.file.getHeader().setReceiverNumber(RinexUtils.parseString(line, 0, 20));
345 parseInfo.file.getHeader().setReceiverType(RinexUtils.parseString(line, 20, 20));
346 parseInfo.file.getHeader().setReceiverVersion(RinexUtils.parseString(line, 40, 20));
347 },
348 LineParser::headerNext),
349
350
351 ANT_NB_TYPE(line -> RinexLabels.ANT_NB_TYPE.matches(RinexUtils.getLabel(line)),
352 (line, parseInfo) -> {
353 parseInfo.file.getHeader().setAntennaNumber(RinexUtils.parseString(line, 0, 20));
354 parseInfo.file.getHeader().setAntennaType(RinexUtils.parseString(line, 20, 20));
355 },
356 LineParser::headerNext),
357
358
359 APPROX_POSITION_XYZ(line -> RinexLabels.APPROX_POSITION_XYZ.matches(RinexUtils.getLabel(line)),
360 (line, parseInfo) -> parseInfo.file.getHeader().setApproxPos(new Vector3D(RinexUtils.parseDouble(line, 0, 14),
361 RinexUtils.parseDouble(line, 14, 14),
362 RinexUtils.parseDouble(line, 28, 14))),
363 LineParser::headerNext),
364
365
366 ANTENNA_DELTA_H_E_N(line -> RinexLabels.ANTENNA_DELTA_H_E_N.matches(RinexUtils.getLabel(line)),
367 (line, parseInfo) -> {
368 parseInfo.file.getHeader().setAntennaHeight(RinexUtils.parseDouble(line, 0, 14));
369 parseInfo.file.getHeader().setEccentricities(new Vector2D(RinexUtils.parseDouble(line, 14, 14),
370 RinexUtils.parseDouble(line, 28, 14)));
371 },
372 LineParser::headerNext),
373
374
375 ANTENNA_DELTA_X_Y_Z(line -> RinexLabels.ANTENNA_DELTA_X_Y_Z.matches(RinexUtils.getLabel(line)),
376 (line, parseInfo) -> parseInfo.file.getHeader().setAntennaReferencePoint(new Vector3D(RinexUtils.parseDouble(line, 0, 14),
377 RinexUtils.parseDouble(line, 14, 14),
378 RinexUtils.parseDouble(line, 28, 14))),
379 LineParser::headerNext),
380
381
382 ANTENNA_PHASE_CENTER(line -> RinexLabels.ANTENNA_PHASE_CENTER.matches(RinexUtils.getLabel(line)),
383 (line, parseInfo) -> {
384 parseInfo.file.getHeader().setPhaseCenterSystem(SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 0, 1)));
385 parseInfo.file.getHeader().setObservationCode(RinexUtils.parseString(line, 2, 3));
386 parseInfo.file.getHeader().setAntennaPhaseCenter(new Vector3D(RinexUtils.parseDouble(line, 5, 9),
387 RinexUtils.parseDouble(line, 14, 14),
388 RinexUtils.parseDouble(line, 28, 14)));
389 },
390 LineParser::headerNext),
391
392
393 ANTENNA_B_SIGHT_XYZ(line -> RinexLabels.ANTENNA_B_SIGHT_XYZ.matches(RinexUtils.getLabel(line)),
394 (line, parseInfo) -> parseInfo.file.getHeader().setAntennaBSight(new Vector3D(RinexUtils.parseDouble(line, 0, 14),
395 RinexUtils.parseDouble(line, 14, 14),
396 RinexUtils.parseDouble(line, 28, 14))),
397 LineParser::headerNext),
398
399
400 ANTENNA_ZERODIR_AZI(line -> RinexLabels.ANTENNA_ZERODIR_AZI.matches(RinexUtils.getLabel(line)),
401 (line, parseInfo) -> parseInfo.file.getHeader().setAntennaAzimuth(FastMath.toRadians(RinexUtils.parseDouble(line, 0, 14))),
402 LineParser::headerNext),
403
404
405 ANTENNA_ZERODIR_XYZ(line -> RinexLabels.ANTENNA_ZERODIR_XYZ.matches(RinexUtils.getLabel(line)),
406 (line, parseInfo) -> parseInfo.file.getHeader().setAntennaZeroDirection(new Vector3D(RinexUtils.parseDouble(line, 0, 14),
407 RinexUtils.parseDouble(line, 14, 14),
408 RinexUtils.parseDouble(line, 28, 14))),
409 LineParser::headerNext),
410
411
412 WAVELENGTH_FACT_L1_2(line -> RinexLabels.WAVELENGTH_FACT_L1_2.matches(RinexUtils.getLabel(line)),
413 (line, parseInfo) -> {
414
415 },
416 LineParser::headerNext),
417
418
419 OBS_SCALE_FACTOR(line -> RinexLabels.OBS_SCALE_FACTOR.matches(RinexUtils.getLabel(line)),
420 (line, parseInfo) -> {
421 final int scaleFactor = FastMath.max(1, RinexUtils.parseInt(line, 0, 6));
422 final int nbObsScaleFactor = RinexUtils.parseInt(line, 6, 6);
423 final List<ObservationType> types = new ArrayList<>(nbObsScaleFactor);
424 for (int i = 0; i < nbObsScaleFactor; i++) {
425 types.add(ObservationType.valueOf(RinexUtils.parseString(line, 16 + (6 * i), 2)));
426 }
427 parseInfo.file.getHeader().addScaleFactorCorrection(parseInfo.file.getHeader().getSatelliteSystem(),
428 new ScaleFactorCorrection(scaleFactor, types));
429 },
430 LineParser::headerNext),
431
432
433 CENTER_OF_MASS_XYZ(line -> RinexLabels.CENTER_OF_MASS_XYZ.matches(RinexUtils.getLabel(line)),
434 (line, parseInfo) -> parseInfo.file.getHeader().setCenterMass(new Vector3D(RinexUtils.parseDouble(line, 0, 14),
435 RinexUtils.parseDouble(line, 14, 14),
436 RinexUtils.parseDouble(line, 28, 14))),
437 LineParser::headerNext),
438
439
440
441
442 DOI(line -> RinexLabels.DOI.matches(RinexUtils.getLabel(line)),
443 (line, parseInfo) -> parseInfo.file.getHeader().setDoi(RinexUtils.parseString(line, 0, RinexUtils.LABEL_INDEX)),
444 LineParser::headerNext),
445
446
447
448
449 LICENSE(line -> RinexLabels.LICENSE.matches(RinexUtils.getLabel(line)),
450 (line, parseInfo) -> parseInfo.file.getHeader().setLicense(RinexUtils.parseString(line, 0, RinexUtils.LABEL_INDEX)),
451 LineParser::headerNext),
452
453
454
455
456 STATION_INFORMATION(line -> RinexLabels.STATION_INFORMATION.matches(RinexUtils.getLabel(line)),
457 (line, parseInfo) -> parseInfo.file.getHeader().setStationInformation(RinexUtils.parseString(line, 0, RinexUtils.LABEL_INDEX)),
458 LineParser::headerNext),
459
460
461 SYS_NB_TYPES_OF_OBSERV(line -> RinexLabels.SYS_NB_TYPES_OF_OBSERV.matches(RinexUtils.getLabel(line)) ||
462 RinexLabels.NB_TYPES_OF_OBSERV.matches(RinexUtils.getLabel(line)),
463 (line, parseInfo) -> {
464 final double version = parseInfo.file.getHeader().getFormatVersion();
465 if (parseInfo.nbTypes < 0) {
466
467 if (version < 3) {
468
469 parseInfo.currentSystem = parseInfo.file.getHeader().getSatelliteSystem();
470 parseInfo.nbTypes = RinexUtils.parseInt(line, 0, 6);
471 } else {
472
473 parseInfo.currentSystem = SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 0, 1));
474 parseInfo.nbTypes = RinexUtils.parseInt(line, 3, 3);
475 if (parseInfo.currentSystem != parseInfo.file.getHeader().getSatelliteSystem() &&
476 parseInfo.file.getHeader().getSatelliteSystem() != SatelliteSystem.MIXED) {
477 throw new OrekitException(OrekitMessages.INCONSISTENT_SATELLITE_SYSTEM,
478 parseInfo.lineNumber, parseInfo.name,
479 parseInfo.file.getHeader().getSatelliteSystem(),
480 parseInfo.currentSystem);
481 }
482 }
483 }
484
485 final int firstIndex = version < 3 ? 10 : 7;
486 final int increment = version < 3 ? 6 : 4;
487 final int size = version < 3 ? 2 : 3;
488 for (int i = firstIndex;
489 (i + size) <= RinexUtils.LABEL_INDEX && parseInfo.typesObs.size() < parseInfo.nbTypes;
490 i += increment) {
491 final String type = RinexUtils.parseString(line, i, size);
492 try {
493 parseInfo.typesObs.add(ObservationType.valueOf(type));
494 } catch (IllegalArgumentException iae) {
495 throw new OrekitException(iae, OrekitMessages.UNKNOWN_RINEX_FREQUENCY,
496 type, parseInfo.name, parseInfo.lineNumber);
497 }
498 }
499
500 if (parseInfo.typesObs.size() == parseInfo.nbTypes) {
501
502 parseInfo.file.getHeader().setTypeObs(parseInfo.currentSystem, parseInfo.typesObs);
503 parseInfo.typesObs.clear();
504 parseInfo.nbTypes = -1;
505 }
506
507 },
508 LineParser::headerNbTypesObs),
509
510
511 SIGNAL_STRENGTH_UNIT(line -> RinexLabels.SIGNAL_STRENGTH_UNIT.matches(RinexUtils.getLabel(line)),
512 (line, parseInfo) -> parseInfo.file.getHeader().setSignalStrengthUnit(RinexUtils.parseString(line, 0, 20)),
513 LineParser::headerNext),
514
515
516 INTERVAL(line -> RinexLabels.INTERVAL.matches(RinexUtils.getLabel(line)),
517 (line, parseInfo) -> parseInfo.file.getHeader().setInterval(RinexUtils.parseDouble(line, 0, 10)),
518 LineParser::headerNext),
519
520
521 TIME_OF_FIRST_OBS(line -> RinexLabels.TIME_OF_FIRST_OBS.matches(RinexUtils.getLabel(line)),
522 (line, parseInfo) -> {
523 if (parseInfo.file.getHeader().getSatelliteSystem() == SatelliteSystem.MIXED) {
524
525 try {
526 parseInfo.timeScale = ObservationTimeScale.
527 valueOf(RinexUtils.parseString(line, 48, 3)).
528 getTimeScale(parseInfo.timeScales);
529 } catch (IllegalArgumentException iae) {
530 throw new OrekitException(iae,
531 OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
532 parseInfo.lineNumber, parseInfo.name, line);
533 }
534 } else {
535 final ObservationTimeScale observationTimeScale = parseInfo.file.getHeader().getSatelliteSystem().getObservationTimeScale();
536 if (observationTimeScale == null) {
537 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
538 parseInfo.lineNumber, parseInfo.name, line);
539 }
540 parseInfo.timeScale = observationTimeScale.getTimeScale(parseInfo.timeScales);
541 }
542 parseInfo.file.getHeader().setTFirstObs(new AbsoluteDate(RinexUtils.parseInt(line, 0, 6),
543 RinexUtils.parseInt(line, 6, 6),
544 RinexUtils.parseInt(line, 12, 6),
545 RinexUtils.parseInt(line, 18, 6),
546 RinexUtils.parseInt(line, 24, 6),
547 RinexUtils.parseDouble(line, 30, 13),
548 parseInfo.timeScale));
549 },
550 LineParser::headerNext),
551
552
553 TIME_OF_LAST_OBS(line -> RinexLabels.TIME_OF_LAST_OBS.matches(RinexUtils.getLabel(line)),
554 (line, parseInfo) -> parseInfo.file.getHeader().setTLastObs(new AbsoluteDate(RinexUtils.parseInt(line, 0, 6),
555 RinexUtils.parseInt(line, 6, 6),
556 RinexUtils.parseInt(line, 12, 6),
557 RinexUtils.parseInt(line, 18, 6),
558 RinexUtils.parseInt(line, 24, 6),
559 RinexUtils.parseDouble(line, 30, 13),
560 parseInfo.timeScale)),
561 LineParser::headerNext),
562
563
564 RCV_CLOCK_OFFS_APPL(line -> RinexLabels.RCV_CLOCK_OFFS_APPL.matches(RinexUtils.getLabel(line)),
565 (line, parseInfo) -> parseInfo.file.getHeader().setClockOffsetApplied(RinexUtils.parseInt(line, 0, 6) > 0),
566 LineParser::headerNext),
567
568
569 SYS_DCBS_APPLIED(line -> RinexLabels.SYS_DCBS_APPLIED.matches(RinexUtils.getLabel(line)),
570 (line, parseInfo) -> parseInfo.file.getHeader().addAppliedDCBS(new AppliedDCBS(SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 0, 1)),
571 RinexUtils.parseString(line, 2, 17),
572 RinexUtils.parseString(line, 20, 40))),
573 LineParser::headerNext),
574
575
576 SYS_PCVS_APPLIED(line -> RinexLabels.SYS_PCVS_APPLIED.matches(RinexUtils.getLabel(line)),
577 (line, parseInfo) -> parseInfo.file.getHeader().addAppliedPCVS(new AppliedPCVS(SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 0, 1)),
578 RinexUtils.parseString(line, 2, 17),
579 RinexUtils.parseString(line, 20, 40))),
580 LineParser::headerNext),
581
582
583 SYS_SCALE_FACTOR(line -> RinexLabels.SYS_SCALE_FACTOR.matches(RinexUtils.getLabel(line)),
584 (line, parseInfo) -> {
585
586 int scaleFactor = 1;
587 if (parseInfo.nbObsScaleFactor < 0) {
588
589 parseInfo.currentSystem = SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 0, 1));
590 scaleFactor = RinexUtils.parseInt(line, 2, 4);
591 parseInfo.nbObsScaleFactor = RinexUtils.parseInt(line, 8, 2);
592 }
593
594 if (parseInfo.nbObsScaleFactor == 0) {
595 parseInfo.typesObsScaleFactor.addAll(parseInfo.file.getHeader().getTypeObs().get(parseInfo.currentSystem));
596 } else {
597 for (int i = 11; i < RinexUtils.LABEL_INDEX && parseInfo.typesObsScaleFactor.size() < parseInfo.nbObsScaleFactor; i += 4) {
598 parseInfo.typesObsScaleFactor.add(ObservationType.valueOf(RinexUtils.parseString(line, i, 3)));
599 }
600 }
601
602 if (parseInfo.typesObsScaleFactor.size() >= parseInfo.nbObsScaleFactor) {
603
604 parseInfo.file.getHeader().addScaleFactorCorrection(parseInfo.currentSystem,
605 new ScaleFactorCorrection(scaleFactor,
606 new ArrayList<>(parseInfo.typesObsScaleFactor)));
607 parseInfo.nbObsScaleFactor = -1;
608 parseInfo.typesObsScaleFactor.clear();
609 }
610
611 },
612 LineParser::headerNext),
613
614
615 SYS_PHASE_SHIFT(line -> RinexLabels.SYS_PHASE_SHIFT.matches(RinexUtils.getLabel(line)),
616 (line, parseInfo) -> {
617
618 if (parseInfo.phaseShiftNbSat < 0) {
619
620 parseInfo.currentSystem = SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 0, 1));
621 final String to = RinexUtils.parseString(line, 2, 3);
622 parseInfo.phaseShiftTypeObs = to.isEmpty() ? null : ObservationType.valueOf(to.length() < 3 ? "L" + to : to);
623 parseInfo.corrPhaseShift = RinexUtils.parseDouble(line, 6, 8);
624 parseInfo.phaseShiftNbSat = RinexUtils.parseInt(line, 16, 2);
625 }
626
627 for (int i = 19; i + 3 < RinexUtils.LABEL_INDEX && parseInfo.satPhaseShift.size() < parseInfo.phaseShiftNbSat; i += 4) {
628 final SatelliteSystem system = line.charAt(i) == ' ' ?
629 parseInfo.currentSystem :
630 SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, i, 1));
631 final int prn = RinexUtils.parseInt(line, i + 1, 2);
632 parseInfo.satPhaseShift.add(new SatInSystem(system,
633 system == SatelliteSystem.SBAS ?
634 prn + 100 :
635 (system == SatelliteSystem.QZSS ? prn + 192 : prn)));
636 }
637
638 if (parseInfo.satPhaseShift.size() == parseInfo.phaseShiftNbSat) {
639
640 parseInfo.file.getHeader().addPhaseShiftCorrection(new PhaseShiftCorrection(parseInfo.currentSystem,
641 parseInfo.phaseShiftTypeObs,
642 parseInfo.corrPhaseShift,
643 new ArrayList<>(parseInfo.satPhaseShift)));
644 parseInfo.phaseShiftNbSat = -1;
645 parseInfo.satPhaseShift.clear();
646 }
647
648 },
649 LineParser::headerPhaseShift),
650
651
652 GLONASS_SLOT_FRQ_NB(line -> RinexLabels.GLONASS_SLOT_FRQ_NB.matches(RinexUtils.getLabel(line)),
653 (line, parseInfo) -> {
654
655 if (parseInfo.nbGlonass < 0) {
656
657 parseInfo.nbGlonass = RinexUtils.parseInt(line, 0, 3);
658 }
659
660 for (int i = 4;
661 i < RinexUtils.LABEL_INDEX && parseInfo.file.getHeader().getGlonassChannels().size() < parseInfo.nbGlonass;
662 i += 7) {
663 final SatelliteSystem system = SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, i, 1));
664 final int prn = RinexUtils.parseInt(line, i + 1, 2);
665 final int k = RinexUtils.parseInt(line, i + 4, 2);
666 parseInfo.file.getHeader().addGlonassChannel(new GlonassSatelliteChannel(new SatInSystem(system, prn), k));
667 }
668
669 },
670 LineParser::headerNext),
671
672
673 GLONASS_COD_PHS_BIS(line -> RinexLabels.GLONASS_COD_PHS_BIS.matches(RinexUtils.getLabel(line)),
674 (line, parseInfo) -> {
675
676
677 final String c1c = RinexUtils.parseString(line, 1, 3);
678 if (!c1c.isEmpty()) {
679 parseInfo.file.getHeader().setC1cCodePhaseBias(RinexUtils.parseDouble(line, 5, 8));
680 }
681
682
683 final String c1p = RinexUtils.parseString(line, 14, 3);
684 if (!c1p.isEmpty()) {
685 parseInfo.file.getHeader().setC1pCodePhaseBias(RinexUtils.parseDouble(line, 18, 8));
686 }
687
688
689 final String c2c = RinexUtils.parseString(line, 27, 3);
690 if (!c2c.isEmpty()) {
691 parseInfo.file.getHeader().setC2cCodePhaseBias(RinexUtils.parseDouble(line, 31, 8));
692 }
693
694
695 final String c2p = RinexUtils.parseString(line, 40, 3);
696 if (!c2p.isEmpty()) {
697 parseInfo.file.getHeader().setC2pCodePhaseBias(RinexUtils.parseDouble(line, 44, 8));
698 }
699
700 },
701 LineParser::headerNext),
702
703
704 LEAP_SECONDS(line -> RinexLabels.LEAP_SECONDS.matches(RinexUtils.getLabel(line)),
705 (line, parseInfo) -> {
706 parseInfo.file.getHeader().setLeapSeconds(RinexUtils.parseInt(line, 0, 6));
707 if (parseInfo.file.getHeader().getFormatVersion() >= 3.0) {
708 parseInfo.file.getHeader().setLeapSecondsFuture(RinexUtils.parseInt(line, 6, 6));
709 parseInfo.file.getHeader().setLeapSecondsWeekNum(RinexUtils.parseInt(line, 12, 6));
710 parseInfo.file.getHeader().setLeapSecondsDayNum(RinexUtils.parseInt(line, 18, 6));
711 }
712 },
713 LineParser::headerNext),
714
715
716 NB_OF_SATELLITES(line -> RinexLabels.NB_OF_SATELLITES.matches(RinexUtils.getLabel(line)),
717 (line, parseInfo) -> parseInfo.file.getHeader().setNbSat(RinexUtils.parseInt(line, 0, 6)),
718 LineParser::headerNext),
719
720
721 PRN_NB_OF_OBS(line -> RinexLabels.PRN_NB_OF_OBS.matches(RinexUtils.getLabel(line)),
722 (line, parseInfo) -> {
723 final String systemName = RinexUtils.parseString(line, 3, 1);
724 if (!systemName.isEmpty()) {
725 final SatelliteSystem system = SatelliteSystem.parseSatelliteSystem(systemName);
726 final int prn = RinexUtils.parseInt(line, 4, 2);
727 parseInfo.currentSat = new SatInSystem(system,
728 system == SatelliteSystem.SBAS ?
729 prn + 100 :
730 (system == SatelliteSystem.QZSS ? prn + 192 : prn));
731 parseInfo.nbTypes = 0;
732 }
733 final List<ObservationType> types = parseInfo.file.getHeader().getTypeObs().get(parseInfo.currentSat.getSystem());
734
735 final int firstIndex = 6;
736 final int increment = 6;
737 final int size = 6;
738 for (int i = firstIndex;
739 (i + size) <= RinexUtils.LABEL_INDEX && parseInfo.nbTypes < types.size();
740 i += increment) {
741 final String nb = RinexUtils.parseString(line, i, size);
742 if (!nb.isEmpty()) {
743 parseInfo.file.getHeader().setNbObsPerSatellite(parseInfo.currentSat, types.get(parseInfo.nbTypes),
744 RinexUtils.parseInt(line, i, size));
745 }
746 ++parseInfo.nbTypes;
747 }
748
749 },
750 LineParser::headerNext),
751
752
753 END(line -> RinexLabels.END.matches(RinexUtils.getLabel(line)),
754 (line, parseInfo) -> {
755
756 parseInfo.headerCompleted = true;
757
758
759 final double version = parseInfo.file.getHeader().getFormatVersion();
760
761
762 if (version < 3) {
763 if (parseInfo.file.getHeader().getMarkerName() == null ||
764 parseInfo.file.getHeader().getObserverName() == null ||
765 parseInfo.file.getHeader().getReceiverNumber() == null ||
766 parseInfo.file.getHeader().getAntennaNumber() == null ||
767 parseInfo.file.getHeader().getTFirstObs() == null ||
768 version < 2.20 && parseInfo.file.getHeader().getApproxPos() == null ||
769 version < 2.20 && Double.isNaN(parseInfo.file.getHeader().getAntennaHeight()) ||
770 parseInfo.file.getHeader().getTypeObs().isEmpty()) {
771 throw new OrekitException(OrekitMessages.INCOMPLETE_HEADER, parseInfo.name);
772 }
773
774 } else {
775 if (parseInfo.file.getHeader().getMarkerName() == null ||
776 parseInfo.file.getHeader().getObserverName() == null ||
777 parseInfo.file.getHeader().getReceiverNumber() == null ||
778 parseInfo.file.getHeader().getAntennaNumber() == null ||
779 Double.isNaN(parseInfo.file.getHeader().getAntennaHeight()) &&
780 parseInfo.file.getHeader().getAntennaReferencePoint() == null ||
781 parseInfo.file.getHeader().getTFirstObs() == null ||
782 parseInfo.file.getHeader().getTypeObs().isEmpty()) {
783 throw new OrekitException(OrekitMessages.INCOMPLETE_HEADER, parseInfo.name);
784 }
785 }
786 },
787 LineParser::headerEndNext),
788
789
790 RINEX_2_DATA_SAT_LIST(line -> true,
791 (line, parseInfo) -> {
792 for (int index = 32; parseInfo.satObs.size() < parseInfo.nbSatObs && index < 68; index += 3) {
793
794 final SatelliteSystem system = line.charAt(index) == ' ' ?
795 parseInfo.file.getHeader().getSatelliteSystem() :
796 SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, index, 1));
797 if (system != parseInfo.file.getHeader().getSatelliteSystem() &&
798 parseInfo.file.getHeader().getSatelliteSystem() != SatelliteSystem.MIXED) {
799 throw new OrekitException(OrekitMessages.INCONSISTENT_SATELLITE_SYSTEM,
800 parseInfo.lineNumber, parseInfo.name,
801 parseInfo.file.getHeader().getSatelliteSystem(),
802 system);
803 }
804 final int prn = RinexUtils.parseInt(line, index + 1, 2);
805 final SatInSystem satellite = new SatInSystem(system,
806 system == SatelliteSystem.SBAS ? prn + 100 : prn);
807 parseInfo.satObs.add(satellite);
808
809
810 final int nbObservables = parseInfo.file.getHeader().getTypeObs().get(parseInfo.file.getHeader().getSatelliteSystem()).size();
811 final int nbLines = (nbObservables + MAX_OBS_PER_RINEX_2_LINE - 1) / MAX_OBS_PER_RINEX_2_LINE;
812 parseInfo.nextObsStartLineNumber += nbLines;
813 }
814 },
815 LineParser::first2),
816
817
818 RINEX_2_DATA_FIRST(line -> true,
819 (line, parseInfo) -> {
820
821
822 parseInfo.eventFlag = RinexUtils.parseInt(line, 28, 1);
823
824
825 parseInfo.nbSatObs = RinexUtils.parseInt(line, 29, 3);
826 final int nbLinesSat = (parseInfo.nbSatObs + MAX_SAT_PER_RINEX_2_LINE - 1) / MAX_SAT_PER_RINEX_2_LINE;
827
828 if (parseInfo.eventFlag < 2) {
829
830 parseInfo.specialRecord = false;
831 parseInfo.cycleSlip = false;
832 final int nbSat = parseInfo.file.getHeader().getNbSat();
833 if (nbSat != -1 && parseInfo.nbSatObs > nbSat) {
834
835 throw new OrekitException(OrekitMessages.INCONSISTENT_NUMBER_OF_SATS,
836 parseInfo.lineNumber, parseInfo.name,
837 parseInfo.nbSatObs, nbSat);
838 }
839 parseInfo.nextObsStartLineNumber = parseInfo.lineNumber + nbLinesSat;
840
841
842 parseInfo.rcvrClkOffset = RinexUtils.parseDouble(line, 68, 12);
843 if (Double.isNaN(parseInfo.rcvrClkOffset)) {
844 parseInfo.rcvrClkOffset = 0.0;
845 }
846
847 } else if (parseInfo.eventFlag < 6) {
848
849
850 parseInfo.specialRecord = true;
851 parseInfo.cycleSlip = false;
852 parseInfo.nextObsStartLineNumber = parseInfo.lineNumber + parseInfo.nbSatObs + 1;
853 } else if (parseInfo.eventFlag == 6) {
854
855 parseInfo.specialRecord = false;
856 parseInfo.cycleSlip = true;
857 parseInfo.nextObsStartLineNumber = parseInfo.lineNumber + nbLinesSat;
858 } else {
859
860 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
861 parseInfo.lineNumber, parseInfo.name, line);
862 }
863
864
865 parseInfo.satObs.clear();
866 if (!parseInfo.specialRecord) {
867
868
869 parseInfo.setTObs(new AbsoluteDate(RinexUtils.convert2DigitsYear(RinexUtils.parseInt(line, 1, 2)),
870 RinexUtils.parseInt(line, 4, 2),
871 RinexUtils.parseInt(line, 7, 2),
872 RinexUtils.parseInt(line, 10, 2),
873 RinexUtils.parseInt(line, 13, 2),
874 RinexUtils.parseDouble(line, 15, 11),
875 parseInfo.timeScale));
876
877
878 RINEX_2_DATA_SAT_LIST.parsingMethod.parse(line, parseInfo);
879
880 }
881
882
883 parseInfo.indexObsSat = 0;
884 parseInfo.observations.clear();
885
886 },
887 LineParser::first2),
888
889
890 RINEX_2_IGNORED_SPECIAL_RECORD(line -> true,
891 (line, parseInfo) -> {
892
893 },
894 LineParser::ignore2),
895
896
897 RINEX_2_OBSERVATION(line -> true,
898 (line, parseInfo) -> {
899 final List<ObservationType> types = parseInfo.file.getHeader().getTypeObs().get(parseInfo.file.getHeader().getSatelliteSystem());
900 for (int index = 0;
901 parseInfo.observations.size() < types.size() && index < 80;
902 index += 16) {
903 final ObservationData observationData;
904 if (parseInfo.cycleSlip) {
905
906 observationData = null;
907 } else {
908
909 final ObservationType type = types.get(parseInfo.observations.size());
910 final double scaling = getScaling(parseInfo, type, parseInfo.currentSystem);
911 observationData = new ObservationData(type,
912 scaling * RinexUtils.parseDouble(line, index, 14),
913 RinexUtils.parseInt(line, index + 14, 1),
914 RinexUtils.parseInt(line, index + 15, 1));
915 }
916 parseInfo.observations.add(observationData);
917 }
918
919 if (parseInfo.observations.size() == types.size()) {
920
921 if (!parseInfo.cycleSlip) {
922 parseInfo.file.addObservationDataSet(new ObservationDataSet(parseInfo.satObs.get(parseInfo.indexObsSat),
923 parseInfo.tObs,
924 parseInfo.eventFlag,
925 parseInfo.rcvrClkOffset,
926 new ArrayList<>(parseInfo.observations)));
927 }
928 parseInfo.indexObsSat++;
929 parseInfo.observations.clear();
930 }
931
932 },
933 LineParser::observation2),
934
935
936 RINEX_3_OBSERVATION(line -> true,
937 (line, parseInfo) -> {
938 final SatelliteSystem system = SatelliteSystem.parseSatelliteSystem(RinexUtils.parseString(line, 0, 1));
939 final int prn = RinexUtils.parseInt(line, 1, 2);
940 final SatInSystem sat = new SatInSystem(system,
941 system == SatelliteSystem.SBAS ?
942 prn + 100 :
943 (system == SatelliteSystem.QZSS ? prn + 192 : prn));
944 final List<ObservationType> types = parseInfo.file.getHeader().getTypeObs().get(sat.getSystem());
945 for (int index = 3;
946 parseInfo.observations.size() < types.size();
947 index += 16) {
948 final ObservationData observationData;
949 if (parseInfo.specialRecord || parseInfo.cycleSlip) {
950
951 observationData = null;
952 } else {
953
954 final ObservationType type = types.get(parseInfo.observations.size());
955 final double scaling = getScaling(parseInfo, type, sat.getSystem());
956 observationData = new ObservationData(type,
957 scaling * RinexUtils.parseDouble(line, index, 14),
958 RinexUtils.parseInt(line, index + 14, 1),
959 RinexUtils.parseInt(line, index + 15, 1));
960 }
961 parseInfo.observations.add(observationData);
962 }
963
964 if (!(parseInfo.specialRecord || parseInfo.cycleSlip)) {
965 parseInfo.file.addObservationDataSet(new ObservationDataSet(sat,
966 parseInfo.tObs,
967 parseInfo.eventFlag,
968 parseInfo.rcvrClkOffset,
969 new ArrayList<>(parseInfo.observations)));
970 }
971 parseInfo.observations.clear();
972
973 },
974 LineParser::observation3),
975
976
977 RINEX_3_DATA_FIRST(line -> line.startsWith(">"),
978 (line, parseInfo) -> {
979
980
981 parseInfo.eventFlag = RinexUtils.parseInt(line, 31, 1);
982
983
984 parseInfo.nbSatObs = RinexUtils.parseInt(line, 32, 3);
985
986 if (parseInfo.eventFlag < 2) {
987
988 parseInfo.specialRecord = false;
989 parseInfo.cycleSlip = false;
990 final int nbSat = parseInfo.file.getHeader().getNbSat();
991 if (nbSat != -1 && parseInfo.nbSatObs > nbSat) {
992
993 throw new OrekitException(OrekitMessages.INCONSISTENT_NUMBER_OF_SATS,
994 parseInfo.lineNumber, parseInfo.name,
995 parseInfo.nbSatObs, nbSat);
996 }
997 parseInfo.nextObsStartLineNumber = parseInfo.lineNumber + parseInfo.nbSatObs + 1;
998
999
1000 parseInfo.rcvrClkOffset = RinexUtils.parseDouble(line, 41, 15);
1001 if (Double.isNaN(parseInfo.rcvrClkOffset)) {
1002 parseInfo.rcvrClkOffset = 0.0;
1003 }
1004
1005 } else if (parseInfo.eventFlag < 6) {
1006
1007
1008 parseInfo.specialRecord = true;
1009 parseInfo.cycleSlip = false;
1010 parseInfo.nextObsStartLineNumber = parseInfo.lineNumber + parseInfo.nbSatObs + 1;
1011 } else if (parseInfo.eventFlag == 6) {
1012
1013 parseInfo.specialRecord = false;
1014 parseInfo.cycleSlip = true;
1015 parseInfo.nextObsStartLineNumber = parseInfo.lineNumber + parseInfo.nbSatObs + 1;
1016 } else {
1017
1018 throw new OrekitException(OrekitMessages.UNABLE_TO_PARSE_LINE_IN_FILE,
1019 parseInfo.lineNumber, parseInfo.name, line);
1020 }
1021
1022
1023 parseInfo.satObs.clear();
1024 if (!parseInfo.specialRecord) {
1025
1026
1027 parseInfo.setTObs(new AbsoluteDate(RinexUtils.parseInt(line, 2, 4),
1028 RinexUtils.parseInt(line, 7, 2),
1029 RinexUtils.parseInt(line, 10, 2),
1030 RinexUtils.parseInt(line, 13, 2),
1031 RinexUtils.parseInt(line, 16, 2),
1032 RinexUtils.parseDouble(line, 18, 11),
1033 parseInfo.timeScale));
1034
1035 }
1036
1037
1038 parseInfo.observations.clear();
1039
1040 },
1041 parseInfo -> Collections.singleton(RINEX_3_OBSERVATION));
1042
1043
1044
1045 private final Predicate<String> canHandle;
1046
1047
1048 private final ParsingMethod parsingMethod;
1049
1050
1051 private final Function<ParseInfo, Iterable<LineParser>> allowedNextProvider;
1052
1053
1054
1055
1056
1057
1058 LineParser(final Predicate<String> canHandle, final ParsingMethod parsingMethod,
1059 final Function<ParseInfo, Iterable<LineParser>> allowedNextProvider) {
1060 this.canHandle = canHandle;
1061 this.parsingMethod = parsingMethod;
1062 this.allowedNextProvider = allowedNextProvider;
1063 }
1064
1065
1066
1067
1068
1069 private static Iterable<LineParser> commentNext(final ParseInfo parseInfo) {
1070 return parseInfo.headerCompleted ? headerEndNext(parseInfo) : headerNext(parseInfo);
1071 }
1072
1073
1074
1075
1076
1077 private static Iterable<LineParser> headerNext(final ParseInfo parseInfo) {
1078 if (parseInfo.file.getHeader().getFormatVersion() < 3) {
1079
1080 return Arrays.asList(PROGRAM, COMMENT, MARKER_NAME, MARKER_NUMBER, MARKER_TYPE, OBSERVER_AGENCY,
1081 REC_NB_TYPE_VERS, ANT_NB_TYPE, APPROX_POSITION_XYZ, ANTENNA_DELTA_H_E_N,
1082 ANTENNA_DELTA_X_Y_Z, ANTENNA_B_SIGHT_XYZ, WAVELENGTH_FACT_L1_2, OBS_SCALE_FACTOR,
1083 CENTER_OF_MASS_XYZ, SYS_NB_TYPES_OF_OBSERV, INTERVAL, TIME_OF_FIRST_OBS, TIME_OF_LAST_OBS,
1084 RCV_CLOCK_OFFS_APPL, LEAP_SECONDS, NB_OF_SATELLITES, PRN_NB_OF_OBS, END);
1085 } else if (parseInfo.file.getHeader().getFormatVersion() < 4) {
1086
1087 return Arrays.asList(PROGRAM, COMMENT, MARKER_NAME, MARKER_NUMBER, MARKER_TYPE, OBSERVER_AGENCY,
1088 REC_NB_TYPE_VERS, ANT_NB_TYPE, APPROX_POSITION_XYZ, ANTENNA_DELTA_H_E_N,
1089 ANTENNA_DELTA_X_Y_Z, ANTENNA_PHASE_CENTER, ANTENNA_B_SIGHT_XYZ, ANTENNA_ZERODIR_AZI,
1090 ANTENNA_ZERODIR_XYZ, CENTER_OF_MASS_XYZ, SYS_NB_TYPES_OF_OBSERV, SIGNAL_STRENGTH_UNIT,
1091 INTERVAL, TIME_OF_FIRST_OBS, TIME_OF_LAST_OBS, RCV_CLOCK_OFFS_APPL,
1092 SYS_DCBS_APPLIED, SYS_PCVS_APPLIED, SYS_SCALE_FACTOR, SYS_PHASE_SHIFT,
1093 GLONASS_SLOT_FRQ_NB, GLONASS_COD_PHS_BIS, LEAP_SECONDS, NB_OF_SATELLITES,
1094 PRN_NB_OF_OBS, END);
1095 } else {
1096
1097 return Arrays.asList(PROGRAM, COMMENT, MARKER_NAME, MARKER_NUMBER, MARKER_TYPE, OBSERVER_AGENCY,
1098 REC_NB_TYPE_VERS, ANT_NB_TYPE, APPROX_POSITION_XYZ, ANTENNA_DELTA_H_E_N,
1099 ANTENNA_DELTA_X_Y_Z, ANTENNA_PHASE_CENTER, ANTENNA_B_SIGHT_XYZ, ANTENNA_ZERODIR_AZI,
1100 ANTENNA_ZERODIR_XYZ, CENTER_OF_MASS_XYZ, DOI, LICENSE, STATION_INFORMATION,
1101 SYS_NB_TYPES_OF_OBSERV, SIGNAL_STRENGTH_UNIT, INTERVAL, TIME_OF_FIRST_OBS, TIME_OF_LAST_OBS,
1102 RCV_CLOCK_OFFS_APPL, SYS_DCBS_APPLIED, SYS_PCVS_APPLIED, SYS_SCALE_FACTOR, SYS_PHASE_SHIFT,
1103 GLONASS_SLOT_FRQ_NB, GLONASS_COD_PHS_BIS, LEAP_SECONDS, NB_OF_SATELLITES,
1104 PRN_NB_OF_OBS, END);
1105 }
1106 }
1107
1108
1109
1110
1111
1112 private static Iterable<LineParser> headerEndNext(final ParseInfo parseInfo) {
1113 return Collections.singleton(parseInfo.file.getHeader().getFormatVersion() < 3 ?
1114 RINEX_2_DATA_FIRST : RINEX_3_DATA_FIRST);
1115 }
1116
1117
1118
1119
1120
1121 private static Iterable<LineParser> headerNbTypesObs(final ParseInfo parseInfo) {
1122 if (parseInfo.typesObs.size() < parseInfo.nbTypes) {
1123 return Arrays.asList(COMMENT, SYS_NB_TYPES_OF_OBSERV);
1124 } else {
1125 return headerNext(parseInfo);
1126 }
1127 }
1128
1129
1130
1131
1132
1133 private static Iterable<LineParser> headerPhaseShift(final ParseInfo parseInfo) {
1134 if (parseInfo.satPhaseShift.size() < parseInfo.phaseShiftNbSat) {
1135 return Arrays.asList(COMMENT, SYS_PHASE_SHIFT);
1136 } else {
1137 return headerNext(parseInfo);
1138 }
1139 }
1140
1141
1142
1143
1144
1145 private static Iterable<LineParser> first2(final ParseInfo parseInfo) {
1146 if (parseInfo.specialRecord) {
1147 return Collections.singleton(RINEX_2_IGNORED_SPECIAL_RECORD);
1148 } else if (parseInfo.satObs.size() < parseInfo.nbSatObs) {
1149 return Collections.singleton(RINEX_2_DATA_SAT_LIST);
1150 } else {
1151 return Collections.singleton(RINEX_2_OBSERVATION);
1152 }
1153 }
1154
1155
1156
1157
1158
1159 private static Iterable<LineParser> ignore2(final ParseInfo parseInfo) {
1160 if (parseInfo.lineNumber < parseInfo.nextObsStartLineNumber) {
1161 return Collections.singleton(RINEX_2_IGNORED_SPECIAL_RECORD);
1162 } else {
1163 return Arrays.asList(COMMENT, RINEX_2_DATA_FIRST);
1164 }
1165 }
1166
1167
1168
1169
1170
1171 private static Iterable<LineParser> observation2(final ParseInfo parseInfo) {
1172 if (parseInfo.lineNumber < parseInfo.nextObsStartLineNumber) {
1173 return Collections.singleton(RINEX_2_OBSERVATION);
1174 } else {
1175 return Arrays.asList(COMMENT, RINEX_2_DATA_FIRST);
1176 }
1177 }
1178
1179
1180
1181
1182
1183 private static Iterable<LineParser> observation3(final ParseInfo parseInfo) {
1184 if (parseInfo.lineNumber < parseInfo.nextObsStartLineNumber) {
1185 return Collections.singleton(RINEX_3_OBSERVATION);
1186 } else {
1187 return Arrays.asList(COMMENT, RINEX_3_DATA_FIRST);
1188 }
1189 }
1190
1191
1192
1193
1194
1195
1196
1197 private static double getScaling(final ParseInfo parseInfo, final ObservationType type,
1198 final SatelliteSystem system) {
1199
1200 for (final ScaleFactorCorrection scaleFactorCorrection :
1201 parseInfo.file.getHeader().getScaleFactorCorrections(system)) {
1202
1203 if (scaleFactorCorrection.getTypesObsScaled().contains(type)) {
1204 return 1.0 / scaleFactorCorrection.getCorrection();
1205 }
1206 }
1207
1208
1209 return 1.0;
1210
1211 }
1212
1213 }
1214
1215
1216 @FunctionalInterface
1217 private interface ParsingMethod {
1218
1219
1220
1221
1222 void parse(String line, ParseInfo parseInfo);
1223 }
1224
1225 }