Skip to content

Commit

Permalink
Adding xan heatmap --normalize row
Browse files Browse the repository at this point in the history
Related to #439
  • Loading branch information
Yomguithereal committed Jan 16, 2025
1 parent 738153e commit fe1d677
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 9 deletions.
6 changes: 5 additions & 1 deletion docs/cmd/network.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,11 @@ xan network options:
in the resulting graph.
network edgelist options:
-U, --undirected Whether the graph is undirected.
-U, --undirected Whether the graph is undirected.
--nodes <path> Path to a CSV file containing node metadata
(use "-" to feed the file from stdin).
--node-column <name> Name of the column containing node keys.
[default: node]
Common options:
-h, --help Display this message
Expand Down
55 changes: 47 additions & 8 deletions src/cmd/heatmap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@ use crate::config::{Config, Delimiter};
use crate::util;
use crate::CliResult;

// TODO: finish normalize modes
// TODO: failure when input file is emptyish

// Taken from: https://stackoverflow.com/questions/3942878/how-to-decide-font-color-in-white-or-black-depending-on-background-color
fn text_should_be_black(color: &[u8; 4]) -> bool {
(color[0] as f32 * 0.299 + color[1] as f32 * 0.587 + color[2] as f32 * 0.114) > 150.0
Expand All @@ -28,6 +25,10 @@ impl Normalization {
fn is_column(&self) -> bool {
matches!(self, Self::Column)
}

fn is_row(&self) -> bool {
matches!(self, Self::Row)
}
}

impl<'de> Deserialize<'de> for Normalization {
Expand Down Expand Up @@ -151,6 +152,39 @@ impl Matrix {
}
}

fn compute_row_extent(
row: &[Option<f64>],
forced_extent: (Option<f64>, Option<f64>),
) -> Option<(f64, f64)> {
let mut extent = None;

if let (Some(forced_min), Some(forced_max)) = forced_extent {
return Some((forced_min, forced_max));
}

for cell in row.iter().flatten() {
match extent.as_mut() {
None => extent = Some((*cell, *cell)),
Some((min, max)) => {
if cell < min {
*min = *cell;
}
if cell > max {
*max = *cell;
}
}
}
}

if let (Some((min, _)), Some(forced_min)) = (extent.as_mut(), forced_extent.0) {
*min = forced_min;
} else if let (Some((_, max)), Some(forced_max)) = (extent.as_mut(), forced_extent.1) {
*max = forced_max;
}

extent
}

static USAGE: &str = "
Draw a heatmap from CSV data.
Expand Down Expand Up @@ -338,11 +372,16 @@ pub fn run(argv: &[&str]) -> CliResult<()> {
match cell {
None => print!("{}", " ".repeat(scale)),
Some(f) => {
// TODO: if the column has no value, things will get messy...
let (min, max) = col_extents
.as_ref()
.and_then(|extents| extents[col_i])
.unwrap_or(full_extent);
// TODO: deal with the case when no extent can be found
// TODO: hoist extent computation
let (min, max) = if args.flag_normalize.is_row() {
compute_row_extent(row, (args.flag_min, args.flag_max)).unwrap()
} else {
col_extents
.as_ref()
.and_then(|extents| extents[col_i])
.unwrap_or(full_extent)
};

let normalized = (f - min) / (max - min);

Expand Down

0 comments on commit fe1d677

Please sign in to comment.