1
  2
  3
  4
  5
  6
  7
  8
  9
 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
// FIXME: Add some examples of using analysis functions.
/*!
Functions and data types for analyzing soundings from radiosondes or models.

Library to represent an atmospheric sounding with pressure as the vertical coordinate.

# Examples
```
use optional::{Optioned, some};
use metfor::{HectoPascal, Celsius, Feet};

use sounding_analysis::{Sounding, StationInfo};

fn main() {

    // Create  pressure profile
    let pressure_profile: Vec<Optioned<HectoPascal>> =
        vec![1000.0, 925.0, 850.0, 700.0, 500.0, 300.0, 250.0, 100.0]
            .into_iter()
            .map(HectoPascal)
            .map(some)
            .collect();

    // Create a temperature profile
    let temperature_profile: Vec<Optioned<Celsius>> =
        vec![13.0, 7.0, 5.0, -4.5, -20.6, -44.0, -52.0, -56.5]
            .into_iter()
            .map(Celsius)
            .map(some)
            .collect();

    // Create some station info
    let stn = StationInfo::new_with_values(None, (45.6789, -115.6789), Feet(992.0));

    // Create a valid time. This uses a `chrono::NaiveDateTime`, and you should always assume
    // that valid times are in UTC.
    let vt = chrono::NaiveDate::from_ymd(2018,3,8).and_hms(12,0,0);

    // Use the builder pattern to construct a sounding.
    let snd = Sounding::new()
        .with_station_info(stn)
        .with_valid_time(vt)
        .with_lead_time(24)  // Lead time in hours for forecast soundings.
        .with_pressure_profile(pressure_profile)
        .with_temperature_profile(temperature_profile)
        .with_station_pressure(some(HectoPascal(1013.25)))
        .with_sfc_temperature(some(Celsius(15.0)));

    // Top down and bottom up iterators are provided. If surface data is available, it is
    // inserted into the profile.
    let mut iter = snd.top_down();

    let mut data_row = iter.next().unwrap();
    assert_eq!(data_row.pressure, some(HectoPascal(100.0)));
    assert_eq!(data_row.temperature, some(Celsius(-56.5)));

    data_row = iter.next().unwrap();
    assert_eq!(data_row.pressure, some(HectoPascal(250.0)));
    assert_eq!(data_row.temperature, some(Celsius(-52.0)));

    data_row = iter.next().unwrap();
    assert_eq!(data_row.pressure, some(HectoPascal(300.0)));
    assert_eq!(data_row.temperature, some(Celsius(-44.0)));

    data_row = iter.next().unwrap();
    assert_eq!(data_row.pressure, some(HectoPascal(500.0)));
    assert_eq!(data_row.temperature, some(Celsius(-20.6)));

    data_row = iter.next().unwrap();
    assert_eq!(data_row.pressure, some(HectoPascal(700.0)));
    assert_eq!(data_row.temperature, some(Celsius(-4.5)));

    data_row = iter.next().unwrap();
    assert_eq!(data_row.pressure, some(HectoPascal(850.0)));
    assert_eq!(data_row.temperature, some(Celsius(5.0)));

    data_row = iter.next().unwrap();
    assert_eq!(data_row.pressure, some(HectoPascal(925.0)));
    assert_eq!(data_row.temperature, some(Celsius(7.0)));

    data_row = iter.next().unwrap();
    assert_eq!(data_row.pressure, some(HectoPascal(1000.0)));
    assert_eq!(data_row.temperature, some(Celsius(13.0)));

    // THIS ONE IS THE SURFACE DATA!
    data_row = iter.next().unwrap();
    assert_eq!(data_row.pressure, some(HectoPascal(1013.25)));
    assert_eq!(data_row.temperature, some(Celsius(15.0)));

    assert_eq!(iter.next(), None);

    // Profiles and surface values can also be accessed via getter methods. Read the docs!
}
```

You probably noticed a lot of `optional::Optioned`s in the example. Basically, anything can be
missing, and missing values are common in upper air soundings. For example, at high altitude the
dew point or humidity are often missing (if not totally inaccurate).

*/
#![doc(test(attr(deny(warnings))))]
#![deny(missing_docs)]

//
// API
//
#[allow(deprecated)]
pub use crate::{
    error::{AnalysisError, Result},
    indexes::{haines, haines_high, haines_low, haines_mid, hot_dry_windy, precipitable_water},
    interpolation::{linear_interpolate, linear_interpolate_sounding},
    layers::{
        cold_surface_temperature_layer, dendritic_snow_zone, effective_inflow_layer,
        hail_growth_zone, inversions, layer_agl, melting_freezing_energy_area, pressure_layer,
        sfc_based_inversion, warm_surface_temperature_layer, warm_temperature_layer_aloft,
        warm_wet_bulb_layer_aloft, Layer, Layers,
    },
    levels::{
        freezing_levels, max_temperature_in_layer, max_temperature_in_profile,
        max_wet_bulb_in_layer, max_wet_bulb_in_profile, wet_bulb_zero_levels, Level, Levels,
    },
    parcel::{
        average_parcel, convective_parcel, effective_layer_parcel, lowest_level_parcel,
        mixed_layer_parcel, most_unstable_parcel, pressure_parcel, surface_parcel, Parcel,
    },
    parcel_profile::{
        dcape, lift_parcel, mix_down, robust_convective_parcel_ascent, ParcelAscentAnalysis,
        ParcelProfile,
    },
    precip_type::{
        adjust_precip_type_intensity, bourgouin_precip_type, check_precip_type_intensity,
        nssl_precip_type, PrecipType,
    },
    profile::{
        equivalent_potential_temperature, hydrolapse, potential_temperature, relative_humidity,
        relative_humidity_ice, sfc_to_level_temperature_lapse_rate, temperature_lapse_rate,
        theta_e_lapse_rate, wet_bulb,
    },
    sounding::{DataRow, Sounding, StationInfo},
    wind::{bunkers_storm_motion, mean_wind, sr_helicity},
};

pub mod experimental;

#[doc(hidden)]
pub use crate::sounding::doctest;

//
// Internal use only
//

// Modules
mod error;
mod indexes;
mod interpolation;
mod layers;
mod levels;
mod parcel;
mod parcel_profile;
mod precip_type;
mod profile;
mod sounding;
mod wind;