///|
/// Convert a vector to one CSV row.
pub fn vector_to_csv(values : Array[Double]) -> String {
let mut result = ""
for i, value in values {
if i > 0 {
result = result + ","
}
result = result + value.to_string()
}
result
}
///|
pub fn matrix_to_csv(matrix : Matrix) -> String {
let mut result = ""
for i in 0.. 0 {
result = result + "\n"
}
result = result + vector_to_csv(matrix.row(i))
}
result
}
///|
pub fn estimates_to_csv(
estimates : Array[Array[Double]],
truth : Array[Array[Double]],
) -> String {
let mut result = "index,estimate,truth,error\n"
let count = if estimates.length() < truth.length() {
estimates.length()
} else {
truth.length()
}
for i in 0.. String {
"count,rmse,mae,max_error,final_error\n" +
metrics.count().to_string() +
"," +
metrics.rmse().to_string() +
"," +
metrics.mae().to_string() +
"," +
metrics.max_error().to_string() +
"," +
metrics.final_error().to_string() +
"\n"
}
///|
/// Produce a concise Markdown table suitable for a CI artifact or README.
pub fn metrics_to_markdown(metrics : ErrorMetrics) -> String {
"| Metric | Value |\n| --- | ---: |\n" +
"| samples | " +
metrics.count().to_string() +
" |\n" +
"| RMSE | " +
metrics.rmse().to_string() +
" |\n" +
"| MAE | " +
metrics.mae().to_string() +
" |\n" +
"| maximum error | " +
metrics.max_error().to_string() +
" |\n" +
"| final error | " +
metrics.final_error().to_string() +
" |\n"
}
///|
pub fn update_result_to_string(result : UpdateResult) -> String {
match result {
Accepted => "accepted"
RejectedByGate => "rejected_by_gate"
InvalidMeasurement => "invalid_measurement"
SingularInnovation => "singular_innovation"
MissingMeasurement => "missing_measurement"
}
}
///|
pub fn fusion_events_to_csv(events : Array[FusionEvent]) -> String {
let mut result = "timestamp,sensor,result,nis,state\n"
for event in events {
result = result + event.timestamp().to_string() + ","
result = result + event.sensor() + ","
result = result + update_result_to_string(event.result()) + ","
result = result + event.nis().to_string() + ","
result = result + vector_to_csv(event.state()) + "\n"
}
result
}
///|
pub fn covariance_to_markdown(covariance : Matrix, digits? : Int) -> String {
let precision = match digits {
None => 6
Some(value) => if value < 0 { 0 } else if value > 12 { 12 } else { value }
}
let _ = precision
let mut result = "| |"
for j in 0.. String {
let mut result = "timestamp,truth,measurement,missing,outlier\n"
for sample in samples {
result = result + sample.timestamp().to_string() + ","
result = result + vector_to_csv(sample.truth()) + ","
result = result + vector_to_csv(sample.measurement()) + ","
result = result + (if sample.missing() { "true" } else { "false" }) + ","
result = result + (if sample.outlier() { "true" } else { "false" }) + "\n"
}
result
}
///|
pub fn report_line(label : String, value : Double, unit : String) -> String {
label + ": " + value.to_string() + " " + unit
}
///|
pub fn report_lines(lines : Array[(String, Double, String)]) -> String {
let mut result = ""
for line in lines {
result = result + report_line(line.0, line.1, line.2) + "\n"
}
result
}