#weather #sounding #meteorology #skew-t


Data formats and algorithms for atmospheric soundings. The base crate is meant to be a common base for other crates to build on. These crates may be for managing a data-store, displaying data, or saving and loading files.

31 releases (10 breaking)

✓ Uses Rust 2018 edition

new 0.10.0 Jan 13, 2019
0.9.2 Dec 25, 2018
0.8.1 Nov 28, 2018
0.7.0 Jun 2, 2018
0.1.0 Nov 30, 2017

#14 in Science

Download history 24/week @ 2018-10-27 147/week @ 2018-11-03 221/week @ 2018-11-10 76/week @ 2018-11-17 33/week @ 2018-11-24 272/week @ 2018-12-01 90/week @ 2018-12-08 57/week @ 2018-12-15 44/week @ 2018-12-22 357/week @ 2018-12-29 10/week @ 2019-01-05 45/week @ 2019-01-12 124/week @ 2019-01-19

500 downloads per month
Used in 4 crates (3 directly)

Custom license

756 lines

Build Status Build status Latest Version docs


Library to represent an atmospheric sounding with pressure as the vertical coordinate. The base crate is meant to be a common base for other crates to build on. These crates may be for managing a data-store, displaying data, or saving and loading files.

The emphasis of this crate is data representation and a common type for systems using sounding data to build on and use.


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

use sounding_base::{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]

    // 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]

    // 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_lead_time(24)  // Lead time in hours for forecast soundings.

    // 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)));

    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::Optioneds 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).


~13K SLoC