Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move qc features into dedicated library #160

Merged
merged 28 commits into from
Sep 7, 2023
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Move rinex-qc features into dedicated library
Signed-off-by: Guillaume W. Bres <guillaume.bressaix@gmail.com>
  • Loading branch information
gwbres committed Sep 7, 2023
commit 56f420e9e73762b8b6159405d969c5b726279e77
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[workspace]
members = ["rinex", "crx2rnx", "rnx2crx", "rinex-cli", "ublox-rnx", "sinex"]
members = ["rinex", "crx2rnx", "rnx2crx", "qc-traits", "rinex-qc", "rinex-cli", "ublox-rnx", "sinex"]
21 changes: 21 additions & 0 deletions qc-traits/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
[package]
name = "rinex-qc-traits"
version = "0.1.0"
license = "MIT OR Apache-2.0"
authors = ["Guillaume W. Bres <guillaume.bressaix@gmail.com>"]
description = "RINEX quality analysis specific traits"
homepage = "https://github.com/georust/rinex"
repository = "https://github.com/georust/rinex"
keywords = ["rinex", "timing", "gps", "glonass", "galileo"]
categories = ["science", "science::geo", "parsing"]
edition = "2021"

[features]
default = [] # no features by default

[package.metadata.docs.rs]
all-features = true
rustdoc-args = ["--cfg", "docrs", "--generate-link-to-definition"]

[dependencies]
horrorshow = "0.8"
11 changes: 11 additions & 0 deletions qc-traits/src/html.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
//! RINEX QC reports in HTML
use horrorshow::RenderBox;

pub trait HtmlReport {
/// Renders self to plain HTML.
/// Generates a whole HTML entity.
fn to_html(&self) -> String;
/// Renders self as an HTML node
/// to embed within external HTML.
fn to_inline_html(&self) -> Box<dyn RenderBox +'_>;
}
4 changes: 4 additions & 0 deletions qc-traits/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
//! Specific traits to generate RINEX quality reports.

mod html;
pub use html::HtmlReport;
3 changes: 2 additions & 1 deletion rinex-cli/Cargo.toml
Original file line number Diff line number Diff line change
@@ -18,7 +18,8 @@ pretty_env_logger = "0.5"
clap = { version = "4", features = ["derive", "color"] }
rand = "0.8"
serde_json = "1"
sp3 = "1.0.0"
sp3 = { version = "1.0.0", features = ["serde", "flate2"] }
rinex-qc = { path = "../rinex-qc" }
rinex = { path = "../rinex", features = ["serde", "flate2", "sbas", "obs", "nav", "qc", "processing"] }
thiserror = "1"
itertools = "0.11"
2 changes: 1 addition & 1 deletion rinex-cli/src/analysis/sampling.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::plot::PlotContext;
use itertools::Itertools;
use plotly::Histogram; //.sorted()
use rinex::quality::QcContext;
use rinex_qc::QcContext;

