Added comment to prevent myself from doing something silly in the future.
[trakem2.git] / mpi / fruitfly / registration / Optimize.java
blobc6a679a6e3512c4cf0074ee01b82059e950570b5
1 package mpi.fruitfly.registration;
3 import java.util.List;
4 import ini.trakem2.display.Patch;
5 import ini.trakem2.display.Layer;
6 import ini.trakem2.display.Display;
7 import mpi.fruitfly.analysis.FitLine;
9 public class Optimize {
11 /**
12 * minimize the overall displacement of a set of tiles, propagate the
13 * estimated models to a corresponding set of patches and redraw
15 * @param tiles
16 * @param patches
17 * @param fixed_tiles do not touch these tiles
18 * @param update_this
20 * TODO revise convergence check
21 * particularly for unguided minimization, it is hard to identify
22 * convergence due to presence of local minima
24 * Johannes Schindelin suggested to start from a good guess, which is
25 * e.g. the propagated unoptimized pose of a tile relative to its
26 * connected tile that was already identified during RANSAC
27 * correpondence check. Thank you, Johannes, great hint!
29 static public void minimizeAll(
30 List< Tile > tiles,
31 List< Patch > patches,
32 List< Tile > fixed_tiles,
33 float max_error )
35 int num_patches = patches.size();
37 double od = Double.MAX_VALUE;
38 double dd = Double.MAX_VALUE;
39 double min_d = Double.MAX_VALUE;
40 double max_d = Double.MIN_VALUE;
41 int iteration = 1;
42 int cc = 0;
43 double[] dall = new double[100];
44 int next = 0;
45 //while ( cc < 10 )
47 final Observer observer = new Observer();
49 final Layer layer = patches.get(0).getLayer();
51 while ( next < 100000 ) // safety check
52 // while ( next < 10000 ) // safety check
54 for ( int i = 0; i < num_patches; ++i )
56 Tile tile = tiles.get( i );
57 if ( fixed_tiles.contains( tile ) ) continue;
58 tile.update();
59 tile.minimizeModel();
60 tile.update();
61 patches.get( i ).getAffineTransform().setTransform( tile.getModel().getAffine() );
62 //IJ.showStatus( "displacement: overall => " + od + ", current => " + tile.getDistance() );
64 double cd = 0.0;
65 min_d = Double.MAX_VALUE;
66 max_d = Double.MIN_VALUE;
67 for ( Tile t : tiles )
69 t.update();
70 double d = t.getDistance();
71 if ( d < min_d ) min_d = d;
72 if ( d > max_d ) max_d = d;
73 cd += d;
75 cd /= tiles.size();
76 dd = Math.abs( od - cd );
77 od = cd;
78 //IJ.showStatus( "displacement: " + od + " [" + min_d + "; " + max_d + "] after " + iteration + " iterations");
80 observer.add( od );
82 //cc = d < 0.00025 ? cc + 1 : 0;
83 cc = dd < 0.001 ? cc + 1 : 0;
85 if (dall.length == next) {
86 double[] dall2 = new double[dall.length + 100];
87 System.arraycopy(dall, 0, dall2, 0, dall.length);
88 dall = dall2;
90 dall[next++] = dd;
92 // cut the last 'n'
93 if (next > 100) { // wait until completing at least 'n' iterations
94 double[] dn = new double[100];
95 System.arraycopy(dall, dall.length - 100, dn, 0, 100);
96 // fit curve
97 double[] ft = FitLine.fitLine(dn);
98 // ft[1] StdDev
99 // ft[2] m (slope)
100 //if ( Math.abs( ft[ 1 ] ) < 0.001 )
102 // TODO revise convergence check or start from better guesses
103 if ( od < max_error && ft[ 2 ] >= 0.0 )
105 System.out.println( "Exiting at iteration " + next + " with slope " + ft[ 2 ] );
106 break;
111 ++iteration;
113 if (0 == iteration / 1000) Display.repaint(layer, null, 0, false); // do the entire canvas, and do not update the navigator
115 // f.close();
117 System.out.println( "Successfully optimized configuration of " + tiles.size() + " tiles:" );
118 System.out.println( " average displacement: " + od + "px" );
119 System.out.println( " minimal displacement: " + min_d + "px" );
120 System.out.println( " maximal displacement: " + max_d + "px" );
123 static private class Observer
125 public int i; // iteration
126 public double v; // value
127 public double d; // first derivative
128 public double m; // mean
129 public double var; // variance
130 public double std; // standard-deviation
132 public void add( double new_value )
134 if ( i == 0 )
136 i = 1;
137 v = new_value;
138 d = 0.0;
139 m = v;
140 var = 0.0;
141 std = 0.0;
143 else
145 d = new_value - v;
146 v = new_value;
147 m = ( v + m * ( double )i++ ) / ( double )i;
148 double tmp = v - m;
149 var += tmp * tmp / ( double )i;
150 std = Math.sqrt( var );