1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
//! Save data and have a glance at it with quick plots.
//! Leave the detailed plotting to other interactive tools like gnuplot.
//!
//! Do you have a costly process in Rust and want to save the data for postprocessing?
//! Would you like to still have a basic glance to check it and leave fine-tuning of the plot for later?
//! This is the crate for you!
//!
//! # Philosophy
//!
//! Rust is great at computing, making the perfect plot takes times and repetition.
//! This repetitive process in search of the perfect plot should be done externally,
//! and does not need Rust computing power.
//! Therefore, once you achieve the data in Rust, save it, have a quick glance, and
//! leave a simple gnuplot-script to start the fine tunning of your perfect plot.
//!
//! # Remarks
//!
//! All data will be saved under the folder "target\\preexplorer\\data" in the main directory.
//! Plot scripts are saved under the foleder "target\\preexplorer\\plots".
//!
//! Recall that you will need to [install gnuplot](http://www.gnuplot.info/download.html)
//! to use the crate at its full potential.
//!
//! # Examples
//!
//! Quickly check your results.
//! ```no_run
//! use preexplorer::prelude::*;
//! (0..100).map(|i| i * i)
//!     .preexplore()
//!     .set_title("My computations")
//!     .plot("my_identifier")
//!     .unwrap();
//! ```
//! <img src="https://user-images.githubusercontent.com/37874270/80872430-36391780-8cb2-11ea-9b84-7cb1d95f4f58.png" height="200px">
//!
//! Check numerical simulations.
//! ```no_run
//! use preexplorer::prelude::*;
//! use rand_distr::Exp1;
//! use rand::prelude::*;
//! let simulation_results: Vec<f64> = (0..100).map(|_| thread_rng().sample(Exp1)).collect();
//! pre::Density::new(simulation_results)
//!     .set_title("Empirical Exponential 1")
//!     .plot("my_identifier")
//!     .unwrap();
//! ```
//! <img src="https://user-images.githubusercontent.com/37874270/86490968-88a5bb80-bd69-11ea-913b-9124f33629c0.png" height="200px">
//!
//! Save some data (mostly numerical: matrices, simulation results and related errors, etc).
//! ```no_run
//! use preexplorer::prelude::*;
//! let my_data = vec![0., 1.1, 0.001, 2., 2.3, 0.01, 3., 1.7, 0.02]; // Some data
//! let dimension = 2;
//! pre::Data::new(my_data, dimension)
//!     .set_title("My title")
//!     .plot_later("my_identifier")
//!     .unwrap();
//! ```
//!
//! Plot some function in a grid.
//! ```no_run
//! use preexplorer::prelude::*;
//! use ndarray::Array;
//! let grid = Array::linspace(0., 1., 20);
//! let values = grid.iter().map(|x| x * x);
//! (grid.iter(), values).preexplore()
//!     .set_title("My title")
//!     .plot("my_identifier")
//!     .unwrap();
//! ```
//! <img src="https://user-images.githubusercontent.com/37874270/80872600-27069980-8cb3-11ea-9f3f-4a60e5c4d06a.png" height="200px">
//!
//! Check out the [gallery] for more.
//!
//! [gallery]: https://github.com/rasa200/preexplorer#gallery
//!
//! # Optional features
//!
//! - **`use-serde`** — Enables [serde](https://crates.io/crates/serde) support.

/// Struct with all configurations for saving and ploting.
mod configuration;
/// Generic multi-dimensional data. Not automatically ploted.
mod data;
/// Histograms or realizations of the same variable. Empirical densities.
mod density;
/// Errors wrapper from writting data.
pub mod errors;
/// (Squared) Matrices.
mod matrix;
/// Time-series, indexed by a subset of R.
mod process;
/// Process indexed by 1, 2, 3, ...
mod sequence;
/// 3-dimensional surface.
mod contour;
/// Traits for easy use or self implmentation.
pub mod traits;
/// All you ussually need.
pub mod prelude {
    //! Easily start preexploring you results.
    //!
    //! # Examples
    //!
    //! Quickly check your results.
    //! ```no_run
    //! use preexplorer::prelude::*;
    //! (0..100).map(|i| i * i)
    //!     .preexplore()
    //!     .plot("My first plot")
    //!     .unwrap();
    //! ```
    //!
    //! Check numerical simulations.
    //! ```no_run
    //! use preexplorer::prelude::*;
    //! use rand_distr::Exp1;
    //! use rand::prelude::*;
    //! let simulation_results: Vec<f64> = (0..100).map(|_| thread_rng().sample(Exp1)).collect();
    //! pre::Density::new(simulation_results)
    //!     .set_title("Empirical Exponential 1")
    //!     .plot("My first empirical distribution")
    //!     .unwrap();
    //! ```
    pub use crate as pre;
    pub use crate::traits::*;
}

/// Directory paths.
mod constants {
    /// Path the data directory.
    pub const DATA_DIR: [&str; 3] = [r"target", "preexplorer", "data"];
    /// Path the plot scripts directory.
    pub const PLOT_DIR: [&str; 3] = [r"target", "preexplorer", "plots"];
}

/// Overall, generic functions of the crate
mod functions {

    /// Removes generated artifacts
    ///
    /// Inspired by the [`cargo clean`] command, this methods removes all
    /// artifacts from the target directory that `preexplorer` has generated in the past.
    ///
    /// # Remarks
    ///
    /// This method is particulary useful when you:
    /// - run various versions of a script with identical ids.
    /// - want to delete all previous records as they are no longer useful.
    ///
    /// # Errors
    ///
    /// This function will return an error in the following situations,
    /// but is not limited to just these cases:
    /// - The user lacks permissions to perform [`std::fs::metadata`] call
    /// on the relevant paths.
    /// - Either [`std::fs::remove_file`] or [`std::fs::remove_dir`] errors.
    ///
    /// [`cargo clean`]: https://doc.rust-lang.org/cargo/commands/cargo-clean.html
    /// [`std::fs::metadata`]: https://doc.rust-lang.org/std/fs/fn.metadata.html
    /// [`std::fs::remove_file`]: https://doc.rust-lang.org/std/fs/fn.remove_file.html
    /// [`std::fs::remove_dir`]: https://doc.rust-lang.org/std/fs/fn.remove_dir.html
    pub fn clean() -> Result<(), crate::errors::PreexplorerError> {
        let path = "./target/preexplorer";
        match std::fs::metadata(path) {
            Err(e) => match e.kind() {
                std::io::ErrorKind::NotFound => Ok(()),
                _ => Err(crate::errors::PreexplorerError::Removing(
                    e,
                    String::from("Could not query the relevant directory."),
                )),
            },
            Ok(_) => std::fs::remove_dir_all(path).map_err(|e| {
                crate::errors::PreexplorerError::Removing(
                    e,
                    String::from("Could not remove the relevant directory."),
                )
            }),
        }
    }
}

pub use self::configuration::{Configuration, Style};
pub use self::constants::{DATA_DIR, PLOT_DIR};
pub use self::data::Data;
pub use self::density::{Densities, Density};
pub use self::functions::*;
pub use self::matrix::{Heatmap, Heatmaps};
pub use self::contour::{Contour};
pub use self::process::{
    Process, ProcessBin, ProcessBins, ProcessError, ProcessErrors, ProcessViolin, ProcessViolins,
    Processes,
};
pub use self::sequence::{
    Sequence, SequenceBin, SequenceBins, SequenceError, SequenceErrors, SequenceViolin,
    SequenceViolins, Sequences,
};
pub use self::traits::*;