API¶
The command line wraps these modules; everything can be called from Python.
Running¶
One frame's end-to-end validation run (plan T21-T25).
run_validation(config) streams the stack once: the calibrated velocity
(DISP - CAL, chained) and the station series; the raw velocity, mean
coherence and raw station series are independent of the calibration and are
cached per stack. It then compares with MIDAS by station class, computes the
double-difference sills (raw, calibrated, baseline) with paired bootstrap
CIs, applies the gate and writes the outputs (report.write_outputs).
Compatibility with the trade study (e2e_validation/validate_stack.py):
the raw cache uses the same key and file names, and the outputs the same
names, so trade-study validation/ folders serve as baselines.
RunConfig
¶
Bases: BaseModel
One validation run of one candidate on one frame.
Source code in src/disp2vlm_validation/pipeline.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | |
FrameInputs
¶
Bases: BaseModel
Everything about a frame that does not depend on the candidate.
Source code in src/disp2vlm_validation/pipeline.py
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | |
GoldenCheck
¶
Bases: BaseModel
Golden-epoch check: the candidate's product for tag vs the golden.
Source code in src/disp2vlm_validation/pipeline.py
73 74 75 76 77 78 79 80 | |
load_run_config(path)
¶
RunConfig from YAML.
Source code in src/disp2vlm_validation/pipeline.py
111 112 113 114 115 | |
run_validation(cfg, *, use_cache=True)
¶
Validate one candidate on one frame; return the metrics (also written).
Source code in src/disp2vlm_validation/pipeline.py
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 | |
VLM validation against independent GNSS (Venti plan T57).
A VLM run (opera_vlm) writes one product per target pair (T0, Tk), all
sharing T0, with vertical, vertical_std, east, mode. For
every product and every GNSS station inside it:
- pair residuals: product (3 x 3 pixel median at the station) minus the
GNSS displacement over the same span (median of the daily solutions within
half_window_daysofT0and ofTk), vertical and east; - station rates: the slope of the product's vertical series against time minus the slope of the GNSS up series at the same epochs; the gate is on these (owner target, 2026-10-11: 1-2 mm/yr);
- sigma realism:
z = residual / vertical_stdper span bin, coverage of|z| < 1.96and its robust spread.
Only independent GNSS (UNR daily, MIDAS), frozen per frame in the same cache the DISP-CAL validation uses. Stations in deforming areas or event footprints are reported but not gated (decision 0002).
VlmRunConfig
¶
Bases: BaseModel
One VLM validation run (vlm.yaml).
Source code in src/disp2vlm_validation/vlm.py
245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 | |
run_vlm(cfg)
¶
Validate one VLM run; write metrics_vlm.json and the residual tables.
Source code in src/disp2vlm_validation/vlm.py
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 | |
evaluate_vlm(stats, gate=VLM_GATE)
¶
FAIL reasons of the VLM gate on the gated station-rate statistics.
Source code in src/disp2vlm_validation/vlm.py
226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 | |
A small synthetic frame to try the validator on, offline (demo command).
The frame is 40 x 60 pixels of 2 km (EPSG:32615) with a vertical look. Truth is a 10 mm/yr east-west velocity gradient. Each DISP pair adds a random per-date ramp, the long-wavelength error a calibration should remove, plus 0.5 mm of noise; the stack has two reference blocks (21 dates, 12 days apart).
Three DISP-CAL candidates differ only in how much of the ramp they remove:
perfect (all of it), half and none. Sixteen GNSS stations carry
the true velocity; their MIDAS rates and daily series are written to the
frozen GNSS cache, so nothing is downloaded.
write_demo also writes ready-to-run configs in <root>/configs:
perfect.yaml (no baseline), half.yaml and none.yaml (both against
perfect), and gate.yaml (a per-class target).
demo_config(root, candidate, baseline=None, **overrides)
¶
Run config (as a dict) for one demo candidate.
The demo stack is short (21 dates over 240 days) and small (120 km), so
min_common_dates and sill_min_km are lowered from their full-frame
defaults; n_boot is lowered to keep it quick. Paths are absolute, so the
configs run from any directory.
Source code in src/disp2vlm_validation/demo.py
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 | |
make_demo_frame(root, seed=1)
¶
Write the synthetic frame under root.
Layout: disp/ (DISP pairs), perfect/, half/, none/ (each a
products/<ref>_<sec>/ tree of DISP-CAL products, as cal-disp writes
it), water_mask.tif, los.tif and cache/ (the GNSS cache).
Returns¶
Path
root.
Source code in src/disp2vlm_validation/demo.py
73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | |
write_demo(root, seed=1)
¶
Write the demo frame and its run configs; return the config paths.
Source code in src/disp2vlm_validation/demo.py
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 | |
Gate and requirements¶
The CalVal release gate as data (Venti PRD section 2.7).
One place for the numbers a run is judged by, so the gate logic (plan T23), the reports (T24) and the traceability table all read the same values. A change here changes what passes; it needs a decision record.
GateThresholds
dataclass
¶
Release-gate thresholds; a run FAILS if any condition is violated.
Attributes¶
sill_must_drop : bool
The calibrated double-difference sill must be below the raw one.
sill_rise_max_frac : float
Candidate vs baseline: a sill rise above this fraction that is also
statistically significant fails.
sill_min_pair_km : float
Station pairs shorter than this are not used for the sill.
velocity_rmse_rise_max_mm_yr, velocity_bias_rise_max_mm_yr : float
Candidate vs baseline: velocity RMSE or |bias| vs MIDAS may not rise
by more than this.
bias_statistic : str
Which bias the bias rules use: "median" of the station residuals
(default since decision 0001) or "mean". A mean is moved by a few
outliers, so fixing them on a frame with a bias of the other sign
raised |mean| and failed the gate.
target_abs_bias_mm_yr : float
Release target per frame (reported, not a pass/fail condition), on
the same bias statistic.
bootstrap_ci : float
Confidence level of the station-bootstrap intervals.
velocity_excluded_classes : tuple of str
Station classes left out of the velocity rules (decision 0002): the
deforming areas and event footprints are restored, not calibrated,
so they are reported per class instead of gating the calibration.
Empty restores the all-station rule.
Source code in src/disp2vlm_validation/requirements.py
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 | |
VlmGate
dataclass
¶
VLM gate on per-station vertical rates vs GNSS up (decision 0003, accepted).
Owner target (2026-10-11): VLM vertical rate within 1-2 mm/yr of GNSS. Gated stations: both looks (mode 1), outside deforming areas and event footprints (decision 0002). RMSE is reported, not gated: a handful of local sites (landslides, wells, coast) dominate it. Baseline: LA (F16940 + F18904, 2016-2023), 172 stations: median -0.49, NMAD 1.47, RMSE 2.77 (1.67 without 6 outliers) mm/yr.
Attributes¶
rate_abs_median_max_mm_yr, rate_nmad_max_mm_yr : float Limits on |median| and NMAD of (VLM rate - GNSS up rate). min_stations : int Fewer gated stations than this: not assessed (FAIL with that reason).
Source code in src/disp2vlm_validation/requirements.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | |
The release gate: configuration and evaluation (PRD section 2.7; plan T23).
A run FAILS when any of these holds:
- the calibrated double-difference sill is not below the raw one;
- versus the baseline, the sill rises more than
sill_rise_max_pctand the rise is significant (the paired bootstrap CI of the change is above 0); - versus the baseline, the velocity RMSE or |bias| (vs MIDAS) rises more
than
velocity_rmse_rise_max_mm_yr/velocity_bias_rise_max_mm_yr; the bias is the median of the station residuals unlessbias_statisticsaysmean(decision 0001); - the golden-epoch check fails.
The thresholds come from gate.yaml (per release); the defaults are
disp2vlm_validation.requirements.GATE. |bias| <= target_abs_bias_mm_yr
and per-class targets are reported, not gating.
GateConfig
¶
Bases: BaseModel
Thresholds of one release (gate.yaml).
Source code in src/disp2vlm_validation/gate.py
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | |
ClassTarget
¶
Bases: BaseModel
Reported per-class target (not gating).
Source code in src/disp2vlm_validation/gate.py
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | |
load_gate(path)
¶
GateConfig from a YAML file; defaults when path is None.
Source code in src/disp2vlm_validation/gate.py
99 100 101 102 103 104 105 | |
evaluate(inputs, gate=None)
¶
Apply the gate (see the module docstring).
Source code in src/disp2vlm_validation/gate.py
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 | |
golden_epoch_check(golden, candidate, *, executable='cal-disp', timeout_s=1800.0)
¶
Compare a candidate pair product with the golden via cal-disp validate.
Returns (ok, output). The comparison and its tolerance are cal-disp's
own (validate GOLDEN TEST), so this package does not re-implement it.
Source code in src/disp2vlm_validation/gate.py
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 | |
Metrics¶
Validation metrics: velocity statistics and the double-difference sill.
Double differences (geepers.validation): for every station pair, the
InSAR-minus-GNSS misfit of the relative LOS series (B - A) is reduced to an
RMSE about its mean; gamma = rmse**2 / 2 is the misfit semivariance.
Double differences cancel the datum, so raw and calibrated are directly
comparable; calibration removes long-wavelength error, so the sill (median
gamma of pairs at least sill_min_km apart) must drop.
The sill confidence interval is a station bootstrap: stations are resampled with replacement, each pair weighted by the product of its stations' counts, and the weighted median recomputed. All variants share the same resamples, so their differences are paired. Ported from the trade study (plan T21.1).
DDResult
dataclass
¶
Double-difference results of several variants on common station-dates.
Source code in src/disp2vlm_validation/metrics.py
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | |
change_pct(a, b)
¶
Sill change of a relative to b in %, with its paired 95% CI.
Source code in src/disp2vlm_validation/metrics.py
97 98 99 100 101 102 103 | |
SillResult
dataclass
¶
Sill of one variant with its station-bootstrap 95% interval.
Source code in src/disp2vlm_validation/metrics.py
74 75 76 77 78 79 80 81 82 83 84 85 | |
bootstrap_sills(pairs, *, sill_min_km=50.0, near_max_km=10.0, n_boot=1000, seed=0)
¶
Sill (median gamma of far pairs) per variant with paired bootstrap CIs.
pairs are pairwise_differential_rmse tables (station1, station2,
distance_km, rmse) per variant.
Source code in src/disp2vlm_validation/metrics.py
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 | |
ci95(x)
¶
2.5 and 97.5 percentiles.
Source code in src/disp2vlm_validation/metrics.py
69 70 71 | |
double_differences(insar, gps, coords, *, min_common_dates=30, sill_min_km=50.0, near_max_km=10.0, n_bins=12, n_boot=1000, seed=0)
¶
Pairwise DD RMSE, semivariograms and bootstrap sills per variant.
Parameters¶
insar : mapping of name -> DataFrame dates x stations InSAR LOS series (mm) per variant (raw, calibrated, baseline...). gps : DataFrame dates x stations GNSS LOS series (mm). coords : mapping station -> (lon, lat).
Only station-dates valid in every variant and in GNSS are used, so the variants are compared on the same data.
Source code in src/disp2vlm_validation/metrics.py
106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 | |
velocity_stats(insar, gps)
¶
Residual statistics of InSAR - GNSS (same units as the inputs).
Source code in src/disp2vlm_validation/metrics.py
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | |
weighted_median(x, w)
¶
Weighted median (lower); NaN when no weight is positive.
Source code in src/disp2vlm_validation/metrics.py
58 59 60 61 62 63 64 65 66 | |
Station classes and per-class metrics (PRD section 3.4; plan T22).
A station gets the first class that applies, in this order:
near_event: inside an event area of the event GeoJSON;defo_area: inside a deforming area of the defo GeoJSON;subsiding: GNSS vertical rate belowsubsiding_mm_yr;coastal: withincoast_kmof the sea: a water body of the DISP water mask of at leastsea_min_km2(bays and tidal channels joined to it count; ponds, lakes and rivers do not;sea_min_km2=0is any water);stable: everything else.
Metrics per class compare InSAR and GNSS velocities and, when sigmas are
given, report sigma realism: z = residual / sqrt(sigma_insar^2 +
sigma_gnss^2) should have std near 1 and ~95% of |z| below 1.96 (R-E4,
report only).
classify_stations(stations, *, defo_areas=(), events=(), land=None, pixel_m=30.0, subsiding_mm_yr=-3.0, coast_km=10.0, sea_min_km2=500.0)
¶
Class of every station (see the module docstring for the order).
stations needs lon, lat, vu_mm_yr and, for the coastal class,
row, col on the grid of land (True = land).
Source code in src/disp2vlm_validation/classes.py
107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | |
load_polygons(path)
¶
Shapely geometries of a GeoJSON FeatureCollection (EPSG:4326).
Source code in src/disp2vlm_validation/classes.py
43 44 45 46 47 48 49 50 | |
metrics_by_class(insar, gnss, classes, *, sigma_insar=None, sigma_gnss=None)
¶
class, n, bias, median, rmse, corr, std_z, coverage95 per class and all.
bias is the mean residual, median the median one.
Source code in src/disp2vlm_validation/classes.py
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 | |
normalized_residuals(residual, sigma_insar, sigma_gnss)
¶
residual / sqrt(sigma_insar^2 + sigma_gnss^2) (NaN where sigma is 0).
Source code in src/disp2vlm_validation/classes.py
138 139 140 141 142 143 144 145 146 147 148 | |
sea_mask(land, pixel_m, sea_min_km2)
¶
Water bodies of at least sea_min_km2 (8-connected); all water if 0.
On the four validation frames the seas are 900-15 000 km^2 (Gulf of Mexico, Galveston Bay, Pacific, Atlantic and Long Island Sound) while the largest inland water body is ~300 km^2 (Oklahoma City has ~20 000 small ones), so 500 km^2 separates them.
Source code in src/disp2vlm_validation/classes.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 | |
Data¶
DISP stacks, their DISP-CAL products, and chained per-pixel velocities.
Ported from trade studies/e2e_validation/validate_stack.py (plan T21.2,
T21.4) without hard-coded paths. A stack is the set of DISP-S1 products of a
frame; each epoch may have a DISP-CAL product with the same reference and
secondary dates. Calibrated displacement is DISP - calibration.
Epochs are chained across reference-date blocks as
opera_utils.disp.create_rebased_displacement does: the last cumulative
value of a block is the offset of the next one.
Epoch
dataclass
¶
One DISP product and, if found, its DISP-CAL product.
Source code in src/disp2vlm_validation/stack.py
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | |
VelocityFit
¶
Streaming per-pixel OLS of chained cumulative displacement against time.
Buffers are preallocated and updated in place: fresh full-frame temporaries every epoch cost more in page faults than the arithmetic.
Source code in src/disp2vlm_validation/stack.py
205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 | |
add(block_key, t, disp_m, mask)
¶
Add an epoch of block block_key (its reference date); return cumulative.
Source code in src/disp2vlm_validation/stack.py
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 | |
velocity_mm_yr(min_epochs=5)
¶
OLS slope in mm/yr; NaN with fewer than min_epochs valid epochs.
Source code in src/disp2vlm_validation/stack.py
243 244 245 246 247 248 249 250 251 | |
apply_calibration(epoch)
¶
Calibrated displacement DISP - calibration of one epoch (plan T21.4).
Source code in src/disp2vlm_validation/stack.py
170 171 172 173 174 175 176 177 | |
decimal_year(t)
¶
Decimal year with 365.25-day years from 2000-01-01.
Source code in src/disp2vlm_validation/stack.py
59 60 61 | |
list_epochs(disp_dir, cal_dir=None, *, allow_partial=False)
¶
Epochs of a stack sorted by secondary date, each with its CAL product.
Raises¶
FileNotFoundError
If disp_dir has no DISP product, or a CAL product is missing and
allow_partial is False (then those epochs are skipped instead).
Source code in src/disp2vlm_validation/stack.py
103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 | |
parse_dates(name)
¶
Return the reference and secondary datetimes of a DISP or DISP-CAL file.
Source code in src/disp2vlm_validation/stack.py
46 47 48 49 50 51 52 53 54 55 56 | |
read_epoch(epoch, ref_pixel=None)
¶
Return (calibrated, raw, coherence) for one epoch (float32, metres).
calibrated is DISP - calibration (None without a CAL product);
raw (only with ref_pixel) is DISP referenced to that pixel, and
coherence its temporal coherence.
Source code in src/disp2vlm_validation/stack.py
150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 | |
stream_epochs(epochs, ref_pixel=None, workers=4)
¶
Yield (epoch, read_epoch(epoch)) in order, reading ahead in processes.
workers=0 reads in this process (tests, small stacks).
Source code in src/disp2vlm_validation/stack.py
180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 | |
Independent GNSS: UNR daily stations, MIDAS rates, LOS projection, sampling.
Only daily station positions and their MIDAS rates are used, never the UNR
gridded field the calibration is fitted to (GATE.independent_gnss_only).
Ported from trade studies/e2e_validation/validate_stack.py (plan T21.2,
T21.3).
StationSampler
¶
Median of the valid (land, finite) pixels in a window around each station.
Source code in src/disp2vlm_validation/gnss.py
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | |
__call__(arr)
¶
One value per station; NaN with fewer than min_pixels valid pixels.
Source code in src/disp2vlm_validation/gnss.py
175 176 177 178 179 180 181 182 183 | |
StationSplit
dataclass
¶
Validation stations and the held-out ones (for fitting, e.g. TS-G1's k).
Source code in src/disp2vlm_validation/gnss.py
186 187 188 189 190 191 192 | |
fetch_gnss(bbox, min_span_years=2.0, max_workers=8)
¶
UNR stations in bbox (W, S, E, N): MIDAS ENU rates and daily ENU series.
Returns¶
midas : DataFrame
Index station; lon, lat, v{e,n,u}_mm_yr, sigma_v{e,n,u}_mm_yr,
n_gps_epochs, span_years, first, last (IGS20).
daily : DataFrame
station, date, east, north, up in metres, zeroed by the mean.
Source code in src/disp2vlm_validation/gnss.py
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | |
gnss_los_series(daily, stations, dates)
¶
GNSS LOS displacement (mm) at the acquisition dates: dates x stations.
Source code in src/disp2vlm_validation/gnss.py
139 140 141 142 143 144 145 146 147 148 | |
load_or_fetch_gnss(cache_dir, bbox, *, min_span_years=2.0, refresh=False)
¶
MIDAS and daily GNSS, frozen in cache_dir on first use.
Every run of a frame is then compared with the same GNSS numbers; the
trade-study cache layout (gnss_midas_enu.csv,
gnss_enu_daily.csv.gz) is read as is.
Source code in src/disp2vlm_validation/gnss.py
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 | |
split_held_out(stations, *, exclude=(), held_out_fraction=0.0, seed='disp2vlm')
¶
Split stations into validation and held-out sets, deterministically.
exclude (config, not code: e.g. UH01, a bad record) never enters
either set. The held-out choice hashes each station id with seed, so it
is stable across runs and machines and independent of the station order:
stations used to fit parameters (TS-G1) can never enter validation.
Source code in src/disp2vlm_validation/gnss.py
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 | |
station_pixels(stations, crs, transform, los)
¶
Locate stations on the DISP grid and project MIDAS rates onto the LOS.
los is the 3-band (east, north, up) LOS unit-vector stack of the
DISP-S1-STATIC product on the same grid. Stations outside the frame or
without a look are dropped. Adds row, col, los_{e,n,u},
gps_hz_los_mm_yr, gps_los_mm_yr.
Source code in src/disp2vlm_validation/gnss.py
110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 | |
Reports and CLI¶
Reports and traceability (plan T24).
Per frame: stations.csv, sill_draws.npz, SVG figures and
report.html; across frames: release_summary.html. Every figure is
followed by its data table (the table view the chart conventions require,
and the only form a reviewer can quote). Colours: the validated categorical
order blue (calibrated), orange (raw), aqua (baseline); status colours only
for the verdict, always with a text label.
write_outputs(metrics, stations, dd, out)
¶
stations.csv, sill_draws.npz, figures and report.html in out.
Source code in src/disp2vlm_validation/report.py
318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 | |
write_summary(run_dirs, out, title='Release summary')
¶
release_summary.html across frame runs (their metrics.json).
Source code in src/disp2vlm_validation/report.py
358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 | |
load_traceability()
¶
Entries of the packaged traceability.yaml.
Source code in src/disp2vlm_validation/report.py
61 62 63 64 65 66 | |
disp2vlm-validate command line.
gate prints the release gate and the benchmark frames; run validates
one candidate on one frame (run.yaml, see pipeline.RunConfig); vlm
validates a VLM run against GNSS (vlm.yaml, see vlm.VlmRunConfig);
summary gathers frame runs into release_summary.html; demo
writes a small synthetic frame and its configs to try the others on.
demo(out_dir, /, seed=1)
¶
Write a small synthetic frame and ready-to-run configs (no download).
Then run, e.g., disp2vlm-validate run --config OUT_DIR/configs/perfect.yaml.
Source code in src/disp2vlm_validation/cli.py
109 110 111 112 113 114 115 116 117 118 | |
gate(fmt='text')
¶
Print the CalVal release gate and the benchmark frames (PRD 2.7).
Source code in src/disp2vlm_validation/cli.py
27 28 29 30 31 32 33 34 35 36 37 38 39 | |
main()
¶
Entry point.
Source code in src/disp2vlm_validation/cli.py
121 122 123 124 125 126 | |
run(config, no_cache=False, verbose=False)
¶
Validate one candidate on one frame; write metrics, figures, report.html.
Parameters¶
config
run.yaml (disp2vlm_validation.pipeline.RunConfig).
no_cache
Recompute even when metrics.json has the same config hash.
verbose
Debug logging.
Source code in src/disp2vlm_validation/cli.py
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 | |
summary(runs, /, out=Path('release_summary.html'), title='Release summary')
¶
Gather frame runs (folders with metrics.json) into one HTML page.
Source code in src/disp2vlm_validation/cli.py
93 94 95 96 97 98 99 100 101 102 103 104 105 106 | |
vlm(config, verbose=False)
¶
Validate one VLM run against independent GNSS (vlm.yaml).
See disp2vlm_validation.vlm.VlmRunConfig for the fields.
Source code in src/disp2vlm_validation/cli.py
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 | |