use image::{ImageBuffer, Rgba};
use tracing::{debug, error};
use crate::{
canvas::{legend::LegendField, plot::DataPoint},
data::load_data,
};
use super::DataSet;
pub fn get_data_bounds(data_set: &[DataSet], csv_delimiter: &str) -> ((f32, f32), (f32, f32)) {
let mut min_x = f32::MAX;
let mut min_ux = Some(f32::MAX); let mut min_y = f32::MAX;
let mut min_uy = Some(f32::MAX); let mut max_x = f32::MIN;
let mut max_ux = Some(f32::MIN); let mut max_y = f32::MIN;
let mut max_uy = Some(f32::MIN); for set in data_set.iter() {
let data = load_data(set.data_path.as_str(), set.has_headers, csv_delimiter);
let mut row = 1;
for record in data.iter() {
match record.get(set.x_axis_csv_column) {
Some(string_value) => match string_value.parse::<f32>() {
Ok(value) => {
if value < min_x {
min_x = value;
}
if value > max_x {
max_x = value;
}
}
Err(e) => {
error!(
"Could not parse data in column {}, row {} for x axis, error: {}",
set.x_axis_csv_column, row, e
);
std::process::exit(1);
}
},
None => {
error!(
"Could not extract record in column {} for x axis, row {}",
set.x_axis_csv_column, row
);
std::process::exit(1);
}
};
match set.x_axis_error_bar_csv_column {
Some(column) => match record.get(column) {
Some(string_value) => match string_value.parse::<f32>() {
Ok(value) => {
if value < min_ux.unwrap() {
min_ux = Some(value)
}
if value > max_ux.unwrap() {
max_ux = Some(value)
}
}
Err(e) => {
error!(
"Could not parse data in column {}, row{}, to f32 for error bar x, error: {}",
set.x_axis_csv_column, row, e
);
std::process::exit(1);
}
},
None => {
error!(
"Could not extract record in column {} for error bar x, row {}",
set.x_axis_csv_column, row
);
std::process::exit(1);
}
},
None => min_ux = None,
};
match record.get(set.y_axis_csv_column) {
Some(string_value) => match string_value.parse::<f32>() {
Ok(value) => {
if value < min_y {
min_y = value
}
if value > max_y {
max_y = value
}
}
Err(e) => {
error!(
"Could not parse data in column {}, row {} to f32 for y axis, error: {}",
set.x_axis_csv_column, row, e
);
std::process::exit(1);
}
},
None => {
error!(
"Could not extract record in column {} for y axis, row {}",
set.x_axis_csv_column, row
);
std::process::exit(1);
}
};
match set.y_axis_error_bar_csv_column {
Some(column) => match record.get(column) {
Some(string_value) => match string_value.parse::<f32>() {
Ok(value) => {
if value < min_uy.unwrap() {
min_uy = Some(value)
}
if value > max_uy.unwrap() {
max_uy = Some(value)
}
}
Err(e) => {
error!(
"Could not parse data in column {}, row {} to f32 for y error bar, error: {}",
set.x_axis_csv_column, row, e
);
std::process::exit(1);
}
},
None => {
error!(
"Could not extract record in column {}, row {} for y error bar",
set.x_axis_csv_column, row
);
std::process::exit(1);
}
},
None => min_uy = None,
};
row += 1;
}
}
((min_x, min_y), (max_x, max_y))
}
pub fn build_data_points(
data_set: &[DataSet],
csv_delimiter: &str,
canvas: &mut ImageBuffer<Rgba<u8>, Vec<u8>>,
x_scale_factor: f32,
y_scale_factor: f32,
origin_offset: (u32, u32),
) {
debug!("Building data points...");
for set in data_set.iter() {
let data = load_data(set.data_path.as_str(), set.has_headers, csv_delimiter);
let mut row = 1;
for record in data.iter() {
let x = match record.get(set.x_axis_csv_column) {
Some(string_value) => match string_value.parse::<f32>() {
Ok(value) => value,
Err(e) => {
error!(
"Could not parse data in column {}, row {} for x axis, error: {}",
set.x_axis_csv_column, row, e
);
std::process::exit(1);
}
},
None => {
error!(
"Could not extract record in column {}, row {} for x axis",
set.x_axis_csv_column, row
);
std::process::exit(1);
}
};
let ux = match set.x_axis_error_bar_csv_column {
Some(column) => match record.get(column) {
Some(string_value) => match string_value.parse::<f32>() {
Ok(value) => Some(value),
Err(e) => {
error!(
"Could not parse data in column {}, row{}, to f32 for error bar x, error: {}",
set.x_axis_csv_column, row, e
);
std::process::exit(1);
}
},
None => {
error!(
"Could not extract record in column {}, row {} for error bar x",
set.x_axis_csv_column, row
);
std::process::exit(1);
}
},
None => None,
};
let y = match record.get(set.y_axis_csv_column) {
Some(string_value) => match string_value.parse::<f32>() {
Ok(value) => value,
Err(e) => {
error!(
"Could not parse data in column {}, row {} to f32 for y axis, error: {}",
set.x_axis_csv_column, row, e
);
std::process::exit(1);
}
},
None => {
error!(
"Could not extract record in column {}, row {} for y axis",
set.x_axis_csv_column, row
);
std::process::exit(1);
}
};
let uy = match set.y_axis_error_bar_csv_column {
Some(column) => match record.get(column) {
Some(string_value) => match string_value.parse::<f32>() {
Ok(value) => Some(value),
Err(e) => {
error!(
"Could not parse data in column {}, row {} to f32 for y error bar, error: {}",
set.x_axis_csv_column, row, e
);
std::process::exit(1);
}
},
None => {
error!(
"Could not extract record in column {}, row {} for y error bar",
set.x_axis_csv_column, row
);
std::process::exit(1);
}
},
None => None,
};
let point: DataPoint = DataPoint {
x,
ux,
y,
uy,
colour: set.colour,
symbol: set.symbol,
symbol_radius: set.symbol_radius,
symbol_thickness: set.symbol_thickness,
};
point.draw_point(canvas, x_scale_factor, y_scale_factor, origin_offset);
row += 1;
}
}
}
pub fn get_legend_fields(data_set: &[DataSet]) -> Vec<LegendField> {
let mut legend_fields: Vec<LegendField> = Vec::new();
for set in data_set.iter() {
legend_fields.push(LegendField {
symbol: set.symbol,
symbol_radius: set.symbol_radius,
symbol_thickness: set.symbol_thickness,
colour: set.colour,
name: set.name.to_owned(),
});
}
legend_fields
}