/*
* Sampling histogram
3 changes: 2 additions & 1 deletion rinex-cli/src/analysis/sv_epoch.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,8 @@ use crate::plot::{build_chart_epoch_axis, generate_markers, PlotContext};
use ndarray::Array;
use plotly::common::{Marker, Mode, Title, Visible};
use plotly::layout::Axis;
use rinex::{prelude::*, quality::QcContext};
use rinex::prelude::*;
use rinex_qc::QcContext;

/*
* Sv per epoch analysis
3 changes: 2 additions & 1 deletion rinex-cli/src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use clap::parser::ValuesRef;
use clap::{Arg, ArgAction, ArgMatches, ColorChoice, Command};
use log::{error, info};
use rinex::{prelude::*, quality::QcOpts};
use rinex_qc::QcOpts;
use rinex::prelude::*;
use std::path::Path;
use std::str::FromStr;

2 changes: 1 addition & 1 deletion rinex-cli/src/identification.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::Cli;
use rinex::quality::QcContext;
use rinex::*;
use rinex_qc::QcContext;

/*
* Basic identification operations
3 changes: 2 additions & 1 deletion rinex-cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -17,10 +17,11 @@ use rinex::{
observation::{Combine, Dcb, IonoDelay, Mp},
prelude::RinexType,
prelude::*,
quality::*,
split::Split,
};

use rinex_qc::*;

use cli::Cli;
use identification::rinex_identification;
use plot::PlotContext;
2 changes: 1 addition & 1 deletion rinex-cli/src/plot/mod.rs
Original file line number Diff line number Diff line change
@@ -17,7 +17,7 @@ use plotly::{
mod record;
use rand::Rng;
use rinex::prelude::*;
use rinex::quality::QcContext;
use rinex_qc::QcContext;

mod context;
pub use context::PlotContext;
2 changes: 1 addition & 1 deletion rinex-cli/src/plot/record/ionex.rs
Original file line number Diff line number Diff line change
@@ -7,7 +7,7 @@ use plotly::{
//scatter_mapbox::Fill,
ScatterMapbox,
};
use rinex::quality::QcContext;
use rinex_qc::QcContext;

pub fn plot_tec_map(
ctx: &QcContext,
2 changes: 1 addition & 1 deletion rinex-cli/src/plot/record/meteo.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::plot::{build_chart_epoch_axis, PlotContext}; //generate_markers};
use plotly::common::{Marker, MarkerSymbol, Mode};
use rinex::prelude::*;
use rinex::quality::QcContext;
use rinex_qc::QcContext;

/*
* Plots Meteo RINEX
2 changes: 1 addition & 1 deletion rinex-cli/src/plot/record/navigation.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@
use crate::plot::{build_chart_epoch_axis, PlotContext};
use plotly::common::{Mode, Visible};
use rinex::prelude::*;
use rinex::quality::QcContext;
use rinex_qc::QcContext;

pub fn plot_navigation(ctx: &QcContext, plot_context: &mut PlotContext) {
/*
2 changes: 1 addition & 1 deletion rinex-cli/src/plot/record/observation.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::plot::{build_chart_epoch_axis, generate_markers, PlotContext};
use plotly::common::{Marker, MarkerSymbol, Mode, Visible};
use rinex::quality::QcContext;
use rinex_qc::QcContext;
use rinex::{observation::*, prelude::*};
use std::collections::HashMap;

2 changes: 1 addition & 1 deletion rinex-cli/src/plot/record/sp3.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::plot::{build_chart_epoch_axis, PlotContext};
use plotly::common::{Mode, Visible};
use rinex::prelude::Epoch;
use rinex::quality::QcContext;
use rinex_qc::QcContext;
/*
* Plots High Precision Orbit and Clock data
* provided in the form of an SP3 file
2 changes: 1 addition & 1 deletion rinex-cli/src/plot/skyplot.rs
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ use plotly::{
ScatterPolar,
};
use rinex::prelude::Epoch;
use rinex::quality::QcContext;
use rinex_qc::QcContext;

/*
* Skyplot view
2 changes: 1 addition & 1 deletion rinex-cli/src/preprocessing.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,7 @@ use std::str::FromStr;

use crate::Cli;
use rinex::preprocessing::*;
use rinex::quality::QcContext;
use rinex_qc::QcContext;

pub fn preprocess(ctx: &mut QcContext, cli: &Cli) {
// GNSS filters
18 changes: 7 additions & 11 deletions rinex-qc/src/Cargo.toml → rinex-qc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -24,16 +24,12 @@ serde_json = { version = "1.0", features = ["preserve_order"] }

[dependencies]
serde = { version = "1.0", optional = true, default-features = false, features = ["derive"] }
horrorshow = { version = "0.8" }
hifitime = "3.8"
strum = "0.25"
strum_macros = "0.25"
horrorshow = "0.8"
itertools = "0.11.0"
statrs = { version = "0.16", optional = true }
sp3 = { version = "1.0.0", optional = true, features = ["serde", "flate2"] }
rinex-qc-traits = { path = "../qc-traits", optional = true }
sp3 = { version = "1.0.0", features = ["serde"] }
rinex-qc-traits = { path = "../qc-traits" }
rinex = { path = "../rinex", features = ["obs", "nav", "qc", "processing"] }

[dev-dependencies]
serde_json = "1"
criterion = "0.5"

[[bench]]
name = "benchmark"
harness = false
7 changes: 3 additions & 4 deletions rinex-qc/src/analysis/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::prelude::*;
use rinex::prelude::*;
use rinex_qc_traits::HtmlReport;
use super::{pretty_array, QcOpts};
use horrorshow::{helper::doctype, RenderBox}; //table_lengthy_td
use crate::{pretty_array, QcOpts};
use horrorshow::{html, box_html, helper::doctype, RenderBox}; //table_lengthy_td

mod sv;

@@ -37,7 +37,6 @@ impl QcAnalysis {
Self {
sv: QcSvAnalysis::new(primary, opts),
sampling: QcSamplingAnalysis::new(primary, opts),
#[cfg(feature = "obs")]
observ: QcObsAnalysis::new(primary, opts),
}
}
26 changes: 11 additions & 15 deletions rinex-qc/src/analysis/obs.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
use crate::{carrier, observation::Snr, prelude::*, Carrier};
use itertools::Itertools;
use std::str::FromStr;
use horrorshow::RenderBox;
use rinex_qc_traits::HtmlReport;

use super::{pretty_array, QcOpts};
use itertools::Itertools;
use std::collections::HashMap;
use horrorshow::{box_html, RenderBox};

use statrs::statistics::Statistics;
use crate::{pretty_array, QcOpts};

use rinex::observation::Snr;
use rinex::preprocessing::Derivative;
use rinex::carrier;
use rinex::carrier::Carrier;
use rinex::prelude::{Rinex, Epoch, EpochFlag, Observable};

#[cfg(feature = "processing")]
use crate::preprocessing::*; // include preprocessing toolkit when feasible,
// for complete analysis
use rinex_qc_traits::HtmlReport;
use statrs::statistics::Statistics;

/*
* GNSS signal special formatting
@@ -354,13 +355,10 @@ pub struct QcObsAnalysis {
total_with_obs: usize,
/// Complete epochs, with respect to given signal
complete_epochs: Vec<(Carrier, usize)>,
#[cfg(feature = "obs")]
/// Min. & Max. SNR (signal @ epoch)
snr_stats: HashMap<Observable, ((Epoch, f64), (Epoch, f64))>,
#[cfg(feature = "obs")]
/// SSI statistical analysis (mean, stddev)
ssi_stats: HashMap<Observable, (f64, f64)>,
#[cfg(feature = "obs")]
/// RX clock drift
clock_drift: Vec<(Epoch, f64)>,
}
@@ -529,10 +527,8 @@ impl QcObsAnalysis {
for (obs, data) in snr {
let values: Vec<f64> = data.iter().map(|(_e, value)| *value).collect();
let min = values.clone().min();
println!("MIN: {}", min);
let epoch_min = data.iter().find(|(_e, value)| *value == min).unwrap().0;
let max = values.clone().max();
println!("MAX: {}", max);
let epoch_max = data.iter().find(|(_e, value)| *value == max).unwrap().0;
snr_stats.insert(obs, ((epoch_min, min), (epoch_max, max)));
}
8 changes: 3 additions & 5 deletions rinex-qc/src/analysis/sampling.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use hifitime::Unit;
use horrorshow::box_html;
use rinex::prelude::{Rinex, Epoch, EpochFlag, Duration};

use super::QcOpts;
use crate::prelude::*;
use crate::QcOpts;

#[derive(Debug, Clone)]
pub struct QcSamplingAnalysis {
@@ -19,8 +20,6 @@ pub struct QcSamplingAnalysis {
pub gaps: Vec<(Epoch, Duration)>,
/// Epoch anomalies such as
/// possible receiver loss of lock, bad conditions..
#[cfg(feature = "obs")]
#[cfg_attr(docrs, doc(cfg(feature = "obs")))]
pub anomalies: Vec<(Epoch, EpochFlag)>,
}

@@ -33,7 +32,6 @@ impl QcSamplingAnalysis {
sample_rate: rnx.sample_rate(),
dominant_sample_rate: rnx.dominant_sample_rate(),
gaps: rnx.data_gaps(opts.gap_tolerance).collect(),
#[cfg(feature = "obs")]
anomalies: rnx.epoch_anomalies().collect(),
}
}
6 changes: 3 additions & 3 deletions rinex-qc/src/analysis/sv.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::prelude::*;
use super::{pretty_array, QcOpts};
use rinex::prelude::Rinex;

use horrorshow::RenderBox;
use rinex_qc_traits::HtmlReport;
use horrorshow::{box_html, RenderBox};

#[derive(Debug, Clone)]
pub struct QcSvAnalysis {
@@ -20,7 +20,7 @@ impl QcSvAnalysis {

impl HtmlReport for QcSvAnalysis {
fn to_html(&self) -> String {
todo!()
panic!("sv analysis cannot be rendered on its own")
}
fn to_inline_html(&self) -> Box<dyn RenderBox + '_> {
box_html! {
6 changes: 2 additions & 4 deletions rinex-qc/src/context.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
use std::path::PathBuf;
use rinex_qc_traits::HtmlReport;
use horrorshow::{helper::doctype, RenderBox};

use crate::Rinex;
use crate::prelude::GroundPosition;
use rinex::prelude::{Rinex, GroundPosition};
use horrorshow::{html, box_html, helper::doctype, RenderBox};

use sp3::prelude::SP3;

9 changes: 6 additions & 3 deletions rinex-qc/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
//! RINEX Quality analysis library
use strum_macros::EnumString;
use rinex_qc_traits::HtmlReport;
use horrorshow::html;
use horrorshow::helper::doctype;
use rinex_qc_traits::HtmlReport;

mod opts;
pub use opts::{QcOpts, QcClassification};

mod context;
pub use::context::{QcContext, QcPrimaryData, QcExtraData};
pub use context::{QcContext, QcPrimaryData, QcExtraData};

mod analysis;
use analysis::Analysis;
use analysis::QcAnalysis;

#[derive(Debug, Clone, PartialEq, PartialOrd, Hash, Eq, EnumString)]
pub enum Grade {
@@ -74,6 +75,8 @@ pub(crate) fn pretty_array<A: std::fmt::Display>(list: &Vec<A>) -> String {
s
}

use rinex::preprocessing::{Preprocessing, MaskFilter, MaskOperand, TargetItem};

pub struct QcReport {}

impl QcReport {
Loading