weac.parser package

Subpackages

Submodules

Module contents

Parsers that convert field-profile formats into WEAC layers.

class weac.parser.SMPParser(file_path, *, density_method='P2015', surface_mm=None, surface_method='snowmicropyn', apply_drift_correction=False)[source]

Bases: object

Parser for SMP .PNT files using snowmicropyn.

Parameters:
  • file_path (str)

  • density_method (Literal['P2015', 'CR2020', 'K2020a', 'K2020b'])

  • surface_mm (float | None)

  • surface_method (Literal['snowmicropyn', 'knappe', 'manual'])

  • apply_drift_correction (bool)

__init__(file_path, *, density_method='P2015', surface_mm=None, surface_method='snowmicropyn', apply_drift_correction=False)[source]

Load a .PNT file and mark surface and ground.

Parameters:
  • file_path (str) – Path to the SMP .PNT file.

  • density_method (Literal['P2015', 'CR2020', 'K2020a', 'K2020b']) – Default parameterization for extract_profile().

  • surface_mm (float | None) – Manual surface marker, mm along the probe. When set, the surface is placed here and surface_method is recorded as "manual". Required when surface_method is "manual".

  • surface_method (Literal['snowmicropyn', 'knappe', 'manual']) – "snowmicropyn" calls snowmicropyn.Profile.detect_surface(). "knappe" uses detect_knappe_surface(). "manual" places the surface at surface_mm.

  • apply_drift_correction (bool) – Subtract snowmicropyn’s force offset after the surface marker is set.

file_path: str
density_method: Literal['P2015', 'CR2020', 'K2020a', 'K2020b']
surface_method: Literal['snowmicropyn', 'knappe', 'manual']
loaded_profile: Profile
extract_profile(*, density_method=None)[source]

Return the windowed penetration resistance/density/SSA profile for one parameterization.

Runs the Löwe 2012 shot-noise model plus the selected parameterization on the cropped snowpack and returns a fresh SMPProfile each call (no caching). density_method=None uses the constructor default; surface and ground markers are set once at construction and reused here.

Parameters:

density_method (Literal['P2015', 'CR2020', 'K2020a', 'K2020b'] | None)

Return type:

SMPProfile

extract_layers(*, method='bin', density_method=None, layer_thickness_mm=None, gradient_threshold=12.0)[source]

Segment the SMP density profile into WEAC slab layers (top-down).

The SnowMicroPen is driven normal to the slope, so depth_mm is already a slope-normal depth and is used directly as WEAC Layer.h. Plumb profiles (SnowScope, SnowPilot) still scale by cos(phi); SMP does not.

Parameters:
  • method (Literal['bin', 'gradient']) – Layering mode. "bin" groups at a fixed thickness (or the native spacing); "gradient" cuts where the density gradient over a fixed 2.5 mm span exceeds gradient_threshold.

  • density_method (Literal['P2015', 'CR2020', 'K2020a', 'K2020b'] | None) – Optional parameterization override for this call only (constructor default is unchanged).

  • layer_thickness_mm (float | None) – Bin mode only; None groups at native Loewe spacing with a 1 mm floor, a value groups samples into ~that thickness. Ignored in gradient mode.

  • gradient_threshold (float) – Gradient mode only; cut threshold T in kg/m^3/mm over the 2.5 mm span. Default 12.

Returns:

(layers, density_methods) with layers ordered surface -> ground and density_methods = [parameterization] * len(layers).

Return type:

tuple[list[Layer], list[str]]

class weac.parser.SMPProfile(coordinates, depth_mm, penetration_resistance_kPa, density_kg_m3, ssa_m2_kg, density_method)[source]

Bases: object

Windowed SMP penetration resistance, density, and SSA cropped to the snowpack.

Parameters:
  • coordinates (tuple[float, float] | None)

  • depth_mm (ndarray)

  • penetration_resistance_kPa (ndarray)

  • density_kg_m3 (ndarray)

  • ssa_m2_kg (ndarray)

  • density_method (Literal['P2015', 'CR2020', 'K2020a', 'K2020b'])

coordinates: tuple[float, float] | None
depth_mm: ndarray
penetration_resistance_kPa: ndarray
density_kg_m3: ndarray
ssa_m2_kg: ndarray
density_method: Literal['P2015', 'CR2020', 'K2020a', 'K2020b']
__init__(coordinates, depth_mm, penetration_resistance_kPa, density_kg_m3, ssa_m2_kg, density_method)
Parameters:
  • coordinates (tuple[float, float] | None)

  • depth_mm (ndarray)

  • penetration_resistance_kPa (ndarray)

  • density_kg_m3 (ndarray)

  • ssa_m2_kg (ndarray)

  • density_method (Literal['P2015', 'CR2020', 'K2020a', 'K2020b'])

Return type:

None

class weac.parser.SnowPilotParser(file_path)[source]

Bases: object

Parser for SnowPilot files using the snowpylot library.

Parameters:

file_path (str)

__init__(file_path)[source]
Parameters:

file_path (str)

pit_slope_angle_deg()[source]

