Update tools

This commit is contained in:
Joshua Coles 2023-03-17 18:58:03 +00:00
parent be00b21905
commit b0b1a4ce43
4 changed files with 56 additions and 37 deletions

View File

@ -4,6 +4,7 @@ use bevy::tasks::ParallelSlice;
use crate::system::spaces::square_grid::{Grid2D, Grid3D}; use crate::system::spaces::square_grid::{Grid2D, Grid3D};
use itertools::{Itertools, MinMaxResult}; use itertools::{Itertools, MinMaxResult};
use clap::Parser; use clap::Parser;
use serde::Serialize;
use crate::BoxCountCli; use crate::BoxCountCli;
use crate::cli::cli::OutputFormat; use crate::cli::cli::OutputFormat;
use crate::system::{GriddedPosition, Position}; use crate::system::{GriddedPosition, Position};
@ -15,30 +16,30 @@ fn bb(data: &Vec<Grid2D>) -> ((i32, i32), (i32, i32)) {
.iter().minmax_by(|a, b| a.x.cmp(&b.x)); .iter().minmax_by(|a, b| a.x.cmp(&b.x));
let y = data let y = data
.iter().minmax_by(|a, b| a.x.cmp(&b.x)); .iter().minmax_by(|a, b| a.y.cmp(&b.y));
match (x, y) { match (x, y) {
(MinMaxResult::MinMax(min_x, max_x), MinMaxResult::MinMax(min_y, max_y)) => { (MinMaxResult::MinMax(min_x, max_x), MinMaxResult::MinMax(min_y, max_y)) => {
((min_x.x, min_y.y), (max_x.x, max_y.y)) ((min_x.x, min_y.y), (max_x.x, max_y.y))
}, }
_ => panic!("Cannot determine bounding box") _ => panic!("Cannot determine bounding box")
} }
} }
fn box_count_2d(data: &Vec<Grid2D>, box_number: u32) -> usize { fn box_count_2d(data: &Vec<Grid2D>, box_number: u32) -> (f64, usize) {
let n = data.len(); let ((x_min, y_min), (x_max, y_max)) = bb(data);
let ((x_min, x_max), (y_min, y_max)) = bb(data);
let x_range = (x_max - x_min) as f64; let x_range = (x_max - x_min) as f64;
let y_range = (y_max - y_min) as f64; let y_range = (y_max - y_min) as f64;
let w: f64 = x_range / (box_number as f64); let w: f64 = x_range / (box_number as f64);
data.iter() let boxes_occupied = data.iter()
.map(|Grid2D { x, y }| [((x - x_min) as f64 / w) as u32, ((y - y_min) as f64 / w) as u32]) .map(|Grid2D { x, y }| [((x - x_min) as f64 / w) as i32, ((y - y_min) as f64 / w) as i32])
.unique() .unique()
.count() .count();
(w, boxes_occupied)
} }
fn box_count_3d(data: &Vec<Grid3D>, size: u32) -> usize { fn box_count_3d(data: &Vec<Grid3D>, size: u32) -> usize {
@ -110,6 +111,25 @@ fn box_count_nd<const N: usize>(data: &Vec<[f32; N]>, size: u32) -> usize {
.count(); .count();
} }
pub fn main(cli: &BoxCountCli) { #[derive(Serialize)]
let particles = read(&cli.path, cli.format); struct FDRow {
w: f64,
n_occupied: usize,
}
pub(crate) fn main(cli: &BoxCountCli) {
let particles: Vec<Grid2D> = read(&cli.path, cli.format);
let n_particles = dbg!(particles.len());
let box_side_counts = 1..500;
let mut writer = csv::Writer::from_path(&cli.output)
.expect("Unable to create csv");
box_side_counts
.map(|box_side_count| box_count_2d(&particles, box_side_count))
// .filter(|(w, n_occupied)| *n_occupied < n_particles) // Remove saturated values
.map(|(w, n_occupied)| FDRow { w, n_occupied })
.for_each(|row| writer.serialize(row).expect("Failed to write row"));
writer.flush().unwrap();
} }

View File

@ -1,3 +1,4 @@
use std::fs::File;
use std::path::Path; use std::path::Path;
use serde::de::DeserializeOwned; use serde::de::DeserializeOwned;
use crate::cli::cli::OutputFormat; use crate::cli::cli::OutputFormat;

View File

@ -12,8 +12,10 @@ use serde::de::DeserializeOwned;
use serde::Deserialize; use serde::Deserialize;
use svg::Node; use svg::Node;
use svg::node::element::Rectangle; use svg::node::element::Rectangle;
use crate::RenderCli;
use crate::system::Position; use crate::system::Position;
use crate::system::spaces::hexagonal::HexPosition; use crate::system::spaces::hexagonal::HexPosition;
use crate::tools::read;
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
struct Args { struct Args {
@ -60,30 +62,10 @@ impl ToSvg for HexPosition {
} }
} }
fn read_json<T: Position>(args: &Args) -> Vec<T> where T: DeserializeOwned { pub(crate) fn main(args: &RenderCli) {
serde_json::from_reader::<_, Vec<HistoryLine<T>>>(File::open(&args.path).expect("Failed to open file")) let positions: Vec<Grid2D> = read::<Grid2D>(&args.path, args.format);
.expect("Failed to read json")
.iter()
.map(|l| (l.position.clone()))
.collect::<Vec<_>>()
}
fn read_csv<T: Position>(args: &Args) -> Vec<T> where T: DeserializeOwned { let size: i32 = args.image_size as i32;
csv::Reader::from_path(&args.path).expect("Failed to read positions csv").deserialize::<T>()
.collect::<Result<Vec<T>, _>>()
.unwrap()
}
fn main() {
let args = Args::parse();
dbg!(&args);
let positions: Vec<Grid2D> = match args.format {
OutputFormat::FullDataJson => read_json::<Grid2D>(&args),
OutputFormat::Positions => read_csv::<Grid2D>(&args),
};
let size: i32 = 800;
let max_x = positions.iter().max_by(|a, b| a.x.abs().cmp(&b.x.abs())).unwrap().x.abs(); let max_x = positions.iter().max_by(|a, b| a.x.abs().cmp(&b.x.abs())).unwrap().x.abs();
let max_y = positions.iter().max_by(|a, b| a.y.abs().cmp(&b.y.abs())).unwrap().y.abs(); let max_y = positions.iter().max_by(|a, b| a.y.abs().cmp(&b.y.abs())).unwrap().y.abs();
let max_size = max_x.max(max_y) * size; let max_size = max_x.max(max_y) * size;
@ -105,5 +87,5 @@ fn main() {
svg.append(position.to_svg(size)); svg.append(position.to_svg(size));
} }
svg::write(File::create(args.output).unwrap(), &svg).unwrap(); svg::write(File::create(&args.output).unwrap(), &svg).unwrap();
} }

