Processing#

easysnowdata.processing#

Pure processing functions (design contract §2.6): xarray in, xarray out, no I/O.

  • masks — Sentinel-2 SCL and HLS Fmask masks, nodata masking

  • optical — baseline harmonization, scale/offset, spectral indices, RGB composites and stretches

  • sar — dB conversion, border-noise removal, slope/aspect and the local incidence angle

  • snow — snow-product class tables, binary snow and the SNODAS flat-file reader

  • wateryear — vectorized water-year helpers

  • categorical — CF flag attributes for categorical products (the contract’s replacement for class_info dicts)

  • contract — the output contract (§2.5): CRS via both accessors, dim names, nodata policy, provenance attrs

add_water_year_coords

Attach water_year and dowy coordinates along dim.

apply_fmask

Mask obj to NaN where Fmask flags are set (fmask defaults to obj["Fmask"]).

binary_snow

Turn a MODIS/VIIRS snow-cover band into a 0/1 snow mask.

apply_scl_mask

Mask obj to NaN where the SCL class is in remove (scl defaults to obj["scl"]).

day_of_water_year

Day of the water year, 1-indexed (1 October = 1 in the northern hemisphere).

db_to_linear

10 ** (x / 10).

decode_udm2

Decode a PlanetScope UDM2 mask into named variables.

evi

Enhanced Vegetation Index 2.5 (nir - red) / (nir + 6 red - 7.5 blue + 1) (reflectance 0–1).

flag_mask

Boolean mask that is True where the array holds any of meanings.

flags

Read CF flag attributes into a DataFrame with value, meaning, color.

fmask_aerosol_level

The aerosol level 0–3 encoded in Fmask bits 6–7.

fmask_bit

The value (0/1) of bit in each Fmask pixel.

fmask_mask

Boolean mask that is True where a pixel is kept.

from_class_info

Convert the legacy {value: {"name": ..., "color": ...}} dict to flag lists.

harmonize_s2_baseline

Undo the post-2022-01-25 Sentinel-2 L2A offset so all dates share one baseline.

linear_to_db

10 log10(x); non-positive values become NaN.

local_incidence_angle

Local incidence angle from a DEM and the ellipsoidal incidence angle.

look_azimuth

Radar look azimuth in degrees from the platform heading.

mask_nodata

Replace the nodata value with NaN (converting integers to float).

ndbi

Normalized Difference Built-up Index as used here: (nir - swir22) / (nir + swir22).

ndsi

Normalized Difference Snow Index (green - swir16) / (green + swir16).

ndvi

Normalized Difference Vegetation Index (nir - red) / (nir + red).

ndwi

Normalized Difference Water Index (McFeeters) (green - nir) / (green + nir).

ndsi_flag_attrs

CF attributes for an NDSI byte: percentages plus the sentinel meanings.

normalized_difference

(a - b) / (a + b) as float, NaN where the index is undefined.

parse_snodas_header

Parse a NOHRSC .txt header into a dict.

remove_border_noise

Mask falsely low backscatter (border noise) in linear-power data.

rgb

Stack three bands into a band-dimensioned float composite.

scale_offset

Apply value * scale + offset and return float data.

scl_mask

Boolean mask that is True where a pixel is kept (its SCL class is not in remove).

set_flags

Attach CF flag attributes to a categorical DataArray.

slope_aspect

Slope and aspect of a projected DEM, by central differences.

stretch_clahe

Contrast Limited Adaptive Histogram Equalization per band (scikit-image).

stretch_percentile

Percentile contrast stretch per band, clipped to 0–1.

udm1_bit

The value (0/1) of one UDM1 bit ("blackfill", "cloud_udm1", …).

water_year

The water year of each time as an integer (calendar year the WY ends in for the north).

water_year_start

The first day of the water year containing each time (same container type as the input).

easysnowdata.processing.categorical#

CF flag attributes for categorical products.

The design contract (§2.5) forbids Python objects in .attrs: a categorical variable carries flag_values (list of ints), flag_meanings (one space-separated string, blanks inside a meaning become underscores) and flag_colors (space-separated hex strings). These helpers write and read that form; easysnowdata.plotting turns it into colormaps and legends.

meaning_key

Normalise a class name to a CF flag_meanings token (blanks → underscores).

easysnowdata.processing.contract#

Output-contract helpers (design contract §2.5), shared by every theme loader.

Pure functions: they rename dimensions, write the CRS with both the rio and odc accessors, mask nodata the way the contract prescribes (categorical keeps the sentinel with rio.nodata set; continuous is NaN-masked with encoded_nodata preserved) and stamp the standard provenance attributes (source, source_url, product_id, data_citation, license, easysnowdata_version). No I/O.

geographic_dims

Rename spatial dims to the contract: latitude/longitude for a geographic CRS, y/x for a projected one.

write_crs

Write crs so that both obj.rio.crs and obj.odc.crs read it.

mask_continuous

NaN-mask a continuous variable and keep the encoded nodata value.

set_categorical_nodata

Keep the source sentinel and record it as rio.nodata (and attrs['nodata']).

provenance

The standard provenance attrs for a catalog product loaded via source.

apply_variables

Apply the catalog Variable definitions present in ds.

finalize

Bring a loaded object onto the output contract.

easysnowdata.processing.masks#

Quality masks: Sentinel-2 SCL classes, HLS Fmask bits, nodata.

easysnowdata.processing.optical#

Optical processing: Sentinel-2 baseline harmonization, scale/offset, spectral indices, RGB composites and contrast stretches. Pure functions.

easysnowdata.processing.sar#

SAR backscatter helpers: dB conversion and Sentinel-1 border-noise removal.

easysnowdata.processing.snow#

Snow-product processing: class tables, binary snow, SNODAS headers.

Pure functions (design contract §2.6). The class tables are the MODIS and VIIRS sentinel values that share a byte with the NDSI percentage, so they are what turns a raw granule into something a user can threshold.

repair_fill_values

Put the upstream 256/265 fill values back to 255 and return uint8.

snodas_members

Group a SNODAS day's tar into {stem: {"dat": ..., "txt": ...}}.

snodas_array

Build a georeferenced DataArray from one SNODAS .dat and its header.

easysnowdata.processing.wateryear#

Vectorized water-year helpers.

This is the single copy of these functions (§12 Q16): the scalar utils.datetime_to_WY/datetime_to_DOWY that used to be applied with pd.Index.map and the global_snow_networks utils/utils.py implementations are both reconciled here. The names wy_start/wy_end from that repo are water_year_bounds(), wy_date_range is water_year_range(), wy_length is water_year_length() and add_wy_coords is add_water_year_coords(); all of them also take a hemisphere, which the originals did not.

A northern-hemisphere water year starts 1 October and is named for the calendar year in which it ends (WY 2021 = 2020-10-01 … 2021-09-30); a southern-hemisphere one starts 1 April and is named for the year it starts. For aggregation prefer the pandas anchored offsets: ds.resample(time="YS-OCT").max(). Day-of-water-year has no pandas primitive, hence day_of_water_year() and add_water_year_coords().

water_year_bounds

First and last day of water year year.

water_year_range

Daily DatetimeIndex spanning water year year (365 or 366 days).

water_year_length

Number of days in water year year — 366 when 29 February falls inside it.