sounding_analysis/
lib.rs

1// FIXME: Add some examples of using analysis functions.
2/*!
3[![Github Actions](https://github.com/rnleach/sounding-analysis/actions/workflows/rust.yml/badge.svg)](https://github.com/rnleach/sounding-analysis/actions)
4
5Functions and data types for analyzing soundings from radiosondes or models.
6
7Library to represent an atmospheric sounding with pressure as the vertical coordinate.
8
9# Examples
10```
11use optional::{Optioned, some};
12use metfor::{HectoPascal, Celsius, Feet};
13
14use sounding_analysis::{Sounding, StationInfo};
15
16fn main() {
17
18    // Create  pressure profile
19    let pressure_profile: Vec<Optioned<HectoPascal>> =
20        vec![1000.0, 925.0, 850.0, 700.0, 500.0, 300.0, 250.0, 100.0]
21            .into_iter()
22            .map(HectoPascal)
23            .map(some)
24            .collect();
25
26    // Create a temperature profile
27    let temperature_profile: Vec<Optioned<Celsius>> =
28        vec![13.0, 7.0, 5.0, -4.5, -20.6, -44.0, -52.0, -56.5]
29            .into_iter()
30            .map(Celsius)
31            .map(some)
32            .collect();
33
34    // Create some station info
35    let stn = StationInfo::new_with_values(None, None, (45.6789, -115.6789), Feet(992.0));
36
37    // Create a valid time. This uses a `chrono::NaiveDateTime`, and you should always assume
38    // that valid times are in UTC.
39    let vt = chrono::NaiveDate::from_ymd_opt(2018,3,8).unwrap().and_hms_opt(12,0,0).unwrap();
40
41    // Use the builder pattern to construct a sounding.
42    let snd = Sounding::new()
43        .with_station_info(stn)
44        .with_valid_time(vt)
45        .with_lead_time(24)  // Lead time in hours for forecast soundings.
46        .with_pressure_profile(pressure_profile)
47        .with_temperature_profile(temperature_profile)
48        .with_station_pressure(some(HectoPascal(1013.25)))
49        .with_sfc_temperature(some(Celsius(15.0)));
50
51    // Top down and bottom up iterators are provided. If surface data is available, it is
52    // inserted into the profile.
53    let mut iter = snd.top_down();
54
55    let mut data_row = iter.next().unwrap();
56    assert_eq!(data_row.pressure, some(HectoPascal(100.0)));
57    assert_eq!(data_row.temperature, some(Celsius(-56.5)));
58
59    data_row = iter.next().unwrap();
60    assert_eq!(data_row.pressure, some(HectoPascal(250.0)));
61    assert_eq!(data_row.temperature, some(Celsius(-52.0)));
62
63    data_row = iter.next().unwrap();
64    assert_eq!(data_row.pressure, some(HectoPascal(300.0)));
65    assert_eq!(data_row.temperature, some(Celsius(-44.0)));
66
67    data_row = iter.next().unwrap();
68    assert_eq!(data_row.pressure, some(HectoPascal(500.0)));
69    assert_eq!(data_row.temperature, some(Celsius(-20.6)));
70
71    data_row = iter.next().unwrap();
72    assert_eq!(data_row.pressure, some(HectoPascal(700.0)));
73    assert_eq!(data_row.temperature, some(Celsius(-4.5)));
74
75    data_row = iter.next().unwrap();
76    assert_eq!(data_row.pressure, some(HectoPascal(850.0)));
77    assert_eq!(data_row.temperature, some(Celsius(5.0)));
78
79    data_row = iter.next().unwrap();
80    assert_eq!(data_row.pressure, some(HectoPascal(925.0)));
81    assert_eq!(data_row.temperature, some(Celsius(7.0)));
82
83    data_row = iter.next().unwrap();
84    assert_eq!(data_row.pressure, some(HectoPascal(1000.0)));
85    assert_eq!(data_row.temperature, some(Celsius(13.0)));
86
87    // THIS ONE IS THE SURFACE DATA!
88    data_row = iter.next().unwrap();
89    assert_eq!(data_row.pressure, some(HectoPascal(1013.25)));
90    assert_eq!(data_row.temperature, some(Celsius(15.0)));
91
92    assert_eq!(iter.next(), None);
93
94    // Profiles and surface values can also be accessed via getter methods. Read the docs!
95}
96```
97
98You probably noticed a lot of `optional::Optioned`s in the example. Basically, anything can be
99missing, and missing values are common in upper air soundings. For example, at high altitude the
100dew point or humidity are often missing (if not totally inaccurate).
101
102*/
103#![doc(test(attr(deny(warnings))))]
104#![deny(missing_docs)]
105
106//
107// API
108//
109pub use crate::{
110    error::{AnalysisError, Result},
111    fire::{hot_dry_windy, pft, pft_analysis, PFTAnalysis},
112    indexes::precipitable_water,
113    interpolation::{linear_interpolate, linear_interpolate_sounding},
114    layers::{
115        cold_surface_temperature_layer, dendritic_snow_zone, effective_inflow_layer,
116        hail_growth_zone, inversions, layer_agl, melting_freezing_energy_area, pressure_layer,
117        sfc_based_inversion, warm_surface_temperature_layer, warm_temperature_layer_aloft,
118        warm_wet_bulb_layer_aloft, Layer, Layers,
119    },
120    levels::{
121        freezing_levels, max_temperature_in_layer, max_temperature_in_profile,
122        max_wet_bulb_in_layer, max_wet_bulb_in_profile, wet_bulb_zero_levels, Level, Levels,
123    },
124    parcel::{
125        average_parcel, convective_parcel, effective_layer_parcel, lowest_level_parcel,
126        mixed_layer_parcel, most_unstable_parcel, pressure_parcel, surface_parcel, Parcel,
127    },
128    parcel_profile::{
129        dcape, lift_parcel, mix_down, robust_convective_parcel_ascent, ParcelAscentAnalysis,
130        ParcelProfile,
131    },
132    precip_type::{
133        bourgouin_precip_type, check_precip_type_intensity, nssl_precip_type, PrecipType,
134    },
135    profile::{
136        equivalent_potential_temperature, hydrolapse, potential_temperature, relative_humidity,
137        relative_humidity_ice, sfc_to_level_temperature_lapse_rate, temperature_lapse_rate,
138        theta_e_lapse_rate, wet_bulb,
139    },
140    sounding::{DataRow, Sounding, StationInfo},
141    wind::{bunkers_storm_motion, mean_wind, sr_helicity},
142};
143
144pub mod experimental;
145
146#[doc(hidden)]
147pub use crate::sounding::doctest;
148
149//
150// Internal use only
151//
152
153// Modules
154mod error;
155mod fire;
156mod indexes;
157mod interpolation;
158mod layers;
159mod levels;
160mod parcel;
161mod parcel_profile;
162mod precip_type;
163mod profile;
164mod sounding;
165mod wind;