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