rsplot 0.3.1__tar.gz → 0.3.2.dev4__tar.gz
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.
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/PKG-INFO +215 -1
- rsplot-0.3.2.dev4/README.md +463 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/pyproject.toml +1 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/cli.py +48 -10
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/common.py +64 -1
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/forecast.py +24 -5
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/overlay.py +172 -43
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/raster.py +168 -44
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/recent.py +29 -7
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/reconstruct.py +27 -5
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/config.py +3 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/geo/boundaries.py +105 -2
- rsplot-0.3.2.dev4/src/rsplot/geo/footprints.py +202 -0
- rsplot-0.3.2.dev4/src/rsplot/geo/processing.py +202 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/map_frame.py +120 -4
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/overlay.py +5 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/raster.py +5 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/__init__.py +38 -4
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/base.py +16 -1
- rsplot-0.3.2.dev4/src/rsplot/readers/gems.py +426 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/recent.py +59 -16
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/common.py +81 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/forecast.py +7 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/overlay.py +32 -2
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/raster.py +32 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/reconstruct.py +7 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/temporal.py +139 -16
- rsplot-0.3.1/README.md +0 -250
- rsplot-0.3.1/src/rsplot/geo/processing.py +0 -120
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/.gitignore +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/LICENSE +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/__init__.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/__main__.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/__init__.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/fnr.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/meteo.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/station.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/commands/station_trend.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/fnr.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/geo/__init__.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/geo/gridding.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/__init__.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/colormaps.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/fnr.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/meteo.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/station.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/station_trend.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/styles.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/plotting/wind.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/_tropomi.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/era5.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/era5_wind.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/forecast.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/guokong.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/reconstruct.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/tropomi_hcho.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/tropomi_no2.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/tropomi_o3.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/readers/tropomi_o3pr.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/__init__.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/fnr.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/meteo.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/station.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/result_builders/station_trend.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/results.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/stats.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/tiles/__init__.py +0 -0
- {rsplot-0.3.1 → rsplot-0.3.2.dev4}/src/rsplot/tiles/tianditu.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: rsplot
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2.dev4
|
|
4
4
|
Summary: CLI tool for plotting Remote Sensing data, designed for Agent.
|
|
5
5
|
Project-URL: Repository, https://git.lug.ustc.edu.cn/yaoyhu/rsplot
|
|
6
6
|
Project-URL: GitHub, https://github.com/yaoyhu/rsplot
|
|
@@ -217,6 +217,7 @@ Requires-Dist: geopandas>=0.13
|
|
|
217
217
|
Requires-Dist: matplotlib>=3.7
|
|
218
218
|
Requires-Dist: netcdf4>=1.7.3
|
|
219
219
|
Requires-Dist: numpy>=1.24
|
|
220
|
+
Requires-Dist: pyproj>=3.1
|
|
220
221
|
Requires-Dist: rich>=13.0.0
|
|
221
222
|
Requires-Dist: scipy>=1.10
|
|
222
223
|
Requires-Dist: shapely>=2.0
|
|
@@ -436,6 +437,219 @@ writes a JSON sidecar with the same base name. Reconstructed-grid JSON records
|
|
|
436
437
|
both the China-time input and matched UTC archive hour, source file, native and
|
|
437
438
|
output resolution, regional statistics, administrative summaries, and hotspots.
|
|
438
439
|
|
|
440
|
+
## Select multiple regions without configuration
|
|
441
|
+
|
|
442
|
+
`raster` and `overlay` accept a quoted, comma-separated region argument.
|
|
443
|
+
Use English or Chinese commas; surrounding whitespace and embedded line
|
|
444
|
+
breaks are ignored in a list. Province, city, and qualified county/township
|
|
445
|
+
names can be mixed. County and township names still require their city,
|
|
446
|
+
e.g. `中山市/东区街道`. Other commands retain their single-region input.
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
# One map covering three selected townships.
|
|
450
|
+
uv run rsplot raster \
|
|
451
|
+
"中山市/东区街道,中山市/南区街道,中山市/石岐街道" 20260907 \
|
|
452
|
+
--sensor gems -p o3pr --cf 1 --res 0.075 --smooth 0 \
|
|
453
|
+
--basemap none -o ./logs/zhongshan/three_streets_raster.png
|
|
454
|
+
|
|
455
|
+
# The same daily satellite field with observations at 19:00 China time.
|
|
456
|
+
uv run rsplot overlay \
|
|
457
|
+
"中山市/东区街道,中山市/南区街道,中山市/石岐街道" 20260907 \
|
|
458
|
+
--sensor gems -p o3pr --station-datetime 2026090719 \
|
|
459
|
+
--cf 1 --res 0.075 --smooth 0 --basemap none \
|
|
460
|
+
-o ./logs/zhongshan/three_streets_overlay.png
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
These examples use your existing product/station data paths. Optional
|
|
464
|
+
`--data-dir` for raster or `--raster-dir` for overlay overrides the satellite
|
|
465
|
+
root; no named region group needs to be added to configuration.
|
|
466
|
+
|
|
467
|
+
Every member is resolved before reading data. Repeated aliases are removed
|
|
468
|
+
in first-occurrence order; empty items and unknown names fail with an explicit
|
|
469
|
+
error instead of silently omitting regions. The map reads and processes the
|
|
470
|
+
combined extent once, but colors only the union of the selected geometries,
|
|
471
|
+
preserving holes and gaps between disconnected regions. Each member retains
|
|
472
|
+
its boundary and label. Defaults use the coarsest selected level; combined
|
|
473
|
+
maps use automatic geographic ticks. Explicit plot options still take
|
|
474
|
+
precedence. Far-apart selections share one map with intervening whitespace.
|
|
475
|
+
|
|
476
|
+
Combined maps use `联合区域(N个)` as their default name. The JSON adds
|
|
477
|
+
`region.members` with canonical qualified names, administrative levels and
|
|
478
|
+
extents. Existing overall statistics operate on the geometric union, without
|
|
479
|
+
double-counting parent/child overlaps. `member_stats` summarizes each selected
|
|
480
|
+
member using that same statistical grid; for overlay these lists are under
|
|
481
|
+
`raster.member_stats` and `station.member_stats`. A member with no valid data
|
|
482
|
+
remains in the list with zero valid counts and null numeric summaries.
|
|
483
|
+
Members may overlap, so their counts must not be added to recover the union
|
|
484
|
+
count. Grid centers exactly on a member boundary are excluded from that
|
|
485
|
+
member's statistics, even if they lie inside the combined region. Station
|
|
486
|
+
selection retains the existing boundary-tolerance rule. `spatial_summary`
|
|
487
|
+
continues to describe subdivisions, independently of selected-member stats.
|
|
488
|
+
Single-region inputs retain their existing output contract.
|
|
489
|
+
|
|
490
|
+
Run the isolated multi-region regressions:
|
|
491
|
+
|
|
492
|
+
```bash
|
|
493
|
+
uv run python -m unittest discover -s tests -p 'test_multi_regions.py' -v
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
## Raster boundaries and regional statistics
|
|
497
|
+
|
|
498
|
+
`raster`, `overlay`, `forecast` (including station overlays), and
|
|
499
|
+
`reconstruct` prepare separate display and statistics grids:
|
|
500
|
+
|
|
501
|
+
- **Display:** retain valid grid cells that intersect the administrative
|
|
502
|
+
geometry, even when their centers are outside. Clip the colored layer to
|
|
503
|
+
the actual boundary, including holes and disconnected islands. Display
|
|
504
|
+
smoothing uses surrounding values but preserves the input valid-cell mask.
|
|
505
|
+
- **Statistics:** select grid centers **strictly inside** the geometry;
|
|
506
|
+
centers exactly on the boundary are excluded. Each valid selected cell has
|
|
507
|
+
equal weight. Coverage is the valid selected-cell count divided by the
|
|
508
|
+
total selected-cell count, not the percentage of colored land area.
|
|
509
|
+
Existing product-specific gap-filling and statistical smoothing behavior
|
|
510
|
+
remains unchanged; GEMS statistics remain unfilled and unsmoothed.
|
|
511
|
+
|
|
512
|
+
The PNG sidecar adds `boundary_policy` with the selection and weighting
|
|
513
|
+
rules, the displayed intersecting-cell count, and the count whose centers
|
|
514
|
+
are outside. For `overlay`, this block is nested under `raster`.
|
|
515
|
+
A small region can display overlapping cells while having no interior grid
|
|
516
|
+
centers: its statistics then report zero valid cells and null summaries.
|
|
517
|
+
This change does not increase the satellite's native resolution or fill
|
|
518
|
+
missing observations.
|
|
519
|
+
|
|
520
|
+
Run boundary-selection and actual rendering regressions (including holes
|
|
521
|
+
and both PlateCarree and Mercator projections):
|
|
522
|
+
|
|
523
|
+
```bash
|
|
524
|
+
uv run python -m unittest discover -s tests -p 'test_boundary_display.py' -v
|
|
525
|
+
```
|
|
526
|
+
|
|
527
|
+
## GEMS satellite products
|
|
528
|
+
|
|
529
|
+
Use `--sensor gems` with `raster`, `recent`, and `overlay`. Omitting
|
|
530
|
+
`--sensor` retains TROPOMI behavior. GEMS FNR and satellite trend curves are
|
|
531
|
+
not included in this release.
|
|
532
|
+
|
|
533
|
+
Configure the three archive roots in `[paths.data_dirs]`:
|
|
534
|
+
|
|
535
|
+
```toml
|
|
536
|
+
gems_no2 = "/path/to/GEMS/NO2"
|
|
537
|
+
gems_hcho = "/path/to/GEMS/HCHO"
|
|
538
|
+
gems_o3 = "/path/to/GEMS/O3"
|
|
539
|
+
```
|
|
540
|
+
|
|
541
|
+
Alternatively set `RSPLOT_DATA_DIR_GEMS_NO2`, `RSPLOT_DATA_DIR_GEMS_HCHO`,
|
|
542
|
+
and `RSPLOT_DATA_DIR_GEMS_O3`. Each root contains `YYYYMM/DD/*.nc`.
|
|
543
|
+
`--data-dir` (`--raster-dir` for overlay) overrides the configured root.
|
|
544
|
+
|
|
545
|
+
| Product | GEMS variable | Display unit |
|
|
546
|
+
| --- | --- | --- |
|
|
547
|
+
| `no2` | `Data Fields/ColumnAmountNO2Trop` | 10¹⁵ molecules/cm² |
|
|
548
|
+
| `hcho` | `Data Fields/ColumnAmount` | 10¹⁵ molecules/cm² |
|
|
549
|
+
| `o3` | `product/total_ozone_column` | DU |
|
|
550
|
+
| `o3pr` | `product/troposphere_ozone_column` | DU |
|
|
551
|
+
|
|
552
|
+
Both ozone quantities use the O3P files in `gems_o3`; `o3pr` reads the
|
|
553
|
+
provided tropospheric column without reintegrating the profile. Neither
|
|
554
|
+
quantity represents surface ozone concentration.
|
|
555
|
+
|
|
556
|
+
GEMS dates and scan requests use **Asia/Shanghai**. `YYYYMMDDHHMM` selects
|
|
557
|
+
an exact nominal scan; `YYYYMMDD` computes the day's valid-scan mean.
|
|
558
|
+
For example, `202609010845` selects the `20260901_0045` UTC archive scan.
|
|
559
|
+
The filename is the nominal scan time, not a simultaneous observation time
|
|
560
|
+
for every pixel: GEMS scans begin at :45 UTC and take about 30 minutes
|
|
561
|
+
([NESC operation schedule](https://nesc.nier.go.kr/en/html/satellite/operation.do)).
|
|
562
|
+
Missing scan requests report available local times instead of selecting a
|
|
563
|
+
replacement. Duplicate files for one nominal scan are rejected; use a root
|
|
564
|
+
containing one archive version.
|
|
565
|
+
|
|
566
|
+
```bash
|
|
567
|
+
# Exact scan, daily mean, and multi-day mean.
|
|
568
|
+
rsplot raster 安徽 202609011145 --sensor gems -p no2 \
|
|
569
|
+
--basemap none --output /tmp/gems_no2_scan.png
|
|
570
|
+
rsplot raster 安徽 20260901 --sensor gems -p hcho \
|
|
571
|
+
--basemap none --output /tmp/gems_hcho_daily.png
|
|
572
|
+
rsplot raster 安徽 20260901-20260902 --sensor gems -p o3pr \
|
|
573
|
+
--basemap none --output /tmp/gems_o3pr_window.png
|
|
574
|
+
|
|
575
|
+
# Recent daily regional statistics (JSON only).
|
|
576
|
+
rsplot recent 安徽 20260902 --days 2 --source raster --sensor gems -p no2 \
|
|
577
|
+
--output /tmp/gems_no2_recent.json
|
|
578
|
+
|
|
579
|
+
# 11:45 China-time scan with observations at the nearest hour, 12:00.
|
|
580
|
+
rsplot overlay 安徽 202609011145 --sensor gems -p no2 \
|
|
581
|
+
--basemap none --output /tmp/gems_no2_overlay.png
|
|
582
|
+
# Use --station-datetime YYYYMMDDHH for an intentional time override.
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
Each scan is first remapped by pixel/target overlap area in the equal-area
|
|
586
|
+
EPSG:6933 projection, onto a **globally aligned 0.05° analysis grid**. This is
|
|
587
|
+
a numerical analysis spacing, not native satellite resolution. Daily means
|
|
588
|
+
weight valid scans equally at each grid cell; multi-day means then weight
|
|
589
|
+
valid days equally. A daily cell needs at least one valid scan. Window `--n-min`
|
|
590
|
+
continues to count **days**, using the existing product defaults, and is not
|
|
591
|
+
available for a single scan. These are means of available daytime scans,
|
|
592
|
+
not full 24-hour means. Empty scans and failed files do not contribute zeros.
|
|
593
|
+
|
|
594
|
+
For GEMS `raster` and `overlay`, **`--res` controls only the display grid**.
|
|
595
|
+
Display cells receive area-weighted analysis values and are clipped to the
|
|
596
|
+
fixed analysis grid's valid-cell union and the administrative boundary.
|
|
597
|
+
Changing `--res` can change displayed averages, but cannot move the valid
|
|
598
|
+
support or change the scientific statistics. `--smooth` is applied on the
|
|
599
|
+
fixed analysis grid for display only, preserving its valid mask. GEMS
|
|
600
|
+
`recent` uses the same 0.05° analysis spacing and ignores `--res`.
|
|
601
|
+
TROPOMI keeps its existing resolution behavior.
|
|
602
|
+
|
|
603
|
+
When available, GEMS pixel boundaries use file `CornerLongitude` and
|
|
604
|
+
`CornerLatitude` arrays. The checked O3P and NO2 files have centers only;
|
|
605
|
+
their quadrilateral boundaries are **estimates from adjacent unfiltered
|
|
606
|
+
native centers**, with linear extrapolation at the outer scan edge. Missing
|
|
607
|
+
geolocation is not interpolated, and rejected retrievals do not contribute
|
|
608
|
+
values. This is not a recovery of official footprints or extra observations.
|
|
609
|
+
Analysis cells need positive-area overlap with valid footprints; their
|
|
610
|
+
coverage percentage counts valid analysis centers, not precisely observed
|
|
611
|
+
land area. Subcell gaps remain below the 0.05° analysis spacing.
|
|
612
|
+
|
|
613
|
+
Sidecars record `footprint_source` per scan, `spatial_aggregation`,
|
|
614
|
+
`area_crs`, `analysis_resolution_deg`, `display_resolution_deg`, and
|
|
615
|
+
`display_support`. The compatibility `swath.resolution_deg` describes the
|
|
616
|
+
analysis grid. Statistics differ from the previous center-point-binning
|
|
617
|
+
implementation, but remain identical across display resolutions.
|
|
618
|
+
|
|
619
|
+
The initial GEMS filter retains final quality flag **0**, finite coordinates
|
|
620
|
+
and columns, SZA/VZA below 70°, and a nonnegative cloud measure no greater
|
|
621
|
+
than `--cf` (default 0.5). The cloud measures differ: NO2 uses `CloudFraction`,
|
|
622
|
+
HCHO uses `CloudRadianceFraction`, and O3P uses `effective_cloud_fraction`.
|
|
623
|
+
`--qa` applies only to TROPOMI and is rejected for GEMS. Quality-filtered
|
|
624
|
+
negative columns are retained; HCHO gap-filled flag classes are excluded.
|
|
625
|
+
This explicit filter is recorded with each file's version and variable in
|
|
626
|
+
JSON; quality flag meanings must not be transferred between products.
|
|
627
|
+
|
|
628
|
+
GEMS JSON statistics, spatial summaries, and hotspots use the **unfilled,
|
|
629
|
+
unsmoothed** regional grid. Smoothing affects the map only and cannot create
|
|
630
|
+
new valid cells. Sidecars include `sensor`, `quantity`, the requested local
|
|
631
|
+
time, nominal UTC/local scan times, actual observation time ranges, filter
|
|
632
|
+
settings, file failures, and scan-count summaries. Window metadata retains
|
|
633
|
+
per-day diagnostics. Existing TROPOMI fields remain compatible; the boundary
|
|
634
|
+
policy block described above is additive.
|
|
635
|
+
|
|
636
|
+
GEMS `overlay` accepts an exact scan or a daily mean. A daily mean requires
|
|
637
|
+
an explicit `--station-datetime YYYYMMDDHH`; its title and JSON distinguish
|
|
638
|
+
the daily satellite mean from the hourly station observation, without a
|
|
639
|
+
fictitious scan-time offset. Exact scans match the nearest station hour
|
|
640
|
+
(at most 30 minutes, ties forward). A missing station hour is an error.
|
|
641
|
+
`--station-datetime` records a manual override and its time difference.
|
|
642
|
+
NO2 pairs with NO2; O3/O3PR pair with O3; HCHO requires an explicit `--var`.
|
|
643
|
+
Satellite columns and station concentrations retain independent colorbars
|
|
644
|
+
and units; the map shows spatial juxtaposition, not a column-to-surface
|
|
645
|
+
conversion.
|
|
646
|
+
|
|
647
|
+
Run the self-contained GEMS regressions without adding pytest:
|
|
648
|
+
|
|
649
|
+
```bash
|
|
650
|
+
uv run python -m unittest discover -s tests -p 'test_gems.py' -v
|
|
651
|
+
```
|
|
652
|
+
|
|
439
653
|
## License
|
|
440
654
|
|
|
441
655
|
This project is distributed under the license in `LICENSE`.
|