// Traits pub use crate::traits::{Configurable, Plotable, Saveable}; use core::fmt::Display; use core::ops::Add; pub mod bin; pub mod comparison; pub mod error; pub mod violin; pub use bin::{ProcessBin, ProcessBins}; pub use comparison::Processes; pub use error::{ProcessError, ProcessErrors}; pub use violin::{ProcessViolin, ProcessViolins}; /// Indexed sequence of values. /// /// # Remarks /// /// With the [prelude] module, we can easily convert a tuple of [IntoIterator] structs /// into [Process] for ease of use. The same can be achieved with the /// [new] method. /// /// # Examples /// /// Quick plot. /// ```no_run /// use preexplorer::prelude::*; /// ((0..10), (0..10)).preexplore().plot("my_identifier").unwrap(); /// ``` /// /// Compare [Process] structs. /// ```no_run /// use preexplorer::prelude::*; /// pre::Processes::new(vec![ /// ((0..10), (0..10)).preexplore(), /// ((0..10), (0..10)).preexplore(), /// ]) /// .plot("my_identifier").unwrap(); /// ``` /// /// [prelude]: prelude/index.html /// [IntoIterator]: https://doc.rust-lang.org/core/iter/trait.IntoIterator.html /// [Process]: struct.Process.html /// [new]: struct.Process.html#method.new #[derive(Debug, PartialEq, Clone)] #[cfg_attr(feature = "use-serde", derive(serde::Serialize, serde::Deserialize))] pub struct Process where T: Display + Clone, S: Display + Clone, { domain: Vec, image: Vec, config: crate::configuration::Configuration, } impl Process where T: Display + Clone, S: Display + Clone, { /// Construct a new ``Process``. /// /// # Examples /// /// From a complicated computation. /// ``` /// use preexplorer::prelude::*; /// let data = (0..10).map(|i| i * i + 1); /// let pro = pre::Process::new((0..10), data); /// ``` pub fn new(domain: I, image: J) -> Process where I: IntoIterator, J: IntoIterator, { let domain: Vec = domain.into_iter().collect(); let image: Vec = image.into_iter().collect(); let config = crate::configuration::Configuration::default(); Process { domain, image, config, } } } impl Add for Process where T: Display + Clone, S: Display + Clone, { type Output = crate::Processes; fn add(self, other: crate::Process) -> crate::Processes { let mut cmp = self.into(); cmp += other; cmp } } impl Configurable for Process where T: Display + Clone, S: Display + Clone, { fn configuration_mut(&mut self) -> &mut crate::configuration::Configuration { &mut self.config } fn configuration(&self) -> &crate::configuration::Configuration { &self.config } } impl Saveable for Process where T: Display + Clone, S: Display + Clone, { fn plotable_data(&self) -> String { // Initial warning if self.domain.is_empty() { eprintln!("Warning: There is no data."); } let mut plotable_data = String::new(); for (time, value) in self.domain.clone().into_iter().zip(self.image.clone()) { plotable_data.push_str(&format!("{}\t{}\n", time, value)); } plotable_data } } impl Plotable for Process where T: Display + Clone, S: Display + Clone, { fn plot_script(&self) -> String { let mut gnuplot_script = self.opening_plot_script(); let dashtype = self.dashtype().unwrap_or(1); gnuplot_script += &format!( "plot {:?} using 1:2 with {} dashtype {}\n", self.data_path(), self.style(), dashtype, ); gnuplot_script += &self.ending_plot_script(); gnuplot_script } }