demo-spectra.rs
2.2 kB · rust · 58 lines
1use mrlycore::errors::Result;2use mrlyfig::{ink, plot, save, Board};3use mrlymath::{six, three};4use mrlynum::graph::{census, largest_component};5use mrlynum::spectrum::{laplacian_spectrum, spectral_fit, spectral_points};67const WINDOW: f64 = 0.10;89fn main() -> Result<()> {10 let cell = six::cut(&three::create(23, 3, 2, 2)?)?;11 let whole = six::graph::slice_core_graph(&cell)?;12 let pieces = census(&whole).components;13 let network = largest_component(&whole);14 let values = laplacian_spectrum(&network, true)?;15 let points = spectral_points(&values);16 let (intercept, slope, fitted) = spectral_fit(&values, WINDOW).expect("the low window fits");17 assert_eq!(18 (network.nodes.len(), network.branches.len(), pieces),19 (306, 378, 1)20 );21 assert_eq!((points.len(), fitted), (286, 30));22 assert!((2.0 * slope - 1.253284).abs() < 1e-5);2324 let mut board = Board::square();25 let frame = board.frame(0.08);26 let xs: Vec<f64> = points.iter().map(|p| p.0.ln()).collect();27 let ys: Vec<f64> = points.iter().map(|p| p.1.ln()).collect();28 let (left, right) = (xs[0], *xs.last().unwrap());29 let (foot, roof) = (ys[0], 0.0);30 let at = |x: f64, y: f64| {31 (32 frame.x + frame.w * (x - left) / (right - left),33 frame.y + frame.h * (1.0 - (y - foot) / (roof - foot)),34 )35 };36 let ray = |x: f64| intercept + slope * x;37 let reach = |from: f64, to: f64| {38 let low = ((foot - intercept) / slope).max(from);39 let high = ((roof - intercept) / slope).min(to);40 (at(low, ray(low)), at(high, ray(high)))41 };4243 let (edge, _) = at(xs[fitted - 1], roof);44 board.rect(frame.x, frame.y, edge - frame.x, frame.h, ink::panel());45 plot::axis(&mut board, frame, ink::line());46 let mut stair = vec![at(xs[0], ys[0])];47 for index in 1..points.len() {48 stair.push(at(xs[index], ys[index - 1]));49 stair.push(at(xs[index], ys[index]));50 }51 board.polyline(&stair, 4.0, ink::blue());52 let (a, b) = reach(left, right);53 board.segment(a, b, 2.5, ink::fade(ink::yellow(), 0.6));54 let (a, b) = reach(left, xs[fitted - 1]);55 board.segment(a, b, 6.0, ink::yellow());56 save("demo-spectra", &board)?;57 Ok(())58}