diff --git a/Cargo.toml b/Cargo.toml index 636b75d..860fc9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ lazy_static = "1.4" log = "0.4" ndarray = { version = "0.13", features = ["rayon"] } piecewise-linear = "0.1" +plotly = { version = "0.6", features = ["kaleido", "plotly_ndarray"] } y4m = "0.7" [dev-dependencies] diff --git a/examples/toroid25d.rs b/examples/toroid25d.rs index b610e9d..e9e01b3 100644 --- a/examples/toroid25d.rs +++ b/examples/toroid25d.rs @@ -36,17 +36,18 @@ fn main() { //driver.set_steps_per_frame(80); driver.set_steps_per_frame(120); //driver.set_steps_per_frame(200); - driver.add_y4m_renderer(&*format!("toroid25d.5-flt{}-{}-feat{}um-{:.1e}A-{:.1e}s--radii{}um-{}um-{}um-{}um.y4m", - std::mem::size_of::() * 8, - *size_px, - m_to_um(feat_size), - peak_current, - current_duration, - m_to_um(conductor_outer_rad), - m_to_um(ferro_inner_rad), - m_to_um(ferro_outer_rad), - m_to_um(ferro_depth), - )); + // driver.add_y4m_renderer(&*format!("toroid25d.5-flt{}-{}-feat{}um-{:.1e}A-{:.1e}s--radii{}um-{}um-{}um-{}um.y4m", + // std::mem::size_of::() * 8, + // *size_px, + // m_to_um(feat_size), + // peak_current, + // current_duration, + // m_to_um(conductor_outer_rad), + // m_to_um(ferro_inner_rad), + // m_to_um(ferro_outer_rad), + // m_to_um(ferro_depth), + // )); + driver.add_plotly_renderer(); let conductor_region = CylinderZ::new( Vec2::new(half_width, half_width), conductor_outer_rad); diff --git a/src/driver.rs b/src/driver.rs index c9a5441..0b39569 100644 --- a/src/driver.rs +++ b/src/driver.rs @@ -64,6 +64,10 @@ impl Driver { self.add_renderer(render::Y4MRenderer::new(output), &*name); } + pub fn add_plotly_renderer(&mut self) { + self.add_renderer(render::PlotlyRenderer, "plotly"); + } + pub fn add_term_renderer(&mut self) { self.add_renderer(render::ColorTermRenderer, "terminal"); } diff --git a/src/render.rs b/src/render.rs index e5b12b8..045f216 100644 --- a/src/render.rs +++ b/src/render.rs @@ -1,11 +1,13 @@ use ansi_term::Color::RGB; -use crate::geom::{Meters, Vec2, Vec3}; +use crate::geom::{Index, Meters, Vec2, Vec3, Vec3u}; use crate::{flt::{Flt, Real}, Material as _}; use crate::mat; use crate::sim::{Cell, GenericSim}; use crate::meas::AbstractMeasurement; use font8x8::{BASIC_FONTS, GREEK_FONTS, UnicodeFonts as _}; use log::{trace, info}; +use plotly::{Plot, ImageFormat}; +use plotly::heat_map::HeatMap; use image::{RgbImage, Rgb}; use imageproc::{pixelops, drawing}; use std::fs::File; @@ -324,6 +326,33 @@ impl Renderer for Y4MRenderer { } } +pub struct PlotlyRenderer; + +impl Renderer for PlotlyRenderer { + fn render(&mut self, state: &dyn GenericSim, measurements: &[Box]) { + let mut plot = Plot::new(); + let mut xv = Vec::new(); + let mut yv = Vec::new(); + let mut zv = Vec::new(); + for z in 0..state.depth() { + for y in 0..state.height() { + for x in 0..state.width() { + let cell = state.get(Index(Vec3u::new(x, y, z))); + if cell.e().mag() > 10.0 { + xv.push(x); + yv.push(y); + zv.push(z); + } + } + } + } + let heat_map = HeatMap::new(xv, yv, zv); + plot.add_trace(heat_map); + let name = format!("frame{}", state.step_no()); + plot.save(&*name, ImageFormat::PNG, state.width() as _, state.height() as _, 1.0); + } +} + #[derive(Default)] pub struct MultiRenderer { renderers: Vec>,