Architecture¶
The zephyr repository serves as extraction engine within the Zephyr ecosystem. For how a request gets here in the first place (frontend → GitHub issue → this pipeline), see The Zephyr Ecosystem and Using the Web Interface.
Repository Structure¶
zephyr/
├── src/zephyr/ # Core Python package
│ ├── process_manager.py # Orchestrates the full extraction workflow
│ ├── file_fetch.py # Locates NetCDF files matching a request
│ ├── fileload.py # Opens files and detects/normalises grid type
│ ├── path_constructor.py # Builds directory paths from query options
│ ├── date_range_selector.py # Filters files by date range
│ ├── nearest_grid_point.py # Nearest-grid-point extraction logic
│ ├── rectangular_clipping.py # Rectangular clipping logic
│ ├── unrotation.py # Rotated-grid -> regular lat/lon conversion
│ ├── transform_lcc.py # LCC -> regular lat/lon conversion
│ ├── add_attributes.py # Adds version attributes to output datasets
│ └── version.py # Package version
├── run/
│ └── launch_zephyr.py # CLI entry point
├── tests/
│ ├── zephyr/ # Unit tests for core extraction logic
│ ├── find_files/ # Tests for file-finding and path logic
│ └── requests/ # Integration tests for each dataset type
├── tools/
│ └── setup.sh # Environment setup script (uv sync + Jupyter kernel)
├── pyproject.toml # Package metadata and dependencies (runtime, test, docs)
└── uv.lock # Pinned, resolved dependency versions
Processing Flow¶
launch_zephyr.py hands off to ProcessManager
(src/zephyr/process_manager.py), which drives the whole pipeline for a
single request:
flowchart TD
A["Read JSON request"] --> B["file_fetch.FileExtractor:<br/>find matching files under /net/atmos/data"]
B --> C["fileload.read_file:<br/>open file, detect grid type"]
C --> D{"Grid type?"}
D -->|"Rotated"| E["unrotation.py"]
D -->|"LCC"| F["transform_lcc.py"]
D -->|"Regular"| G["(no transform)"]
E --> H["extraction_query_options.selected_option"]
F --> H
G --> H
H -->|"nearest_grid_point"| I["nearest_grid_point.py"]
H -->|"rectangular_clipping"| J["rectangular_clipping.py"]
I --> K["add_attributes.py:<br/>zephyr / zephyr-request version, issue ID"]
J --> K
K --> L["Write output NetCDF"]
file_fetch.FileExtractorturnsfiles_query_optionsinto one or more directory paths (viapath_constructor.py’s per-datasetDirectoryPathBuildersubclasses) and, within each, usesdate_range_selector.pyto keep only the files overlapping the requestedstart/end.fileload.read_fileopens each matching file and detects its grid type (regular / rotated / LCC) — see Supported Datasets.Depending on
extraction_query_options.selected_option,process_nearest_gridpoint.pyorprocess_rectangular_clipping.pybuilds the spatial subset (usingnearest_grid_point.py/rectangular_clipping.py, after unrotating or reprojecting the grid if needed).add_attributes.pystamps the output with the zephyr version, and — if provided — thezephyr_request_versionandgithub_issue_idfor traceability back to the originating request.The result is written to
--output_directorywith a filename prefix describing the extraction (see Running an Extraction).