gnss-js 1.3.1 → 1.4.0
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 +201 -5
- package/dist/analysis.d.cts +68 -3
- package/dist/analysis.d.ts +68 -3
- package/dist/analysis.js +5 -3
- package/dist/{chunk-5SPJH4MG.js → chunk-2K3FCJBX.js} +1 -1
- package/dist/{chunk-OZCYOM5D.js → chunk-3U5AX7PY.js} +1 -1
- package/dist/{chunk-G3N4S3DM.js → chunk-3ZAFWOT6.js} +202 -7
- package/dist/{chunk-7EEWQ5DU.js → chunk-65CQINSB.js} +6 -1
- package/dist/{chunk-W5WKEV7U.js → chunk-FIEWO4J4.js} +2 -0
- package/dist/{chunk-CC2R4JGS.js → chunk-PQYBTE42.js} +3 -1
- package/dist/{chunk-USHP4IND.js → chunk-PX7TPPTQ.js} +4 -4
- package/dist/constants.cjs +3 -0
- package/dist/constants.d.cts +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +3 -1
- package/dist/{gnss-BT6ulR17.d.cts → gnss-BtXrG3zH.d.cts} +3 -1
- package/dist/{gnss-C-tgoYNa.d.ts → gnss-DhnEr0Dy.d.ts} +3 -1
- package/dist/index.cjs +210 -8
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +11 -7
- package/dist/orbit.cjs +3 -1
- package/dist/orbit.js +2 -1
- package/dist/positioning.cjs +5 -6
- package/dist/positioning.js +3 -3
- package/dist/rinex.js +2 -2
- package/dist/rtcm3.cjs +5 -0
- package/dist/rtcm3.js +2 -2
- package/dist/signals.js +2 -2
- package/package.json +1 -1
package/dist/analysis.cjs
CHANGED
|
@@ -22,6 +22,7 @@ var analysis_exports = {};
|
|
|
22
22
|
__export(analysis_exports, {
|
|
23
23
|
CompletenessAccumulator: () => CompletenessAccumulator,
|
|
24
24
|
CycleSlipAccumulator: () => CycleSlipAccumulator,
|
|
25
|
+
IonoAccumulator: () => IonoAccumulator,
|
|
25
26
|
MultipathAccumulator: () => MultipathAccumulator,
|
|
26
27
|
analyzeQuality: () => analyzeQuality
|
|
27
28
|
});
|
|
@@ -215,6 +216,14 @@ var ARC_GAP_FACTOR = 5;
|
|
|
215
216
|
|
|
216
217
|
// src/analysis/multipath.ts
|
|
217
218
|
var MIN_ARC_LENGTH = 10;
|
|
219
|
+
var MP_JUMP_M = 1.25;
|
|
220
|
+
var MP_JUMP_WINDOW = 5;
|
|
221
|
+
var MP_EDIT_SIGMA = 3;
|
|
222
|
+
function median(values) {
|
|
223
|
+
const s = [...values].sort((a, b) => a - b);
|
|
224
|
+
const m = s.length >> 1;
|
|
225
|
+
return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
|
|
226
|
+
}
|
|
218
227
|
var MultipathAccumulator = class {
|
|
219
228
|
state = /* @__PURE__ */ new Map();
|
|
220
229
|
results = [];
|
|
@@ -271,6 +280,11 @@ var MultipathAccumulator = class {
|
|
|
271
280
|
const gap = bandState.lastTime > 0 ? (time - bandState.lastTime) / 1e3 : 0;
|
|
272
281
|
if (bandState.lastTime > 0 && gap > this.interval * ARC_GAP_FACTOR) {
|
|
273
282
|
this.closeArc(prn, band, refBand, bandState);
|
|
283
|
+
} else if (bandState.arc.rawMp.length > 0) {
|
|
284
|
+
const recent = bandState.arc.rawMp.slice(-MP_JUMP_WINDOW);
|
|
285
|
+
if (Math.abs(mp - median(recent)) > MP_JUMP_M) {
|
|
286
|
+
this.closeArc(prn, band, refBand, bandState);
|
|
287
|
+
}
|
|
274
288
|
}
|
|
275
289
|
bandState.arc.times.push(time);
|
|
276
290
|
bandState.arc.rawMp.push(mp);
|
|
@@ -290,13 +304,25 @@ var MultipathAccumulator = class {
|
|
|
290
304
|
closeArc(prn, band, refBand, state) {
|
|
291
305
|
const arc = state.arc;
|
|
292
306
|
if (arc.times.length >= MIN_ARC_LENGTH) {
|
|
293
|
-
|
|
307
|
+
let keep = arc.times.map((_, i) => i);
|
|
308
|
+
let mean = 0;
|
|
309
|
+
for (let pass = 0; pass < 3; pass++) {
|
|
310
|
+
mean = keep.reduce((s, i) => s + arc.rawMp[i], 0) / keep.length;
|
|
311
|
+
const sigma = Math.sqrt(
|
|
312
|
+
keep.reduce((s, i) => s + (arc.rawMp[i] - mean) ** 2, 0) / keep.length
|
|
313
|
+
);
|
|
314
|
+
const kept = keep.filter(
|
|
315
|
+
(i) => Math.abs(arc.rawMp[i] - mean) <= MP_EDIT_SIGMA * sigma
|
|
316
|
+
);
|
|
317
|
+
if (kept.length === keep.length || kept.length < MIN_ARC_LENGTH) break;
|
|
318
|
+
keep = kept;
|
|
319
|
+
}
|
|
294
320
|
const sys = prn[0];
|
|
295
321
|
const bLabel = BAND_LABELS[sys]?.[band] ?? band;
|
|
296
322
|
const rLabel = BAND_LABELS[sys]?.[refBand] ?? refBand;
|
|
297
323
|
const label = `${prn} MP ${bLabel}-${rLabel}`;
|
|
298
|
-
const points =
|
|
299
|
-
time:
|
|
324
|
+
const points = keep.map((i) => ({
|
|
325
|
+
time: arc.times[i],
|
|
300
326
|
mp: arc.rawMp[i] - mean
|
|
301
327
|
}));
|
|
302
328
|
const rms = Math.sqrt(
|
|
@@ -350,7 +376,7 @@ var MultipathAccumulator = class {
|
|
|
350
376
|
refBand,
|
|
351
377
|
rms,
|
|
352
378
|
count,
|
|
353
|
-
satellites: seriesList.
|
|
379
|
+
satellites: new Set(seriesList.map((s) => s.prn)).size
|
|
354
380
|
});
|
|
355
381
|
}
|
|
356
382
|
const sysOrder = "GRECIJS";
|
|
@@ -668,6 +694,171 @@ var CompletenessAccumulator = class {
|
|
|
668
694
|
}
|
|
669
695
|
};
|
|
670
696
|
|
|
697
|
+
// src/analysis/ionosphere.ts
|
|
698
|
+
var TEC_FACTOR = 403e15;
|
|
699
|
+
var GF_JUMP_M = 0.15;
|
|
700
|
+
var MIN_ARC_LENGTH2 = 10;
|
|
701
|
+
function median2(values) {
|
|
702
|
+
const s = [...values].sort((a, b) => a - b);
|
|
703
|
+
const m = s.length >> 1;
|
|
704
|
+
return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
|
|
705
|
+
}
|
|
706
|
+
var IonoAccumulator = class {
|
|
707
|
+
state = /* @__PURE__ */ new Map();
|
|
708
|
+
closed = /* @__PURE__ */ new Map();
|
|
709
|
+
interval;
|
|
710
|
+
obsIndices;
|
|
711
|
+
gloChannels;
|
|
712
|
+
pairLabel = /* @__PURE__ */ new Map();
|
|
713
|
+
constructor(header) {
|
|
714
|
+
this.interval = header.interval ?? 30;
|
|
715
|
+
this.obsIndices = buildObsIndices(header);
|
|
716
|
+
this.gloChannels = buildGloChannelMap(header.glonassSlots);
|
|
717
|
+
}
|
|
718
|
+
/** Observation callback — wire this into parseRinexStream. */
|
|
719
|
+
onObservation = (time, prn, _codes, values) => {
|
|
720
|
+
const sys = prn[0];
|
|
721
|
+
const bandMap = this.obsIndices.get(sys) ?? this.obsIndices.get("_v2");
|
|
722
|
+
if (!bandMap) return;
|
|
723
|
+
const bandData = /* @__PURE__ */ new Map();
|
|
724
|
+
for (const [band, { C, L }] of bandMap) {
|
|
725
|
+
if (C === null) continue;
|
|
726
|
+
const cVal = values[C];
|
|
727
|
+
const lVal = values[L];
|
|
728
|
+
const freq = getFreq(this.gloChannels, prn, band);
|
|
729
|
+
if (cVal != null && cVal !== 0 && lVal != null && lVal !== 0 && freq) {
|
|
730
|
+
bandData.set(band, { C: cVal, L: lVal, f: freq });
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
if (bandData.size < 2) return;
|
|
734
|
+
const pairs = DUAL_FREQ_PAIRS[sys] ?? [];
|
|
735
|
+
for (const [bi, bj] of pairs) {
|
|
736
|
+
const di = bandData.get(bi);
|
|
737
|
+
const dj = bandData.get(bj);
|
|
738
|
+
if (!di || !dj) continue;
|
|
739
|
+
const \u03BBi = C_LIGHT / di.f;
|
|
740
|
+
const \u03BBj = C_LIGHT / dj.f;
|
|
741
|
+
const gamma = di.f * di.f / (dj.f * dj.f);
|
|
742
|
+
const l4 = di.L * \u03BBi - dj.L * \u03BBj;
|
|
743
|
+
const p4 = dj.C - di.C;
|
|
744
|
+
const pairKey = `${bi}-${bj}`;
|
|
745
|
+
if (!this.pairLabel.has(`${sys}:${pairKey}`)) {
|
|
746
|
+
const bLabel = BAND_LABELS[sys]?.[bi] ?? bi;
|
|
747
|
+
const rLabel = BAND_LABELS[sys]?.[bj] ?? bj;
|
|
748
|
+
this.pairLabel.set(`${sys}:${pairKey}`, `${bLabel}-${rLabel}`);
|
|
749
|
+
}
|
|
750
|
+
this.push(prn, pairKey, time, l4, p4, di.f, gamma);
|
|
751
|
+
break;
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
push(prn, pairKey, time, l4, p4, fi, gamma) {
|
|
755
|
+
if (!isFinite(l4) || !isFinite(p4)) return;
|
|
756
|
+
let satStates = this.state.get(prn);
|
|
757
|
+
if (!satStates) {
|
|
758
|
+
satStates = /* @__PURE__ */ new Map();
|
|
759
|
+
this.state.set(prn, satStates);
|
|
760
|
+
}
|
|
761
|
+
let ps = satStates.get(pairKey);
|
|
762
|
+
if (!ps) {
|
|
763
|
+
ps = {
|
|
764
|
+
arc: { times: [], l4: [], p4: [], fi, gamma },
|
|
765
|
+
lastTime: 0,
|
|
766
|
+
lastL4: 0
|
|
767
|
+
};
|
|
768
|
+
satStates.set(pairKey, ps);
|
|
769
|
+
}
|
|
770
|
+
const gap = ps.lastTime > 0 ? (time - ps.lastTime) / 1e3 : 0;
|
|
771
|
+
if (ps.lastTime > 0 && gap > this.interval * ARC_GAP_FACTOR) {
|
|
772
|
+
this.closeArc(prn, pairKey, ps);
|
|
773
|
+
} else if (ps.arc.times.length > 0 && Math.abs(l4 - ps.lastL4) > GF_JUMP_M) {
|
|
774
|
+
this.closeArc(prn, pairKey, ps);
|
|
775
|
+
}
|
|
776
|
+
if (ps.arc.times.length === 0) {
|
|
777
|
+
ps.arc.fi = fi;
|
|
778
|
+
ps.arc.gamma = gamma;
|
|
779
|
+
}
|
|
780
|
+
ps.arc.times.push(time);
|
|
781
|
+
ps.arc.l4.push(l4);
|
|
782
|
+
ps.arc.p4.push(p4);
|
|
783
|
+
ps.lastTime = time;
|
|
784
|
+
ps.lastL4 = l4;
|
|
785
|
+
}
|
|
786
|
+
/** External cycle-slip notification — close affected arcs. */
|
|
787
|
+
notifySlip(_time, prn, bands) {
|
|
788
|
+
const satStates = this.state.get(prn);
|
|
789
|
+
if (!satStates) return;
|
|
790
|
+
for (const [pairKey, ps] of satStates) {
|
|
791
|
+
const [bi, bj] = pairKey.split("-");
|
|
792
|
+
if (bands.has(bi) || bands.has(bj)) {
|
|
793
|
+
this.closeArc(prn, pairKey, ps);
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
}
|
|
797
|
+
closeArc(prn, pairKey, ps) {
|
|
798
|
+
const arc = ps.arc;
|
|
799
|
+
if (arc.times.length >= MIN_ARC_LENGTH2) {
|
|
800
|
+
const level = median2(arc.l4.map((v, k) => v - arc.p4[k]));
|
|
801
|
+
const toTecu = arc.fi * arc.fi / TEC_FACTOR / (arc.gamma - 1);
|
|
802
|
+
let satArcs = this.closed.get(prn);
|
|
803
|
+
if (!satArcs) {
|
|
804
|
+
satArcs = /* @__PURE__ */ new Map();
|
|
805
|
+
this.closed.set(prn, satArcs);
|
|
806
|
+
}
|
|
807
|
+
let points = satArcs.get(pairKey);
|
|
808
|
+
if (!points) {
|
|
809
|
+
points = [];
|
|
810
|
+
satArcs.set(pairKey, points);
|
|
811
|
+
}
|
|
812
|
+
for (let k = 0; k < arc.times.length; k++) {
|
|
813
|
+
points.push({
|
|
814
|
+
time: arc.times[k],
|
|
815
|
+
stec: (arc.l4[k] - level) * toTecu
|
|
816
|
+
});
|
|
817
|
+
}
|
|
818
|
+
}
|
|
819
|
+
ps.arc = { times: [], l4: [], p4: [], fi: arc.fi, gamma: arc.gamma };
|
|
820
|
+
}
|
|
821
|
+
/** Finalize: close remaining arcs, keep one pair per satellite. */
|
|
822
|
+
finalize() {
|
|
823
|
+
for (const [prn, satStates] of this.state) {
|
|
824
|
+
for (const [pairKey, ps] of satStates) {
|
|
825
|
+
this.closeArc(prn, pairKey, ps);
|
|
826
|
+
}
|
|
827
|
+
}
|
|
828
|
+
const series = [];
|
|
829
|
+
let sum = 0;
|
|
830
|
+
let count = 0;
|
|
831
|
+
let maxStec = 0;
|
|
832
|
+
for (const [prn, satArcs] of this.closed) {
|
|
833
|
+
let bestKey = null;
|
|
834
|
+
let bestLen = 0;
|
|
835
|
+
for (const [pairKey, points2] of satArcs) {
|
|
836
|
+
if (points2.length > bestLen) {
|
|
837
|
+
bestLen = points2.length;
|
|
838
|
+
bestKey = pairKey;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
if (!bestKey) continue;
|
|
842
|
+
const points = satArcs.get(bestKey);
|
|
843
|
+
points.sort((a, b) => a.time - b.time);
|
|
844
|
+
const sys = prn[0];
|
|
845
|
+
for (const p of points) {
|
|
846
|
+
sum += p.stec;
|
|
847
|
+
count++;
|
|
848
|
+
if (p.stec > maxStec) maxStec = p.stec;
|
|
849
|
+
}
|
|
850
|
+
series.push({
|
|
851
|
+
prn,
|
|
852
|
+
system: sys,
|
|
853
|
+
label: this.pairLabel.get(`${sys}:${bestKey}`) ?? bestKey,
|
|
854
|
+
points
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
series.sort((a, b) => a.prn.localeCompare(b.prn));
|
|
858
|
+
return { series, maxStec, meanStec: count > 0 ? sum / count : 0 };
|
|
859
|
+
}
|
|
860
|
+
};
|
|
861
|
+
|
|
671
862
|
// src/rinex/crx.ts
|
|
672
863
|
function crxRepair(old, diff) {
|
|
673
864
|
const chars = old.split("");
|
|
@@ -1457,8 +1648,10 @@ function computeStats(header, epochs, satellitesSeen) {
|
|
|
1457
1648
|
// src/analysis/quality-analysis.ts
|
|
1458
1649
|
async function analyzeQuality(file, header, onProgress, signal) {
|
|
1459
1650
|
const mpAccum = new MultipathAccumulator(header);
|
|
1651
|
+
const ionoAccum = new IonoAccumulator(header);
|
|
1460
1652
|
const csAccum = new CycleSlipAccumulator(header, (time, prn, bands) => {
|
|
1461
1653
|
mpAccum.notifySlip(time, prn, bands);
|
|
1654
|
+
ionoAccum.notifySlip(time, prn, bands);
|
|
1462
1655
|
});
|
|
1463
1656
|
const compAccum = new CompletenessAccumulator(header);
|
|
1464
1657
|
await parseRinexStream(
|
|
@@ -1468,6 +1661,7 @@ async function analyzeQuality(file, header, onProgress, signal) {
|
|
|
1468
1661
|
(time, prn, codes, values) => {
|
|
1469
1662
|
csAccum.onObservation(time, prn, codes, values);
|
|
1470
1663
|
mpAccum.onObservation(time, prn, codes, values);
|
|
1664
|
+
ionoAccum.onObservation(time, prn, codes, values);
|
|
1471
1665
|
compAccum.onObservation(time, prn, codes, values);
|
|
1472
1666
|
},
|
|
1473
1667
|
true
|
|
@@ -1476,13 +1670,15 @@ async function analyzeQuality(file, header, onProgress, signal) {
|
|
|
1476
1670
|
return {
|
|
1477
1671
|
cycleSlips: csAccum.finalize(),
|
|
1478
1672
|
completeness: compAccum.finalize(),
|
|
1479
|
-
multipath: mpAccum.finalize()
|
|
1673
|
+
multipath: mpAccum.finalize(),
|
|
1674
|
+
iono: ionoAccum.finalize()
|
|
1480
1675
|
};
|
|
1481
1676
|
}
|
|
1482
1677
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1483
1678
|
0 && (module.exports = {
|
|
1484
1679
|
CompletenessAccumulator,
|
|
1485
1680
|
CycleSlipAccumulator,
|
|
1681
|
+
IonoAccumulator,
|
|
1486
1682
|
MultipathAccumulator,
|
|
1487
1683
|
analyzeQuality
|
|
1488
1684
|
});
|
package/dist/analysis.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { R as RinexHeader } from './parser-JPjjFgeP.cjs';
|
|
2
|
-
import {
|
|
2
|
+
import { i as OnSlipDetected } from './gnss-BtXrG3zH.cjs';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Multipath analysis from RINEX dual-frequency observations.
|
|
@@ -196,16 +196,81 @@ declare class CompletenessAccumulator {
|
|
|
196
196
|
finalize(): CompletenessResult;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Slant ionospheric delay from dual-frequency observations.
|
|
201
|
+
*
|
|
202
|
+
* Geometry-free phase combination levelled to the geometry-free code,
|
|
203
|
+
* per continuous arc:
|
|
204
|
+
* L4 = λi·Li − λj·Lj = (γ−1)·I_i + B (phase; B = ambiguity bias)
|
|
205
|
+
* P4 = C_j − C_i = (γ−1)·I_i + DCBs (code)
|
|
206
|
+
* with γ = (f_i/f_j)² and I_i the slant ionospheric delay on band i.
|
|
207
|
+
* The arc levelling constant B̂ = median(L4 − P4) transfers the code's
|
|
208
|
+
* absolute level onto the low-noise phase; slant TEC follows as
|
|
209
|
+
* STEC [TECU] = (L4 − B̂)/(γ−1) · f_i² / 40.3e16.
|
|
210
|
+
*
|
|
211
|
+
* The result carries the receiver+satellite differential code biases
|
|
212
|
+
* (not removed here — several TECU per satellite), so series are
|
|
213
|
+
* DCB-biased but shape-faithful: diurnal variation, gradients and
|
|
214
|
+
* disturbances read correctly.
|
|
215
|
+
*
|
|
216
|
+
* The geometry-free phase is also a sensitive cycle-slip detector:
|
|
217
|
+
* arcs split on epoch-to-epoch L4 jumps beyond GF_JUMP_M, in addition
|
|
218
|
+
* to time gaps and external slip notifications.
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
interface IonoPoint {
|
|
222
|
+
/** Epoch time in milliseconds. */
|
|
223
|
+
time: number;
|
|
224
|
+
/** Slant TEC in TECU (DCB-biased). */
|
|
225
|
+
stec: number;
|
|
226
|
+
}
|
|
227
|
+
interface IonoSeries {
|
|
228
|
+
/** Satellite PRN, e.g. "G01". */
|
|
229
|
+
prn: string;
|
|
230
|
+
/** System letter, e.g. "G". */
|
|
231
|
+
system: string;
|
|
232
|
+
/** Band pair used, e.g. "L1-L2". */
|
|
233
|
+
label: string;
|
|
234
|
+
/** Time series of slant TEC values (TECU, DCB-biased). */
|
|
235
|
+
points: IonoPoint[];
|
|
236
|
+
}
|
|
237
|
+
interface IonoResult {
|
|
238
|
+
/** Per-satellite slant TEC time series. */
|
|
239
|
+
series: IonoSeries[];
|
|
240
|
+
/** Highest single STEC sample across all series (TECU). */
|
|
241
|
+
maxStec: number;
|
|
242
|
+
/** Mean STEC across all samples (TECU). */
|
|
243
|
+
meanStec: number;
|
|
244
|
+
}
|
|
245
|
+
declare class IonoAccumulator {
|
|
246
|
+
private state;
|
|
247
|
+
private closed;
|
|
248
|
+
private interval;
|
|
249
|
+
private obsIndices;
|
|
250
|
+
private gloChannels;
|
|
251
|
+
private pairLabel;
|
|
252
|
+
constructor(header: RinexHeader);
|
|
253
|
+
/** Observation callback — wire this into parseRinexStream. */
|
|
254
|
+
onObservation: (time: number, prn: string, _codes: string[], values: (number | null)[]) => void;
|
|
255
|
+
private push;
|
|
256
|
+
/** External cycle-slip notification — close affected arcs. */
|
|
257
|
+
notifySlip(_time: number, prn: string, bands: Set<string>): void;
|
|
258
|
+
private closeArc;
|
|
259
|
+
/** Finalize: close remaining arcs, keep one pair per satellite. */
|
|
260
|
+
finalize(): IonoResult;
|
|
261
|
+
}
|
|
262
|
+
|
|
199
263
|
/**
|
|
200
264
|
* Combined quality analysis — runs cycle slip detection, data completeness,
|
|
201
|
-
* and
|
|
265
|
+
* multipath and ionosphere analysis in a single file re-parse pass.
|
|
202
266
|
*/
|
|
203
267
|
|
|
204
268
|
interface QualityResult {
|
|
205
269
|
cycleSlips: CycleSlipResult;
|
|
206
270
|
completeness: CompletenessResult;
|
|
207
271
|
multipath: MultipathResult;
|
|
272
|
+
iono: IonoResult;
|
|
208
273
|
}
|
|
209
274
|
declare function analyzeQuality(file: File, header: RinexHeader, onProgress?: (percent: number) => void, signal?: AbortSignal): Promise<QualityResult>;
|
|
210
275
|
|
|
211
|
-
export { type CompleteSatSignal, type CompleteSignalStats, CompletenessAccumulator, type CompletenessResult, CycleSlipAccumulator, type CycleSlipEvent, type CycleSlipResult, type CycleSlipSignalStats, MultipathAccumulator, type MultipathPoint, type MultipathResult, type MultipathSeries, type MultipathSignalStat, type QualityResult, analyzeQuality };
|
|
276
|
+
export { type CompleteSatSignal, type CompleteSignalStats, CompletenessAccumulator, type CompletenessResult, CycleSlipAccumulator, type CycleSlipEvent, type CycleSlipResult, type CycleSlipSignalStats, IonoAccumulator, type IonoPoint, type IonoResult, type IonoSeries, MultipathAccumulator, type MultipathPoint, type MultipathResult, type MultipathSeries, type MultipathSignalStat, type QualityResult, analyzeQuality };
|
package/dist/analysis.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { R as RinexHeader } from './parser-JPjjFgeP.js';
|
|
2
|
-
import {
|
|
2
|
+
import { i as OnSlipDetected } from './gnss-DhnEr0Dy.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Multipath analysis from RINEX dual-frequency observations.
|
|
@@ -196,16 +196,81 @@ declare class CompletenessAccumulator {
|
|
|
196
196
|
finalize(): CompletenessResult;
|
|
197
197
|
}
|
|
198
198
|
|
|
199
|
+
/**
|
|
200
|
+
* Slant ionospheric delay from dual-frequency observations.
|
|
201
|
+
*
|
|
202
|
+
* Geometry-free phase combination levelled to the geometry-free code,
|
|
203
|
+
* per continuous arc:
|
|
204
|
+
* L4 = λi·Li − λj·Lj = (γ−1)·I_i + B (phase; B = ambiguity bias)
|
|
205
|
+
* P4 = C_j − C_i = (γ−1)·I_i + DCBs (code)
|
|
206
|
+
* with γ = (f_i/f_j)² and I_i the slant ionospheric delay on band i.
|
|
207
|
+
* The arc levelling constant B̂ = median(L4 − P4) transfers the code's
|
|
208
|
+
* absolute level onto the low-noise phase; slant TEC follows as
|
|
209
|
+
* STEC [TECU] = (L4 − B̂)/(γ−1) · f_i² / 40.3e16.
|
|
210
|
+
*
|
|
211
|
+
* The result carries the receiver+satellite differential code biases
|
|
212
|
+
* (not removed here — several TECU per satellite), so series are
|
|
213
|
+
* DCB-biased but shape-faithful: diurnal variation, gradients and
|
|
214
|
+
* disturbances read correctly.
|
|
215
|
+
*
|
|
216
|
+
* The geometry-free phase is also a sensitive cycle-slip detector:
|
|
217
|
+
* arcs split on epoch-to-epoch L4 jumps beyond GF_JUMP_M, in addition
|
|
218
|
+
* to time gaps and external slip notifications.
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
interface IonoPoint {
|
|
222
|
+
/** Epoch time in milliseconds. */
|
|
223
|
+
time: number;
|
|
224
|
+
/** Slant TEC in TECU (DCB-biased). */
|
|
225
|
+
stec: number;
|
|
226
|
+
}
|
|
227
|
+
interface IonoSeries {
|
|
228
|
+
/** Satellite PRN, e.g. "G01". */
|
|
229
|
+
prn: string;
|
|
230
|
+
/** System letter, e.g. "G". */
|
|
231
|
+
system: string;
|
|
232
|
+
/** Band pair used, e.g. "L1-L2". */
|
|
233
|
+
label: string;
|
|
234
|
+
/** Time series of slant TEC values (TECU, DCB-biased). */
|
|
235
|
+
points: IonoPoint[];
|
|
236
|
+
}
|
|
237
|
+
interface IonoResult {
|
|
238
|
+
/** Per-satellite slant TEC time series. */
|
|
239
|
+
series: IonoSeries[];
|
|
240
|
+
/** Highest single STEC sample across all series (TECU). */
|
|
241
|
+
maxStec: number;
|
|
242
|
+
/** Mean STEC across all samples (TECU). */
|
|
243
|
+
meanStec: number;
|
|
244
|
+
}
|
|
245
|
+
declare class IonoAccumulator {
|
|
246
|
+
private state;
|
|
247
|
+
private closed;
|
|
248
|
+
private interval;
|
|
249
|
+
private obsIndices;
|
|
250
|
+
private gloChannels;
|
|
251
|
+
private pairLabel;
|
|
252
|
+
constructor(header: RinexHeader);
|
|
253
|
+
/** Observation callback — wire this into parseRinexStream. */
|
|
254
|
+
onObservation: (time: number, prn: string, _codes: string[], values: (number | null)[]) => void;
|
|
255
|
+
private push;
|
|
256
|
+
/** External cycle-slip notification — close affected arcs. */
|
|
257
|
+
notifySlip(_time: number, prn: string, bands: Set<string>): void;
|
|
258
|
+
private closeArc;
|
|
259
|
+
/** Finalize: close remaining arcs, keep one pair per satellite. */
|
|
260
|
+
finalize(): IonoResult;
|
|
261
|
+
}
|
|
262
|
+
|
|
199
263
|
/**
|
|
200
264
|
* Combined quality analysis — runs cycle slip detection, data completeness,
|
|
201
|
-
* and
|
|
265
|
+
* multipath and ionosphere analysis in a single file re-parse pass.
|
|
202
266
|
*/
|
|
203
267
|
|
|
204
268
|
interface QualityResult {
|
|
205
269
|
cycleSlips: CycleSlipResult;
|
|
206
270
|
completeness: CompletenessResult;
|
|
207
271
|
multipath: MultipathResult;
|
|
272
|
+
iono: IonoResult;
|
|
208
273
|
}
|
|
209
274
|
declare function analyzeQuality(file: File, header: RinexHeader, onProgress?: (percent: number) => void, signal?: AbortSignal): Promise<QualityResult>;
|
|
210
275
|
|
|
211
|
-
export { type CompleteSatSignal, type CompleteSignalStats, CompletenessAccumulator, type CompletenessResult, CycleSlipAccumulator, type CycleSlipEvent, type CycleSlipResult, type CycleSlipSignalStats, MultipathAccumulator, type MultipathPoint, type MultipathResult, type MultipathSeries, type MultipathSignalStat, type QualityResult, analyzeQuality };
|
|
276
|
+
export { type CompleteSatSignal, type CompleteSignalStats, CompletenessAccumulator, type CompletenessResult, CycleSlipAccumulator, type CycleSlipEvent, type CycleSlipResult, type CycleSlipSignalStats, IonoAccumulator, type IonoPoint, type IonoResult, type IonoSeries, MultipathAccumulator, type MultipathPoint, type MultipathResult, type MultipathSeries, type MultipathSignalStat, type QualityResult, analyzeQuality };
|
package/dist/analysis.js
CHANGED
|
@@ -1,14 +1,16 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CompletenessAccumulator,
|
|
3
3
|
CycleSlipAccumulator,
|
|
4
|
+
IonoAccumulator,
|
|
4
5
|
MultipathAccumulator,
|
|
5
6
|
analyzeQuality
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import "./chunk-
|
|
8
|
-
import "./chunk-
|
|
7
|
+
} from "./chunk-3ZAFWOT6.js";
|
|
8
|
+
import "./chunk-3U5AX7PY.js";
|
|
9
|
+
import "./chunk-FIEWO4J4.js";
|
|
9
10
|
export {
|
|
10
11
|
CompletenessAccumulator,
|
|
11
12
|
CycleSlipAccumulator,
|
|
13
|
+
IonoAccumulator,
|
|
12
14
|
MultipathAccumulator,
|
|
13
15
|
analyzeQuality
|
|
14
16
|
};
|