Add treemap visualization code

finchie
Apr 30, 2024, 7:24 AM
UKNTVY7Z7SSOL4KM7J26MZUTU6WP2D5346KMYCYS7WGKFBSDBJ2AC

Dependencies

  • [2] C43IWI7G Move visualization logic into separate module

Change contents

  • file addition: treemap.rs (----------)
    [2.21]
    use crate::Annotations;
    use charming::{
    element::{ItemStyle, Label},
    series::{TreemapData, TreemapLevel},
    };
    use guppy::graph::PackageMetadata;
    // TODO: reference
    const COLORS: [&str; 9] = [
    "#5470c6", "#91cc75", "#fac858", "#ee6666", "#73c0de", "#3ba272", "#fc8452", "#9a60b4",
    "#ea7ccc",
    ];
    pub fn color() -> Vec<String> {
    COLORS
    .iter()
    .map(|color| color.to_string())
    .collect::<Vec<String>>()
    }
    pub fn data<'graph>(
    annotations: &Annotations,
    packages: &[PackageMetadata<'graph>],
    ) -> Vec<TreemapData> {
    let mut treemap_items = Vec::new();
    for pkg in packages {
    // Recursively call this function for all direct dependencies
    let direct_dependencies = pkg.direct_links().map(|link| link.to()).collect::<Vec<_>>();
    let empty_vec = Vec::new();
    let self_times = annotations
    .pkg(pkg.id())
    .map(|node| node.timings().unwrap_or(&empty_vec))
    .unwrap_or(&empty_vec)
    .iter()
    .map(|message| TreemapData {
    value: message.duration,
    id: None,
    name: Some(format!("{:?} {:?}", message.mode, message.target.kind)),
    upper_label: None,
    visual_dimension: None,
    children: vec![],
    children_visible_min: None,
    });
    let mut children = data(annotations, &direct_dependencies);
    children.extend(self_times);
    let mut total_duration = 0_f64;
    for child in &children {
    total_duration += child.value;
    }
    let dependent_count = pkg.reverse_direct_links().count();
    let relative_duration = if dependent_count == 0 {
    total_duration
    } else {
    total_duration / (dependent_count as f64)
    };
    treemap_items.push(TreemapData {
    value: relative_duration,
    id: None,
    name: Some(pkg.name().to_string()),
    upper_label: Some(Label::new().show(true)),
    visual_dimension: None,
    children,
    children_visible_min: Some(200_000),
    })
    }
    treemap_items
    }
    pub fn levels(depth: usize) -> Vec<TreemapLevel> {
    let mut levels = Vec::with_capacity(depth);
    levels.extend([
    TreemapLevel {
    item_style: Some(ItemStyle::new().border_width(1).gap_width(0)),
    upper_label: Some(Label::new().show(false)),
    },
    TreemapLevel {
    item_style: Some(
    ItemStyle::new()
    .border_color("#777")
    .border_width(1)
    .gap_width(0),
    ),
    upper_label: Some(Label::new().show(false)),
    },
    ]);
    while levels.len() < depth {
    levels.push(TreemapLevel {
    item_style: Some(
    ItemStyle::new()
    .border_width(5)
    .gap_width(1)
    .border_color_saturation(0.6),
    ),
    upper_label: None,
    });
    }
    levels
    }