gnss-js 1.0.0 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/analysis.cjs CHANGED
@@ -41,8 +41,20 @@ var C_LIGHT = 299792458;
41
41
  var FREQ = {
42
42
  G: { "1": 157542e4, "2": 12276e5, "5": 117645e4 },
43
43
  R: { "3": 1202025e3 },
44
- E: { "1": 157542e4, "5": 117645e4, "6": 127875e4, "7": 120714e4, "8": 1191795e3 },
45
- C: { "1": 157542e4, "2": 1561098e3, "5": 117645e4, "6": 126852e4, "7": 120714e4 },
44
+ E: {
45
+ "1": 157542e4,
46
+ "5": 117645e4,
47
+ "6": 127875e4,
48
+ "7": 120714e4,
49
+ "8": 1191795e3
50
+ },
51
+ C: {
52
+ "1": 157542e4,
53
+ "2": 1561098e3,
54
+ "5": 117645e4,
55
+ "6": 126852e4,
56
+ "7": 120714e4
57
+ },
46
58
  J: { "1": 157542e4, "2": 12276e5, "5": 117645e4, "6": 127875e4 },
47
59
  I: { "5": 117645e4, "9": 2492028e3 },
48
60
  S: { "1": 157542e4, "5": 117645e4 }
@@ -57,11 +69,28 @@ var BAND_LABELS = {
57
69
  S: { "1": "L1", "5": "L5" }
58
70
  };
59
71
  var DUAL_FREQ_PAIRS = {
60
- G: [["1", "2"], ["1", "5"]],
61
- R: [["1", "2"], ["1", "3"]],
62
- E: [["1", "5"], ["1", "7"], ["1", "6"]],
63
- C: [["2", "7"], ["2", "6"], ["1", "5"]],
64
- J: [["1", "2"], ["1", "5"]],
72
+ G: [
73
+ ["1", "2"],
74
+ ["1", "5"]
75
+ ],
76
+ R: [
77
+ ["1", "2"],
78
+ ["1", "3"]
79
+ ],
80
+ E: [
81
+ ["1", "5"],
82
+ ["1", "7"],
83
+ ["1", "6"]
84
+ ],
85
+ C: [
86
+ ["2", "7"],
87
+ ["2", "6"],
88
+ ["1", "5"]
89
+ ],
90
+ J: [
91
+ ["1", "2"],
92
+ ["1", "5"]
93
+ ],
65
94
  I: [["5", "9"]],
66
95
  S: [["1", "5"]]
67
96
  };
@@ -270,8 +299,18 @@ var MultipathAccumulator = class {
270
299
  time: t,
271
300
  mp: arc.rawMp[i] - mean
272
301
  }));
273
- const rms = Math.sqrt(points.reduce((s, p) => s + p.mp * p.mp, 0) / points.length);
274
- this.results.push({ prn, system: sys, band, refBand, label, points, rms });
302
+ const rms = Math.sqrt(
303
+ points.reduce((s, p) => s + p.mp * p.mp, 0) / points.length
304
+ );
305
+ this.results.push({
306
+ prn,
307
+ system: sys,
308
+ band,
309
+ refBand,
310
+ label,
311
+ points,
312
+ rms
313
+ });
275
314
  }
276
315
  state.arc = { times: [], rawMp: [] };
277
316
  }
@@ -425,10 +464,20 @@ var CycleSlipAccumulator = class {
425
464
  const sigKey = `${sys}:${signal}`;
426
465
  this.countEpoch(sigKey);
427
466
  const stddev = mwSmoothStddev(prevSmooth);
428
- const threshold = Math.max(MW_MIN_THRESHOLD, MW_SIGMA_FACTOR * stddev);
467
+ const threshold = Math.max(
468
+ MW_MIN_THRESHOLD,
469
+ MW_SIGMA_FACTOR * stddev
470
+ );
429
471
  const deviation = Math.abs(mw - prevSmooth.mean);
430
472
  if (deviation > threshold) {
431
- this.recordSlip(sigKey, time, prn, signal, deviation, /* @__PURE__ */ new Set([b1, b2]));
473
+ this.recordSlip(
474
+ sigKey,
475
+ time,
476
+ prn,
477
+ signal,
478
+ deviation,
479
+ /* @__PURE__ */ new Set([b1, b2])
480
+ );
432
481
  mwSmooth.set(pairKey, mwSmoothInit(mw));
433
482
  } else {
434
483
  mwSmooth.set(pairKey, mwSmoothUpdate(prevSmooth, mw));
@@ -483,7 +532,13 @@ var CycleSlipAccumulator = class {
483
532
  }
484
533
  }
485
534
  }
