Skip to content

Met

Bases: BaseInstrument

Class for processing bulk meteorological data.

Contains methods for:

  • Loading data from source files
  • Preprocessing
  • Calculating and converting from/to various useful thermodynamic quantities

Many of the methods are implemented based on their descriptions in Bradley & Fairall (2007). If a particular function/equation lacks a citation, it can likely be found in Appendix A therein.

Burst dictionary conventions

Variables in a burst dict are assumed to be 2-D arrays of shape (n_heights, n_samples), where the first axis corresponds to instrument heights (length self.n_heights) and the second axis is time. The individual thermodynamic methods accept any Numeric type and broadcast over these arrays without modification.

This class requires deployment_type="fixed". Height information is taken from self.z (meters above the sea surface, since Met locks z_convention to ZConvention.MAS) rather than from burst dict keys, so that self.z remains the single source of truth. self.z has shape (n_heights,) when z is passed to the initializer (a constant height per sensor), or (n_heights, n_samples) when z is supplied as a time-varying name_map data variable (e.g. a height referenced to a fluctuating mean sea surface).

Standard burst dict input keys recognized by Met.derive:

t         : air temperature (deg C)
p         : atmospheric pressure (mbar)
rh        : relative humidity (%)
sp        : seawater salinity (practical, PSS-78) -- optional, corrects vapor-pressure quantities

Output keys added by Met.derive

e_s         : saturation vapor pressure (mbar)
e           : water vapor pressure (mbar)
rho_v       : water vapor density (kg/m^3)
w           : mixing ratio (kg/kg)
q           : specific humidity (kg/kg)
t_v         : virtual temperature (deg C)
rho_air     : moist air density (kg/m^3)
rho_air_dry : dry air density (kg/m^3)
cp          : specific heat capacity (J/(kg K))
L_v         : latent heat of vaporization (J/kg)
nu          : kinematic viscosity (m^2/s)
theta       : potential temperature (deg C)
References

Bradley, E. F., & Fairall, C. W. (2007). A guide to making climate quality meteorological and flux measurements at sea.

