- cleanup

This commit is contained in:
w.pomp committed 2026-08-03 14:43:04 +02:00
1 parent 687c37360d
commit 1563352d42
4 files changed
+7 -614

No files matched your search

+1 -366
View File
@@ -499,13 +499,9 @@ impl Sigma {
mod tests {
use super::*;
use crate::filter::gaussian_smooth;
use crate::julia_image;
use crate::transform::Transform;
use algos::OptimizationConfig;
use algos::optimization::{bfgs_minimize, gradient_descent_minimize};
use ndarray::{MeshIndex, array, meshgrid, stack};
use ndarray_npy::NpzWriter;
use std::fs::File;
use ndarray::array;
#[test]
fn derivative() -> Result<(), Box<dyn std::error::Error>> {
@@ -526,39 +522,6 @@ mod tests {
Ok(())
}
#[test]
fn metric() -> Result<(), Box<dyn std::error::Error>> {
let im_a = array![0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0];
let im_b = array![1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0];
// let a = gaussian_smooth(im_a.view(), &[4.0])?;
// let b = gaussian_smooth(im_b.view(), &[4.0])?;
let a = im_a;
let b = im_b;
// let points = vec![vec![3.0], vec![4.0], vec![5.0], vec![6.0], vec![7.0], vec![8.0]];
// let m = MattesMetric::new_from_arrays(a.view(), b.view(), SamplingArg::FixedAt(points))?
// .with_fixed_mu(vec![Some(1.0), None]);
let m = MattesMetric::new_from_arrays(a.view(), b.view(), SamplingArg::Fixed(20), 5, 0.05)?
.with_fixed_mu(vec![Some(1.0), None]);
// let m = MattesMetric::new_all_from_arrays(im_a.view(), im_b.view())?.with_fixed_mu(vec![Some(1.0), None]);
let mu = Array1::linspace(-4.0, 2.0, 601);
let mut v = Vec::new();
let mut d = Vec::new();
for x in &mu {
v.push(m.evaluate(&[*x]));
d.push(m.gradient(&[*x]).unwrap()[0]);
}
let mut npz = NpzWriter::new(File::create(
std::env::home_dir().unwrap().join("tmp/metric.npz"),
)?);
npz.add_array("mu", &mu)?;
npz.add_array("v", &Array1::from_vec(v))?;
npz.add_array("d", &Array1::from_vec(d))?;
npz.add_array("a", &a)?;
npz.add_array("b", &b)?;
Ok(())
}
#[test]
fn metric2() -> Result<(), Box<dyn std::error::Error>> {
let im_a = array![0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0];
@@ -597,135 +560,6 @@ mod tests {
Ok(())
}
#[test]
fn metric1() -> Result<(), Box<dyn std::error::Error>> {
let im_a = julia_image(
&[60, 80],
&[1.0, 0.0, 0.0, 1.0, 0.0, 0.0],
&[29.5, 39.5],
&[-0.8, 0.156],
)
.mapv(|i| i as f64);
let im_b = julia_image(
&[60, 80],
&[1.0, 0.0, 0.0, 1.0, 10.0, -20.0],
&[29.5, 39.5],
&[-0.8, 0.156],
)
.mapv(|i| i as f64);
let a = gaussian_smooth(im_a.view(), &[30.0, 40.0])?;
let b = gaussian_smooth(im_b.view(), &[30.0, 40.0])?;
let m = MattesMetric::new_from_arrays(a.view(), b.view(), SamplingArg::Fixed(250), 3, 0.2)?
.with_fixed_mu(vec![Some(1.0), Some(0.0), Some(0.0), Some(1.0), None, None]);
let mut npz = NpzWriter::new(File::create(
std::env::home_dir().unwrap().join("tmp/metric.npz"),
)?);
let s = 200;
let mu = Array1::linspace(-50.0, 50.0, s);
let (mux, muy) = meshgrid((&mu, &mu), MeshIndex::XY);
let mu = stack(Axis(0), &[mux, muy])?;
let mut v = Array2::zeros([s, s]);
let mut d = Array3::zeros([2, s, s]);
for (mui, (vi, mut di)) in mu
.lanes(Axis(0))
.into_iter()
.zip_eq(v.iter_mut().zip_eq(d.lanes_mut(Axis(0))))
{
*vi = m.evaluate(mui.to_vec().as_slice());
di.assign(&Array1::from_vec(
m.gradient(mui.to_vec().as_slice()).unwrap(),
));
}
npz.add_array("a", &a)?;
npz.add_array("b", &b)?;
npz.add_array("mu", &mu)?;
npz.add_array("v", &v)?;
npz.add_array("d", &d)?;
Ok(())
}
#[test]
fn metric3() -> Result<(), Box<dyn std::error::Error>> {
let im_a = julia_image(
&[100, 1],
&[1.0, 0.0, 0.0, 0.01, 0.0, 0.0],
&[99.5, 0.5],
&[-0.8, 0.156],
)
.slice(s![.., 0])
.mapv(|i| i as f64);
let im_b =
Transform::new(vec![1.0, 0.0], vec![im_a.shape()[0]]).interpolate::<1, _, _>(&im_a)?;
let a = gaussian_smooth(im_a.view(), &[25.0])?;
let b = gaussian_smooth(im_b.view(), &[25.0])?;
let m = MattesMetric::new_from_arrays(a.view(), b.view(), SamplingArg::Fixed(100), 6, 0.1)?
.with_fixed_mu(vec![None, None]);
let mut npz = NpzWriter::new(File::create(
std::env::home_dir().unwrap().join("tmp/metric.npz"),
)?);
let s = 200;
let translate = Array1::linspace(-50.0, 50.0, s);
let scale = Array1::logspace(10.0, -1.0, 1.0, s);
let (mux, muy) = meshgrid((&scale, &translate), MeshIndex::XY);
let mu = stack(Axis(0), &[mux, muy])?;
let mut v = Array2::zeros([s, s]);
let mut d = Array3::zeros([2, s, s]);
for (mui, (vi, mut di)) in mu
.lanes(Axis(0))
.into_iter()
.zip_eq(v.iter_mut().zip_eq(d.lanes_mut(Axis(0))))
{
*vi = m.evaluate(mui.to_vec().as_slice());
di.assign(&Array1::from_vec(
m.gradient(mui.to_vec().as_slice()).unwrap(),
));
}
npz.add_array("a", &a)?;
npz.add_array("b", &b)?;
npz.add_array("mu", &mu)?;
npz.add_array("v", &v)?;
npz.add_array("d", &d)?;
Ok(())
}
#[test]
fn metric4() -> Result<(), Box<dyn std::error::Error>> {
let im_a = julia_image(
&[100, 1],
&[1.0, 0.0, 0.0, 0.01, 0.0, 0.0],
&[99.5, 0.5],
&[-0.8, 0.156],
)
.slice(s![.., 0])
.mapv(|i| i as f64);
let im_b =
Transform::new(vec![1.0, 0.0], vec![im_a.shape()[0]]).interpolate::<1, _, _>(&im_a)?;
let a = gaussian_smooth(im_a.view(), &[50.0])?;
let b = gaussian_smooth(im_b.view(), &[50.0])?;
let m =
MattesMetric::new_from_arrays(a.view(), b.view(), SamplingArg::Fixed(1000), 3, 0.05)?
.with_fixed_mu(vec![None, Some(0.0)]);
let mut npz = NpzWriter::new(File::create(
std::env::home_dir().unwrap().join("tmp/metric.npz"),
)?);
let mu = Array1::logspace(2.0, -1.0, 1.0, 1000);
let mut v = Vec::new();
let mut d = Vec::new();
for mui in &mu {
v.push(m.evaluate(&[*mui]));
d.push(m.gradient(&[*mui]).unwrap()[0]);
}
npz.add_array("a", &a)?;
npz.add_array("b", &b)?;
npz.add_array("mu", &mu)?;
npz.add_array("v", &Array1::from(v))?;
npz.add_array("d", &Array1::from(d))?;
Ok(())
}
#[test]
fn optimize() -> Result<(), Box<dyn std::error::Error>> {
let im_a = array![0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0];
@@ -749,205 +583,6 @@ mod tests {
Ok(())
}
#[test]
fn parzen_test() -> Result<(), Box<dyn std::error::Error>> {
let a = array![0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0];
let b = array![0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0];
let fixed = BSpline::<0, _>::new(a.view());
let moving = BSpline::<3, _>::new(b.view());
let mus = [0.0, 0.001];
let mut npz = NpzWriter::new(File::create(
std::env::home_dir().unwrap().join("tmp/metric.npz"),
)?);
let s = a.len() as f64;
// let center = (s - 1.0) / 2.0;
let mut rng = rand::rng();
let idx = (&mut rng)
.random_iter::<f64>()
.take(25)
.map(|i| i * s - 0.5)
.collect::<Vec<_>>();
for (index, mu) in mus.iter().enumerate() {
let mut mem_f = fixed.get_mem();
let mut mem_m = moving.get_mem();
let mut w = Vec::new();
let mut dw = Vec::new();
let mut a = Vec::new();
let mut b = Vec::new();
let mut db = Vec::new();
for u in idx.clone() {
let v = u + mu;
if (-0.5 < v) && (v <= s - 0.5) {
let f = fixed.evaluate_at_continuous_index(&[u], &mut mem_f)?;
let (m, d) = moving
.evaluate_value_and_derivative_at_continuous_index(&[v], &mut mem_m)?;
// let j = image_jacobian(&[v], &[center], &d);
a.push(f);
b.push(m);
db.push(d);
// the metric wouldn't be smooth if we'd drop a point abruptly,
// so apply a 0 <= weight <= 1 to points within 5% of the edge
if 20.0 * (v + 0.5) < s {
let k = 60.0 * (v + 0.5) / s - 1.5;
w.push(square_bspline_integral(k));
dw.push(vec![square_bspline(k) * 60.0 / s]);
} else if 20.0 * (v + 0.5) > 19.0 * s {
let k = 60.0 * (s - v - 0.5) / s - 1.5;
w.push(square_bspline_integral(k));
dw.push(vec![-square_bspline(k) * 60.0 / s]);
} else {
w.push(1.0);
dw.push(vec![0.0]);
}
// let dw = image_jacobian(&[v], &[center], &dw);
}
}
let alpha = w.iter().sum::<f64>();
let mut dalpha = [0.0];
for i in dw.iter() {
for (j, a) in i.iter().zip_eq(dalpha.iter_mut()) {
*a += j;
}
}
let (j, dj) = parzen(alpha, &dalpha, &a, &b, &db, &w, &dw, 0.0, 2.0, 5);
let db = db.iter().map(|i| i[0]).collect::<Vec<_>>();
let dw = dw.iter().map(|i| i[0]).collect::<Vec<_>>();
npz.add_array(format!("idx{}", index), &Array1::from_vec(idx.clone()))?;
npz.add_array(format!("a{}", index), &Array1::from_vec(a))?;
npz.add_array(format!("b{}", index), &Array1::from_vec(b))?;
npz.add_array(format!("db{}", index), &Array1::from_vec(db))?;
npz.add_array(format!("w{}", index), &Array1::from_vec(w))?;
npz.add_array(format!("dw{}", index), &Array1::from_vec(dw))?;
npz.add_array(format!("j{}", index), &j)?;
npz.add_array(format!("dj{}", index), &dj)?;
}
Ok(())
}
#[test]
fn metric_test() -> Result<(), Box<dyn std::error::Error>> {
let a = array![0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0];
let b = array![0.0, 0.0, 1.0, 0.0, 1.0, 2.0, 1.0, 0.0, 1.0, 0.0, 0.0];
let fixed = BSpline::<0, _>::new(a.view());
let moving = BSpline::<3, _>::new(b.view());
let mus = Array1::linspace(-10.0, 10.0, 500);
let s = a.len() as f64;
let mut rng = rand::rng();
let idx = (&mut rng)
.random_iter::<f64>()
.take(25)
.map(|i| i * s - 0.5)
.collect::<Vec<_>>();
let mut metrics = Vec::new();
let mut dmetrics = Vec::new();
for mu in &mus {
let mut mem_f = fixed.get_mem();
let mut mem_m = moving.get_mem();
let mut w = Vec::new();
let mut dw = Vec::new();
let mut a = Vec::new();
let mut b = Vec::new();
let mut db = Vec::new();
for u in idx.clone() {
let v = u + mu;
if (-0.5 < v) && (v <= s - 0.5) {
let f = fixed.evaluate_at_continuous_index(&[u], &mut mem_f)?;
let (m, d) = moving
.evaluate_value_and_derivative_at_continuous_index(&[v], &mut mem_m)?;
// let j = image_jacobian(&[v], &[center], &d);
a.push(f);
b.push(m);
db.push(d);
// the metric wouldn't be smooth if we'd drop a point abruptly,
// so apply a 0 <= weight <= 1 to points within 5% of the edge
if 20.0 * (v + 0.5) < s {
let k = 60.0 * (v + 0.5) / s - 1.5;
w.push(square_bspline_integral(k));
dw.push(vec![square_bspline(k) * 60.0 / s]);
} else if 20.0 * (v + 0.5) > 19.0 * s {
let k = 60.0 * (s - v - 0.5) / s - 1.5;
w.push(square_bspline_integral(k));
dw.push(vec![-square_bspline(k) * 60.0 / s]);
} else {
w.push(1.0);
dw.push(vec![0.0]);
}
// let dw = image_jacobian(&[v], &[center], &dw);
}
}
let alpha = w.iter().sum::<f64>();
let mut dalpha = [0.0];
for i in dw.iter() {
for (j, a) in i.iter().zip_eq(dalpha.iter_mut()) {
*a += j;
}
}
let (jpdf, d_jpdf_m) = parzen(alpha, &dalpha, &a, &b, &db, &w, &dw, 0.0, 2.0, 5);
let pdf_f = jpdf.axis_iter(Axis(0)).map(|i| i.sum()).collect::<Vec<_>>();
let pdf_m = jpdf.axis_iter(Axis(1)).map(|i| i.sum()).collect::<Vec<_>>();
let d_pdf_m = d_jpdf_m
.axis_iter(Axis(1))
.map(|i| i.sum())
.collect::<Vec<_>>();
let mut metric = 0.0;
let mut dmetric = vec![0.0];
let mut n;
let mut m;
for ((row, d_row), k) in jpdf
.axis_iter(Axis(0))
.zip_eq(d_jpdf_m.axis_iter(Axis(0)))
.zip_eq(pdf_f)
{
debug_assert_eq!(row.len(), d_row.shape()[0]);
debug_assert_eq!(row.len(), pdf_m.len());
for ((&j, dj), (i, di)) in row
.into_iter()
.zip_eq(d_row.axis_iter(Axis(0)))
.zip_eq(pdf_m.iter().zip(d_pdf_m.iter()))
{
// check for non-zero bin contribution
if (j > 1e-16) && (i * k > 1e-16) {
metric -= j * (j / (i * k)).ln();
n = (j / (i * k)).ln() + 1.0;
m = di * j / i;
for (d, g) in dmetric.iter_mut().zip_eq(dj) {
*d += m - n * g; // eq 23 of Thevenaz & Unser paper [3]
}
}
}
}
metrics.push(metric);
dmetrics.push(dmetric);
}
let mut npz = NpzWriter::new(File::create(
std::env::home_dir().unwrap().join("tmp/metric.npz"),
)?);
npz.add_array("mu", &mus)?;
npz.add_array("metric", &Array1::from_vec(metrics))?;
npz.add_array(
"dmetric",
&Array1::from_vec(dmetrics.iter().map(|d| d[0]).collect()),
)?;
Ok(())
}
#[test]
fn test_square_bspline_integral() -> Result<(), Box<dyn std::error::Error>> {
let x = Array1::linspace(-2.0, 2.0, 500);