pub struct DORIS {
pub header: Header,
pub record: Record,
pub production: Option<ProductionAttributes>,
}Expand description
DORIS is composed of a Header and a Record section.
use std::str::FromStr;
use doris_rs::prelude::*;
let doris = DORIS::from_gzip_file("data/DOR/V3/cs2rx18164.gz")
.unwrap();
assert_eq!(doris.header.satellite, "CRYOSAT-2");
let agency = "CNES".to_string(); // Agency / producer
let program = "Expert".to_string(); // Software name
let run_by = "CNES".to_string(); // Operator
let date = "20180614 090016 UTC".to_string(); // Date of production
let observer = "SPA_BN1_4.7P1".to_string(); // Operator
assert_eq!(doris.header.program, Some(program));
assert_eq!(doris.header.run_by, Some(run_by));
assert_eq!(doris.header.date, Some(date)); // currently not interpreted
assert_eq!(doris.header.observer, Some(observer));
assert_eq!(doris.header.agency, Some(agency));
assert!(doris.header.doi.is_none());
assert!(doris.header.license.is_none());
let observables = vec![
Observable::UnambiguousPhaseRange(Frequency::DORIS1), // phase, in meters of prop.
Observable::UnambiguousPhaseRange(Frequency::DORIS2),
Observable::PseudoRange(Frequency::DORIS1), // decoded pseudo range
Observable::PseudoRange(Frequency::DORIS2),
Observable::Power(Frequency::DORIS1), // received power
Observable::Power(Frequency::DORIS2), // received power
Observable::FrequencyRatio, // f1/f2 ratio (=drift image)
Observable::Pressure, // pressure, at ground station level (hPa)
Observable::Temperature, // temperature, at ground station level (°C)
Observable::HumidityRate, // saturation rate, at ground station level (%)
];
assert_eq!(doris.header.observables, observables);
assert_eq!(doris.header.ground_stations.len(), 53); // network
// Stations helper
let site_matcher = Matcher::Site("TOULOUSE");
let toulouse = GroundStation::default()
.with_domes(DOMES::from_str("10003S005").unwrap())
.with_site_name("TOULOUSE") // site name
.with_site_label("TLSB") // site label/mnemonic
.with_unique_id(13) // file dependent
.with_frequency_shift(0) // f1/f2 site shift for this day
.with_beacon_revision(3); // DORIS 3rd generation
// helper
assert_eq!(doris.ground_station(site_matcher), Some(toulouse));Fields§
§header: HeaderHeader gives general information
record: RecordRecord gives the actual file content
production: Option<ProductionAttributes>ProductionAttributes is attached to files that were named according to the standard conventions.
Implementations§
Source§impl DORIS
impl DORIS
Sourcepub fn with_header(&self, header: Header) -> Self
pub fn with_header(&self, header: Header) -> Self
Sourcepub fn replace_header(&mut self, header: Header)
pub fn replace_header(&mut self, header: Header)
Replace Header with mutable access.
Sourcepub fn with_record(&self, record: Record) -> Self
pub fn with_record(&self, record: Record) -> Self
Sourcepub fn replace_record(&mut self, record: Record)
pub fn replace_record(&mut self, record: Record)
Replace Record with mutable access.
Sourcepub fn format<W: Write>(
&self,
writer: &mut BufWriter<W>,
) -> Result<(), FormattingError>
pub fn format<W: Write>( &self, writer: &mut BufWriter<W>, ) -> Result<(), FormattingError>
Format DORIS into writable I/O using efficient buffered writer and following standard specifications. This is the mirror operation of Self::parse.
Sourcepub fn from_file<P: AsRef<Path>>(path: P) -> Result<DORIS, ParsingError>
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<DORIS, ParsingError>
Parses DORIS from local readable file.
Sourcepub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), FormattingError>
pub fn to_file<P: AsRef<Path>>(&self, path: P) -> Result<(), FormattingError>
Dumps DORIS into writable local file (as readable ASCII UTF-8) using efficient buffered formatting. This is the mirror operation of Self::from_file.
use doris_rs::prelude::*;
let doris = DORIS::from_gzip_file("data/DOR/V3/cs2rx18164.gz")
.unwrap();
doris.to_file("demo.txt")
.unwrap();
let parsed = DORIS::from_file("demo.txt")
.unwrap();
assert_eq!(parsed.header.satellite, "CRYOSAT-2");
assert_eq!(parsed.header.ground_stations.len(), 53); // NetworkSourcepub fn from_gzip_file<P: AsRef<Path>>(path: P) -> Result<DORIS, ParsingError>
Available on crate feature flate2 only.
pub fn from_gzip_file<P: AsRef<Path>>(path: P) -> Result<DORIS, ParsingError>
flate2 only.Parses DORIS from local gzip compressed file.
use std::str::FromStr;
use doris_rs::prelude::*;
let doris = DORIS::from_gzip_file("data/DOR/V3/cs2rx18164.gz")
.unwrap();
assert_eq!(doris.header.satellite, "CRYOSAT-2");
let agency = "CNES".to_string(); // Agency / producer
let program = "Expert".to_string(); // Software name
let run_by = "CNES".to_string(); // Operator
let date = "20180614 090016 UTC".to_string(); // Date of production
let observer = "SPA_BN1_4.7P1".to_string(); // Operator
assert_eq!(doris.header.program, Some(program));
assert_eq!(doris.header.run_by, Some(run_by));
assert_eq!(doris.header.date, Some(date)); // currently not interpreted
assert_eq!(doris.header.observer, Some(observer));
assert_eq!(doris.header.agency, Some(agency));
assert!(doris.header.doi.is_none());
assert!(doris.header.license.is_none());
let observables = vec![
Observable::UnambiguousPhaseRange(Frequency::DORIS1), // phase, in meters of prop.
Observable::UnambiguousPhaseRange(Frequency::DORIS2),
Observable::PseudoRange(Frequency::DORIS1), // decoded pseudo range
Observable::PseudoRange(Frequency::DORIS2),
Observable::Power(Frequency::DORIS1), // received power
Observable::Power(Frequency::DORIS2), // received power
Observable::FrequencyRatio, // f1/f2 ratio (=drift image)
Observable::Pressure, // pressure, at ground station level (hPa)
Observable::Temperature, // temperature, at ground station level (°C)
Observable::HumidityRate, // saturation rate, at ground station level (%)
];
assert_eq!(doris.header.observables, observables);
assert_eq!(doris.header.ground_stations.len(), 53); // network
// Stations helper
let site_matcher = Matcher::Site("TOULOUSE");
let toulouse = GroundStation::default()
.with_domes(DOMES::from_str("10003S005").unwrap())
.with_site_name("TOULOUSE") // site name
.with_site_label("TLSB") // site label/mnemonic
.with_unique_id(13) // file dependent
.with_frequency_shift(0) // f1/f2 site shift for this day
.with_beacon_revision(3); // DORIS 3rd generation
// helper
assert_eq!(doris.ground_station(site_matcher), Some(toulouse));Sourcepub fn to_gzip_file<P: AsRef<Path>>(
&self,
path: P,
) -> Result<(), FormattingError>
Available on crate feature flate2 only.
pub fn to_gzip_file<P: AsRef<Path>>( &self, path: P, ) -> Result<(), FormattingError>
flate2 only.Dumps and gzip encodes DORIS into writable local file, using efficient buffered formatting. This is the mirror operation of Self::from_gzip_file.
use doris_rs::prelude::*;
let doris = DORIS::from_gzip_file("data/DOR/V3/cs2rx18164.gz")
.unwrap();
doris.to_gzip_file("demo.gz")
.unwrap();
let parsed = DORIS::from_gzip_file("demo.gz")
.unwrap();
assert_eq!(parsed.header.satellite, "CRYOSAT-2");
assert_eq!(parsed.header.ground_stations.len(), 53); // NetworkSourcepub fn is_merged(&self) -> bool
pub fn is_merged(&self) -> bool
Determines whether this structure results of combining several structures into a single one. This is determined by the presence of a custom yet somewhat standardized Header comment.
Sourcepub fn ground_station<'a>(&self, matcher: Matcher<'a>) -> Option<GroundStation>
pub fn ground_station<'a>(&self, matcher: Matcher<'a>) -> Option<GroundStation>
Returns GroundStation information for matching site
Sourcepub fn satellite_clock_offset_iter(
&self,
) -> Box<dyn Iterator<Item = (Epoch, ClockOffset)> + '_>
pub fn satellite_clock_offset_iter( &self, ) -> Box<dyn Iterator<Item = (Epoch, ClockOffset)> + '_>
Returns measurement satellite ClockOffset Iterator for all Epochs, in chronological order
use doris_rs::prelude::*;
let doris = DORIS::from_gzip_file("data/DOR/V3/cs2rx18164.gz")
.unwrap();
assert_eq!(doris.header.satellite, "CRYOSAT-2");
for (i, (epoch, clock_offset)) in doris.satellite_clock_offset_iter().enumerate() {
assert_eq!(clock_offset.extrapolated, false); // actual measurement
if i == 0 {
assert_eq!(clock_offset.offset.to_seconds(), -4.326631626);
} else if i == 10 {
assert_eq!(clock_offset.offset.to_seconds(), -4.326631711);
}
}Sourcepub fn sampling_histogram(
&self,
) -> Box<dyn Iterator<Item = (Duration, usize)> + '_>
pub fn sampling_histogram( &self, ) -> Box<dyn Iterator<Item = (Duration, usize)> + '_>
Returns histogram analysis of the sampling period, as (Duration, population usize) tuple.
use doris_rs::prelude::*;
use itertools::Itertools;
let doris = DORIS::from_gzip_file("data/DOR/V3/cs2rx18164.gz")
.unwrap();
// requires more than 2 measurements
let (sampling_period, population) = doris.sampling_histogram()
.sorted()
.nth(0) // dominant
.unwrap();
assert_eq!(sampling_period, Duration::from_seconds(3.0));Sourcepub fn dominant_sampling_period(&self) -> Option<Duration>
pub fn dominant_sampling_period(&self) -> Option<Duration>
Studies actual measurement rate and returns the highest value in the histogram as the dominant sampling rate
use doris_rs::prelude::*;
use itertools::Itertools;
let doris = DORIS::from_gzip_file("data/DOR/V3/cs2rx18164.gz")
.unwrap();
// requires more than 2 measurements
let sampling_period = doris.dominant_sampling_period()
.unwrap();
assert_eq!(sampling_period, Duration::from_seconds(3.0));Sourcepub fn standard_filename(&self) -> String
pub fn standard_filename(&self) -> String
Generates (guesses) a standardized (uppercase) filename from this actual DORIS data set. This is particularly useful when initiated from a file that did not follow standard naming conventions.
use doris_rs::prelude::*;
// parse standard file
let doris = DORIS::from_gzip_file("data/DOR/V3/cs2rx18164.gz")
.unwrap();
assert_eq!(doris.standard_filename(), "CS2RX18164.gz");
// Dump using random name
doris.to_file("example.txt")
.unwrap();
// parse back & use
let parsed = DORIS::from_file("example.txt")
.unwrap();
assert_eq!(parsed.header.satellite, "CRYOSAT-2");
// when coming from non standard names,
// all fields are deduced from actual content.
assert_eq!(parsed.standard_filename(), "CRYOS18164");Sourcepub fn substract(&self, rhs: &Self) -> Self
pub fn substract(&self, rhs: &Self) -> Self
Copies and returns new DORIS that is the result of ground station observation differentiation. See [Self::observations_substract_mut] for more information.
use doris_rs::prelude::*;
let parsed = DORIS::from_gzip_file("data/DOR/V3/cs2rx18164.gz")
.unwrap();
// basic example, this will produce a NULL DORIS.
// Standard use case is to use a synchronous observation of the
// same network.
let residuals = parsed.substract(&parsed);
// dump
residuals.to_file("residuals.txt")
.unwrap();Sourcepub fn substract_mut(&mut self, rhs: &Self)
pub fn substract_mut(&mut self, rhs: &Self)
Substract (in place) this DORIS file to another, creating a “residual” DORIS file. All synchronous measurements of matching stations are substracted to one another. Satellite clock offset is preserved. All other stations observations (non-synchronous, no remote counter part) are dropped: you are left with residual content only after this operation.
Trait Implementations§
impl StructuralPartialEq for DORIS
Auto Trait Implementations§
impl Freeze for DORIS
impl RefUnwindSafe for DORIS
impl Send for DORIS
impl Sync for DORIS
impl Unpin for DORIS
impl UnwindSafe for DORIS
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more