Slope angle from CAAML validSlopeAngle if present, else None.

Return type:

float | None

extract_layers(slope_angle_deg=0.0)[source]

Extract layers from snowpit.

Depths and thicknesses in CAAML are measured along the vertical. For WEAC, pass the same slope angle (degrees from horizontal) as ScenarioConfig.phi; thicknesses and matching depths are scaled to slope-normal by cos(phi). The default 0 leaves depths unchanged (vertical equals slope-normal on flat terrain). To use the angle stored in the pit file, pass slope_angle_deg=parser.pit_slope_angle_deg() or 0.0.

Parameters:

slope_angle_deg (float)

Return type:

tuple[list[Layer], list[str]]

get_density_for_layer_range(layer_top_mm, layer_bottom_mm, sp_density_layers, *, depth_scale=1.0)[source]

Public wrapper for _get_density_for_layer_range().

Parameters:
  • layer_top_mm (float)

  • layer_bottom_mm (float)

  • sp_density_layers (list[DensityObs])

  • depth_scale (float)

Return type:

float | None

class weac.parser.SnowScopeParser(file_path, *, density_method='HAGENMULLER2018', semilog_slope=None, semilog_intercept=None)[source]

Bases: object

Parser for SnowScope CSV files.

Parameters:
  • file_path (str)

  • density_method (DensityMethod)

  • semilog_slope (float | None)

  • semilog_intercept (float | None)

__init__(file_path, *, density_method='HAGENMULLER2018', semilog_slope=None, semilog_intercept=None)[source]
Parameters:
  • file_path (str)

  • density_method (Literal['HAGENMULLER2018'])

  • semilog_slope (float | None)

  • semilog_intercept (float | None)

extract_profile(*, density_method=None, semilog_slope=None, semilog_intercept=None)[source]

Return depth, penetration resistance, and density for one parameterization.

Converts penetration resistance (kPa) to density (kg/m³) via the semilog model D = a ln(F) + b, clipping sub-1 kg/m³ values.

Coefficients are chosen in order: call-level semilog_slope / semilog_intercept, then call-level density_method, then constructor custom semilog (if set), else the constructor density_method preset.

Parameters:
  • density_method (Literal['HAGENMULLER2018'] | None)

  • semilog_slope (float | None)

  • semilog_intercept (float | None)

Return type:

SnowScopeProfile

extract_layers(slope_angle_deg=0.0, *, method='bin', density_method=None, semilog_slope=None, semilog_intercept=None, layer_thickness_mm=None, gradient_threshold=12.0)[source]

Segment the SnowScope density profile into WEAC slab layers (top-down).

The SnowScope probe descends along the global vertical, so depth_mm is a plumb depth while WEAC Layer.h is slope-normal. As in the SnowPilot parser, thicknesses are converted plumb -> slope-normal by cos(phi) via plumb_to_slope_normal(). The SnowScope file records no slope, so slope_angle_deg defaults to 0 (no scaling); scale only when the angle is known (pass it explicitly).

Parameters:
  • slope_angle_deg (float) – Slope angle [deg from horizontal]. 0 leaves h as recorded; non-zero scales h by cos(phi).

  • method (Literal['bin', 'gradient']) – Layering mode. "bin" groups at a fixed thickness (or the native spacing); "gradient" cuts where the density gradient over a fixed 2.5 mm span exceeds gradient_threshold.

  • density_method (Literal['HAGENMULLER2018'] | None) – Optional preset override for this call only.

  • semilog_slope (float | None) – Optional semilog slope a in D = a ln(F) + b for this call; must be paired with semilog_intercept.

  • semilog_intercept (float | None) – Optional semilog intercept b; must be paired with semilog_slope. Takes precedence over density_method.

  • layer_thickness_mm (float | None) – Bin mode only; None groups at native sample spacing with a 1 mm floor, a value groups samples into ~that thickness. Ignored in gradient mode.

  • gradient_threshold (float) – Gradient mode only; cut threshold T in kg/m^3/mm over the 2.5 mm span. Default 12.

Returns:

(layers, density_methods) with layers ordered surface -> ground and density_methods = [parameterization] * len(layers).

Return type:

tuple[list[Layer], list[str]]

class weac.parser.SnowScopeProfile(depth_mm, penetration_resistance_kPa, density_kg_m3, density_method)[source]

Bases: object

Aligned SnowScope penetration resistance and derived density.

Parameters:
  • depth_mm (ndarray)

  • penetration_resistance_kPa (ndarray)

  • density_kg_m3 (ndarray)

  • density_method (Literal['HAGENMULLER2018', 'CUSTOM'])

depth_mm: ndarray
penetration_resistance_kPa: ndarray
density_kg_m3: ndarray
density_method: Literal['HAGENMULLER2018', 'CUSTOM']
__init__(depth_mm, penetration_resistance_kPa, density_kg_m3, density_method)
Parameters:
  • depth_mm (ndarray)

  • penetration_resistance_kPa (ndarray)

  • density_kg_m3 (ndarray)

  • density_method (Literal['HAGENMULLER2018', 'CUSTOM'])

Return type:

None