tipstar0125 / ahc

ahc
0 stars 0 forks source link

plotly使い方 #11

Open tipstar0125 opened 7 months ago

tipstar0125 commented 7 months ago
use calamine::{Reader, Xlsx};
use plotly::{
    layout::{Axis, GridPattern, Layout, LayoutGrid},
    Plot, Scatter,
};
use regex::Regex;

fn plot_on_off(names: &[String], data: &[Vec<f64>]) {
    let max = 4;
    let plot_num = (names.len() + (max - 1)) / max;
    for n in 0..plot_num {
        let lower = max * n;
        let upper = (max * (n + 1)).min(names.len());
        let mut plot = Plot::new();
        for i in lower..upper {
            let mut x = vec![];
            let mut y = vec![];
            for (j, row) in data.iter().enumerate() {
                x.push(j);
                y.push(row[i]);
            }
            let j = i % max;
            if j == 0 {
                let trace = Scatter::new(x, y).name(names[i].as_str());
                plot.add_trace(trace);
            } else {
                let trace = Scatter::new(x, y)
                    .name(names[i].as_str())
                    .x_axis(format!("x{}", (j + 1) % (max + 1)))
                    .y_axis(format!("y{}", (j + 1) % (max + 1)));
                plot.add_trace(trace);
            }
        }

        let layout = Layout::new()
            .grid(
                LayoutGrid::new()
                    .columns(2)
                    .rows(2)
                    .pattern(GridPattern::Independent),
            )
            .x_axis(Axis::new().dtick(20.0).tick_angle(-45.0))
            .x_axis2(Axis::new().dtick(20.0).tick_angle(-45.0))
            .x_axis3(Axis::new().dtick(20.0).tick_angle(-45.0))
            .x_axis4(Axis::new().dtick(20.0).tick_angle(-45.0))
            .y_axis(Axis::new().range(vec![0, 15]).dtick(2.0))
            .y_axis2(Axis::new().range(vec![0, 15]).dtick(2.0))
            .y_axis3(Axis::new().range(vec![0, 15]).dtick(2.0))
            .y_axis4(Axis::new().range(vec![0, 15]).dtick(2.0));

        plot.set_layout(layout);
        plot.write_html(format!("out{}.html", n + 1));
    }
}

fn plot_uvc_reset(names: &[String], data: &[Vec<f64>]) {
    let mut plot = Plot::new();
    for i in 0..names.len() {
        let mut x = vec![];
        let mut y = vec![];
        for (j, row) in data.iter().enumerate() {
            x.push(j);
            y.push(row[i]);
        }
        let trace = Scatter::new(x, y).name(names[i].as_str());
        plot.add_trace(trace);
    }

    let layout = Layout::new()
        .height(800)
        .x_axis(Axis::new().dtick(20.0).tick_angle(-45.0))
        .y_axis(Axis::new().range(vec![0, 15]).dtick(2.0));

    plot.set_layout(layout);
    plot.write_html("out.html");
}

fn plot_limiter(names: &[String], data: &[Vec<f64>], filename: &str) {
    let mut plot = Plot::new();
    for i in 0..names.len() {
        let mut x = vec![];
        let mut y = vec![];
        for (j, row) in data.iter().enumerate() {
            x.push(j);
            y.push(row[i]);
        }
        let trace = Scatter::new(x, y)
            .name(names[i].as_str())
            .x_axis(format!("x{}", i + 1))
            .y_axis(format!("y{}", i + 1));
        plot.add_trace(trace);
    }

    let layout = Layout::new()
        .height(600)
        .grid(
            LayoutGrid::new()
                .columns(1)
                .rows(2)
                .pattern(GridPattern::Independent),
        )
        .x_axis(Axis::new().dtick(20.0).tick_angle(-45.0))
        .x_axis2(Axis::new().dtick(20.0).tick_angle(-45.0))
        .y_axis(Axis::new().range(vec![-2, 16]).dtick(2.0))
        .y_axis2(Axis::new().range(vec![-0.2, 2.0]).dtick(0.2));

    plot.set_layout(layout);
    let filename = filename.to_string() + "_limiter.html";
    plot.write_html(filename);
}

