Skip to content

Commit

Permalink
Context improvements (#209)
Browse files Browse the repository at this point in the history
* Improve context definitions and clock usage
* clk interpolation will always be required
* improving context definition & usage
---------

Signed-off-by: Guillaume W. Bres <[email protected]>
  • Loading branch information
gwbres authored Mar 11, 2024
1 parent 0b4ea04 commit e9f9838
Show file tree
Hide file tree
Showing 29 changed files with 1,061 additions and 1,218 deletions.
32 changes: 16 additions & 16 deletions rinex-cli/src/analysis/sampling.rs
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
use crate::graph::PlotContext;
use itertools::Itertools;
use plotly::Histogram; //.sorted()
use rinex::prelude::RnxContext;
use plotly::Histogram;
use rinex::prelude::{ProductType, RnxContext};

/*
* Sampling histogram
*/
pub fn histogram(ctx: &RnxContext, plot_ctx: &mut PlotContext) {
plot_ctx.add_timedomain_plot("Sampling Histogram", "Count");
if let Some(data) = ctx.obs_data() {
let histogram = data.sampling_histogram().sorted();
let durations: Vec<_> = histogram.clone().map(|(dt, _)| dt.to_string()).collect();
let populations: Vec<_> = histogram.clone().map(|(_, pop)| pop.to_string()).collect();
let histogram = Histogram::new_xy(durations, populations).name("Sampling Histogram");
plot_ctx.add_trace(histogram);
}
// Run similar analysis on NAV context
if let Some(data) = &ctx.nav_data() {
let histogram = data.sampling_histogram().sorted();
let durations: Vec<_> = histogram.clone().map(|(dt, _)| dt.to_string()).collect();
let populations: Vec<_> = histogram.clone().map(|(_, pop)| pop.to_string()).collect();
let histogram = Histogram::new_xy(durations, populations).name("(NAV) Sampling Histogram");
plot_ctx.add_trace(histogram);
for product in [
ProductType::Observation,
ProductType::MeteoObservation,
ProductType::BroadcastNavigation,
ProductType::HighPrecisionClock,
ProductType::Ionex,
] {
if let Some(data) = ctx.rinex(product) {
let histogram = data.sampling_histogram().sorted();
let durations: Vec<_> = histogram.clone().map(|(dt, _)| dt.to_string()).collect();
let populations: Vec<_> = histogram.clone().map(|(_, pop)| pop.to_string()).collect();
let histogram = Histogram::new_xy(durations, populations).name(&format!("{}", product));
plot_ctx.add_trace(histogram);
}
}
}
109 changes: 7 additions & 102 deletions rinex-cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use std::{
};

use clap::{value_parser, Arg, ArgAction, ArgMatches, ColorChoice, Command};
use map_3d::{ecef2geodetic, geodetic2ecef, rad2deg, Ellipsoid};
use rinex::prelude::*;
use walkdir::WalkDir;

use crate::{fops::open_with_web_browser, Error};

use map_3d::{geodetic2ecef, Ellipsoid};

// identification mode
mod identify;
// graph mode
Expand Down Expand Up @@ -54,6 +54,9 @@ pub struct Context {
/// $WORKSPACE is either manually definedd by CLI or we create it (as is).
/// $PRIMARYFILE is determined from the most major file contained in the dataset.
pub workspace: PathBuf,
/// Context name is derived from the primary file loaded in Self,
/// and mostly used in session products generation.
pub name: String,
/// (RX) reference position to be used in further analysis.
/// It is either (priority order is important)
/// 1. manually defined by CLI
Expand All @@ -68,7 +71,7 @@ impl Context {
*/
pub fn context_stem(data: &RnxContext) -> String {
let ctx_major_stem: &str = data
.rinex_path()
.primary_path()
.expect("failed to determine a context name")
.file_stem()
.expect("failed to determine a context name")
Expand Down Expand Up @@ -111,104 +114,6 @@ impl Context {
open_with_web_browser(path.to_string_lossy().as_ref());
}
}
/*
* Creates File/Data context defined by user.
* Regroups all provided files/folders,
*/
pub fn from_cli(cli: &Cli) -> Result<Self, Error> {
let mut data = RnxContext::default();
let max_depth = match cli.matches.get_one::<u8>("depth") {
Some(value) => *value as usize,
None => 5usize,
};

/* load all directories recursively, one by one */
for dir in cli.input_directories() {
let walkdir = WalkDir::new(dir).max_depth(max_depth);
for entry in walkdir.into_iter().filter_map(|e| e.ok()) {
if !entry.path().is_dir() {
let path = entry.path();
let ret = data.load(&path.to_path_buf());
if ret.is_err() {
warn!(
"failed to load \"{}\": {}",
path.display(),
ret.err().unwrap()
);
}
}
}
}
// load individual files, if any
for filepath in cli.input_files() {
let ret = data.load(&Path::new(filepath).to_path_buf());
if ret.is_err() {
warn!("failed to load \"{}\": {}", filepath, ret.err().unwrap());
}
}
let data_stem = Self::context_stem(&data);
let data_position = data.ground_position();
Ok(Self {
data,
quiet: cli.matches.get_flag("quiet"),
workspace: {
let path = match std::env::var("RINEX_WORKSPACE") {
Ok(path) => Path::new(&path).join(data_stem).to_path_buf(),
_ => match cli.matches.get_one::<PathBuf>("workspace") {
Some(base_dir) => Path::new(base_dir).join(data_stem).to_path_buf(),
None => Path::new("WORKSPACE").join(data_stem).to_path_buf(),
},
};
// make sure the workspace is viable and exists, otherwise panic
create_dir_all(&path).unwrap_or_else(|e| {
panic!(
"failed to create session workspace \"{}\": {:?}",
path.display(),
e
)
});
info!("session workspace is \"{}\"", path.to_string_lossy());
path
},
rx_ecef: {
match cli.manual_position() {
Some((x, y, z)) => {
let (mut lat, mut lon, _) = ecef2geodetic(x, y, z, Ellipsoid::WGS84);
lat = rad2deg(lat);
lon = rad2deg(lon);
info!(
"using manually defined position: {:?} [ECEF] (lat={:.5}°, lon={:.5}°",
(x, y, z),
lat,
lon
);
Some((x, y, z))
},
None => {
if let Some(data_pos) = data_position {
let (x, y, z) = data_pos.to_ecef_wgs84();
let (mut lat, mut lon, _) = ecef2geodetic(x, y, z, Ellipsoid::WGS84);
lat = rad2deg(lat);
lon = rad2deg(lon);
info!(
"position defined in dataset: {:?} [ECEF] (lat={:.5}°, lon={:.5}°",
(x, y, z),
lat,
lon
);
Some((x, y, z))
} else {
// this is not a problem in basic opmodes,
// but will most likely prevail advanced opmodes.
// Let the user know.
warn!("no RX position defined");
None
}
},
}
},
})
}
}

impl Cli {
Expand All @@ -219,7 +124,7 @@ impl Cli {
Command::new("rinex-cli")
.author("Guillaume W. Bres, <[email protected]>")
.version(env!("CARGO_PKG_VERSION"))
.about("RINEX post processing (command line)")
.about("RINEX post processing")
.arg_required_else_help(true)
.color(ColorChoice::Always)
.arg(Arg::new("filepath")
Expand Down
2 changes: 1 addition & 1 deletion rinex-cli/src/cli/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ pub fn subcommand() -> Command {
.short_flag('s')
.long_flag("split")
.arg_required_else_help(true)
.about("Split input files at specified Epoch.")
.about("Split input file(s) at specified Epoch")
.arg(
Arg::new("split")
.value_parser(value_parser!(Epoch))
Expand Down
Loading

0 comments on commit e9f9838

Please sign in to comment.