Source code for snowprofile.profiles

# -*- coding: utf-8 -*-

import typing

import pydantic

from snowprofile._base_classes import BaseProfile, BaseProfile2
from snowprofile._constants import QUALITY_FLAGS, GRAIN_SHAPES, MANUAL_WETNESS, MANUAL_HARDNESS, \
    manual_wetness_attribution, manual_hardness_attribution

__all__ = ['Stratigraphy',
           'TemperatureProfile', 'DensityProfile', 'LWCProfile',
           'SSAProfile', 'SSAPointProfile',
           'HardnessProfile', 'HardnessPointProfile',
           'StrengthProfile', 'ImpurityProfile',
           'ScalarProfile', 'VectorialProfile']


[docs] class Stratigraphy(BaseProfile): """ Measurements of the snowpack stratigraphy, according to the international snowpack classification, Fierz et al. 2009. The ``data`` key contains: - ``top_height``: Top height of the snow layer (m) - ``bottom_height``: Bottom height of the snow layer (m) - ``thickness``: Thickness of the snow layer (m) - ``grain_1``: Primary snow grain shape - ``grain_2``: Secondary snow grain shape - ``grain_size``: Snow grain size (m) - ``grain_size_max``: Maximum snow grain size (m) - ``hardness``: Manual hand hardness (intermediates are allowed, details in Fierz et al., 2009): - F: Fist (1) - 4F : 4 Fingers (2) - 1F : 1 Finger (3) - P : Pencil (4) - K : Knife (5) - ``wetness``: Manual snow wetness (intermediates are allowed, details in Fierz et al., 2009): - D : Dry (1) - M : Moist (2) - W : Wet (3) - V : Very wet (4) - S : Soaked (5) - ``formation_time``: Date of the layer formation - ``formation_period_begin``: Date of the begining of the layer formation - ``formation_period_end``: Date of the end of the layer formation - ``loc``: Layer of concern, possible values are 'no', 'top', 'bottom', 'all', 'true', 'false' - ``comment``: Comment on the layer - ``uncertainty``: Quantitative uncertainty on the layer (see :ref:`uncertainty`) - ``quality``: Quality flag on the layer (see :ref:`uncertainty`) """ _data_config = dict( grain_1=dict(type='O', values=GRAIN_SHAPES + [None]), grain_2=dict(type='O', values=GRAIN_SHAPES + [None]), grain_size=dict(min=0, nan_allowed=True), grain_size_max=dict(min=0, optional=True, nan_allowed=True), hardness=dict(type='O', values=MANUAL_HARDNESS + [None], translate=manual_hardness_attribution, ), wetness=dict(type='O', values=MANUAL_WETNESS + [None], translate=manual_wetness_attribution, ), loc=dict(type='O', optional=True, values=['no', 'top', 'bottom', 'all', 'true', 'false', None]), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), comment=dict(optional=True, type='O', ), additional_data=dict(optional=True, type='O', ), formation_time=dict(optional=True, type='O'), formation_period_begin=dict(optional=True, type='O'), formation_period_end=dict(optional=True, type='O'), )
[docs] class TemperatureProfile(BaseProfile2): """ Vertical profile of temperature profile. The ``data`` key contains: - ``height``: Height of the temperature measurement (m) - ``temperature``: Temperature value (°C) - ``uncertainty``: Quantitative uncertainty of the point measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the point measurement. See :ref:`uncertainty` for details. """ method_of_measurement: typing.Optional[typing.Literal[ "Thermometer", "IR thermometer", "IR photography", "other"]] = None _data_config = dict( _mode='Point', temperature=dict(max=0), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), )
[docs] class DensityProfile(BaseProfile2): """ Vertical profile of density (kg/m3). The ``data`` key contains: - ``top_height``: Top height of the measurement (m) - ``bottom_height``: Bottom height of the measurement (m) - ``thickness``: Thickness (m) - ``density``: Density value (kg/m3) - ``uncertainty``: Quantitative uncertainty of the point measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the point measurement. See :ref:`uncertainty` for details. """ method_of_measurement: typing.Optional[typing.Literal[ "Snow Tube", "Snow Cylinder", "Snow Cutter", "Snow wedge Cutter", "other gravimetric measurement method", "Denoth Probe", "SnowPro Probe", "Snow Fork", "other dielectric permittivity method", "Tomography", "SMP", "Neutron scattering probe", "other"]] = pydantic.Field( None, description="Measurement method") probed_volume: typing.Optional[float] = pydantic.Field( None, description="Probe volume (m3)") probed_diameter: typing.Optional[float] = pydantic.Field( None, description="Probe diameter (m)") probed_length: typing.Optional[float] = pydantic.Field( None, description="Probe length (m)") probed_thickness: typing.Optional[float] = pydantic.Field( None, description="Probe thickness (vertical dimension, m)") _data_config = dict( density=dict(min=0, max=917), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), )
[docs] class LWCProfile(BaseProfile2): """ Vertical profile of LWC (Liquid water content, % by volume). The ``data`` key contains: - ``top_height``: Top height of the measurement (m) - ``bottom_height``: Bottom height of the measurement (m) - ``thickness``: Thickness (m) - ``lwc``: Liqud water content (% vol.) - ``uncertainty``: Quantitative uncertainty of the measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the measurement. See :ref:`uncertainty` for details. """ method_of_measurement: typing.Optional[typing.Literal[ "Denoth Probe", "Snow Fork", "SnowPro Probe", "WISe", "other dielectric permittivity method", "MRI", "other"]] = pydantic.Field( None, description="Measurement method") probed_thickness: typing.Optional[float] = pydantic.Field( None, description="Probe thickness (vertical dimension of measurement, m)") _data_config = dict( lwc=dict(min=0, max=100), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), )
class _SSAProfile(BaseProfile2): """ Vertical profile of SSA (Specific surface area, m2/kg). Base class for SSA, whether the profile is a point profile or a layer profile. """ method_of_measurement: typing.Optional[typing.Literal[ "Ice Cube", "IRIS", "InfraSnow", "DUFFISSS-1310", "DUFFISSS-1550", "HISSGraS", "ASSSAP", "other IR integrating sphere", "SWIRcam", "SnowImager", "other NIR method", "Tomography", "SMP", "other"]] = pydantic.Field( None, description="Measurement method") probed_thickness: typing.Optional[float] = pydantic.Field( None, description="Probe thickness (vertical dimension of measurement, m)")
[docs] class SSAProfile(_SSAProfile): """ Vertical profile of SSA (Specific surface area, m2/kg), measured on layers (volume). The ``data`` key contains: - ``top_height``: Top height of the measurement (m) - ``bottom_height``: Bottom height of the measurement (m) - ``thickness``: Thickness (m) - ``ssa``: SSA value (m2/kg) - ``uncertainty``: Quantitative uncertainty of the measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the measurement. See :ref:`uncertainty` for details. """ _data_config = dict( ssa=dict(min=0), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), ) type: typing.Literal['SSAProfile'] = 'SSAProfile'
[docs] class SSAPointProfile(_SSAProfile): """ Vertical profile of SSA (Specific Surface Area), measured at points (heights). The ``data`` key contains: - ``height``: Height of the measurement (m) - ``ssa``: SSA value (m2/kg) - ``uncertainty``: Quantitative uncertainty of the measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the measurement. See :ref:`uncertainty` for details. """ _data_config = dict( _mode='Point', ssa=dict(min=0), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), ) type: typing.Literal['SSAPointProfile'] = 'SSAPointProfile'
class _HardnessProfile(BaseProfile2): """ Vertical profile of hardness (N). Base class for both RAMSONDE profile or simple hardness profile from other source. """ method_of_measurement: typing.Optional[typing.Literal[ "SnowMicroPen", "Ram Sonde", "Push-Pull Gauge", "Avatech SP1", "Avatech SP2", "Scope propagation labs", "other automatic penetrometer", "other"]] = pydantic.Field( None, description="Measurement method") surface_of_indentation: typing.Optional[float] = pydantic.Field( None, description='Indentation surface of the measurement tool (m2)') penetration_speed: typing.Optional[float] = pydantic.Field( None, description='Penetration speed (m/s)')
[docs] class HardnessPointProfile(_HardnessProfile): """ Vertical profile of hardness. The ``data`` key contains: - ``height``: Height of the measurement (m) - ``hardness``: Hardness value (N) - ``uncertainty``: Quantitative uncertainty of the measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the measurement. See :ref:`uncertainty` for details. """ _data_config = dict( _mode='Point', hardness=dict(min=0), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), ) type: typing.Literal['HardnessPointProfile'] = 'HardnessPointProfile'
[docs] class HardnessProfile(_HardnessProfile): """ Vertical profile of hardness profile, measured on snow layers (e.g. for RamSonde measurements). The ``data`` key contains: - ``top_height``: Top height of the measurement (m) - ``bottom_height``: Bottom height of the measurement (m) - ``thickness``: Thickness (m) - ``hardness`` (N): Hardness value (N) - ``weight_hammer`` (kg) - ``weight_tube`` (kg) - ``n_drops`` (-) - ``drop_height`` (m) - ``uncertainty``: Quantitative uncertainty of the measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the measurement. See :ref:`uncertainty` for details. """ _data_config = dict( hardness=dict(min=0), weight_hammer=dict(min=0, optional=True), weight_tube=dict(min=0, optional=True), n_drops=dict(type=int, min=0, optional=True), drop_height=dict(min=0, optional=True), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), ) # TODO: Computation of hardness from other data ? type: typing.Literal['HardnessProfile'] = 'HardnessProfile'
[docs] class StrengthProfile(BaseProfile2): """ Vertical profile of strength (N). The ``data`` key contains: - ``top_height``: Top height of the measurement (m) - ``bottom_height``: Bottom height of the measurement (m) - ``thickness``: Thickness (m) - ``strength``: Strength value (N) - ``fracture_character`` (optional): - SP: Sudden planar - SC: Sudden collapse - SDN: Sudden (both) - RP: Resistant planar - PC: Progressive compression - RES: Resistant (both) - BRK or B: Break - X: Other/Unknown - ``uncertainty``: Quantitative uncertainty of the measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the measurement. See :ref:`uncertainty` for details. """ method_of_measurement: typing.Optional[typing.Literal[ "Shear Frame", "other"]] = pydantic.Field( None, description="Measurement method") strength_type: typing.Optional[typing.Literal[ "compressive", "tensile", "shear", "mixed", "other"]] = pydantic.Field( None, description="Shear direction: compressive, tensile, shear, other or mixed") probed_area: typing.Optional[float] = pydantic.Field( None, description="Probed area (m2)") _data_config = dict( strength=dict(min=0), fracture_character=dict(optional=True, nan_allowed=True, values=["SDN", "SP", "SC", "RES", "PC", "RP", "BRK", "B", "X", None], type='O'), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), )
[docs] class ImpurityProfile(BaseProfile2): """ Vertical profile of impurities (mass or volume fraction). The ``data`` key contains: - ``top_height``: Top height of the measurement (m) - ``bottom_height``: Bottom height of the measurement (m) - ``thickness``: Thickness (m) - ``mass_fraction``: Mass fraction of impurity (%) - ``volume_fraction``: Volume fration of impurity (%) - ``uncertainty``: Quantitative uncertainty of the measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the measurement. See :ref:`uncertainty` for details. """ method_of_measurement: typing.Optional[typing.Literal[ "other"]] = pydantic.Field( None, description="Measurement method") impurity_type: typing.Literal[ "Black Carbon", "Dust", "Isotopes", "Other"] = pydantic.Field( description="Impurity type for the profile") probed_volume: typing.Optional[float] = pydantic.Field( None, description="Probe volume (m3)") probed_diameter: typing.Optional[float] = pydantic.Field( None, description="Probe volume (m)") probed_length: typing.Optional[float] = pydantic.Field( None, description="Probe length (m)") probed_thickness: typing.Optional[float] = pydantic.Field( None, description="Probe thickness (vertical dimension, m)") _data_config = dict( mass_fraction=dict(min=0, max=100, optional=True, nan_allowed=True), volume_fraction=dict(min=0, max=100, optional=True, nan_allowed=True), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), )
[docs] class ScalarProfile(BaseProfile2): """ Other profile of scalar data (not covered by other Profile class). The ``data`` key contains: - ``top_height``: Top height of the measurement (m) - ``bottom_height``: Bottom height of the measurement (m) - ``thickness``: Thickness (m) - ``data``: Data value - ``uncertainty``: Quantitative uncertainty of the measurement (same unit as data). See :ref:`uncertainty` for details. - ``quality``: Quality flag of the measurement. See :ref:`uncertainty` for details. """ method_of_measurement: str = pydantic.Field( description="Measurement method description") unit: str = pydantic.Field( description="Unit (SI unit please)") parameter: str = pydantic.Field( description="Measured parameter") _data_config = dict( data=dict(), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), )
[docs] class VectorialProfile(ScalarProfile): """ Other profile of vectorial data (data inherently multi-dimensional, with same unit and type). The ``data`` key is a pandas.DataFrame with key data containing a python list of values. """ rank: int = pydantic.Field( gt = 1, description="Length of the vector (>1, otherwise use OtherScalarProfile)") _data_config = dict( data=dict(type='O'), uncertainty=dict(optional=True, nan_allowed=True), quality=dict(optional=True, type='O', values=QUALITY_FLAGS + [None]), )