fn plot_bat_charge(names: &[String], data: &[Vec<f64>], filename: &str) {
    let mut plot = Plot::new();
    for i in 0..names.len() {
        let mut x = vec![];
        let mut y = vec![];
        for (j, row) in data.iter().enumerate() {
            x.push(j);
            y.push(row[i]);
        }
        let trace = Scatter::new(x, y)
            .name(names[i].as_str())
            .x_axis(format!("x{}", i + 1))
            .y_axis(format!("y{}", i + 1));
        plot.add_trace(trace);
    }

    let layout = Layout::new()
        .height(600)
        .grid(
            LayoutGrid::new()
                .columns(1)
                .rows(2)
                .pattern(GridPattern::Independent),
        )
        .x_axis(Axis::new().dtick(300.0).tick_angle(-45.0))
        .x_axis2(Axis::new().dtick(300.0).tick_angle(-45.0))
        .y_axis(Axis::new().range(vec![10, 15]).dtick(0.5))
        .y_axis2(Axis::new().range(vec![-3.0, 0.5]).dtick(0.5));

    plot.set_layout(layout);
    let filename = filename.to_string() + ".html";
    plot.write_html(filename);
}

fn plot_bat_discharge(names: &[String], data: &[Vec<f64>], filename: &str) {
    let mut plot = Plot::new();
    for i in 0..names.len() {
        let mut x = vec![];
        let mut y = vec![];
        for (j, row) in data.iter().enumerate() {
            x.push(j);
            y.push(row[i]);
        }
        let trace = Scatter::new(x, y)
            .name(names[i].as_str())
            .x_axis(format!("x{}", i + 1))
            .y_axis(format!("y{}", i + 1));
        plot.add_trace(trace);
    }

    let layout = Layout::new()
        .height(600)
        .grid(
            LayoutGrid::new()
                .columns(1)
                .rows(2)
                .pattern(GridPattern::Independent),
        )
        .x_axis(Axis::new().dtick(300.0).tick_angle(-45.0))
        .x_axis2(Axis::new().dtick(300.0).tick_angle(-45.0))
        .y_axis(Axis::new().range(vec![6, 15]).dtick(1.0))
        .y_axis2(Axis::new().range(vec![-0.5, 3.0]).dtick(0.5));

    plot.set_layout(layout);
    let filename = filename.to_string() + ".html";
    plot.write_html(filename);
}

fn read_excel_gl840(
    name: &str,
) -> Result<(Vec<String>, Vec<Vec<f64>>), Box<dyn std::error::Error>> {
    let excel_name = name.to_string() + ".xlsx";
    let mut workbook: Xlsx<_> = calamine::open_workbook(excel_name)?;
    let re = Regex::new(r"CH[0-9]++").unwrap();
    let mut channel_names = vec![];
    let mut data_start_row = 0;
    let data_start_col = 3;
    let mut res = vec![vec![]];

    if let Some(Ok(range)) = workbook.worksheet_range(name) {
        for (i, row) in range.rows().enumerate() {
            if !row.is_empty() && re.is_match(row[0].to_string().as_str()) {
                channel_names.push(row[1].to_string());
            } else if !row.is_empty() && row[0].to_string().as_str() == "NO." {
                data_start_row = i + 1;
                break;
            }
        }
        let mut data: Vec<Vec<f64>> = vec![];
        let channel_num = channel_names.len();
        for (i, row) in range.rows().enumerate() {
            if i >= data_start_row {
                let mut row_data = vec![];
                for x in row.iter().skip(data_start_col).take(channel_num) {
                    if let calamine::DataType::Float(d) = x {
                        row_data.push(*d);
                    }
                }
                data.push(row_data);
            }
        }
        res = data;
        // plot_on_off(&channel_names, &data);
    }
    Ok((channel_names, res))
}

