- Home
- Documentation
- API reference
- Readers
- hyperproc.readers.prisma
hyperproc.readers.prisma¶
Source-derived reference
Generated from the current hyperproc 0.1.2 checkout.
Implementation: hyperproc/readers/prisma.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.
PRISMA (ASI) reader for L1 / L2B / L2C / L2D HDF-EOS5 granules.
A Python port of the parts of prismaread <https://github.com/irea-cnr-mi/prismaread>_
(pr_convert) that matter for analysis. Four things about the format catch
people out, and this module handles all of them:
- Cubes are stored band-interleaved, shaped
(rows, bands, cols), not(rows, cols, bands). Reading them naively transposes your image. - Wavelengths run descending in both spectrometers - the first VNIR band is ~977 nm, the last ~407 nm. They are flipped to ascending here.
- Some bands are not acquired at all and carry a centre wavelength of
exactly
0.0, flagged inList_Cw_*_Flags. On this granule that is 3 VNIR and 2 SWIR bands. They are dropped - a 0 nm band is not data. - VNIR and SWIR overlap around 943-977 nm.
join_prioritydecides which spectrometer wins there, matching prismaread's argument of the same name.
DN are stored as uint16 and rescaled per spectrometer. L2 uses a min/max
stretch, L1 a factor and offset::
L2: value = ScaleMin + DN * (ScaleMax - ScaleMin) / 65535
L1: value = DN / ScaleFactor - Offset (W m-2 sr-1 um-1)
L1 ships no per-pixel angles and no elevation. When the L2C (or L2B) file of
the same acquisition sits beside it, its Geometric Fields and its refined
geolocation are borrowed (angles_source="l2", the default); otherwise the
view angles are computed from the satellite ephemeris in the file and the sun
angles are the scene-level values. Elevation is left to
:func:hyperproc.atmos.dem.add_elevation.
Levels differ in geometry, not in cube layout:
======= =================================== ========================== level grid georeferencing ======= =================================== ========================== L1 1000 x 1000 swath, TOA radiance lat/lon arrays L2B 1000 x 1000 swath, surface radiance lat/lon arrays L2C 1000 x 1000 swath, reflectance lat/lon arrays L2D n x m UTM grid, reflectance EPSG + affine transform ======= =================================== ==========================
DN_MAX = 65535.0
module-attribute
¶
LEVEL_SPEC = {'L1': ('radiance', 'W/m^2/sr/um', 'at-sensor radiance'), 'L2B': ('radiance', 'W/m^2/sr/um', 'at-surface radiance'), 'L2C': ('reflectance', '1', 'surface reflectance'), 'L2D': ('reflectance', '1', 'surface reflectance')}
module-attribute
¶
ANGLE_FIELDS = {'sza': 'Solar_Zenith_Angle', 'vza': 'Observing_Angle', 'raa': 'Rel_Azimuth_Angle'}
module-attribute
¶
L2C_MAPS = {'aot': ('AOT', 'AOT_Map'), 'aex': ('AEX', 'AEX_Map'), 'cot': ('COT', 'COT_Map'), 'wvm': ('WVM', 'WVM_Map')}
module-attribute
¶
_GRANULE = re.compile('^PRS_(?P<level>L1|L2B|L2C|L2D)_(?P<type>\\w+?)_(?P<rest>.+)\\.he5$', re.IGNORECASE)
module-attribute
¶
L1_MASKS = {'cloud': ('Cloud_Mask', 'cloud (ASI L1 mask: 1 = cloudy)'), 'sunglint': ('SunGlint_Mask', 'sun glint (ASI L1 mask: 1 = glint)'), 'landcover': ('LandCover_Mask', 'ASI L1 land cover class (0 water, 1 snow, 2 bare, 3 crops, 4 forest, 5 wetland, 6 urban)')}
module-attribute
¶
open_prisma(path: str | Path, cube: str = 'full', join_priority: str = 'swir', wl_range: tuple[float, float] | None = None, good_bands_only: bool = False, angles: bool = True, latlon: bool = False, err_matrix: bool = False, extras: bool = True, angles_source: str = 'l2', geolocation: str = 'l2') -> xr.Dataset
¶
Open a PRISMA granule.
| PARAMETER | DESCRIPTION |
|---|---|
path
|
TYPE:
|
cube
|
TYPE:
|
join_priority
|
which spectrometer wins in the ~943-977 nm overlap when
TYPE:
|
wl_range
|
TYPE:
|
good_bands_only
|
not supported - ASI ships no per-band quality flag.
Raises, with a pointer to
TYPE:
|
angles
|
attach per-pixel
TYPE:
|
latlon
|
attach the per-pixel
TYPE:
|
err_matrix
|
attach the per-band pixel error matrix, band-aligned with
the cube (same subset, order and overlap resolution), lazy uint8:
TYPE:
|
extras
|
for L2C, attach the AOT / AEX / COT / WVM maps.
TYPE:
|
angles_source
|
L1 only.
TYPE:
|
geolocation
|
L1 only.
TYPE:
|
| RETURNS | DESCRIPTION |
|---|---|
Dataset
|
Dataset with |
Dataset
|
|
Source code in hyperproc/readers/prisma.py
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 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 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 | |
_read_arm(f, swath: str, arm: str, err: bool = False)
¶
Read one spectrometer: rescale, drop unacquired bands, fix axis order.
Returns (data, wavelength, fwhm, arm_label, band_index, err) where
err is the lazily read error matrix with the same band selection, or
None. Every later selection (overlap, sort, wl_range) goes through
:func:_take so the six stay aligned.
Source code in hyperproc/readers/prisma.py
_take(part, k)
¶
Apply one band selection (mask or index array) to every element of a part.
Source code in hyperproc/readers/prisma.py
_resolve_overlap(parts, priority: str)
¶
Drop the losing spectrometer's bands in the wavelength range both cover.
Source code in hyperproc/readers/prisma.py
_dec(v)
¶
_scene_attrs(f, path: Path, level: str, units: str, cube: str, join: str) -> dict
¶
Source code in hyperproc/readers/prisma.py
_fill_mask(f, swath: str) -> np.ndarray | None
¶
(y, x) True where L2D padding sits outside the acquired swath.
_add_grid(ds: xr.Dataset, f, level: str, swath: str, latlon: bool, fill: np.ndarray | None = None) -> None
¶
L2D gets a UTM affine grid; the swath levels get lat/lon arrays.
Source code in hyperproc/readers/prisma.py
_add_angles(ds: xr.Dataset, f, swath: str, fill: np.ndarray | None = None) -> None
¶
Source code in hyperproc/readers/prisma.py
_add_l1_masks(ds: xr.Dataset, f, swath: str) -> None
¶
Source code in hyperproc/readers/prisma.py
_l2_sibling(path: Path, rest: str) -> Path | None
¶
The L2C (else L2B) file of the same acquisition beside an L1 file.
Source code in hyperproc/readers/prisma.py
_borrow_geolocation(ds: xr.Dataset, sib: Path) -> None
¶
Source code in hyperproc/readers/prisma.py
_add_l1_geometry(ds: xr.Dataset, f, sib: Path | None) -> None
¶
Per-pixel angles for L1: from the L2 sibling when given, else ephemeris + scene sun angles.
Source code in hyperproc/readers/prisma.py
_view_from_ephemeris(f, ds: xr.Dataset)
¶
View zenith/azimuth per pixel from the WGS-84 satellite positions in the file.
Line times are spread linearly between the product start and stop times; the ephemeris (GPS seconds of day, 18 s ahead of UTC) is interpolated to them; the ground point is the pixel's lat/lon at sea level (elevation changes the angles by hundredths of a degree at 615 km).
Source code in hyperproc/readers/prisma.py
_add_l2c_maps(ds: xr.Dataset, f) -> None
¶
AOT / Angstrom exponent / cloud optical thickness / water vapour.