- Home
- Documentation
- API reference
- Atmosphere
- hyperproc.atmos.inputs
hyperproc.atmos.inputs¶
Source-derived reference
Generated from the current hyperproc 0.1.2 checkout.
Implementation: hyperproc/atmos/inputs.py. Signatures, defaults, docstrings, and expandable source are extracted statically; the module is not imported or executed. Names beginning with _ are implementation details, not a stable public API.
Use the function signature as the authority for individual parameter defaults and return annotations. Original docstrings sometimes group parameter names or wrap return descriptions across lines; these descriptions are preserved rather than inferred or rewritten.
Turn a hyperproc L1B dataset into the three ENVI files ISOFIT reads.
isofit apply_oe wants, for one scene:
<fid>_rdn
at-sensor radiance in µW cm⁻² nm⁻¹ sr⁻¹, band-interleaved-by-line float32,
with wavelength and fwhm (nm) in the header;
<fid>_loc
three float64 bands: longitude, latitude (WGS-84 degrees), elevation (m);
<fid>_obs
eleven float64 bands in JPL's order: path length (m), to-sensor azimuth
and zenith, to-sun azimuth and zenith (degrees), solar phase, slope,
aspect, cos(i), UTC time (decimal hours), Earth-sun distance (AU).
The file id fid is not free: apply_oe slices it from the radiance
file name and parses the acquisition time out of it with a per-sensor
pattern, so :data:SENSORS carries that pattern for every hyperproc sensor
together with the radiance unit factor and the apply_oe sensor code.
Every hyperproc reader already exposes the ingredients as dataset layers
(sza, saa, vza, vaa, slope, aspect, cos_i, elev, lat, lon and, for the
JPL products, path_length, utc_time, solar_phase), so the writer here is
mostly bookkeeping: unit scaling, NaN to -9999, and streaming the cube out in
row blocks so a full granule never sits in memory.
SENSORS: dict[str, SensorSpec] = {'EMIT': SensorSpec('emit', 1.0, 'emit%Y%m%dt%H%M%S', altitude_km=420.0, tested=True), 'AVIRIS-3': SensorSpec('av3', 1.0, 'AV3%Y%m%dt%H%M%S', id_pattern='^AV3\\d{8}t\\d{6}', tested=True), 'AVIRIS-5': SensorSpec('av5', 1.0, 'AV5%Y%m%dt%H%M%S', id_pattern='^AV5\\d{8}t\\d{6}', tested=True), 'AVIRIS-NG': SensorSpec('ang', 1.0, 'ang%Y%m%dt%H%M%S', id_pattern='^ang\\d{8}t\\d{6}', tested=True), 'AVIRIS-CLASSIC': SensorSpec('avcl', 1.0, 'f%y%m%dt01p00r01', id_pattern='^f\\d{6}t\\d{2}p\\d{2}r\\d{2}', tested=True), 'NEON': SensorSpec('neon', 1.0, 'NIS01_%Y%m%d_%H%M%S'), 'ENMAP': SensorSpec('enmap', 100.0, '%Y%m%dt%H%M%S', rdn='ENMAP_L1B_hyperproc_0_0_{fid}_rdn', altitude_km=653.0, tested=True), 'PRISMA': SensorSpec('prisma', 0.1, '%Y%m%d%H%M%S', rdn='PRS_{fid}_rdn', altitude_km=615.0, tested=True, inversion_windows=((400.0, 1340.0), (1450.0, 1800.0), (1970.0, 2470.0))), 'TANAGER': SensorSpec('tanager', 0.1, '%Y%m%d_%H%M%S_tanager', altitude_km=500.0, tested=True), 'PACE': SensorSpec('oci', 1.0, 'PACE_OCI.%Y%m%dT%H%M%S', altitude_km=676.5, converter='pace_rhot', band_grid='oci_rsr', tested=True), 'DESIS': SensorSpec('NA', 1.0, 'desis%Y%m%dt%H%M%S', rdn='{fid}', altitude_km=400.0, tested=True)}
module-attribute
¶
FILL = -9999.0
module-attribute
¶
RT_RANGE = (350.0, 2500.0)
module-attribute
¶
OBS_BANDS = ('Path length (m)', 'To-sensor azimuth (0 to 360 degrees cw from N)', 'To-sensor zenith (0 to 90 degrees from zenith)', 'To-sun azimuth (0 to 360 degrees cw from N)', 'To-sun zenith (0 to 90 degrees from zenith)', 'Solar phase', 'Slope', 'Aspect', 'Cosine(i)', 'UTC Time', 'Earth-sun distance (AU)')
module-attribute
¶
LOC_BANDS = ('Longitude (WGS-84)', 'Latitude (WGS-84)', 'Elevation (m)')
module-attribute
¶
_ENVI_DTYPE = {'float32': 4, 'float64': 5, 'int16': 2, 'int32': 3, 'uint8': 1}
module-attribute
¶
_ALIASES = {'AVIRIS3': 'AVIRIS-3', 'AVIRIS5': 'AVIRIS-5', 'AVIRIS': 'AVIRIS-3', 'AVIRISNG': 'AVIRIS-NG', 'AVIRISCLASSIC': 'AVIRIS-CLASSIC'}
module-attribute
¶
BAND_GRIDS = {'oci_rsr': oci_rsr_bands}
module-attribute
¶
CONVERTERS = {'pace_rhot': pace_rhot_scales}
module-attribute
¶
SensorSpec
dataclass
¶
How one hyperproc sensor maps onto apply_oe.
| ATTRIBUTE | DESCRIPTION |
|---|---|
code |
the
TYPE:
|
unit_factor |
multiply hyperproc radiance by this to get µW cm⁻² nm⁻¹ sr⁻¹. None means the conversion needs more than a factor and is not implemented yet.
TYPE:
|
fid |
TYPE:
|
rdn |
pattern of the radiance file name, so ISOFIT's slicing of the
name yields exactly
TYPE:
|
altitude_km |
nominal platform altitude, used only when the product carries no path-length layer.
TYPE:
|
tested |
whether this route has been run through ISOFIT on a real granule and the reflectance compared against the provider's own product. A False entry only warns; it changes nothing else.
TYPE:
|
Source code in hyperproc/atmos/inputs.py
code: str
instance-attribute
¶
unit_factor: float | None
instance-attribute
¶
fid: str
instance-attribute
¶
rdn: str = '{fid}_rdn'
class-attribute
instance-attribute
¶
altitude_km: float | None = None
class-attribute
instance-attribute
¶
tested: bool = False
class-attribute
instance-attribute
¶
converter: str | None = None
class-attribute
instance-attribute
¶
id_pattern: str | None = None
class-attribute
instance-attribute
¶
inversion_windows: tuple | None = None
class-attribute
instance-attribute
¶
band_grid: str | None = None
class-attribute
instance-attribute
¶
__init__(code: str, unit_factor: float | None, fid: str, rdn: str = '{fid}_rdn', altitude_km: float | None = None, tested: bool = False, converter: str | None = None, id_pattern: str | None = None, inversion_windows: tuple | None = None, band_grid: str | None = None) -> None
¶
Inputs
dataclass
¶
What :func:prepare_inputs wrote, and what the ISOFIT run needs to know.
Source code in hyperproc/atmos/inputs.py
work_dir: str
instance-attribute
¶
sensor: str
instance-attribute
¶
code: str
instance-attribute
¶
fid: str
instance-attribute
¶
rdn: str
instance-attribute
¶
loc: str
instance-attribute
¶
obs: str
instance-attribute
¶
wavelengths: str
instance-attribute
¶
shape: tuple
instance-attribute
¶
unit_factor: float
instance-attribute
¶
datetime: str
instance-attribute
¶
stem: str
instance-attribute
¶
granule: str
instance-attribute
¶
window: dict | None = None
class-attribute
instance-attribute
¶
bands: list | None = None
class-attribute
instance-attribute
¶
stats: dict = field(default_factory=dict)
class-attribute
instance-attribute
¶
json: Path
property
¶
__init__(work_dir: str, sensor: str, code: str, fid: str, rdn: str, loc: str, obs: str, wavelengths: str, shape: tuple, unit_factor: float, datetime: str, stem: str, granule: str, window: dict | None = None, bands: list | None = None, stats: dict = dict()) -> None
¶
subset(ds)
¶
Apply this run's window and band selection to a dataset.
output(product: str) -> Path
¶
Path of an apply_oe product (rfl, uncert, lbl,
state, h2o, atm_interp, subs_state ...), named the way
ISOFIT names them from the radiance file.
Source code in hyperproc/atmos/inputs.py
save() -> Path
¶
load(work_dir: str | Path) -> 'Inputs'
classmethod
¶
Read <work_dir>/input/inputs.json, rebased onto work_dir.
The file stores absolute paths, so a work directory that was moved or copied would otherwise point every read back at the original and two different runs would silently return the same products.
Source code in hyperproc/atmos/inputs.py
describe() -> str
¶
Source code in hyperproc/atmos/inputs.py
sensor_spec(ds: xr.Dataset) -> tuple[str, SensorSpec]
¶
The :data:SENSORS entry for ds, keyed by its sensor attr.
Source code in hyperproc/atmos/inputs.py
acquisition_time(ds: xr.Dataset) -> datetime
¶
UTC acquisition time from attrs["datetime"].
Source code in hyperproc/atmos/inputs.py
names_for(ds: xr.Dataset) -> tuple[str, str, str]
¶
(sensor_code, fid, radiance_file_name) for ds.
Source code in hyperproc/atmos/inputs.py
hdr_path(binary: Path | str) -> Path
¶
The ENVI header beside a binary: <file>.hdr.
Not Path.with_suffix(".hdr"): a PACE file id carries a dot
(PACE_OCI.20260422T195047_rdn), so that would write PACE_OCI.hdr
and ISOFIT would not find a header at all.
Source code in hyperproc/atmos/inputs.py
write_envi_header(path: Path, lines: int, samples: int, bands: int, dtype: str, description: str = '', band_names=None, wavelength=None, fwhm=None, extra: dict | None = None) -> Path
¶
Write path (the .hdr) for a BIL cube, little-endian.
Source code in hyperproc/atmos/inputs.py
_row_blocks(da: xr.DataArray, target_bytes: int = 256 * 2 ** 20)
¶
Row ranges that follow the dask chunking of da where it has one.
Source code in hyperproc/atmos/inputs.py
_write_cube(da: xr.DataArray, path: Path, factor: float, verbose: bool, band_scale: np.ndarray | None = None, pixel_scale: np.ndarray | None = None) -> None
¶
Stream da (y, x, wavelength) to path as BIL float32, NaN -> FILL.
band_scale (wavelength,) and pixel_scale (y, x) multiply in as
well; they turn a TOA reflectance into radiance without a second pass.
Source code in hyperproc/atmos/inputs.py
_write_layers(arrs: list[np.ndarray], path: Path) -> None
¶
Write 2-D float64 layers as a BIL cube, NaN -> FILL.
Source code in hyperproc/atmos/inputs.py
_layer(ds: xr.Dataset, name: str) -> np.ndarray | None
¶
_latlon(ds: xr.Dataset) -> tuple[np.ndarray, np.ndarray]
¶
Source code in hyperproc/atmos/inputs.py
_phase(sza, vza, saa, vaa)
¶
_earth_sun_au(dt: datetime) -> float
¶
assemble_obs(ds: xr.Dataset, spec: SensorSpec, dt: datetime) -> list[np.ndarray]
¶
The eleven obs layers, float64, NaN where unknown.
Source code in hyperproc/atmos/inputs.py
assemble_loc(ds: xr.Dataset) -> list[np.ndarray]
¶
Longitude, latitude, elevation layers, float64.
Source code in hyperproc/atmos/inputs.py
_apply_window(ds: xr.Dataset, window)
¶
Source code in hyperproc/atmos/inputs.py
_stats(obs: list[np.ndarray], loc: list[np.ndarray], rdn_first: np.ndarray) -> dict
¶
Source code in hyperproc/atmos/inputs.py
oci_rsr_bands() -> np.ndarray
¶
Band centres (nm) of the OCI response functions ISOFIT resamples with.
For the oci sensor ISOFIT replaces its Gaussian resampling with the
measured response functions in data/oci/pace_oci_rsr.nc, whose 270
bands are its own idea of the instrument. Handing it a different band
count makes the look-up table and the instrument model disagree
("conflicting sizes for dimension 'wl'"), so the inputs are written on
this grid.
Source code in hyperproc/atmos/inputs.py
match_bands(wl: np.ndarray, grid: np.ndarray, tol: float = 2.0) -> list
¶
Positions in wl nearest to each wavelength of grid.
Raises when a grid band has no match within tol nm or two grid bands
claim the same one, which would mean the product is not the instrument
the grid describes.
Source code in hyperproc/atmos/inputs.py
pace_rhot_scales(ds: xr.Dataset)
¶
Per-band and per-pixel factors turning OCI rhot into µW cm-2 nm-1 sr-1.
The L1B stores rhot = Lt * pi * d2 / (F0 * cos(sza)) with F0 in
W m-2 um-1 per band and d2 (earth_sun_distance_correction) as a
global attribute; band_index says which F0 each band of the sorted
cube came from. So Lt = rhot * F0 * cos(sza) / (pi * d2) * 0.1.
Source code in hyperproc/atmos/inputs.py
prepare_inputs(ds: xr.Dataset, work_dir: str | Path, window=None, overwrite: bool = False, verbose: bool = True, dem: bool = True) -> Inputs
¶
Write the _rdn, _loc and _obs files for ds under work_dir/input.
| PARAMETER | DESCRIPTION |
|---|---|
ds
|
a hyperproc L1B radiance dataset (any sensor in :data:
TYPE:
|
work_dir
|
the ISOFIT working directory;
TYPE:
|
window
|
optional subset,
DEFAULT:
|
overwrite
|
rewrite files that already exist with the right shape.
TYPE:
|
dem
|
when the dataset has no
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Inputs
|
class: |
Inputs
|
and summary statistics of the geometry. Also saved as |
Inputs
|
|
Source code in hyperproc/atmos/inputs.py
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 | |