fn limiter(name: &str, limit: f64) -> Result<(), Box<dyn std::error::Error>> {
    let excel_name = name.to_string() + ".xlsx";
    let mut workbook: Xlsx<_> = calamine::open_workbook(excel_name)?;
    let re = Regex::new(r"CH[0-9]++").unwrap();
    let mut channel_names = vec![];
    let mut data_start_row = 0;
    let data_start_col = 4;

    if let Some(Ok(range)) = workbook.worksheet_range(name) {
        for (i, row) in range.rows().enumerate() {
            if !row.is_empty() && re.is_match(row[0].to_string().as_str()) {
                channel_names.push(row[1].to_string());
            } else if !row.is_empty() && row[0].to_string().as_str() == "NO." {
                data_start_row = i + 1;
                break;
            }
        }
        let mut data: Vec<Vec<f64>> = vec![];
        let channel_num = channel_names.len();
        for (i, row) in range.rows().enumerate() {
            if i >= data_start_row {
                let mut row_data = vec![];
                for x in row.iter().skip(data_start_col).take(channel_num) {
                    if let calamine::DataType::Float(d) = x {
                        row_data.push(*d);
                    }
                }
                data.push(row_data);
            }
        }
        let mut current_max = 0.0_f64;
        for row in &data {
            current_max = current_max.max(row[1]);
        }

        println!("{}: {}A / {}A", name, current_max, limit);
        plot_limiter(&channel_names, &data, name);
    }
    Ok(())
}

fn read_dir() -> Vec<String> {
    let dir = std::fs::read_dir("./").unwrap();
    let re = Regex::new(r".xlsx$").unwrap();
    let mut files = vec![];
    for item in dir.into_iter() {
        match item {
            std::result::Result::Ok(x) => {
                let name = x.file_name().to_str().unwrap().to_string();
                if re.is_match(name.as_str()) {
                    files.push(name[0..name.len() - 5].to_string());
                }
            }
            std::result::Result::Err(_) => unreachable!(),
        }
    }
    files
}

fn bat(name: &str) -> Result<(), Box<dyn std::error::Error>> {
    let excel_name = name.to_string() + ".xlsx";
    let mut workbook: Xlsx<_> = calamine::open_workbook(excel_name)?;
    let re = Regex::new(r"CH[0-9]++").unwrap();
    let mut channel_names = vec![];
    let mut data_start_row = 0;
    let data_start_col = 4;

    if let Some(Ok(range)) = workbook.worksheet_range(name) {
        for (i, row) in range.rows().enumerate() {
            if !row.is_empty() && re.is_match(row[0].to_string().as_str()) {
                channel_names.push(row[1].to_string());
            } else if !row.is_empty() && row[0].to_string().as_str() == "NO." {
                data_start_row = i + 1;
                break;
            }
        }
        let mut data: Vec<Vec<f64>> = vec![];
        let channel_num = channel_names.len();
        for (i, row) in range.rows().enumerate() {
            if i >= data_start_row {
                let mut row_data = vec![];
                for x in row.iter().skip(data_start_col).take(channel_num) {
                    if let calamine::DataType::Float(d) = x {
                        row_data.push(*d);
                    }
                }
                data.push(row_data);
            }
        }
        // plot_bat_charge(&channel_names, &data, name);
        plot_bat_discharge(&channel_names, &data, name);
    }
    Ok(())
}

fn main() {
    // let (channel_names, data) = read_excel_gl840("reset_all").unwrap();
    // plot_on_off(&channel_names, &data);
    // plot_uvc_reset(&channel_names, &data);
    // let files = read_dir();
    // let limits = vec![
    //     1.1, 0.6, 1.5, 2.7, 0.4, 1.2, 0.4, 1.9, 2.3, 2.7, 4.1, 4.1, 3.6, 0.8, 4.1, 2.9,
    // ];
    // for (file, limit) in files.iter().zip(limits) {
    //     let _ = limiter(file, limit);
    // }
    // let _ = bat("charge");
    let _ = bat("discharge");
}
tipstar0125 commented 7 months ago
use plotly::{
    layout::{Axis, GridPattern, Layout, LayoutGrid},
    Bar, Histogram, Plot, Scatter,
};
use rand_distr::{Distribution, Normal, Uniform};

fn main() {
    let mut plot = Plot::new();
    // let trace = Histogram::new(vec![0.0, 1.2, 1.3, 1.2, 1.3]);
    let trace = Bar::new(vec!["aaa", "bbb", "ccc", "ddd"], vec![0, 1, 2, 1]).name("h");
    plot.add_trace(trace);
    let layout = Layout::new()
        // .x_axis(Axis::new().range(vec![0, 4]))
        .y_axis(Axis::new().range(vec![0, 10]));
    plot.set_layout(layout);
    plot.show();
    // plot.write_html("out.html");
}