486
- this.prev.set(prn, { time, mwSmooth, gf: gfMap, phase: phaseM, code: codeM });
535
+ this.prev.set(prn, {
536
+ time,
537
+ mwSmooth,
538
+ gf: gfMap,
539
+ phase: phaseM,
540
+ code: codeM
541
+ });
487
542
  };
488
543
  finalize() {
489
544
  const satSlipCounts = {};
@@ -491,7 +546,10 @@ var CycleSlipAccumulator = class {
491
546
  satSlipCounts[ev.prn] = (satSlipCounts[ev.prn] ?? 0) + 1;
492
547
  }
493
548
  const signalStats = [];
494
- const allKeys = /* @__PURE__ */ new Set([...this.signalEpochs.keys(), ...this.signalSlips.keys()]);
549
+ const allKeys = /* @__PURE__ */ new Set([
550
+ ...this.signalEpochs.keys(),
551
+ ...this.signalSlips.keys()
552
+ ]);
495
553
  for (const sigKey of allKeys) {
496
554
  const [sys, ...rest] = sigKey.split(":");
497
555
  const signal = rest.join(":");
@@ -650,10 +708,20 @@ function parseCrxDataLine(line, ntype) {
650
708
  if (token.length >= 3 && token[1] === "&") {
651
709
  const arcOrder = parseInt(token[0]);
652
710
  const value = parseInt(token.substring(2));
653
- fields.push({ empty: false, init: true, arcOrder, value: isNaN(value) ? 0 : value });
711
+ fields.push({
712
+ empty: false,
713
+ init: true,
714
+ arcOrder,
715
+ value: isNaN(value) ? 0 : value
716
+ });
654
717
  } else {
655
718
  const value = parseInt(token);
656
- fields.push({ empty: false, init: false, arcOrder: -1, value: isNaN(value) ? 0 : value });
719
+ fields.push({
720
+ empty: false,
721
+ init: false,
722
+ arcOrder: -1,
723
+ value: isNaN(value) ? 0 : value
724
+ });
657
725
  }
658
726
  }
659
727
  const flagStr = pos < line.length ? line.substring(pos) : "";
@@ -663,7 +731,10 @@ function crxDecompress(prev, field) {
663
731
  if (field.init) {
664
732
  const a = new Array(Math.max(field.arcOrder + 1, 1)).fill(0);
665
733
  a[0] = field.value;
666
- return { state: { accum: a, order: 0, arcOrder: field.arcOrder }, result: field.value };
734
+ return {
735
+ state: { accum: a, order: 0, arcOrder: field.arcOrder },
736
+ result: field.value
737
+ };
667
738
  }
668
739
  if (!prev) {
669
740
  return { state: { accum: [0], order: 0, arcOrder: 0 }, result: 0 };
@@ -676,7 +747,10 @@ function crxDecompress(prev, field) {
676
747
  for (let k = order; k >= 1; k--) {
677
748
  accum[k - 1] += accum[k];
678
749
  }
679
- return { state: { accum, order, arcOrder: prev.arcOrder }, result: accum[0] };
750
+ return {
751
+ state: { accum, order, arcOrder: prev.arcOrder },
752
+ result: accum[0]
753
+ };
680
754
  }
681
755
 
682
756
  // src/rinex/parser.ts
@@ -684,7 +758,9 @@ var CHUNK_SIZE = 2 * 1024 * 1024;
684
758
  var yieldToMain = () => new Promise((r) => setTimeout(r, 0));
685
759
  var noYield = () => Promise.resolve();
686
760
  var SYSTEM_ORDER = ["G", "R", "E", "C", "J", "I", "S"];
687
- var SYSTEM_RANK = Object.fromEntries(SYSTEM_ORDER.map((s, i) => [s, i]));
761
+ var SYSTEM_RANK = Object.fromEntries(
762
+ SYSTEM_ORDER.map((s, i) => [s, i])
763
+ );
688
764
  function systemCmp(a, b) {
689
765
  const ra = SYSTEM_RANK[a.charAt(0)] ?? 99;
690
766
  const rb = SYSTEM_RANK[b.charAt(0)] ?? 99;
@@ -867,7 +943,11 @@ function parseEpochLine3(line) {
867
943
  const wholeSec = Math.floor(sc);
868
944
  const ms = Math.round((sc - wholeSec) * 1e3);
869
945
  const time = Date.UTC(yr, mo - 1, dy, hr, mn, wholeSec, ms);
870
- return { time, flag: isNaN(flag) ? 0 : flag, numSats: isNaN(numSats) ? 0 : numSats };
946
+ return {
947
+ time,
948
+ flag: isNaN(flag) ? 0 : flag,
949
+ numSats: isNaN(numSats) ? 0 : numSats
950
+ };
871
951
  }
872
952
  function parseEpochLine2(line) {
873
953
  const yr2 = parseInt(line.substring(1, 3));
@@ -889,7 +969,12 @@ function parseEpochLine2(line) {
889
969
  const id = satPart.substring(i, i + 3).trim();
890
970
  if (id) satIds.push(id);
891
971
  }
892
- return { time, flag: isNaN(flag) ? 0 : flag, numSats: isNaN(numSats) ? 0 : numSats, satIds };
972
+ return {
973
+ time,
974
+ flag: isNaN(flag) ? 0 : flag,
975
+ numSats: isNaN(numSats) ? 0 : numSats,
976
+ satIds
977
+ };
893
978
  }
894
979
  async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode) {
895
980
  const skipEpochs = !!workerMode;
@@ -942,16 +1027,19 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
942
1027
  if (!skipEpochs) {
943
1028
  const snrBySys = {};
944
1029
  for (const [sys, vals] of Object.entries(snrPerSystemAccum)) {
945
- if (vals.length > 0) snrBySys[sys] = vals.reduce((a, b) => a + b, 0) / vals.length;
1030
+ if (vals.length > 0)
1031
+ snrBySys[sys] = vals.reduce((a, b) => a + b, 0) / vals.length;
946
1032
  }
947
1033
  const meanSnr = snrValues.length > 0 ? snrValues.reduce((a, b) => a + b, 0) / snrValues.length : null;
948
1034
  const snrPerSat = {};
949
1035
  for (const [prn, vals] of Object.entries(snrPerSatAccum)) {
950
- if (vals.length > 0) snrPerSat[prn] = vals.reduce((a, b) => a + b, 0) / vals.length;
1036
+ if (vals.length > 0)
1037
+ snrPerSat[prn] = vals.reduce((a, b) => a + b, 0) / vals.length;
951
1038
  }
952
1039
  const snrPerSatBand = {};
953
1040
  for (const [key, vals] of Object.entries(snrPerSatBandAccum)) {
954
- if (vals.length > 0) snrPerSatBand[key] = vals.reduce((a, b) => a + b, 0) / vals.length;
1041
+ if (vals.length > 0)
1042
+ snrPerSatBand[key] = vals.reduce((a, b) => a + b, 0) / vals.length;
955
1043
  }
956
1044
  epochs.push({
957
1045
  time: epochInfo.time,
@@ -996,7 +1084,8 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
996
1084
  const codes = header.obsTypes[sys] ?? [];
997
1085
  if (onSatObs && epochInfo) {
998
1086
  const values = new Array(codes.length);
999
- for (let i = 0; i < codes.length; i++) values[i] = readObsValue(obsLine, i);
1087
+ for (let i = 0; i < codes.length; i++)
1088
+ values[i] = readObsValue(obsLine, i);
1000
1089
  if (!skipEpochs) {
1001
1090
  for (const { idx, band } of getSnrIndices(sys)) {
1002
1091
  const val = values[idx] ?? null;
@@ -1233,7 +1322,10 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1233
1322
  v2SnrBandInfo = snrIndicesWithBandV2(header.obsTypes);
1234
1323
  v2SatIndex = 0;
1235
1324
  v2CurrentSatLine = 0;
1236
- const continuationLines = Math.max(0, Math.ceil((info.numSats - 12) / 12));
1325
+ const continuationLines = Math.max(
1326
+ 0,
1327
+ Math.ceil((info.numSats - 12) / 12)
1328
+ );
1237
1329
  if (continuationLines > 0) {
1238
1330
  v2ContinuationSatsRemaining = continuationLines;
1239
1331
  } else {
@@ -1273,7 +1365,9 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1273
1365
  const magic = new Uint8Array(await file.slice(0, 2).arrayBuffer());
1274
1366
  const isGz = magic[0] === 31 && magic[1] === 139;
1275
1367
  if (magic[0] === 31 && magic[1] === 157) {
1276
- throw new Error("Unix compress (.Z) files are not supported. Please decompress first (e.g. uncompress or gzip -d).");
1368
+ throw new Error(
1369
+ "Unix compress (.Z) files are not supported. Please decompress first (e.g. uncompress or gzip -d)."
1370
+ );
1277
1371
  }
1278
1372
  if (isGz) {
1279
1373
  let bytesRead = 0;
@@ -1289,7 +1383,9 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1289
1383
  if (done) break;
1290
1384
  bytesRead += value.byteLength;
1291
1385
  processChunkText(decoder.decode(value, { stream: true }), false);
1292
- onProgress?.(Math.min(99, Math.round(bytesRead / (file.size * 4) * 100)));
1386
+ onProgress?.(
1387
+ Math.min(99, Math.round(bytesRead / (file.size * 4) * 100))
1388
+ );
1293
1389
  await yield_();
1294
1390
  }
1295
1391
  processChunkText(decoder.decode(), true);
@@ -1299,7 +1395,10 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1299
1395
  const end = Math.min(offset + CHUNK_SIZE, file.size);
1300
1396
  const slice = file.slice(offset, end);
1301
1397
  const arrayBuf = await slice.arrayBuffer();
1302
- processChunkText(decoder.decode(arrayBuf, { stream: end < file.size }), false);
1398
+ processChunkText(
1399
+ decoder.decode(arrayBuf, { stream: end < file.size }),
1400
+ false
1401
+ );
1303
1402
  onProgress?.(Math.min(99, Math.round(end / file.size * 100)));
1304
1403
  await yield_();
1305
1404
  }
@@ -1307,19 +1406,27 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
1307
1406
  processChunkText("", true);
1308
1407
  }
1309
1408
  }
1310
- if (epochInfo && satLinesRemaining === 0 && crxPhase === "epoch") finishEpoch();
1311
- if (!header) throw new Error("No valid RINEX header found (missing END OF HEADER).");
1409
+ if (epochInfo && satLinesRemaining === 0 && crxPhase === "epoch")
1410
+ finishEpoch();
1411
+ if (!header)
1412
+ throw new Error("No valid RINEX header found (missing END OF HEADER).");
1312
1413
  onProgress?.(100);
1313
- return { header, epochs, stats: computeStats(header, epochs, satellitesSeen) };
1414
+ return {
1415
+ header,
1416
+ epochs,
1417
+ stats: computeStats(header, epochs, satellitesSeen)
1418
+ };
1314
1419
  }
1315
1420
  function computeStats(header, epochs, satellitesSeen) {
1316
1421
  const n = epochs.length;
1317
1422
  const startTime = n > 0 ? new Date(epochs[0].time) : header.timeOfFirstObs;
1318
1423
  const endTime = n > 0 ? new Date(epochs[n - 1].time) : header.timeOfLastObs;
1319
1424
  let duration = null;
1320
- if (startTime && endTime) duration = (endTime.getTime() - startTime.getTime()) / 1e3;
1425
+ if (startTime && endTime)
1426
+ duration = (endTime.getTime() - startTime.getTime()) / 1e3;
1321
1427
  let interval = header.interval;
1322
- if (interval === null && n >= 2) interval = (epochs[1].time - epochs[0].time) / 1e3;
1428
+ if (interval === null && n >= 2)
1429
+ interval = (epochs[1].time - epochs[0].time) / 1e3;
1323
1430
  const uniqueSatsPerSystem = {};
1324
1431
  let totalUnique = 0;
1325
1432
  const systems = [];
package/dist/analysis.js CHANGED
@@ -3,9 +3,9 @@ import {
3
3
  CycleSlipAccumulator,
4
4
  MultipathAccumulator,
5
5
  analyzeQuality
6
- } from "./chunk-Y3R57B5P.js";
7
- import "./chunk-CB6EOOLA.js";
8
- import "./chunk-354IRDOG.js";
6
+ } from "./chunk-SO3POWWR.js";
7
+ import "./chunk-HBLU2EJ4.js";
8
+ import "./chunk-LWNTWBHB.js";
9
9
  export {
10
10
  CompletenessAccumulator,
11
11
  CycleSlipAccumulator,
@@ -33,10 +33,7 @@ function keplerPosition(eph, t) {
33
33
  }
34
34
  const sinE = Math.sin(Ek);
35
35
  const cosE = Math.cos(Ek);
36
- const vk = Math.atan2(
37
- Math.sqrt(1 - eph.e * eph.e) * sinE,
38
- cosE - eph.e
39
- );
36
+ const vk = Math.atan2(Math.sqrt(1 - eph.e * eph.e) * sinE, cosE - eph.e);
40
37
  const phik = vk + eph.omega;
41
38
  const sin2phi = Math.sin(2 * phik);
42
39
  const cos2phi = Math.cos(2 * phik);
@@ -199,7 +196,10 @@ function invert4x4(m) {
199
196
  let det = a[0] * inv[0] + a[1] * inv[4] + a[2] * inv[8] + a[3] * inv[12];
200
197
  if (Math.abs(det) < 1e-20) return null;
201
198
  det = 1 / det;
202
- const result = Array.from({ length: 4 }, () => new Array(4).fill(0));
199
+ const result = Array.from(
200
+ { length: 4 },
201
+ () => new Array(4).fill(0)
202
+ );
203
203
  for (let i = 0; i < 4; i++) {
204
204
  for (let j = 0; j < 4; j++) {
205
205
  result[i][j] = inv[i * 4 + j] * det;
@@ -316,10 +316,16 @@ var GAL_EPOCH_MS = GPS_EPOCH_MS;
316
316
  function ephInfoToEphemeris(info) {
317
317
  const sys = info.prn.charAt(0);
318
318
  if (sys === "R") {
319
- if (info.x === void 0 || info.y === void 0 || info.z === void 0) return null;
320
- if (info.vx === void 0 || info.vy === void 0 || info.vz === void 0) return null;
319
+ if (info.x === void 0 || info.y === void 0 || info.z === void 0)
320
+ return null;
321
+ if (info.vx === void 0 || info.vy === void 0 || info.vz === void 0)
322
+ return null;
321
323
  const now = new Date(info.lastReceived);
322
- const utcMidnight = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate());
324
+ const utcMidnight = Date.UTC(
325
+ now.getUTCFullYear(),
326
+ now.getUTCMonth(),
327
+ now.getUTCDate()
328
+ );
323
329
  const tbSec = (info.tb ?? 0) * 900;
324
330
  const moscowOffset = 3 * 3600;
325
331
  const tocMs = utcMidnight + (tbSec - moscowOffset) * 1e3;
@@ -344,7 +350,8 @@ function ephInfoToEphemeris(info) {
344
350
  freqNum: info.freqChannel ?? 0
345
351
  };
346
352
  }
347
- if (info.sqrtA === void 0 || info.eccentricity === void 0 || info.inclination === void 0 || info.omega0 === void 0 || info.argPerigee === void 0 || info.meanAnomaly === void 0 || info.toe === void 0 || info.week === void 0) return null;
353
+ if (info.sqrtA === void 0 || info.eccentricity === void 0 || info.inclination === void 0 || info.omega0 === void 0 || info.argPerigee === void 0 || info.meanAnomaly === void 0 || info.toe === void 0 || info.week === void 0)
354
+ return null;
348
355
  let epochMs;
349
356
  const tocSec = info.toc ?? info.toe;
350
357
  if (sys === "C") {
@@ -98,14 +98,18 @@ async function ntripFetch(proxyUrl, path, headers, signal) {
98
98
  } catch (err) {
99
99
  if (err instanceof Error && err.name === "AbortError") throw err;
100
100
  const message = err instanceof Error ? err.message : "The service may be temporarily unavailable.";
101
- throw new Error(`Could not reach the NTRIP proxy: ${message}`, { cause: err });
101
+ throw new Error(`Could not reach the NTRIP proxy: ${message}`, {
102
+ cause: err
103
+ });
102
104
  }
103
105
  }
104
106
  async function fetchSourcetable(proxyUrl, info, signal) {
105
107
  const headers = ntripHeaders(info);
106
108
  const res = await ntripFetch(proxyUrl, "/", headers, signal);
107
109
  if (res.status === 401) {
108
- throw new Error("Authentication required. Please provide valid credentials.");
110
+ throw new Error(
111
+ "Authentication required. Please provide valid credentials."
112
+ );
109
113
  }
110
114
  if (!res.ok) {
111
115
  throw new Error(`Caster returned ${res.status} ${res.statusText}`);
@@ -117,7 +121,12 @@ async function connectToMountpoint(proxyUrl, info, signal) {
117
121
  const headers = ntripHeaders(info);
118
122
  const controller = new AbortController();
119
123
  const combinedSignal = signal ? AbortSignal.any([signal, controller.signal]) : controller.signal;
120
- const res = await ntripFetch(proxyUrl, `/${info.mountpoint}`, headers, combinedSignal);
124
+ const res = await ntripFetch(
125
+ proxyUrl,
126
+ `/${info.mountpoint}`,
127
+ headers,
128
+ combinedSignal
129
+ );
121
130
  if (res.status === 401) {
122
131
  throw new Error("Authentication required for this mountpoint.");
123
132
  }
@@ -128,7 +137,9 @@ async function connectToMountpoint(proxyUrl, info, signal) {
128
137
  throw new Error(`Caster returned ${res.status} ${res.statusText}`);
129
138
  }
130
139
  if (!res.body) {
131
- throw new Error("No response body \u2014 streaming not supported by this environment.");
140
+ throw new Error(
141
+ "No response body \u2014 streaming not supported by this environment."
142
+ );
132
143
  }
133
144
  return {
134
145
  reader: res.body.getReader(),
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  SYSTEM_NAMES
3
- } from "./chunk-354IRDOG.js";
3
+ } from "./chunk-LWNTWBHB.js";
4
4
 
5
5
  // src/rinex/crx.ts
6
6
  function crxRepair(old, diff) {
@@ -42,10 +42,20 @@ function parseCrxDataLine(line, ntype) {
42
42
  if (token.length >= 3 && token[1] === "&") {
43
43
  const arcOrder = parseInt(token[0]);
44
44
  const value = parseInt(token.substring(2));
45
- fields.push({ empty: false, init: true, arcOrder, value: isNaN(value) ? 0 : value });
45
+ fields.push({
46
+ empty: false,
47
+ init: true,
48
+ arcOrder,
49
+ value: isNaN(value) ? 0 : value
50
+ });
46
51
  } else {
47
52
  const value = parseInt(token);
48
- fields.push({ empty: false, init: false, arcOrder: -1, value: isNaN(value) ? 0 : value });
53
+ fields.push({
54
+ empty: false,
55
+ init: false,
56
+ arcOrder: -1,
57
+ value: isNaN(value) ? 0 : value
58
+ });
49
59
  }
50
60
  }
51
61
  const flagStr = pos < line.length ? line.substring(pos) : "";
@@ -55,7 +65,10 @@ function crxDecompress(prev, field) {
55
65
  if (field.init) {
56
66
  const a = new Array(Math.max(field.arcOrder + 1, 1)).fill(0);
57
67
  a[0] = field.value;
58
- return { state: { accum: a, order: 0, arcOrder: field.arcOrder }, result: field.value };
68
+ return {
69
+ state: { accum: a, order: 0, arcOrder: field.arcOrder },
70
+ result: field.value
71
+ };
59
72
  }
60
73
  if (!prev) {
61
74
  return { state: { accum: [0], order: 0, arcOrder: 0 }, result: 0 };
@@ -68,7 +81,10 @@ function crxDecompress(prev, field) {
68
81
  for (let k = order; k >= 1; k--) {
69
82
  accum[k - 1] += accum[k];
70
83
  }
71
- return { state: { accum, order, arcOrder: prev.arcOrder }, result: accum[0] };
84
+ return {
85
+ state: { accum, order, arcOrder: prev.arcOrder },
86
+ result: accum[0]
87
+ };
72
88
  }
73
89
 
74
90
  // src/rinex/parser.ts
@@ -76,7 +92,9 @@ var CHUNK_SIZE = 2 * 1024 * 1024;
76
92
  var yieldToMain = () => new Promise((r) => setTimeout(r, 0));
77
93
  var noYield = () => Promise.resolve();
78
94
  var SYSTEM_ORDER = ["G", "R", "E", "C", "J", "I", "S"];
79
- var SYSTEM_RANK = Object.fromEntries(SYSTEM_ORDER.map((s, i) => [s, i]));
95
+ var SYSTEM_RANK = Object.fromEntries(
96
+ SYSTEM_ORDER.map((s, i) => [s, i])
97
+ );
80
98
  function systemCmp(a, b) {
81
99
  const ra = SYSTEM_RANK[a.charAt(0)] ?? 99;
82
100
  const rb = SYSTEM_RANK[b.charAt(0)] ?? 99;
@@ -262,7 +280,11 @@ function parseEpochLine3(line) {
262
280
  const wholeSec = Math.floor(sc);
263
281
  const ms = Math.round((sc - wholeSec) * 1e3);
264
282
  const time = Date.UTC(yr, mo - 1, dy, hr, mn, wholeSec, ms);
265
- return { time, flag: isNaN(flag) ? 0 : flag, numSats: isNaN(numSats) ? 0 : numSats };
283
+ return {
284
+ time,
285
+ flag: isNaN(flag) ? 0 : flag,
286
+ numSats: isNaN(numSats) ? 0 : numSats
287
+ };
266
288
  }
267
289
  function parseEpochLine2(line) {
268
290
  const yr2 = parseInt(line.substring(1, 3));
@@ -284,7 +306,12 @@ function parseEpochLine2(line) {
284
306
  const id = satPart.substring(i, i + 3).trim();
285
307
  if (id) satIds.push(id);
286
308
  }
287
- return { time, flag: isNaN(flag) ? 0 : flag, numSats: isNaN(numSats) ? 0 : numSats, satIds };
309
+ return {
310
+ time,
311
+ flag: isNaN(flag) ? 0 : flag,
312
+ numSats: isNaN(numSats) ? 0 : numSats,
313
+ satIds
314
+ };
288
315
  }
289
316
  async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode) {
290
317
  const skipEpochs = !!workerMode;
@@ -337,16 +364,19 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
337
364
  if (!skipEpochs) {
338
365
  const snrBySys = {};
339
366
  for (const [sys, vals] of Object.entries(snrPerSystemAccum)) {
340
- if (vals.length > 0) snrBySys[sys] = vals.reduce((a, b) => a + b, 0) / vals.length;
367
+ if (vals.length > 0)
368
+ snrBySys[sys] = vals.reduce((a, b) => a + b, 0) / vals.length;
341
369
  }
342
370
  const meanSnr = snrValues.length > 0 ? snrValues.reduce((a, b) => a + b, 0) / snrValues.length : null;
343
371
  const snrPerSat = {};
344
372
  for (const [prn, vals] of Object.entries(snrPerSatAccum)) {
345
- if (vals.length > 0) snrPerSat[prn] = vals.reduce((a, b) => a + b, 0) / vals.length;
373
+ if (vals.length > 0)
374
+ snrPerSat[prn] = vals.reduce((a, b) => a + b, 0) / vals.length;
346
375
  }
347
376
  const snrPerSatBand = {};
348
377
  for (const [key, vals] of Object.entries(snrPerSatBandAccum)) {
349
- if (vals.length > 0) snrPerSatBand[key] = vals.reduce((a, b) => a + b, 0) / vals.length;
378
+ if (vals.length > 0)
379
+ snrPerSatBand[key] = vals.reduce((a, b) => a + b, 0) / vals.length;
350
380
  }
351
381
  epochs.push({
352
382
  time: epochInfo.time,
@@ -391,7 +421,8 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
391
421
  const codes = header.obsTypes[sys] ?? [];
392
422
  if (onSatObs && epochInfo) {
393
423
  const values = new Array(codes.length);
394
- for (let i = 0; i < codes.length; i++) values[i] = readObsValue(obsLine, i);
424
+ for (let i = 0; i < codes.length; i++)
425
+ values[i] = readObsValue(obsLine, i);
395
426
  if (!skipEpochs) {
396
427
  for (const { idx, band } of getSnrIndices(sys)) {
397
428
  const val = values[idx] ?? null;
@@ -628,7 +659,10 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
628
659
  v2SnrBandInfo = snrIndicesWithBandV2(header.obsTypes);
629
660
  v2SatIndex = 0;
630
661
  v2CurrentSatLine = 0;
631
- const continuationLines = Math.max(0, Math.ceil((info.numSats - 12) / 12));
662
+ const continuationLines = Math.max(
663
+ 0,
664
+ Math.ceil((info.numSats - 12) / 12)
665
+ );
632
666
  if (continuationLines > 0) {
633
667
  v2ContinuationSatsRemaining = continuationLines;
634
668
  } else {
@@ -668,7 +702,9 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
668
702
  const magic = new Uint8Array(await file.slice(0, 2).arrayBuffer());
669
703
  const isGz = magic[0] === 31 && magic[1] === 139;
670
704
  if (magic[0] === 31 && magic[1] === 157) {
671
- throw new Error("Unix compress (.Z) files are not supported. Please decompress first (e.g. uncompress or gzip -d).");
705
+ throw new Error(
706
+ "Unix compress (.Z) files are not supported. Please decompress first (e.g. uncompress or gzip -d)."
707
+ );
672
708
  }
673
709
  if (isGz) {
674
710
  let bytesRead = 0;
@@ -684,7 +720,9 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
684
720
  if (done) break;
685
721
  bytesRead += value.byteLength;
686
722
  processChunkText(decoder.decode(value, { stream: true }), false);
687
- onProgress?.(Math.min(99, Math.round(bytesRead / (file.size * 4) * 100)));
723
+ onProgress?.(
724
+ Math.min(99, Math.round(bytesRead / (file.size * 4) * 100))
725
+ );
688
726
  await yield_();
689
727
  }
690
728
  processChunkText(decoder.decode(), true);
@@ -694,7 +732,10 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
694
732
  const end = Math.min(offset + CHUNK_SIZE, file.size);
695
733
  const slice = file.slice(offset, end);
696
734
  const arrayBuf = await slice.arrayBuffer();
697
- processChunkText(decoder.decode(arrayBuf, { stream: end < file.size }), false);
735
+ processChunkText(
736
+ decoder.decode(arrayBuf, { stream: end < file.size }),
737
+ false
738
+ );
698
739
  onProgress?.(Math.min(99, Math.round(end / file.size * 100)));
699
740
  await yield_();
700
741
  }
@@ -702,19 +743,27 @@ async function parseRinexStream(file, onProgress, signal, onSatObs, workerMode)
702
743
  processChunkText("", true);
703
744
  }
704
745
  }
705
- if (epochInfo && satLinesRemaining === 0 && crxPhase === "epoch") finishEpoch();
706
- if (!header) throw new Error("No valid RINEX header found (missing END OF HEADER).");
746
+ if (epochInfo && satLinesRemaining === 0 && crxPhase === "epoch")
747
+ finishEpoch();
748
+ if (!header)
749
+ throw new Error("No valid RINEX header found (missing END OF HEADER).");
707
750
  onProgress?.(100);
708
- return { header, epochs, stats: computeStats(header, epochs, satellitesSeen) };
751
+ return {
752
+ header,
753
+ epochs,
754
+ stats: computeStats(header, epochs, satellitesSeen)
755
+ };
709
756
  }
710
757
  function computeStats(header, epochs, satellitesSeen) {
711
758
  const n = epochs.length;
712
759
  const startTime = n > 0 ? new Date(epochs[0].time) : header.timeOfFirstObs;
713
760
  const endTime = n > 0 ? new Date(epochs[n - 1].time) : header.timeOfLastObs;
714
761
  let duration = null;
715
- if (startTime && endTime) duration = (endTime.getTime() - startTime.getTime()) / 1e3;
762
+ if (startTime && endTime)
763
+ duration = (endTime.getTime() - startTime.getTime()) / 1e3;
716
764
  let interval = header.interval;
717
- if (interval === null && n >= 2) interval = (epochs[1].time - epochs[0].time) / 1e3;
765
+ if (interval === null && n >= 2)
766
+ interval = (epochs[1].time - epochs[0].time) / 1e3;
718
767
  const uniqueSatsPerSystem = {};
719
768
  let totalUnique = 0;
720
769
  const systems = [];