gnss-js 2.13.1 → 2.14.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 +525 -0
- package/dist/analysis.d.cts +135 -1
- package/dist/analysis.d.ts +135 -1
- package/dist/analysis.js +9 -1
- package/dist/{chunk-MFCPYUEI.js → chunk-GGWK7XLZ.js} +496 -1
- package/dist/{chunk-PQLPPFIK.js → chunk-TETPRPZ2.js} +122 -4
- package/dist/index.cjs +620 -4
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +14 -2
- package/dist/positioning.cjs +125 -4
- package/dist/positioning.d.cts +47 -1
- package/dist/positioning.d.ts +47 -1
- package/dist/positioning.js +7 -1
- package/dist/troposphere.cjs +5056 -0
- package/dist/troposphere.d.cts +78 -0
- package/dist/troposphere.d.ts +78 -0
- package/dist/troposphere.js +5025 -0
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ __export(src_exports, {
|
|
|
24
24
|
BAND_LABELS: () => BAND_LABELS,
|
|
25
25
|
BAND_PRESETS: () => BAND_PRESETS,
|
|
26
26
|
BDS_SATELLITES: () => BDS_SATELLITES,
|
|
27
|
+
BLQ_CONSTITUENTS: () => BLQ_CONSTITUENTS,
|
|
27
28
|
BitReader: () => BitReader,
|
|
28
29
|
CONSTELLATIONS: () => CONSTELLATIONS,
|
|
29
30
|
C_LIGHT: () => C_LIGHT,
|
|
@@ -121,6 +122,7 @@ __export(src_exports, {
|
|
|
121
122
|
analyzeQuality: () => analyzeQuality,
|
|
122
123
|
antexFreqOfGroup: () => antexFreqOfGroup,
|
|
123
124
|
applyHelmert: () => applyHelmert,
|
|
125
|
+
applyHelmertFit: () => applyHelmertFit,
|
|
124
126
|
applyIonoDcb: () => applyIonoDcb,
|
|
125
127
|
applyOrbitClock: () => applyOrbitClock,
|
|
126
128
|
biasMetres: () => biasMetres,
|
|
@@ -168,6 +170,7 @@ __export(src_exports, {
|
|
|
168
170
|
ecefToAzEl: () => ecefToAzEl,
|
|
169
171
|
ecefToGeodetic: () => ecefToGeodetic,
|
|
170
172
|
ephInfoToEphemeris: () => ephInfoToEphemeris,
|
|
173
|
+
estimateHelmert: () => estimateHelmert,
|
|
171
174
|
estimateNarrowlaneFcb: () => estimateNarrowlaneFcb,
|
|
172
175
|
estimateNetworkFcbs: () => estimateNetworkFcbs,
|
|
173
176
|
estimateWidelaneFcb: () => estimateWidelaneFcb,
|
|
@@ -179,6 +182,7 @@ __export(src_exports, {
|
|
|
179
182
|
feedNavicBlock: () => feedNavicBlock,
|
|
180
183
|
fetchSourcetable: () => fetchSourcetable,
|
|
181
184
|
findSatBias: () => findSatBias,
|
|
185
|
+
fitCoordinateSeries: () => fitCoordinateSeries,
|
|
182
186
|
fixPppPosition: () => fixPppPosition,
|
|
183
187
|
fmtD: () => fmtD,
|
|
184
188
|
fmtF: () => fmtF,
|
|
@@ -273,12 +277,14 @@ __export(src_exports, {
|
|
|
273
277
|
nlWavelength: () => nlWavelength,
|
|
274
278
|
nmeaCoordToDecimal: () => nmeaCoordToDecimal,
|
|
275
279
|
obsEpochToDate: () => obsEpochToDate,
|
|
280
|
+
oceanLoadingEnu: () => oceanLoadingEnu,
|
|
276
281
|
oem4Frames: () => oem4Frames,
|
|
277
282
|
padL: () => padL,
|
|
278
283
|
padR: () => padR,
|
|
279
284
|
parseAntex: () => parseAntex,
|
|
280
285
|
parseBiasSinex: () => parseBiasSinex,
|
|
281
286
|
parseBinex: () => parseBinex,
|
|
287
|
+
parseBlq: () => parseBlq,
|
|
282
288
|
parseClk: () => parseClk,
|
|
283
289
|
parseCrxDataLine: () => parseCrxDataLine,
|
|
284
290
|
parseIonex: () => parseIonex,
|
|
@@ -16804,6 +16810,103 @@ function solidEarthTide(rcv, sun, moon) {
|
|
|
16804
16810
|
return disp;
|
|
16805
16811
|
}
|
|
16806
16812
|
|
|
16813
|
+
// src/positioning/ocean-loading.ts
|
|
16814
|
+
var BLQ_CONSTITUENTS = [
|
|
16815
|
+
"M2",
|
|
16816
|
+
"S2",
|
|
16817
|
+
"N2",
|
|
16818
|
+
"K2",
|
|
16819
|
+
"K1",
|
|
16820
|
+
"O1",
|
|
16821
|
+
"P1",
|
|
16822
|
+
"Q1",
|
|
16823
|
+
"Mf",
|
|
16824
|
+
"Mm",
|
|
16825
|
+
"Ssa"
|
|
16826
|
+
];
|
|
16827
|
+
var ARGS = [
|
|
16828
|
+
[140519e-9, 2, -2, 0, 0],
|
|
16829
|
+
// M2
|
|
16830
|
+
[145444e-9, 0, 0, 0, 0],
|
|
16831
|
+
// S2
|
|
16832
|
+
[13788e-8, 2, -3, 1, 0],
|
|
16833
|
+
// N2
|
|
16834
|
+
[145842e-9, 2, 0, 0, 0],
|
|
16835
|
+
// K2
|
|
16836
|
+
[72921e-9, 1, 0, 0, 0.25],
|
|
16837
|
+
// K1
|
|
16838
|
+
[67598e-9, 1, -2, 0, -0.25],
|
|
16839
|
+
// O1
|
|
16840
|
+
[72523e-9, -1, 0, 0, -0.25],
|
|
16841
|
+
// P1
|
|
16842
|
+
[64959e-9, 1, -3, 1, -0.25],
|
|
16843
|
+
// Q1
|
|
16844
|
+
[53234e-10, 0, 2, 0, 0],
|
|
16845
|
+
// Mf
|
|
16846
|
+
[26392e-10, 0, 1, -1, 0],
|
|
16847
|
+
// Mm
|
|
16848
|
+
[3982e-10, 2, 0, 0, 0]
|
|
16849
|
+
// Ssa
|
|
16850
|
+
];
|
|
16851
|
+
var D2R2 = Math.PI / 180;
|
|
16852
|
+
function oceanLoadingEnu(c, utcMs) {
|
|
16853
|
+
const day = Math.floor(utcMs / 864e5);
|
|
16854
|
+
const fday = (utcMs - day * 864e5) / 1e3;
|
|
16855
|
+
const days = day - Date.UTC(1975, 0, 1) / 864e5 + 1;
|
|
16856
|
+
const t = (27392.500528 + 1.000000035 * days) / 36525;
|
|
16857
|
+
const t2 = t * t;
|
|
16858
|
+
const t3 = t2 * t;
|
|
16859
|
+
const a = [
|
|
16860
|
+
fday,
|
|
16861
|
+
(279.69668 + 36000.768930485 * t + 303e-6 * t2) * D2R2,
|
|
16862
|
+
// H0
|
|
16863
|
+
(270.434358 + 481267.88314137 * t - 1133e-6 * t2 + 19e-7 * t3) * D2R2,
|
|
16864
|
+
// S0
|
|
16865
|
+
(334.329653 + 4069.0340329577 * t - 0.010325 * t2 - 12e-6 * t3) * D2R2,
|
|
16866
|
+
// P0
|
|
16867
|
+
2 * Math.PI
|
|
16868
|
+
];
|
|
16869
|
+
const dp = [0, 0, 0];
|
|
16870
|
+
for (let i = 0; i < ARGS.length; i++) {
|
|
16871
|
+
let ang = 0;
|
|
16872
|
+
for (let j = 0; j < 5; j++) ang += a[j] * ARGS[i][j];
|
|
16873
|
+
for (let k = 0; k < 3; k++)
|
|
16874
|
+
dp[k] += c.amplitude[i][k] * Math.cos(ang - c.phase[i][k] * D2R2);
|
|
16875
|
+
}
|
|
16876
|
+
return [-dp[1], -dp[2], dp[0]];
|
|
16877
|
+
}
|
|
16878
|
+
function parseBlq(text) {
|
|
16879
|
+
const out = /* @__PURE__ */ new Map();
|
|
16880
|
+
const lines = text.split(/\r?\n/);
|
|
16881
|
+
for (let i = 0; i < lines.length; i++) {
|
|
16882
|
+
const l = lines[i];
|
|
16883
|
+
if (!l.trim() || l.startsWith("$$")) continue;
|
|
16884
|
+
const name = l.trim().split(/\s+/)[0].toUpperCase();
|
|
16885
|
+
const rows = [];
|
|
16886
|
+
let j = i + 1;
|
|
16887
|
+
while (j < lines.length && rows.length < 6) {
|
|
16888
|
+
const r = lines[j];
|
|
16889
|
+
j++;
|
|
16890
|
+
if (r.startsWith("$$") || !r.trim()) continue;
|
|
16891
|
+
const v = r.trim().split(/\s+/).map(Number);
|
|
16892
|
+
if (v.length !== 11 || v.some((x) => !Number.isFinite(x))) break;
|
|
16893
|
+
rows.push(v);
|
|
16894
|
+
}
|
|
16895
|
+
if (rows.length === 6) {
|
|
16896
|
+
out.set(name, {
|
|
16897
|
+
amplitude: BLQ_CONSTITUENTS.map(
|
|
16898
|
+
(_, k) => [rows[0][k], rows[1][k], rows[2][k]]
|
|
16899
|
+
),
|
|
16900
|
+
phase: BLQ_CONSTITUENTS.map(
|
|
16901
|
+
(_, k) => [rows[3][k], rows[4][k], rows[5][k]]
|
|
16902
|
+
)
|
|
16903
|
+
});
|
|
16904
|
+
i = j - 1;
|
|
16905
|
+
}
|
|
16906
|
+
}
|
|
16907
|
+
return out;
|
|
16908
|
+
}
|
|
16909
|
+
|
|
16807
16910
|
// src/positioning/ppp-corrections.ts
|
|
16808
16911
|
function applyCorrections(corrections, geom, ctx) {
|
|
16809
16912
|
if (corrections.evaluate) return corrections.evaluate(geom, ctx);
|
|
@@ -16821,6 +16924,14 @@ function createPppCorrections(cfg) {
|
|
|
16821
16924
|
const sun = sunEcef(timeMs);
|
|
16822
16925
|
const moon = moonEcef(timeMs);
|
|
16823
16926
|
const tideDisp = useTides ? solidEarthTide(rcvEcef, sun, moon) : [0, 0, 0];
|
|
16927
|
+
if (cfg.oceanLoading) {
|
|
16928
|
+
const [e, n, u] = oceanLoadingEnu(cfg.oceanLoading, timeMs);
|
|
16929
|
+
const [lat, lon] = ecefToGeodetic(rcvEcef[0], rcvEcef[1], rcvEcef[2]);
|
|
16930
|
+
const d = enuToEcef([e, n, u], lat, lon);
|
|
16931
|
+
tideDisp[0] += d[0];
|
|
16932
|
+
tideDisp[1] += d[1];
|
|
16933
|
+
tideDisp[2] += d[2];
|
|
16934
|
+
}
|
|
16824
16935
|
return { timeMs, sun, moon, tideDisp };
|
|
16825
16936
|
},
|
|
16826
16937
|
evaluate(geom, ctx) {
|
|
@@ -16875,7 +16986,7 @@ function createPppCorrections(cfg) {
|
|
|
16875
16986
|
rangeM += interpPcv(off, zenithDeg);
|
|
16876
16987
|
}
|
|
16877
16988
|
}
|
|
16878
|
-
if (
|
|
16989
|
+
if (ctx) {
|
|
16879
16990
|
rangeM -= dot(e, ctx.tideDisp);
|
|
16880
16991
|
}
|
|
16881
16992
|
if (useWindup && frame) {
|
|
@@ -17261,7 +17372,7 @@ var PppEngine = class {
|
|
|
17261
17372
|
for (const ci of clkIdx.values()) P[ci][ci] = CLK_VAR;
|
|
17262
17373
|
P[IDX_ZWD][IDX_ZWD] += ztdQ * (ei > 0 ? 1 : 0);
|
|
17263
17374
|
const rcv = [x[IDX_X], x[IDX_Y], x[IDX_Z]];
|
|
17264
|
-
const [latRad, , heightM] = ecefToGeodetic(rcv[0], rcv[1], rcv[2]);
|
|
17375
|
+
const [latRad, lonRad, heightM] = ecefToGeodetic(rcv[0], rcv[1], rcv[2]);
|
|
17265
17376
|
const epochCtx = corrections?.epochContext?.(epoch.timeMs, rcv) ?? null;
|
|
17266
17377
|
const vis = [];
|
|
17267
17378
|
let epochZhd = 0;
|
|
@@ -17294,7 +17405,17 @@ var PppEngine = class {
|
|
|
17294
17405
|
const pIf = g * o.c1 - (g - 1) * o.c2;
|
|
17295
17406
|
const lIf = g * (o.l1 * lam1) - (g - 1) * (o.l2 * lam2);
|
|
17296
17407
|
if (!Number.isFinite(pIf) || !Number.isFinite(lIf)) continue;
|
|
17297
|
-
const trop = opts.troposphere ?? true ?
|
|
17408
|
+
const trop = opts.troposphere ?? true ? opts.troposphereModel ? opts.troposphereModel.delays(
|
|
17409
|
+
epoch.timeMs,
|
|
17410
|
+
latRad,
|
|
17411
|
+
lonRad,
|
|
17412
|
+
heightM,
|
|
17413
|
+
elRad,
|
|
17414
|
+
azRad
|
|
17415
|
+
) : {
|
|
17416
|
+
...niellMapping(elRad, latRad, heightM, epoch.timeMs),
|
|
17417
|
+
gradient: 0
|
|
17418
|
+
} : { zhd: 0, mh: 0, mw: 0, gradient: 0 };
|
|
17298
17419
|
const { zhd, mh, mw } = trop;
|
|
17299
17420
|
epochZhd = zhd;
|
|
17300
17421
|
const geom = {
|
|
@@ -17319,7 +17440,7 @@ var PppEngine = class {
|
|
|
17319
17440
|
lIf,
|
|
17320
17441
|
satClkM: sat.state.clkM,
|
|
17321
17442
|
range,
|
|
17322
|
-
tropoFixed: zhd * mh + corr.rangeM,
|
|
17443
|
+
tropoFixed: zhd * mh + trop.gradient + corr.rangeM,
|
|
17323
17444
|
mw,
|
|
17324
17445
|
windupM: corr.phaseWindupM,
|
|
17325
17446
|
slip,
|
|
@@ -19314,6 +19435,495 @@ async function analyzeQuality(file, header, onProgress, signal) {
|
|
|
19314
19435
|
};
|
|
19315
19436
|
}
|
|
19316
19437
|
|
|
19438
|
+
// src/analysis/noise-model.ts
|
|
19439
|
+
function cholesky(M, n) {
|
|
19440
|
+
for (let j = 0; j < n; j++) {
|
|
19441
|
+
let d = M[j * n + j];
|
|
19442
|
+
for (let k = 0; k < j; k++) d -= M[j * n + k] ** 2;
|
|
19443
|
+
if (d <= 0) return false;
|
|
19444
|
+
d = Math.sqrt(d);
|
|
19445
|
+
M[j * n + j] = d;
|
|
19446
|
+
for (let i = j + 1; i < n; i++) {
|
|
19447
|
+
let s = M[i * n + j];
|
|
19448
|
+
for (let k = 0; k < j; k++) s -= M[i * n + k] * M[j * n + k];
|
|
19449
|
+
M[i * n + j] = s / d;
|
|
19450
|
+
}
|
|
19451
|
+
}
|
|
19452
|
+
return true;
|
|
19453
|
+
}
|
|
19454
|
+
function forward(L, n, b) {
|
|
19455
|
+
for (let i = 0; i < n; i++) {
|
|
19456
|
+
let s = b[i];
|
|
19457
|
+
for (let k = 0; k < i; k++) s -= L[i * n + k] * b[k];
|
|
19458
|
+
b[i] = s / L[i * n + i];
|
|
19459
|
+
}
|
|
19460
|
+
}
|
|
19461
|
+
function flickerCovariance(idx) {
|
|
19462
|
+
const N = idx[idx.length - 1] + 1;
|
|
19463
|
+
const h = new Float64Array(N);
|
|
19464
|
+
h[0] = 1;
|
|
19465
|
+
for (let i = 1; i < N; i++) h[i] = h[i - 1] * (i - 1 + 0.5) / i;
|
|
19466
|
+
const n = idx.length;
|
|
19467
|
+
const F = new Float64Array(n * n);
|
|
19468
|
+
for (let a = 0; a < n; a++)
|
|
19469
|
+
for (let b = 0; b <= a; b++) {
|
|
19470
|
+
const ia = idx[a];
|
|
19471
|
+
const ib = idx[b];
|
|
19472
|
+
let s = 0;
|
|
19473
|
+
for (let k = 0; k <= ib; k++) s += h[ia - k] * h[ib - k];
|
|
19474
|
+
F[a * n + b] = s;
|
|
19475
|
+
F[b * n + a] = s;
|
|
19476
|
+
}
|
|
19477
|
+
let tr = 0;
|
|
19478
|
+
for (let a = 0; a < n; a++) tr += F[a * n + a];
|
|
19479
|
+
const scale = n / tr;
|
|
19480
|
+
for (let i = 0; i < F.length; i++) F[i] *= scale;
|
|
19481
|
+
return F;
|
|
19482
|
+
}
|
|
19483
|
+
var MAX_SAMPLES = 360;
|
|
19484
|
+
function fitWhiteFlicker(A, y, tYears) {
|
|
19485
|
+
let rows = A.map((_, i) => i);
|
|
19486
|
+
if (rows.length > MAX_SAMPLES) {
|
|
19487
|
+
const step = rows.length / MAX_SAMPLES;
|
|
19488
|
+
rows = Array.from({ length: MAX_SAMPLES }, (_, k) => Math.floor(k * step));
|
|
19489
|
+
}
|
|
19490
|
+
const n = rows.length;
|
|
19491
|
+
const p = A[0]?.length ?? 0;
|
|
19492
|
+
if (n < p + 5) return null;
|
|
19493
|
+
const dts = rows.slice(1).map((r, k) => tYears[r] - tYears[rows[k]]).filter((d) => d > 0).sort((a, b) => a - b);
|
|
19494
|
+
const dt = dts[dts.length >> 1] ?? 1 / 365.25;
|
|
19495
|
+
const t0 = tYears[rows[0]];
|
|
19496
|
+
const idx = rows.map((r) => Math.round((tYears[r] - t0) / dt));
|
|
19497
|
+
for (let k = 1; k < n; k++)
|
|
19498
|
+
if (idx[k] <= idx[k - 1]) idx[k] = idx[k - 1] + 1;
|
|
19499
|
+
const F = flickerCovariance(idx);
|
|
19500
|
+
const evaluate = (phi) => {
|
|
19501
|
+
const C2 = new Float64Array(n * n);
|
|
19502
|
+
for (let i = 0; i < n * n; i++) C2[i] = phi * F[i];
|
|
19503
|
+
for (let i = 0; i < n; i++) C2[i * n + i] += 1 - phi;
|
|
19504
|
+
if (!cholesky(C2, n)) return null;
|
|
19505
|
+
const Aw = Array.from({ length: p }, (_, j) => {
|
|
19506
|
+
const col = Float64Array.from(rows, (r) => A[r][j]);
|
|
19507
|
+
forward(C2, n, col);
|
|
19508
|
+
return col;
|
|
19509
|
+
});
|
|
19510
|
+
const yw = Float64Array.from(rows, (r) => y[r]);
|
|
19511
|
+
forward(C2, n, yw);
|
|
19512
|
+
const N = Array.from(
|
|
19513
|
+
{ length: p },
|
|
19514
|
+
(_, a) => Array.from({ length: p }, (_2, b) => {
|
|
19515
|
+
let s = 0;
|
|
19516
|
+
for (let i = 0; i < n; i++) s += Aw[a][i] * Aw[b][i];
|
|
19517
|
+
return s;
|
|
19518
|
+
})
|
|
19519
|
+
);
|
|
19520
|
+
const rhs = Array.from({ length: p }, (_, a) => {
|
|
19521
|
+
let s = 0;
|
|
19522
|
+
for (let i = 0; i < n; i++) s += Aw[a][i] * yw[i];
|
|
19523
|
+
return s;
|
|
19524
|
+
});
|
|
19525
|
+
const Ninv = invert(N);
|
|
19526
|
+
if (!Ninv) return null;
|
|
19527
|
+
const beta = Ninv.map((row) => row.reduce((s, v, k) => s + v * rhs[k], 0));
|
|
19528
|
+
let rss = 0;
|
|
19529
|
+
for (let i = 0; i < n; i++) {
|
|
19530
|
+
let m = 0;
|
|
19531
|
+
for (let j = 0; j < p; j++) m += Aw[j][i] * beta[j];
|
|
19532
|
+
rss += (yw[i] - m) ** 2;
|
|
19533
|
+
}
|
|
19534
|
+
const sigma2 = rss / n;
|
|
19535
|
+
let logdet = 0;
|
|
19536
|
+
for (let i = 0; i < n; i++) logdet += 2 * Math.log(C2[i * n + i]);
|
|
19537
|
+
const logL = -0.5 * (n * Math.log(sigma2) + logdet + n);
|
|
19538
|
+
return {
|
|
19539
|
+
logL,
|
|
19540
|
+
velocity: beta[1],
|
|
19541
|
+
velocitySigma: Math.sqrt(sigma2 * Ninv[1][1])
|
|
19542
|
+
};
|
|
19543
|
+
};
|
|
19544
|
+
let best = null;
|
|
19545
|
+
for (let k = 0; k <= 20; k++) {
|
|
19546
|
+
const phi = Math.min(k / 20, 0.995);
|
|
19547
|
+
const r = evaluate(phi);
|
|
19548
|
+
if (r && (!best || r.logL > best.r.logL)) best = { phi, r };
|
|
19549
|
+
}
|
|
19550
|
+
if (!best) return null;
|
|
19551
|
+
let lo = Math.max(0, best.phi - 0.05);
|
|
19552
|
+
let hi = Math.min(0.995, best.phi + 0.05);
|
|
19553
|
+
const g = (Math.sqrt(5) - 1) / 2;
|
|
19554
|
+
for (let it = 0; it < 12; it++) {
|
|
19555
|
+
const a = hi - g * (hi - lo);
|
|
19556
|
+
const b = lo + g * (hi - lo);
|
|
19557
|
+
const ra = evaluate(a);
|
|
19558
|
+
const rb = evaluate(b);
|
|
19559
|
+
if (!ra || !rb) break;
|
|
19560
|
+
if (ra.logL > rb.logL) {
|
|
19561
|
+
hi = b;
|
|
19562
|
+
if (ra.logL > best.r.logL) best = { phi: a, r: ra };
|
|
19563
|
+
} else {
|
|
19564
|
+
lo = a;
|
|
19565
|
+
if (rb.logL > best.r.logL) best = { phi: b, r: rb };
|
|
19566
|
+
}
|
|
19567
|
+
}
|
|
19568
|
+
return {
|
|
19569
|
+
flickerShare: best.phi,
|
|
19570
|
+
velocitySigma: best.r.velocitySigma,
|
|
19571
|
+
velocity: best.r.velocity
|
|
19572
|
+
};
|
|
19573
|
+
}
|
|
19574
|
+
function invert(N) {
|
|
19575
|
+
const p = N.length;
|
|
19576
|
+
const M = N.map((row, i) => [
|
|
19577
|
+
...row,
|
|
19578
|
+
...Array.from({ length: p }, (_, j) => i === j ? 1 : 0)
|
|
19579
|
+
]);
|
|
19580
|
+
for (let c = 0; c < p; c++) {
|
|
19581
|
+
let piv = c;
|
|
19582
|
+
for (let r = c + 1; r < p; r++)
|
|
19583
|
+
if (Math.abs(M[r][c]) > Math.abs(M[piv][c])) piv = r;
|
|
19584
|
+
if (Math.abs(M[piv][c]) < 1e-14) return null;
|
|
19585
|
+
[M[c], M[piv]] = [M[piv], M[c]];
|
|
19586
|
+
const d = M[c][c];
|
|
19587
|
+
for (let k = 0; k < 2 * p; k++) M[c][k] /= d;
|
|
19588
|
+
for (let r = 0; r < p; r++) {
|
|
19589
|
+
if (r === c) continue;
|
|
19590
|
+
const f = M[r][c];
|
|
19591
|
+
if (f === 0) continue;
|
|
19592
|
+
for (let k = 0; k < 2 * p; k++) M[r][k] -= f * M[c][k];
|
|
19593
|
+
}
|
|
19594
|
+
}
|
|
19595
|
+
return M.map((row) => row.slice(p));
|
|
19596
|
+
}
|
|
19597
|
+
|
|
19598
|
+
// src/analysis/coordinate-series.ts
|
|
19599
|
+
var MS_PER_YEAR = 365.25 * 864e5;
|
|
19600
|
+
var TWO_PI2 = 2 * Math.PI;
|
|
19601
|
+
var MIN_SIGMA_M = 5e-4;
|
|
19602
|
+
function lsq(A, y, w) {
|
|
19603
|
+
const p = A[0]?.length ?? 0;
|
|
19604
|
+
const N = Array.from({ length: p }, () => new Array(p).fill(0));
|
|
19605
|
+
const b = new Array(p).fill(0);
|
|
19606
|
+
for (let i = 0; i < A.length; i++) {
|
|
19607
|
+
const a = A[i];
|
|
19608
|
+
for (let j = 0; j < p; j++) {
|
|
19609
|
+
b[j] += w[i] * a[j] * y[i];
|
|
19610
|
+
for (let k = 0; k < p; k++) N[j][k] += w[i] * a[j] * a[k];
|
|
19611
|
+
}
|
|
19612
|
+
}
|
|
19613
|
+
const M = N.map((row, i) => [
|
|
19614
|
+
...row,
|
|
19615
|
+
...Array.from({ length: p }, (_, j) => i === j ? 1 : 0)
|
|
19616
|
+
]);
|
|
19617
|
+
for (let c = 0; c < p; c++) {
|
|
19618
|
+
let piv = c;
|
|
19619
|
+
for (let r = c + 1; r < p; r++)
|
|
19620
|
+
if (Math.abs(M[r][c]) > Math.abs(M[piv][c])) piv = r;
|
|
19621
|
+
if (Math.abs(M[piv][c]) < 1e-12) return null;
|
|
19622
|
+
[M[c], M[piv]] = [M[piv], M[c]];
|
|
19623
|
+
const d = M[c][c];
|
|
19624
|
+
for (let k = 0; k < 2 * p; k++) M[c][k] /= d;
|
|
19625
|
+
for (let r = 0; r < p; r++) {
|
|
19626
|
+
if (r === c) continue;
|
|
19627
|
+
const f = M[r][c];
|
|
19628
|
+
if (f === 0) continue;
|
|
19629
|
+
for (let k = 0; k < 2 * p; k++) M[r][k] -= f * M[c][k];
|
|
19630
|
+
}
|
|
19631
|
+
}
|
|
19632
|
+
const Ninv = M.map((row) => row.slice(p));
|
|
19633
|
+
const x = Ninv.map((row) => row.reduce((s, v, k) => s + v * b[k], 0));
|
|
19634
|
+
return { x, Ninv };
|
|
19635
|
+
}
|
|
19636
|
+
function median3(xs) {
|
|
19637
|
+
const s = [...xs].sort((a, b) => a - b);
|
|
19638
|
+
const m = s.length >> 1;
|
|
19639
|
+
return s.length % 2 ? s[m] : (s[m - 1] + s[m]) / 2;
|
|
19640
|
+
}
|
|
19641
|
+
function robustSigma(xs) {
|
|
19642
|
+
if (xs.length < 2) return 0;
|
|
19643
|
+
const m = median3(xs);
|
|
19644
|
+
return 1.4826 * median3(xs.map((x) => Math.abs(x - m)));
|
|
19645
|
+
}
|
|
19646
|
+
function designRow(tMs, d) {
|
|
19647
|
+
const dt = (tMs - d.refEpochMs) / MS_PER_YEAR;
|
|
19648
|
+
const row = [1, dt];
|
|
19649
|
+
for (const j of d.jumps) row.push(tMs >= j ? 1 : 0);
|
|
19650
|
+
if (d.seasonal) {
|
|
19651
|
+
const ph = TWO_PI2 * (tMs / MS_PER_YEAR);
|
|
19652
|
+
row.push(Math.sin(ph), Math.cos(ph), Math.sin(2 * ph), Math.cos(2 * ph));
|
|
19653
|
+
}
|
|
19654
|
+
return row;
|
|
19655
|
+
}
|
|
19656
|
+
function fitComponent(t, y, w, used, d) {
|
|
19657
|
+
const A = [];
|
|
19658
|
+
const yy = [];
|
|
19659
|
+
const ww = [];
|
|
19660
|
+
for (let i = 0; i < t.length; i++) {
|
|
19661
|
+
if (!used[i]) continue;
|
|
19662
|
+
A.push(designRow(t[i], d));
|
|
19663
|
+
yy.push(y[i]);
|
|
19664
|
+
ww.push(w[i]);
|
|
19665
|
+
}
|
|
19666
|
+
if (A.length <= (A[0]?.length ?? 0)) return null;
|
|
19667
|
+
const s = lsq(A, yy, ww);
|
|
19668
|
+
if (!s) return null;
|
|
19669
|
+
const residuals = t.map(
|
|
19670
|
+
(ti, i) => y[i] - designRow(ti, d).reduce((acc, a, k) => acc + a * s.x[k], 0)
|
|
19671
|
+
);
|
|
19672
|
+
let wrss = 0;
|
|
19673
|
+
let sumW = 0;
|
|
19674
|
+
for (let i = 0; i < t.length; i++) {
|
|
19675
|
+
if (!used[i]) continue;
|
|
19676
|
+
wrss += w[i] * residuals[i] ** 2;
|
|
19677
|
+
sumW += w[i];
|
|
19678
|
+
}
|
|
19679
|
+
return { ...s, wrss, sumW, residuals };
|
|
19680
|
+
}
|
|
19681
|
+
function fitCoordinateSeries(samples, opts = {}) {
|
|
19682
|
+
const pts = [...samples].sort((a, b) => a.tMs - b.tMs);
|
|
19683
|
+
if (pts.length < 5) return null;
|
|
19684
|
+
const t = pts.map((p) => p.tMs);
|
|
19685
|
+
const spanYears = (t[t.length - 1] - t[0]) / MS_PER_YEAR;
|
|
19686
|
+
if (spanYears <= 0) return null;
|
|
19687
|
+
const ref = [0, 1, 2].map(
|
|
19688
|
+
(k2) => median3(pts.map((p) => p.ecef[k2]))
|
|
19689
|
+
);
|
|
19690
|
+
const [lat, lon] = ecefToGeodetic(ref[0], ref[1], ref[2]);
|
|
19691
|
+
const sl = Math.sin(lat);
|
|
19692
|
+
const cl = Math.cos(lat);
|
|
19693
|
+
const so = Math.sin(lon);
|
|
19694
|
+
const co = Math.cos(lon);
|
|
19695
|
+
const enu = pts.map((p) => {
|
|
19696
|
+
const dx = p.ecef[0] - ref[0];
|
|
19697
|
+
const dy = p.ecef[1] - ref[1];
|
|
19698
|
+
const dz = p.ecef[2] - ref[2];
|
|
19699
|
+
return [
|
|
19700
|
+
-so * dx + co * dy,
|
|
19701
|
+
-sl * co * dx - sl * so * dy + cl * dz,
|
|
19702
|
+
cl * co * dx + cl * so * dy + sl * dz
|
|
19703
|
+
];
|
|
19704
|
+
});
|
|
19705
|
+
const weights = [0, 1, 2].map(
|
|
19706
|
+
(k2) => pts.map((p) => {
|
|
19707
|
+
const s = p.sigmaEnu?.[k2];
|
|
19708
|
+
return s && s > 0 ? 1 / Math.max(s, MIN_SIGMA_M) ** 2 : 1;
|
|
19709
|
+
})
|
|
19710
|
+
);
|
|
19711
|
+
const series = [0, 1, 2].map((k2) => enu.map((v) => v[k2]));
|
|
19712
|
+
const seasonal = opts.seasonal === "auto" || opts.seasonal === void 0 ? spanYears >= 2 : opts.seasonal;
|
|
19713
|
+
const design = {
|
|
19714
|
+
refEpochMs: opts.refEpochMs ?? (t[0] + t[t.length - 1]) / 2,
|
|
19715
|
+
jumps: [...opts.jumps ?? []].filter((j) => j > t[0] && j <= t[t.length - 1]).sort((a, b) => a - b),
|
|
19716
|
+
seasonal
|
|
19717
|
+
};
|
|
19718
|
+
const detected = /* @__PURE__ */ new Set();
|
|
19719
|
+
const k = opts.outlierK ?? 4;
|
|
19720
|
+
const used = pts.map(() => true);
|
|
19721
|
+
const fitAll = () => [0, 1, 2].map(
|
|
19722
|
+
(c) => fitComponent(t, series[c], weights[c], used, design)
|
|
19723
|
+
);
|
|
19724
|
+
const robustPass = () => {
|
|
19725
|
+
for (let iter = 0; iter < 10; iter++) {
|
|
19726
|
+
const sol2 = fitAll();
|
|
19727
|
+
if (sol2.some((s) => !s)) return null;
|
|
19728
|
+
const scales = sol2.map(
|
|
19729
|
+
(s) => Math.max(robustSigma(s.residuals.filter((_, i) => used[i])), 1e-4)
|
|
19730
|
+
);
|
|
19731
|
+
let changed = false;
|
|
19732
|
+
for (let i = 0; i < t.length; i++) {
|
|
19733
|
+
const bad = sol2.some(
|
|
19734
|
+
(s, c) => Math.abs(s.residuals[i]) > k * scales[c]
|
|
19735
|
+
);
|
|
19736
|
+
if (bad === used[i]) {
|
|
19737
|
+
used[i] = !bad;
|
|
19738
|
+
changed = true;
|
|
19739
|
+
}
|
|
19740
|
+
}
|
|
19741
|
+
if (!changed) return sol2;
|
|
19742
|
+
}
|
|
19743
|
+
return fitAll();
|
|
19744
|
+
};
|
|
19745
|
+
let sol = robustPass();
|
|
19746
|
+
if (!sol) return null;
|
|
19747
|
+
if (opts.detectJumps ?? true) {
|
|
19748
|
+
const minSide = opts.minSamplesPerSide ?? 5;
|
|
19749
|
+
for (let added = 0; added < (opts.maxJumps ?? 3); added++) {
|
|
19750
|
+
const idx = t.map((_, i) => i).filter((i) => used[i]);
|
|
19751
|
+
const nUsed = idx.length;
|
|
19752
|
+
const bicOf = (s, p) => s.reduce((acc, c) => acc + nUsed * Math.log(c.wrss / c.sumW), 0) + 3 * p * Math.log(nUsed);
|
|
19753
|
+
const p0 = designRow(t[0], design).length;
|
|
19754
|
+
const bic0 = bicOf(sol, p0);
|
|
19755
|
+
let best = null;
|
|
19756
|
+
for (let j = minSide; j <= nUsed - minSide; j++) {
|
|
19757
|
+
const tj = (t[idx[j - 1]] + t[idx[j]]) / 2;
|
|
19758
|
+
if (design.jumps.some((x) => Math.abs(x - tj) < 7 * 864e5))
|
|
19759
|
+
continue;
|
|
19760
|
+
const trial = {
|
|
19761
|
+
...design,
|
|
19762
|
+
jumps: [...design.jumps, tj].sort((a, b) => a - b)
|
|
19763
|
+
};
|
|
19764
|
+
const s = [0, 1, 2].map(
|
|
19765
|
+
(c) => fitComponent(t, series[c], weights[c], used, trial)
|
|
19766
|
+
);
|
|
19767
|
+
if (s.some((x) => !x)) continue;
|
|
19768
|
+
const bic = bicOf(s, p0 + 1);
|
|
19769
|
+
if (!best || bic < best.bic)
|
|
19770
|
+
best = { tMs: tj, bic, sol: s };
|
|
19771
|
+
}
|
|
19772
|
+
if (!best || bic0 - best.bic <= 10) break;
|
|
19773
|
+
design.jumps = [...design.jumps, best.tMs].sort((a, b) => a - b);
|
|
19774
|
+
detected.add(best.tMs);
|
|
19775
|
+
sol = robustPass();
|
|
19776
|
+
if (!sol) return null;
|
|
19777
|
+
}
|
|
19778
|
+
}
|
|
19779
|
+
const nJ = design.jumps.length;
|
|
19780
|
+
const component = (c) => {
|
|
19781
|
+
const s = sol[c];
|
|
19782
|
+
const nUsed = used.filter(Boolean).length;
|
|
19783
|
+
const p = s.x.length;
|
|
19784
|
+
const vf = nUsed > p ? s.wrss / (nUsed - p) : 1;
|
|
19785
|
+
const amp = (i) => seasonal ? Math.hypot(s.x[i], s.x[i + 1]) : null;
|
|
19786
|
+
const noise = opts.noiseModel ?? true ? fitWhiteFlicker(
|
|
19787
|
+
t.flatMap((ti, i) => used[i] ? [designRow(ti, design)] : []),
|
|
19788
|
+
series[c].filter((_, i) => used[i]),
|
|
19789
|
+
t.flatMap((ti, i) => used[i] ? [ti / MS_PER_YEAR] : [])
|
|
19790
|
+
) : null;
|
|
19791
|
+
return {
|
|
19792
|
+
offset: s.x[0],
|
|
19793
|
+
velocity: s.x[1],
|
|
19794
|
+
velocitySigma: Math.sqrt(s.Ninv[1][1] * vf),
|
|
19795
|
+
velocitySigmaRealistic: noise?.velocitySigma ?? null,
|
|
19796
|
+
flickerShare: noise?.flickerShare ?? null,
|
|
19797
|
+
steps: s.x.slice(2, 2 + nJ),
|
|
19798
|
+
annualAmplitude: amp(2 + nJ),
|
|
19799
|
+
semiannualAmplitude: amp(4 + nJ),
|
|
19800
|
+
wrms: Math.sqrt(s.wrss / s.sumW)
|
|
19801
|
+
};
|
|
19802
|
+
};
|
|
19803
|
+
const points = pts.map((p, i) => ({
|
|
19804
|
+
tMs: p.tMs,
|
|
19805
|
+
enu: enu[i],
|
|
19806
|
+
model: [0, 1, 2].map((c) => series[c][i] - sol[c].residuals[i]),
|
|
19807
|
+
outlier: !used[i]
|
|
19808
|
+
}));
|
|
19809
|
+
return {
|
|
19810
|
+
refEcef: ref,
|
|
19811
|
+
refEpochMs: design.refEpochMs,
|
|
19812
|
+
e: component(0),
|
|
19813
|
+
n: component(1),
|
|
19814
|
+
u: component(2),
|
|
19815
|
+
jumps: design.jumps.map((tMs) => ({ tMs, detected: detected.has(tMs) })),
|
|
19816
|
+
points,
|
|
19817
|
+
spanYears,
|
|
19818
|
+
used: used.filter(Boolean).length,
|
|
19819
|
+
outliers: used.filter((u) => !u).length,
|
|
19820
|
+
seasonal
|
|
19821
|
+
};
|
|
19822
|
+
}
|
|
19823
|
+
|
|
19824
|
+
// src/analysis/network-alignment.ts
|
|
19825
|
+
function applyHelmertFit(x, f) {
|
|
19826
|
+
const [r1, r2, r3] = f.r;
|
|
19827
|
+
return [
|
|
19828
|
+
x[0] + f.t[0] + f.d * x[0] - r3 * x[1] + r2 * x[2],
|
|
19829
|
+
x[1] + f.t[1] + r3 * x[0] + f.d * x[1] - r1 * x[2],
|
|
19830
|
+
x[2] + f.t[2] - r2 * x[0] + r1 * x[1] + f.d * x[2]
|
|
19831
|
+
];
|
|
19832
|
+
}
|
|
19833
|
+
function solve(N, b) {
|
|
19834
|
+
const n = b.length;
|
|
19835
|
+
const M = N.map((row, i) => [...row, b[i]]);
|
|
19836
|
+
for (let c = 0; c < n; c++) {
|
|
19837
|
+
let p = c;
|
|
19838
|
+
for (let r = c + 1; r < n; r++)
|
|
19839
|
+
if (Math.abs(M[r][c]) > Math.abs(M[p][c])) p = r;
|
|
19840
|
+
if (Math.abs(M[p][c]) < 1e-6) return null;
|
|
19841
|
+
[M[c], M[p]] = [M[p], M[c]];
|
|
19842
|
+
for (let r = 0; r < n; r++) {
|
|
19843
|
+
if (r === c) continue;
|
|
19844
|
+
const f = M[r][c] / M[c][c];
|
|
19845
|
+
for (let k = c; k <= n; k++) M[r][k] -= f * M[c][k];
|
|
19846
|
+
}
|
|
19847
|
+
}
|
|
19848
|
+
return M.map((row, i) => row[n] / row[i]);
|
|
19849
|
+
}
|
|
19850
|
+
function estimateHelmert(from, to, opts = {}) {
|
|
19851
|
+
const model = opts.model ?? "translation";
|
|
19852
|
+
const nPar = model === "translation" ? 3 : 7;
|
|
19853
|
+
const minRefs = opts.minRefs ?? (model === "translation" ? 3 : 4);
|
|
19854
|
+
const maxRes = opts.maxResidualM ?? 0.015;
|
|
19855
|
+
if (from.length !== to.length) return null;
|
|
19856
|
+
const used = from.map(() => true);
|
|
19857
|
+
const c = [0, 1, 2].map(
|
|
19858
|
+
(k) => from.reduce((s, p) => s + p[k], 0) / Math.max(from.length, 1)
|
|
19859
|
+
);
|
|
19860
|
+
for (; ; ) {
|
|
19861
|
+
const idx = used.flatMap((u, i) => u ? [i] : []);
|
|
19862
|
+
if (idx.length < minRefs || idx.length * 3 <= nPar) return null;
|
|
19863
|
+
const N = Array.from(
|
|
19864
|
+
{ length: nPar },
|
|
19865
|
+
() => new Array(nPar).fill(0)
|
|
19866
|
+
);
|
|
19867
|
+
const b = new Array(nPar).fill(0);
|
|
19868
|
+
for (const i of idx) {
|
|
19869
|
+
const x = [from[i][0] - c[0], from[i][1] - c[1], from[i][2] - c[2]];
|
|
19870
|
+
for (let k = 0; k < 3; k++) {
|
|
19871
|
+
const row = new Array(nPar).fill(0);
|
|
19872
|
+
row[k] = 1;
|
|
19873
|
+
if (nPar === 7) {
|
|
19874
|
+
if (k === 0) {
|
|
19875
|
+
row[4] = x[2];
|
|
19876
|
+
row[5] = -x[1];
|
|
19877
|
+
} else if (k === 1) {
|
|
19878
|
+
row[3] = -x[2];
|
|
19879
|
+
row[5] = x[0];
|
|
19880
|
+
} else {
|
|
19881
|
+
row[3] = x[1];
|
|
19882
|
+
row[4] = -x[0];
|
|
19883
|
+
}
|
|
19884
|
+
row[6] = x[k];
|
|
19885
|
+
}
|
|
19886
|
+
const y = to[i][k] - from[i][k];
|
|
19887
|
+
for (let a = 0; a < nPar; a++) {
|
|
19888
|
+
b[a] += row[a] * y;
|
|
19889
|
+
for (let bb = 0; bb < nPar; bb++) N[a][bb] += row[a] * row[bb];
|
|
19890
|
+
}
|
|
19891
|
+
}
|
|
19892
|
+
}
|
|
19893
|
+
const p = solve(N, b);
|
|
19894
|
+
if (!p) return null;
|
|
19895
|
+
const r = nPar === 7 ? [p[3], p[4], p[5]] : [0, 0, 0];
|
|
19896
|
+
const d = nPar === 7 ? p[6] : 0;
|
|
19897
|
+
const t = [
|
|
19898
|
+
p[0] - (d * c[0] - r[2] * c[1] + r[1] * c[2]),
|
|
19899
|
+
p[1] - (r[2] * c[0] + d * c[1] - r[0] * c[2]),
|
|
19900
|
+
p[2] - (-r[1] * c[0] + r[0] * c[1] + d * c[2])
|
|
19901
|
+
];
|
|
19902
|
+
const fit = { model, t, r, d, residuals: [], used, rms: 0 };
|
|
19903
|
+
fit.residuals = from.map((x, i) => {
|
|
19904
|
+
const y = applyHelmertFit(x, fit);
|
|
19905
|
+
return [to[i][0] - y[0], to[i][1] - y[1], to[i][2] - y[2]];
|
|
19906
|
+
});
|
|
19907
|
+
let worst = -1;
|
|
19908
|
+
let worstNorm = maxRes;
|
|
19909
|
+
let ss = 0;
|
|
19910
|
+
for (const i of idx) {
|
|
19911
|
+
const n = Math.hypot(...fit.residuals[i]);
|
|
19912
|
+
ss += n * n;
|
|
19913
|
+
if (n > worstNorm) {
|
|
19914
|
+
worstNorm = n;
|
|
19915
|
+
worst = i;
|
|
19916
|
+
}
|
|
19917
|
+
}
|
|
19918
|
+
fit.rms = Math.sqrt(ss / (3 * idx.length));
|
|
19919
|
+
if (worst < 0 || idx.length <= minRefs) {
|
|
19920
|
+
fit.used = [...used];
|
|
19921
|
+
return fit;
|
|
19922
|
+
}
|
|
19923
|
+
used[worst] = false;
|
|
19924
|
+
}
|
|
19925
|
+
}
|
|
19926
|
+
|
|
19317
19927
|
// src/antex/index.ts
|
|
19318
19928
|
function label(line) {
|
|
19319
19929
|
return (line.length >= 80 ? line.substring(60, 80) : line.substring(60)).trimEnd();
|
|
@@ -20509,6 +21119,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
20509
21119
|
BAND_LABELS,
|
|
20510
21120
|
BAND_PRESETS,
|
|
20511
21121
|
BDS_SATELLITES,
|
|
21122
|
+
BLQ_CONSTITUENTS,
|
|
20512
21123
|
BitReader,
|
|
20513
21124
|
CONSTELLATIONS,
|
|
20514
21125
|
C_LIGHT,
|
|
@@ -20606,6 +21217,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
20606
21217
|
analyzeQuality,
|
|
20607
21218
|
antexFreqOfGroup,
|
|
20608
21219
|
applyHelmert,
|
|
21220
|
+
applyHelmertFit,
|
|
20609
21221
|
applyIonoDcb,
|
|
20610
21222
|
applyOrbitClock,
|
|
20611
21223
|
biasMetres,
|
|
@@ -20653,6 +21265,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
20653
21265
|
ecefToAzEl,
|
|
20654
21266
|
ecefToGeodetic,
|
|
20655
21267
|
ephInfoToEphemeris,
|
|
21268
|
+
estimateHelmert,
|
|
20656
21269
|
estimateNarrowlaneFcb,
|
|
20657
21270
|
estimateNetworkFcbs,
|
|
20658
21271
|
estimateWidelaneFcb,
|
|
@@ -20664,6 +21277,7 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
20664
21277
|
feedNavicBlock,
|
|
20665
21278
|
fetchSourcetable,
|
|
20666
21279
|
findSatBias,
|
|
21280
|
+
fitCoordinateSeries,
|
|
20667
21281
|
fixPppPosition,
|
|
20668
21282
|
fmtD,
|
|
20669
21283
|
fmtF,
|
|
@@ -20758,12 +21372,14 @@ function computePsdDb(centerMHz, halfSpanChips, numPoints, psdFn, f0 = 1023e3, f
|
|
|
20758
21372
|
nlWavelength,
|
|
20759
21373
|
nmeaCoordToDecimal,
|
|
20760
21374
|
obsEpochToDate,
|
|
21375
|
+
oceanLoadingEnu,
|
|
20761
21376
|
oem4Frames,
|
|
20762
21377
|
padL,
|
|
20763
21378
|
padR,
|
|
20764
21379
|
parseAntex,
|
|
20765
21380
|
parseBiasSinex,
|
|
20766
21381
|
parseBinex,
|
|
21382
|
+
parseBlq,
|
|
20767
21383
|
parseClk,
|
|
20768
21384
|
parseCrxDataLine,
|
|
20769
21385
|
parseIonex,
|