fpm_rs/tabular/tables/
benchmark.rs1use polars::prelude::*;
2
3use crate::{
4 Result,
5 benchmark::{BenchmarkFrameRecord, BenchmarkRecord},
6};
7
8pub fn benchmark_runs_dataframe(records: &[BenchmarkRecord]) -> Result<DataFrame> {
10 let length = records.len();
11 let mut run_ids = Vec::with_capacity(length);
12 let mut case_ids = Vec::with_capacity(length);
13 let mut algorithms = Vec::with_capacity(length);
14 let mut algorithm_configurations = Vec::with_capacity(length);
15 let mut dataset_names = Vec::with_capacity(length);
16 let mut dataset_versions = Vec::with_capacity(length);
17 let mut random_seeds = Vec::with_capacity(length);
18 let mut frame_counts = Vec::with_capacity(length);
19 let mut completed_iterations = Vec::with_capacity(length);
20 let mut elapsed_seconds = Vec::with_capacity(length);
21 let mut final_objectives = Vec::with_capacity(length);
22 let mut successes = Vec::with_capacity(length);
23 let mut errors = Vec::with_capacity(length);
24 let mut repetitions = Vec::with_capacity(length);
25 let mut warmups = Vec::with_capacity(length);
26 let mut groups = Vec::with_capacity(length);
27 let mut reference_run_ids = Vec::with_capacity(length);
28 for record in records {
29 run_ids.push(record.run_id.as_str());
30 case_ids.push(record.case_id.as_str());
31 algorithms.push(record.algorithm.as_str());
32 algorithm_configurations.push(record.algorithm_configuration.as_str());
33 dataset_names.push(record.dataset_name.as_str());
34 dataset_versions.push(record.dataset_version.as_deref());
35 random_seeds.push(record.random_seed);
36 frame_counts.push(record.frame_count as u64);
37 completed_iterations.push(record.success.then_some(record.completed_iterations as u64));
38 elapsed_seconds.push(record.elapsed_seconds);
39 final_objectives.push(record.success.then_some(record.final_objective).flatten());
40 successes.push(record.success);
41 errors.push(
42 (!record.success)
43 .then_some(record.error.as_deref())
44 .flatten(),
45 );
46 repetitions.push(
47 record
48 .metadata
49 .get("repetition")
50 .and_then(|value| value.parse::<u64>().ok()),
51 );
52 warmups.push(
53 record
54 .metadata
55 .get("warmup")
56 .and_then(|value| value.parse::<bool>().ok()),
57 );
58 groups.push(record.metadata.get("benchmark_group").map(String::as_str));
59 reference_run_ids.push(record.metadata.get("reference_run_id").map(String::as_str));
60 }
61 Ok(df!(
62 "run_id" => run_ids,
63 "case_id" => case_ids,
64 "algorithm" => algorithms,
65 "algorithm_configuration" => algorithm_configurations,
66 "dataset_name" => dataset_names,
67 "dataset_version" => dataset_versions,
68 "random_seed" => random_seeds,
69 "frame_count" => frame_counts,
70 "completed_iterations" => completed_iterations,
71 "elapsed_seconds" => elapsed_seconds,
72 "final_objective" => final_objectives,
73 "success" => successes,
74 "error" => errors,
75 "repetition" => repetitions,
76 "warmup" => warmups,
77 "benchmark_group" => groups,
78 "reference_run_id" => reference_run_ids,
79 )?)
80}
81
82pub fn benchmark_frames_dataframe(records: &[BenchmarkRecord]) -> Result<DataFrame> {
84 let length = records.iter().map(|record| record.frames.len()).sum();
85 let mut run_ids = Vec::with_capacity(length);
86 let mut frame_indices = Vec::with_capacity(length);
87 let mut original_frame_indices = Vec::with_capacity(length);
88 let mut original_illumination_indices = Vec::with_capacity(length);
89 let mut normalized_l2 = Vec::with_capacity(length);
90 for record in records {
91 for BenchmarkFrameRecord {
92 frame_index,
93 original_frame_index,
94 original_illumination_index,
95 normalized_l2: residual,
96 } in &record.frames
97 {
98 run_ids.push(record.run_id.as_str());
99 frame_indices.push(*frame_index as u64);
100 original_frame_indices.push(*original_frame_index as u64);
101 original_illumination_indices
102 .push(original_illumination_index.map(|value| value as u64));
103 normalized_l2.push(*residual);
104 }
105 }
106 Ok(df!(
107 "run_id" => run_ids,
108 "frame_index" => frame_indices,
109 "original_frame_index" => original_frame_indices,
110 "original_illumination_index" => original_illumination_indices,
111 "normalized_l2" => normalized_l2,
112 )?)
113}
114
115pub fn benchmark_artifacts_dataframe(
117 records: &[BenchmarkRecord],
118 relative_result_paths: &std::collections::BTreeMap<String, String>,
119) -> Result<DataFrame> {
120 let length = records.len();
121 let mut run_ids = Vec::with_capacity(length);
122 let mut roles = Vec::with_capacity(length);
123 let mut relative_paths = Vec::with_capacity(length);
124 for record in records {
125 if let Some(path) = relative_result_paths.get(&record.run_id) {
126 run_ids.push(record.run_id.as_str());
127 roles.push("result_bundle");
128 relative_paths.push(path.as_str());
129 }
130 }
131 Ok(df!(
132 "run_id" => run_ids,
133 "role" => roles,
134 "relative_path" => relative_paths,
135 )?)
136}
137
138pub fn benchmark_metadata_dataframe(records: &[BenchmarkRecord]) -> Result<DataFrame> {
140 const PROMOTED: &[&str] = &[
141 "repetition",
142 "warmup",
143 "benchmark_group",
144 "reference_run_id",
145 ];
146 let length = records
147 .iter()
148 .map(|record| record.metadata.len())
149 .sum::<usize>();
150 let mut run_ids = Vec::with_capacity(length);
151 let mut keys = Vec::with_capacity(length);
152 let mut values = Vec::with_capacity(length);
153 for record in records {
154 for (key, value) in &record.metadata {
155 if PROMOTED.contains(&key.as_str()) {
156 continue;
157 }
158 run_ids.push(record.run_id.as_str());
159 keys.push(key.as_str());
160 values.push(value.as_str());
161 }
162 }
163 Ok(df!(
164 "run_id" => run_ids,
165 "key" => keys,
166 "value" => values,
167 )?)
168}