Source code in src/pytoast/atmosphere/met.py
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
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
class Met(BaseInstrument):
    """Class for processing bulk meteorological data.

    Contains methods for:

    - Loading data from source files
    - Preprocessing
    - Calculating and converting from/to various useful thermodynamic quantities

    Many of the methods are implemented based on their descriptions in Bradley & Fairall (2007). If a particular
    function/equation lacks a citation, it can likely be found in Appendix A therein.

    Burst dictionary conventions
    ----------------------------
    Variables in a burst dict are assumed to be 2-D arrays of shape `(n_heights, n_samples)`, where the first axis
    corresponds to instrument heights (length `self.n_heights`) and the second axis is time. The individual
    thermodynamic methods accept any Numeric type and broadcast over these arrays without modification.

    This class requires `deployment_type="fixed"`. Height information is taken from `self.z` (meters above the sea
    surface, since Met locks `z_convention` to `ZConvention.MAS`) rather than from burst dict keys, so that `self.z`
    remains the single source of truth. `self.z` has shape (n_heights,) when `z` is passed to the initializer (a
    constant height per sensor), or (n_heights, n_samples) when `z` is supplied as a time-varying `name_map` data
    variable (e.g. a height referenced to a fluctuating mean sea surface).

    Standard burst dict input keys recognized by `Met.derive`:

        t         : air temperature (deg C)
        p         : atmospheric pressure (mbar)
        rh        : relative humidity (%)
        sp        : seawater salinity (practical, PSS-78) -- optional, corrects vapor-pressure quantities

    Output keys added by `Met.derive`

        e_s         : saturation vapor pressure (mbar)
        e           : water vapor pressure (mbar)
        rho_v       : water vapor density (kg/m^3)
        w           : mixing ratio (kg/kg)
        q           : specific humidity (kg/kg)
        t_v         : virtual temperature (deg C)
        rho_air     : moist air density (kg/m^3)
        rho_air_dry : dry air density (kg/m^3)
        cp          : specific heat capacity (J/(kg K))
        L_v         : latent heat of vaporization (J/kg)
        nu          : kinematic viscosity (m^2/s)
        theta       : potential temperature (deg C)

    References
    ----------
    Bradley, E. F., & Fairall, C. W. (2007). A guide to making climate quality meteorological and flux measurements at
        sea.
    """

    def __init__(
        self,
        files: str | list,
        name_map: dict,
        deployment_type: str = "fixed",
        fs: float | None = None,
        z: float | list[float] | None = None,
        z_convention: ZConvention = ZConvention.MAS,
        data_keys: str | list[str] | None = None,
        burst_dim: str | None = None,
        **loader_kwargs: Any,
    ) -> None:
        """Initialize a Met object.

        Parameters
        ----------
        files : str or List[str]
            Path(s) to data files. If a list, each element is treated as a file containing data from an individual burst
            period. Supported formats: .npy (saved as a dict), .mat (saved as a MATLAB struct), .csv (variables in
            columns), or .nc (must specify `burst_dim` argument if this is a single file containing multiple bursts). If
            variables are two-dimensional, the larger dimension is assumed to be time and the shorter dimension a
            vertical coordinate.
        name_map : dict
            Mapping of standard variable names to names in the data files, e.g.:

            ```
            {
                "t": "temperature variable name",
                "p": "pressure variable name",
                "rh": "relative humidity name",
                "time": "time variable name",
            }
            ```

            Each value in the mapping may take one of three forms:

            - **str**: name of a single variable in the data file.
            - **list of str**: multiple variable names, used when data from multiple instruments are stored in
              separate variables rather than a 2-D array.
            - **callable**: a function applied to the loaded data object. Useful for unit conversions or combining
              source variables, e.g. `"time": lambda data: data["doy"] + data["hour"] / 24`.
        deployment_type : str, optional
            Must be "fixed" (the only supported value). self.z will be converted to a constant numpy array of
            instrument deployment depths or measurement cell heights.
        fs : float, optional
            Sampling frequency (Hz). If not provided, it will be inferred (and rounded to 2 decimal places) from the
            `time` variable
        z : float or List[float], optional
            Mean height above the surface (m) for each instrument. Defaults to integer indices if not
            specified.
        z_convention : ZConvention, optional
            Convention for vertical coordinate, must be `"m_above_surface"` for Met instruments.
        data_keys : str or List[str], optional
            One or more nested keys to traverse after loading the file (e.g. "Data" if the variables
            in name_map are stored at `burst["Data"]["variable_name"]`).
        burst_dim : str, optional
            Name of the burst dimension inside a monolithic NetCDF file. When given, `files` must be a single `.nc`
            path; the file is opened lazily and each burst is exposed by slicing along this dimension. When None
            (default), each entry in `files` is treated as one burst.
        **loader_kwargs
            Additional keyword arguments forwarded to the underlying file reader selected by extension
            (`pd.read_csv` for `.csv`/`.dat`, `scipy.io.loadmat` for `.mat`, `numpy.load` for `.npy`,
            `xarray.open_dataset` for `.nc`). See `BaseInstrument.__init__`.

        Returns
        -------
        Met
            Initialized Met object.
        """
        files_list = files if isinstance(files, list) else [files]
        Met.validate_inputs(files_list, name_map, deployment_type, fs, z, z_convention, data_keys)
        super().__init__(
            files,
            name_map,
            deployment_type=DeploymentType(deployment_type),
            fs=fs,
            z=z,
            z_convention=z_convention,
            data_keys=data_keys,
            burst_dim=burst_dim,
            **loader_kwargs,
        )

    @staticmethod
    def validate_inputs(
        files: str | list,
        name_map: dict,
        deployment_type: str = "fixed",
        fs: int | float | None = None,
        z: float | int | list[float | int] | None = None,
        z_convention: ZConvention = ZConvention.MAS,
        data_keys: str | list[str] | None = None,
    ) -> None:

        # General validation
        files_list = [files] if isinstance(files, str) else files
        BaseInstrument.validate_common_inputs(files_list, name_map, fs, z, data_keys)

        if deployment_type != "fixed":
            raise ValueError(f"Met.deployment_type must be 'fixed', not {deployment_type!r}")

        if z_convention != ZConvention.MAS:
            raise ValueError(f"Met.z_convention must be {ZConvention.MAS}, not {z_convention}")

    def set_preprocess_opts(self, opts: dict[str, Any]) -> None:
        """Enable preprocessing for all subsequent burst loads using the
        options defined in the input dictionary.

        Parameters
        ----------
        opts : dict
            Preprocessing options. Supported keys:

            despike : dict, optional

                Options for despiking. If not specified, no despiking is applied. Supported keys:

                method : {'threshold', 'goring_nikora', 'recursive_gaussian'}
                    If `threshold`, data is despiked by replacing any samples with a magnitude outside a specified
                    range. If `goring_nikora`, data is despiked using the Goring & Nikora (2002) algorithm. If
                    `recursive_gaussian`, data is despiked using a recursive Gaussian filter.

                If ``{'method': 'goring_nikora', ...}``, additional keys can be (see `goring_nikora` docstring):
                    remaining_spikes : int
                    max_iter : int
                    robust_statistics : bool

                If ``{'method': 'threshold', ...}``, additional keys can be:
                    threshold_min : float
                    threshold_max : float

                If ``{'method': 'recursive_gaussian', ...}``, additional keys can be:
                    alpha : float
                    max_iter : int
        """
        super().set_preprocess_opts(opts)

    def _apply_preprocessing(self, burst_data: Any, keys_to_process: list[str] | None = None) -> Any:
        burst_data = super()._apply_preprocessing(burst_data, keys_to_process=self._burst_var_keys)
        return burst_data

    def t_c2kelvin(self, t: Numeric) -> Numeric:
        """Convert temperature from Celsius to Kelvin."""
        return air_thermo.t_c2kelvin(t)

    def p_mbar2pa(self, p: Numeric) -> Numeric:
        """Convert pressure from millibar to Pascal."""
        return air_thermo.p_mbar2pa(p)

    def saturation_vapor_pressure(self, t: Numeric, p: Numeric, sp: Numeric | None = None) -> Numeric:
        """Saturation vapor pressure given pressure, temperature, and
        (optionally) seawater salinity.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius
        p : Numeric
            Atmospheric pressure in millibar
        sp : Numeric, optional
            If specified, the saturation vapor pressure is corrected to its "above seawater"
            value using salinity in PSU

        Returns
        -------
        Numeric
            Saturation vapor pressure in millibar
        """
        return air_thermo.saturation_vapor_pressure(t, p, sp)

    def water_vapor_pressure(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
        """Water vapor pressure given temperature, pressure, relative humidity,
        and (optionally) seawater salinity.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius
        p : Numeric
            Atmospheric pressure in millibar
        rh : Numeric
            Relative humidity in %
        sp : Numeric, optional
            If specified, the saturation vapor pressure is corrected to its "above seawater"
            value using salinity in PSU

        Returns
        -------
        Numeric
            Water vapor pressure in millibar
        """
        return air_thermo.water_vapor_pressure(t, p, rh, sp)

    def water_vapor_density(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
        """Water vapor density given temperature, pressure, relative humidity,
        and (optionally) seawater salinity.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius
        p : Numeric
            Atmospheric pressure in millibar
        rh : Numeric
            Relative humidity in %
        sp : Numeric, optional
            If specified, the saturation vapor pressure is corrected to its "above seawater"
            value using salinity in PSU

        Returns
        -------
        Numeric
            Water vapor density in kg/m^3
        """
        return air_thermo.water_vapor_density(t, p, rh, sp)

    def mixing_ratio(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
        """Water vapor mixing ratio given temperature, pressure, relative
        humidity, and (optionally) seawater salinity.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius
        p : Numeric
            Atmospheric pressure in millibar
        rh : Numeric
            Relative humidity in %
        sp : Numeric, optional
            If specified, the saturation vapor pressure is corrected to its "above seawater"
            value using salinity in PSU

        Returns
        -------
        Numeric
            Mixing ratio in kg/kg
        """
        return air_thermo.mixing_ratio(t, p, rh, sp)

    def specific_humidity(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
        """Specific humidity given temperature, pressure, relative humidity,
        and (optionally) seawater salinity.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius
        p : Numeric
            Atmospheric pressure in millibar
        rh : Numeric
            Relative humidity in %
        sp : Numeric, optional
            If specified, the saturation vapor pressure is corrected to its "above seawater"
            value using salinity in PSU

        Returns
        -------
        Numeric
            Specific humidity in kg/kg
        """
        return air_thermo.specific_humidity(t, p, rh, sp)

    def virtual_temperature(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
        """Virtual temperature given temperature, pressure, relative humidity,
        and (optionally) seawater salinity.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius
        p : Numeric
            Atmospheric pressure in millibar
        rh : Numeric
            Relative humidity in %
        sp : Numeric, optional
            If specified, the saturation vapor pressure is corrected to its "above seawater"
            value using salinity in PSU

        Returns
        -------
        Numeric
            Virtual temperature in Celcius
        """
        return air_thermo.virtual_temperature(t, p, rh, sp)

    def air_density(self, t: Numeric, p: Numeric, rh: Numeric) -> Numeric:
        """Moist air density given temperature, pressure, and relative
        humidity.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius
        p : Numeric
            Atmospheric pressure in millibar
        rh : Numeric
            Relative humidity in %

        Returns
        -------
        Numeric
            Moist air density in kg/m^3
        """
        return air_thermo.air_density(t, p, rh)

    def dry_air_density(self, t: Numeric, p: Numeric) -> Numeric:
        """Dry air density given temperature and pressure.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius
        p : Numeric
            Atmospheric pressure in millibar

        Returns
        -------
        Numeric
            Dry air density in kg/m^3
        """
        return air_thermo.dry_air_density(t, p)

    def specific_heat(self, t: Numeric) -> Numeric:
        """Specific heat capacity of air at constant pressure.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius

        Returns
        -------
        Numeric
            Specific heat capacity in J/(kg K)
        """
        return air_thermo.specific_heat(t)

    def latent_heat_of_vaporization(self, t: Numeric) -> Numeric:
        """Latent heat of vaporization.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius

        Returns
        -------
        Numeric
            Latent heat of vaporization in J/kg
        """
        return air_thermo.latent_heat_of_vaporization(t)

    def kinematic_viscosity(self, t: Numeric) -> Numeric:
        """Kinematic viscosity of air.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius

        Returns
        -------
        Numeric
            Kinematic viscosity in m^2/s
        """
        return air_thermo.kinematic_viscosity(t)

    def potential_temperature(self, t: Numeric, z: Numeric) -> Numeric:
        """Potential temperature, i.e. the temperature an air parcel would have
        if brought adiabatically to a reference level at the surface.

        Parameters
        ----------
        t : Numeric
            Air temperature in Celcius
        z : Numeric
            Height above the surface in meters. When called via `derive`, this is taken from
            self.z and broadcast over the time dimension automatically.

        Returns
        -------
        Numeric
            Potential temperature in Celcius
        """
        return air_thermo.potential_temperature(t, z)

    def derive(self, burst_data: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
        """Compute all thermodynamic quantities derivable from the variables present in a burst dictionary, and return
        the burst dictionary augmented with those results.

        Each quantity is computed only when all of its required inputs are available as keys in ``burst_data``. The
        method never raises for missing inputs -- it simply skips any quantities it cannot compute. Salinity is treated
        as optional throughout; when the ``"sp"`` key is present its value is forwarded to the vapor-pressure
        calculations.

        Height is always taken from ``self.z`` and is not read from ``burst_data``. When computing potential
        temperature, a 1-D ``self.z`` of shape (n_heights,) is reshaped to (n_heights, 1) so that it broadcasts
        correctly against (n_heights, n_samples) arrays; a time-varying ``self.z`` of shape (n_heights, n_samples) is
        used as-is.

        Input keys recognized
        ----------------------

            t         : air temperature (deg C),         shape (n_heights, n_samples)
            p         : atmospheric pressure (mbar),     shape (n_heights, n_samples)
            rh        : relative humidity (%),           shape (n_heights, n_samples)
            sp        : seawater salinity (PSS-78),      shape (n_heights, n_samples) -- optional

        Output keys added to burst_data (all shape (n_heights, n_samples))
        -------------------------------------------------------------------

            e_s         : saturation vapor pressure (mbar)     -- requires t, p
            rho_air_dry : dry air density (kg/m^3)             -- requires t, p
            e           : water vapor pressure (mbar)          -- requires t, p, rh
            rho_v       : water vapor density (kg/m^3)         -- requires t, p, rh
            w           : mixing ratio (kg/kg)                 -- requires t, p, rh
            q           : specific humidity (kg/kg)            -- requires t, p, rh
            t_v         : virtual temperature (deg C)          -- requires t, p, rh
            rho_air     : moist air density (kg/m^3)           -- requires t, p, rh
            cp          : specific heat capacity (J/(kg K))    -- requires t
            L_v         : latent heat of vaporization (J/kg)   -- requires t
            nu          : kinematic viscosity (m^2/s)          -- requires t
            theta       : potential temperature (deg C)        -- requires t (uses self.z)

        Parameters
        ----------
        burst_data : dict
            Burst dictionary whose keys are standard variable names (see above). Arrays are expected to have shape
            (n_heights, n_samples). The dictionary is modified in-place and also returned.

        Returns
        -------
        dict
            The input ``burst_data`` dictionary with derived quantities added as new keys.
        """
        t = burst_data.get("t")
        p = burst_data.get("p")
        rh = burst_data.get("rh")
        sp = burst_data.get("sp")

        # Temperature-only quantities
        if t is not None:
            burst_data["cp"] = np.asarray(self.specific_heat(t))
            burst_data["L_v"] = np.asarray(self.latent_heat_of_vaporization(t))
            burst_data["nu"] = np.asarray(self.kinematic_viscosity(t))
            # A 1-D self.z (n_heights,) is reshaped to (n_heights, 1) to broadcast over the time axis; a time-varying
            # self.z (n_heights, n_samples) is used as-is.
            z = self.z if self.z.ndim == 2 else self.z.reshape(-1, 1)
            burst_data["theta"] = np.asarray(self.potential_temperature(t, z))

        # Temperature + pressure quantities
        if t is not None and p is not None:
            burst_data["e_s"] = np.asarray(self.saturation_vapor_pressure(t, p, sp))
            burst_data["rho_air_dry"] = np.asarray(self.dry_air_density(t, p))

        # Temperature + pressure + relative humidity quantities
        if t is not None and p is not None and rh is not None:
            burst_data["e"] = np.asarray(self.water_vapor_pressure(t, p, rh, sp))
            burst_data["rho_v"] = np.asarray(self.water_vapor_density(t, p, rh, sp))
            burst_data["w"] = np.asarray(self.mixing_ratio(t, p, rh, sp))
            burst_data["q"] = np.asarray(self.specific_humidity(t, p, rh, sp))
            burst_data["t_v"] = np.asarray(self.virtual_temperature(t, p, rh, sp))
            burst_data["rho_air"] = np.asarray(self.air_density(t, p, rh))

        return burst_data

    @property
    def _burst_var_keys(self) -> list[str]:
        return [k for k in self.name_map if k != "time"]

    def subsample(self, start_idx: int, end_idx: int) -> "Met":
        new_met = self.__class__(
            files=self.files[start_idx:end_idx],
            name_map=self.name_map,
            deployment_type=self.deployment_type,
            fs=self.fs,
            z=self.z,
            data_keys=self.data_keys,
        )
        if self._preprocess_enabled:
            new_met.set_preprocess_opts(self._preprocess_opts)
        return new_met

__init__

__init__(files, name_map, deployment_type='fixed', fs=None, z=None, z_convention=MAS, data_keys=None, burst_dim=None, **loader_kwargs)

Initialize a Met object.

Parameters:

Name Type Description Default
files str or List[str]

Path(s) to data files. If a list, each element is treated as a file containing data from an individual burst period. Supported formats: .npy (saved as a dict), .mat (saved as a MATLAB struct), .csv (variables in columns), or .nc (must specify burst_dim argument if this is a single file containing multiple bursts). If variables are two-dimensional, the larger dimension is assumed to be time and the shorter dimension a vertical coordinate.

required
name_map dict

Mapping of standard variable names to names in the data files, e.g.:

{
    "t": "temperature variable name",
    "p": "pressure variable name",
    "rh": "relative humidity name",
    "time": "time variable name",
}

Each value in the mapping may take one of three forms:

  • str: name of a single variable in the data file.
  • list of str: multiple variable names, used when data from multiple instruments are stored in separate variables rather than a 2-D array.
  • callable: a function applied to the loaded data object. Useful for unit conversions or combining source variables, e.g. "time": lambda data: data["doy"] + data["hour"] / 24.
required
deployment_type str

Must be "fixed" (the only supported value). self.z will be converted to a constant numpy array of instrument deployment depths or measurement cell heights.

'fixed'
fs float

Sampling frequency (Hz). If not provided, it will be inferred (and rounded to 2 decimal places) from the time variable

None
z float or List[float]

Mean height above the surface (m) for each instrument. Defaults to integer indices if not specified.

None
z_convention ZConvention

Convention for vertical coordinate, must be "m_above_surface" for Met instruments.

MAS
data_keys str or List[str]

One or more nested keys to traverse after loading the file (e.g. "Data" if the variables in name_map are stored at burst["Data"]["variable_name"]).

None
burst_dim str

Name of the burst dimension inside a monolithic NetCDF file. When given, files must be a single .nc path; the file is opened lazily and each burst is exposed by slicing along this dimension. When None (default), each entry in files is treated as one burst.

None
**loader_kwargs Any

Additional keyword arguments forwarded to the underlying file reader selected by extension (pd.read_csv for .csv/.dat, scipy.io.loadmat for .mat, numpy.load for .npy, xarray.open_dataset for .nc). See BaseInstrument.__init__.

{}

Returns:

Type Description
Met

Initialized Met object.

Source code in src/pytoast/atmosphere/met.py
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 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
def __init__(
    self,
    files: str | list,
    name_map: dict,
    deployment_type: str = "fixed",
    fs: float | None = None,
    z: float | list[float] | None = None,
    z_convention: ZConvention = ZConvention.MAS,
    data_keys: str | list[str] | None = None,
    burst_dim: str | None = None,
    **loader_kwargs: Any,
) -> None:
    """Initialize a Met object.

    Parameters
    ----------
    files : str or List[str]
        Path(s) to data files. If a list, each element is treated as a file containing data from an individual burst
        period. Supported formats: .npy (saved as a dict), .mat (saved as a MATLAB struct), .csv (variables in
        columns), or .nc (must specify `burst_dim` argument if this is a single file containing multiple bursts). If
        variables are two-dimensional, the larger dimension is assumed to be time and the shorter dimension a
        vertical coordinate.
    name_map : dict
        Mapping of standard variable names to names in the data files, e.g.:

        ```
        {
            "t": "temperature variable name",
            "p": "pressure variable name",
            "rh": "relative humidity name",
            "time": "time variable name",
        }
        ```

        Each value in the mapping may take one of three forms:

        - **str**: name of a single variable in the data file.
        - **list of str**: multiple variable names, used when data from multiple instruments are stored in
          separate variables rather than a 2-D array.
        - **callable**: a function applied to the loaded data object. Useful for unit conversions or combining
          source variables, e.g. `"time": lambda data: data["doy"] + data["hour"] / 24`.
    deployment_type : str, optional
        Must be "fixed" (the only supported value). self.z will be converted to a constant numpy array of
        instrument deployment depths or measurement cell heights.
    fs : float, optional
        Sampling frequency (Hz). If not provided, it will be inferred (and rounded to 2 decimal places) from the
        `time` variable
    z : float or List[float], optional
        Mean height above the surface (m) for each instrument. Defaults to integer indices if not
        specified.
    z_convention : ZConvention, optional
        Convention for vertical coordinate, must be `"m_above_surface"` for Met instruments.
    data_keys : str or List[str], optional
        One or more nested keys to traverse after loading the file (e.g. "Data" if the variables
        in name_map are stored at `burst["Data"]["variable_name"]`).
    burst_dim : str, optional
        Name of the burst dimension inside a monolithic NetCDF file. When given, `files` must be a single `.nc`
        path; the file is opened lazily and each burst is exposed by slicing along this dimension. When None
        (default), each entry in `files` is treated as one burst.
    **loader_kwargs
        Additional keyword arguments forwarded to the underlying file reader selected by extension
        (`pd.read_csv` for `.csv`/`.dat`, `scipy.io.loadmat` for `.mat`, `numpy.load` for `.npy`,
        `xarray.open_dataset` for `.nc`). See `BaseInstrument.__init__`.

    Returns
    -------
    Met
        Initialized Met object.
    """
    files_list = files if isinstance(files, list) else [files]
    Met.validate_inputs(files_list, name_map, deployment_type, fs, z, z_convention, data_keys)
    super().__init__(
        files,
        name_map,
        deployment_type=DeploymentType(deployment_type),
        fs=fs,
        z=z,
        z_convention=z_convention,
        data_keys=data_keys,
        burst_dim=burst_dim,
        **loader_kwargs,
    )

air_density

air_density(t, p, rh)

Moist air density given temperature, pressure, and relative humidity.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required
p Numeric

Atmospheric pressure in millibar

required
rh Numeric

Relative humidity in %

required

Returns:

Type Description
Numeric

Moist air density in kg/m^3

Source code in src/pytoast/atmosphere/met.py
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
def air_density(self, t: Numeric, p: Numeric, rh: Numeric) -> Numeric:
    """Moist air density given temperature, pressure, and relative
    humidity.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius
    p : Numeric
        Atmospheric pressure in millibar
    rh : Numeric
        Relative humidity in %

    Returns
    -------
    Numeric
        Moist air density in kg/m^3
    """
    return air_thermo.air_density(t, p, rh)

derive

derive(burst_data)

Compute all thermodynamic quantities derivable from the variables present in a burst dictionary, and return the burst dictionary augmented with those results.

Each quantity is computed only when all of its required inputs are available as keys in burst_data. The method never raises for missing inputs -- it simply skips any quantities it cannot compute. Salinity is treated as optional throughout; when the "sp" key is present its value is forwarded to the vapor-pressure calculations.

Height is always taken from self.z and is not read from burst_data. When computing potential temperature, a 1-D self.z of shape (n_heights,) is reshaped to (n_heights, 1) so that it broadcasts correctly against (n_heights, n_samples) arrays; a time-varying self.z of shape (n_heights, n_samples) is used as-is.

Input keys recognized
t         : air temperature (deg C),         shape (n_heights, n_samples)
p         : atmospheric pressure (mbar),     shape (n_heights, n_samples)
rh        : relative humidity (%),           shape (n_heights, n_samples)
sp        : seawater salinity (PSS-78),      shape (n_heights, n_samples) -- optional
Output keys added to burst_data (all shape (n_heights, n_samples))
e_s         : saturation vapor pressure (mbar)     -- requires t, p
rho_air_dry : dry air density (kg/m^3)             -- requires t, p
e           : water vapor pressure (mbar)          -- requires t, p, rh
rho_v       : water vapor density (kg/m^3)         -- requires t, p, rh
w           : mixing ratio (kg/kg)                 -- requires t, p, rh
q           : specific humidity (kg/kg)            -- requires t, p, rh
t_v         : virtual temperature (deg C)          -- requires t, p, rh
rho_air     : moist air density (kg/m^3)           -- requires t, p, rh
cp          : specific heat capacity (J/(kg K))    -- requires t
L_v         : latent heat of vaporization (J/kg)   -- requires t
nu          : kinematic viscosity (m^2/s)          -- requires t
theta       : potential temperature (deg C)        -- requires t (uses self.z)

Parameters:

Name Type Description Default
burst_data dict

Burst dictionary whose keys are standard variable names (see above). Arrays are expected to have shape (n_heights, n_samples). The dictionary is modified in-place and also returned.

required

Returns:

Type Description
dict

The input burst_data dictionary with derived quantities added as new keys.

Source code in src/pytoast/atmosphere/met.py
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
def derive(self, burst_data: dict[str, np.ndarray]) -> dict[str, np.ndarray]:
    """Compute all thermodynamic quantities derivable from the variables present in a burst dictionary, and return
    the burst dictionary augmented with those results.

    Each quantity is computed only when all of its required inputs are available as keys in ``burst_data``. The
    method never raises for missing inputs -- it simply skips any quantities it cannot compute. Salinity is treated
    as optional throughout; when the ``"sp"`` key is present its value is forwarded to the vapor-pressure
    calculations.

    Height is always taken from ``self.z`` and is not read from ``burst_data``. When computing potential
    temperature, a 1-D ``self.z`` of shape (n_heights,) is reshaped to (n_heights, 1) so that it broadcasts
    correctly against (n_heights, n_samples) arrays; a time-varying ``self.z`` of shape (n_heights, n_samples) is
    used as-is.

    Input keys recognized
    ----------------------

        t         : air temperature (deg C),         shape (n_heights, n_samples)
        p         : atmospheric pressure (mbar),     shape (n_heights, n_samples)
        rh        : relative humidity (%),           shape (n_heights, n_samples)
        sp        : seawater salinity (PSS-78),      shape (n_heights, n_samples) -- optional

    Output keys added to burst_data (all shape (n_heights, n_samples))
    -------------------------------------------------------------------

        e_s         : saturation vapor pressure (mbar)     -- requires t, p
        rho_air_dry : dry air density (kg/m^3)             -- requires t, p
        e           : water vapor pressure (mbar)          -- requires t, p, rh
        rho_v       : water vapor density (kg/m^3)         -- requires t, p, rh
        w           : mixing ratio (kg/kg)                 -- requires t, p, rh
        q           : specific humidity (kg/kg)            -- requires t, p, rh
        t_v         : virtual temperature (deg C)          -- requires t, p, rh
        rho_air     : moist air density (kg/m^3)           -- requires t, p, rh
        cp          : specific heat capacity (J/(kg K))    -- requires t
        L_v         : latent heat of vaporization (J/kg)   -- requires t
        nu          : kinematic viscosity (m^2/s)          -- requires t
        theta       : potential temperature (deg C)        -- requires t (uses self.z)

    Parameters
    ----------
    burst_data : dict
        Burst dictionary whose keys are standard variable names (see above). Arrays are expected to have shape
        (n_heights, n_samples). The dictionary is modified in-place and also returned.

    Returns
    -------
    dict
        The input ``burst_data`` dictionary with derived quantities added as new keys.
    """
    t = burst_data.get("t")
    p = burst_data.get("p")
    rh = burst_data.get("rh")
    sp = burst_data.get("sp")

    # Temperature-only quantities
    if t is not None:
        burst_data["cp"] = np.asarray(self.specific_heat(t))
        burst_data["L_v"] = np.asarray(self.latent_heat_of_vaporization(t))
        burst_data["nu"] = np.asarray(self.kinematic_viscosity(t))
        # A 1-D self.z (n_heights,) is reshaped to (n_heights, 1) to broadcast over the time axis; a time-varying
        # self.z (n_heights, n_samples) is used as-is.
        z = self.z if self.z.ndim == 2 else self.z.reshape(-1, 1)
        burst_data["theta"] = np.asarray(self.potential_temperature(t, z))

    # Temperature + pressure quantities
    if t is not None and p is not None:
        burst_data["e_s"] = np.asarray(self.saturation_vapor_pressure(t, p, sp))
        burst_data["rho_air_dry"] = np.asarray(self.dry_air_density(t, p))

    # Temperature + pressure + relative humidity quantities
    if t is not None and p is not None and rh is not None:
        burst_data["e"] = np.asarray(self.water_vapor_pressure(t, p, rh, sp))
        burst_data["rho_v"] = np.asarray(self.water_vapor_density(t, p, rh, sp))
        burst_data["w"] = np.asarray(self.mixing_ratio(t, p, rh, sp))
        burst_data["q"] = np.asarray(self.specific_humidity(t, p, rh, sp))
        burst_data["t_v"] = np.asarray(self.virtual_temperature(t, p, rh, sp))
        burst_data["rho_air"] = np.asarray(self.air_density(t, p, rh))

    return burst_data

dry_air_density

dry_air_density(t, p)

Dry air density given temperature and pressure.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required
p Numeric

Atmospheric pressure in millibar

required

Returns:

Type Description
Numeric

Dry air density in kg/m^3

Source code in src/pytoast/atmosphere/met.py
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
def dry_air_density(self, t: Numeric, p: Numeric) -> Numeric:
    """Dry air density given temperature and pressure.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius
    p : Numeric
        Atmospheric pressure in millibar

    Returns
    -------
    Numeric
        Dry air density in kg/m^3
    """
    return air_thermo.dry_air_density(t, p)

kinematic_viscosity

kinematic_viscosity(t)

Kinematic viscosity of air.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required

Returns:

Type Description
Numeric

Kinematic viscosity in m^2/s

Source code in src/pytoast/atmosphere/met.py
414
415
416
417
418
419
420
421
422
423
424
425
426
427
def kinematic_viscosity(self, t: Numeric) -> Numeric:
    """Kinematic viscosity of air.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius

    Returns
    -------
    Numeric
        Kinematic viscosity in m^2/s
    """
    return air_thermo.kinematic_viscosity(t)

latent_heat_of_vaporization

latent_heat_of_vaporization(t)

Latent heat of vaporization.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required

Returns:

Type Description
Numeric

Latent heat of vaporization in J/kg

Source code in src/pytoast/atmosphere/met.py
399
400
401
402
403
404
405
406
407
408
409
410
411
412
def latent_heat_of_vaporization(self, t: Numeric) -> Numeric:
    """Latent heat of vaporization.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius

    Returns
    -------
    Numeric
        Latent heat of vaporization in J/kg
    """
    return air_thermo.latent_heat_of_vaporization(t)

mixing_ratio

mixing_ratio(t, p, rh, sp=None)

Water vapor mixing ratio given temperature, pressure, relative humidity, and (optionally) seawater salinity.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required
p Numeric

Atmospheric pressure in millibar

required
rh Numeric

Relative humidity in %

required
sp Numeric

If specified, the saturation vapor pressure is corrected to its "above seawater" value using salinity in PSU

None

Returns:

Type Description
Numeric

Mixing ratio in kg/kg

Source code in src/pytoast/atmosphere/met.py
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
def mixing_ratio(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
    """Water vapor mixing ratio given temperature, pressure, relative
    humidity, and (optionally) seawater salinity.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius
    p : Numeric
        Atmospheric pressure in millibar
    rh : Numeric
        Relative humidity in %
    sp : Numeric, optional
        If specified, the saturation vapor pressure is corrected to its "above seawater"
        value using salinity in PSU

    Returns
    -------
    Numeric
        Mixing ratio in kg/kg
    """
    return air_thermo.mixing_ratio(t, p, rh, sp)

p_mbar2pa

p_mbar2pa(p)

Convert pressure from millibar to Pascal.

Source code in src/pytoast/atmosphere/met.py
207
208
209
def p_mbar2pa(self, p: Numeric) -> Numeric:
    """Convert pressure from millibar to Pascal."""
    return air_thermo.p_mbar2pa(p)

potential_temperature

potential_temperature(t, z)

Potential temperature, i.e. the temperature an air parcel would have if brought adiabatically to a reference level at the surface.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required
z Numeric

Height above the surface in meters. When called via derive, this is taken from self.z and broadcast over the time dimension automatically.

required

Returns:

Type Description
Numeric

Potential temperature in Celcius

Source code in src/pytoast/atmosphere/met.py
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
def potential_temperature(self, t: Numeric, z: Numeric) -> Numeric:
    """Potential temperature, i.e. the temperature an air parcel would have
    if brought adiabatically to a reference level at the surface.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius
    z : Numeric
        Height above the surface in meters. When called via `derive`, this is taken from
        self.z and broadcast over the time dimension automatically.

    Returns
    -------
    Numeric
        Potential temperature in Celcius
    """
    return air_thermo.potential_temperature(t, z)

saturation_vapor_pressure

saturation_vapor_pressure(t, p, sp=None)

Saturation vapor pressure given pressure, temperature, and (optionally) seawater salinity.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required
p Numeric

Atmospheric pressure in millibar

required
sp Numeric

If specified, the saturation vapor pressure is corrected to its "above seawater" value using salinity in PSU

None

Returns:

Type Description
Numeric

Saturation vapor pressure in millibar

Source code in src/pytoast/atmosphere/met.py
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
def saturation_vapor_pressure(self, t: Numeric, p: Numeric, sp: Numeric | None = None) -> Numeric:
    """Saturation vapor pressure given pressure, temperature, and
    (optionally) seawater salinity.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius
    p : Numeric
        Atmospheric pressure in millibar
    sp : Numeric, optional
        If specified, the saturation vapor pressure is corrected to its "above seawater"
        value using salinity in PSU

    Returns
    -------
    Numeric
        Saturation vapor pressure in millibar
    """
    return air_thermo.saturation_vapor_pressure(t, p, sp)

set_preprocess_opts

set_preprocess_opts(opts)

Enable preprocessing for all subsequent burst loads using the options defined in the input dictionary.

Parameters:

Name Type Description Default
opts dict

Preprocessing options. Supported keys:

despike : dict, optional

Options for despiking. If not specified, no despiking is applied. Supported keys:

method : {'threshold', 'goring_nikora', 'recursive_gaussian'}
    If `threshold`, data is despiked by replacing any samples with a magnitude outside a specified
    range. If `goring_nikora`, data is despiked using the Goring & Nikora (2002) algorithm. If
    `recursive_gaussian`, data is despiked using a recursive Gaussian filter.

If ``{'method': 'goring_nikora', ...}``, additional keys can be (see `goring_nikora` docstring):
    remaining_spikes : int
    max_iter : int
    robust_statistics : bool

If ``{'method': 'threshold', ...}``, additional keys can be:
    threshold_min : float
    threshold_max : float

If ``{'method': 'recursive_gaussian', ...}``, additional keys can be:
    alpha : float
    max_iter : int
required
Source code in src/pytoast/atmosphere/met.py
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
def set_preprocess_opts(self, opts: dict[str, Any]) -> None:
    """Enable preprocessing for all subsequent burst loads using the
    options defined in the input dictionary.

    Parameters
    ----------
    opts : dict
        Preprocessing options. Supported keys:

        despike : dict, optional

            Options for despiking. If not specified, no despiking is applied. Supported keys:

            method : {'threshold', 'goring_nikora', 'recursive_gaussian'}
                If `threshold`, data is despiked by replacing any samples with a magnitude outside a specified
                range. If `goring_nikora`, data is despiked using the Goring & Nikora (2002) algorithm. If
                `recursive_gaussian`, data is despiked using a recursive Gaussian filter.

            If ``{'method': 'goring_nikora', ...}``, additional keys can be (see `goring_nikora` docstring):
                remaining_spikes : int
                max_iter : int
                robust_statistics : bool

            If ``{'method': 'threshold', ...}``, additional keys can be:
                threshold_min : float
                threshold_max : float

            If ``{'method': 'recursive_gaussian', ...}``, additional keys can be:
                alpha : float
                max_iter : int
    """
    super().set_preprocess_opts(opts)

specific_heat

specific_heat(t)

Specific heat capacity of air at constant pressure.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required

Returns:

Type Description
Numeric

Specific heat capacity in J/(kg K)

Source code in src/pytoast/atmosphere/met.py
384
385
386
387
388
389
390
391
392
393
394
395
396
397
def specific_heat(self, t: Numeric) -> Numeric:
    """Specific heat capacity of air at constant pressure.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius

    Returns
    -------
    Numeric
        Specific heat capacity in J/(kg K)
    """
    return air_thermo.specific_heat(t)

specific_humidity

specific_humidity(t, p, rh, sp=None)

Specific humidity given temperature, pressure, relative humidity, and (optionally) seawater salinity.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required
p Numeric

Atmospheric pressure in millibar

required
rh Numeric

Relative humidity in %

required
sp Numeric

If specified, the saturation vapor pressure is corrected to its "above seawater" value using salinity in PSU

None

Returns:

Type Description
Numeric

Specific humidity in kg/kg

Source code in src/pytoast/atmosphere/met.py
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
def specific_humidity(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
    """Specific humidity given temperature, pressure, relative humidity,
    and (optionally) seawater salinity.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius
    p : Numeric
        Atmospheric pressure in millibar
    rh : Numeric
        Relative humidity in %
    sp : Numeric, optional
        If specified, the saturation vapor pressure is corrected to its "above seawater"
        value using salinity in PSU

    Returns
    -------
    Numeric
        Specific humidity in kg/kg
    """
    return air_thermo.specific_humidity(t, p, rh, sp)

t_c2kelvin

t_c2kelvin(t)

Convert temperature from Celsius to Kelvin.

Source code in src/pytoast/atmosphere/met.py
203
204
205
def t_c2kelvin(self, t: Numeric) -> Numeric:
    """Convert temperature from Celsius to Kelvin."""
    return air_thermo.t_c2kelvin(t)

virtual_temperature

virtual_temperature(t, p, rh, sp=None)

Virtual temperature given temperature, pressure, relative humidity, and (optionally) seawater salinity.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required
p Numeric

Atmospheric pressure in millibar

required
rh Numeric

Relative humidity in %

required
sp Numeric

If specified, the saturation vapor pressure is corrected to its "above seawater" value using salinity in PSU

None

Returns:

Type Description
Numeric

Virtual temperature in Celcius

Source code in src/pytoast/atmosphere/met.py
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
def virtual_temperature(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
    """Virtual temperature given temperature, pressure, relative humidity,
    and (optionally) seawater salinity.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius
    p : Numeric
        Atmospheric pressure in millibar
    rh : Numeric
        Relative humidity in %
    sp : Numeric, optional
        If specified, the saturation vapor pressure is corrected to its "above seawater"
        value using salinity in PSU

    Returns
    -------
    Numeric
        Virtual temperature in Celcius
    """
    return air_thermo.virtual_temperature(t, p, rh, sp)

water_vapor_density

water_vapor_density(t, p, rh, sp=None)

Water vapor density given temperature, pressure, relative humidity, and (optionally) seawater salinity.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required
p Numeric

Atmospheric pressure in millibar

required
rh Numeric

Relative humidity in %

required
sp Numeric

If specified, the saturation vapor pressure is corrected to its "above seawater" value using salinity in PSU

None

Returns:

Type Description
Numeric

Water vapor density in kg/m^3

Source code in src/pytoast/atmosphere/met.py
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
def water_vapor_density(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
    """Water vapor density given temperature, pressure, relative humidity,
    and (optionally) seawater salinity.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius
    p : Numeric
        Atmospheric pressure in millibar
    rh : Numeric
        Relative humidity in %
    sp : Numeric, optional
        If specified, the saturation vapor pressure is corrected to its "above seawater"
        value using salinity in PSU

    Returns
    -------
    Numeric
        Water vapor density in kg/m^3
    """
    return air_thermo.water_vapor_density(t, p, rh, sp)

water_vapor_pressure

water_vapor_pressure(t, p, rh, sp=None)

Water vapor pressure given temperature, pressure, relative humidity, and (optionally) seawater salinity.

Parameters:

Name Type Description Default
t Numeric

Air temperature in Celcius

required
p Numeric

Atmospheric pressure in millibar

required
rh Numeric

Relative humidity in %

required
sp Numeric

If specified, the saturation vapor pressure is corrected to its "above seawater" value using salinity in PSU

None

Returns:

Type Description
Numeric

Water vapor pressure in millibar

Source code in src/pytoast/atmosphere/met.py
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
def water_vapor_pressure(self, t: Numeric, p: Numeric, rh: Numeric, sp: Numeric | None = None) -> Numeric:
    """Water vapor pressure given temperature, pressure, relative humidity,
    and (optionally) seawater salinity.

    Parameters
    ----------
    t : Numeric
        Air temperature in Celcius
    p : Numeric
        Atmospheric pressure in millibar
    rh : Numeric
        Relative humidity in %
    sp : Numeric, optional
        If specified, the saturation vapor pressure is corrected to its "above seawater"
        value using salinity in PSU

    Returns
    -------
    Numeric
        Water vapor pressure in millibar
    """
    return air_thermo.water_vapor_pressure(t, p, rh, sp)