View File

@ -2,7 +2,7 @@
#![feature(let_chains)] #![feature(let_chains)]
use std::fs::File; use std::fs::File;
use std::path::{Path, PathBuf}; use std::path::PathBuf;
use anyhow::Context; use anyhow::Context;
use crate::cli::cli::OutputFormat; use crate::cli::cli::OutputFormat;
use crate::system::model::HistoryLine; use crate::system::model::HistoryLine;
@ -25,9 +25,24 @@ enum ToolsCli {
BoxCount(BoxCountCli) BoxCount(BoxCountCli)
} }
#[derive(clap::ValueEnum, Clone, Debug, Copy)]
enum Space {
Grid2D,
}
#[derive(Debug, Args)] #[derive(Debug, Args)]
struct RenderCli { struct RenderCli {
#[arg(value_enum, short, long, default_value_t = OutputFormat::Positions)]
format: OutputFormat,
#[arg(value_enum, short, long, default_value_t = Space::Grid2D)]
space: Space,
path: PathBuf,
output: PathBuf,
#[arg(short, long, default_value_t = 800)]
image_size: u32,
} }
#[derive(Debug, Args)] #[derive(Debug, Args)]
@ -35,6 +50,7 @@ struct BoxCountCli {
#[arg(value_enum, short, long, default_value_t = OutputFormat::Positions)] #[arg(value_enum, short, long, default_value_t = OutputFormat::Positions)]
format: OutputFormat, format: OutputFormat,
path: PathBuf, path: PathBuf,
output: PathBuf,
} }
fn main() { fn main() {
@ -42,7 +58,7 @@ fn main() {
dbg!(&args); dbg!(&args);
match args { match args {
ToolsCli::Render(_) => {} ToolsCli::Render(cli) => tools::render::main(&cli),
ToolsCli::BoxCount(cli) => tools::boxcount::main(&cli), ToolsCli::BoxCount(cli) => tools::boxcount::main(&cli),
} }
} }