dyna3/app-proto/src/diagnostics.rs
2025-06-09 22:21:34 -07:00

103 lines
No EOL
3.2 KiB
Rust

use charming::{
Chart,
WasmRenderer,
component::{Axis, Grid},
element::AxisType,
series::Line,
theme::Theme
};
use sycamore::prelude::*;
use crate::AppState;
// a realization status indicator
#[component]
pub fn RealizationStatus() -> View {
let state = use_context::<AppState>();
let realization_status = state.assembly.realization_status;
view! {
div(
id="realization-status",
class=realization_status.with(
|status| match status {
Ok(_) => "",
Err(_) => "invalid"
}
)
) {
div(class="status")
div {
(realization_status.with(
|status| match status {
Ok(_) => "Target accuracy achieved".to_string(),
Err(message) => message.clone()
}
))
}
}
}
}
// a plot of the loss history from the last realization
#[component]
pub fn LossHistory() -> View {
const CONTAINER_ID: &str = "loss-history";
let state = use_context::<AppState>();
let renderer = WasmRenderer::new_opt(None, Some(180)).theme(Theme::Walden);
on_mount(move || {
create_effect(move || {
// get the loss history
let scaled_loss = state.assembly.descent_history.with(
|history| history.scaled_loss.clone()
);
let step_cnt = scaled_loss.len();
// initialize the chart axes and series
const MIN_INTERVAL: f64 = 0.01;
let mut step_axis = Axis::new()
.type_(AxisType::Category)
.boundary_gap(false);
let scaled_loss_axis = Axis::new()
.type_(AxisType::Value)
.min(0)
.min_interval(MIN_INTERVAL);
// load the chart data. when there's no history, we load the data
// point (0, None) to clear the chart. it would feel more natural to
// load empty data vectors, but that turns out not to clear the
// chart: it instead leads to previous data being re-used
let mut scaled_loss_series = Line::new();
if step_cnt > 0 {
step_axis = step_axis.data(
(0..step_cnt).map(|step| step.to_string()).collect()
);
scaled_loss_series = scaled_loss_series.data(scaled_loss);
} else {
step_axis = step_axis.data(vec![0.to_string()]);
scaled_loss_series = scaled_loss_series.data(vec![None::<f64>]);
}
let chart = Chart::new()
.animation(false)
.x_axis(step_axis)
.y_axis(scaled_loss_axis)
.grid(Grid::new().top(20).right(40).bottom(30).left(60))
.series(scaled_loss_series);
renderer.render(CONTAINER_ID, &chart).unwrap();
});
});
view! {
div(id=CONTAINER_ID)
}
}
#[component]
pub fn Diagnostics() -> View {
view! {
div(id="diagnostics") {
RealizationStatus {}
LossHistory {}
}
}
}