Commit 3479dfe6 authored by Andrey Filippov's avatar Andrey Filippov

working on saving/restoring new parameters

parent ca5bb1b6
/** /**
** **
** FocusingField.jave - save/restore/process sagittal/tangential PSF width ** FocusingField.jave - save/restore/process sagittal/tangential PSF width
** over FOV, together with related data ** over FOV, together with related data
** **
** Copyright (C) 2014 Elphel, Inc. ** Copyright (C) 2014 Elphel, Inc.
** **
** -----------------------------------------------------------------------------** ** -----------------------------------------------------------------------------**
** **
** CalibrationHardwareInterface.java is free software: you can redistribute it and/or modify ** CalibrationHardwareInterface.java is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by ** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or ** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version. ** (at your option) any later version.
** **
** This program is distributed in the hope that it will be useful, ** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of ** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details. ** GNU General Public License for more details.
** **
** You should have received a copy of the GNU General Public License ** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
** -----------------------------------------------------------------------------** ** -----------------------------------------------------------------------------**
** **
*/ */
import ij.IJ; import ij.IJ;
import ij.gui.GenericDialog; import ij.gui.GenericDialog;
...@@ -33,6 +33,7 @@ import java.io.FileWriter; ...@@ -33,6 +33,7 @@ import java.io.FileWriter;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import org.apache.commons.configuration.ConfigurationException; import org.apache.commons.configuration.ConfigurationException;
...@@ -44,6 +45,7 @@ import org.apache.commons.configuration.XMLConfiguration; ...@@ -44,6 +45,7 @@ import org.apache.commons.configuration.XMLConfiguration;
//import Distortions.LMAArrays; // may still reuse? //import Distortions.LMAArrays; // may still reuse?
import Jama.LUDecomposition; import Jama.LUDecomposition;
import Jama.Matrix; import Jama.Matrix;
...@@ -83,91 +85,92 @@ public class FocusingField { ...@@ -83,91 +85,92 @@ public class FocusingField {
double [] currentVector=null; double [] currentVector=null;
double [] nextVector=null; double [] nextVector=null;
double [] savedVector=null; double [] savedVector=null;
private LMAArrays lMAArrays=null; private LMAArrays lMAArrays=null;
private LMAArrays savedLMAArrays=null; private LMAArrays savedLMAArrays=null;
private double [] currentfX=null; // array of "f(x)" - simulated data for all images, combining pixel-X and pixel-Y (odd/even) private double [] currentfX=null; // array of "f(x)" - simulated data for all images, combining pixel-X and pixel-Y (odd/even)
private double [] nextfX=null; // array of "f(x)" - simulated data for all images, combining pixel-X and pixel-Y (odd/even) private double [] nextfX=null; // array of "f(x)" - simulated data for all images, combining pixel-X and pixel-Y (odd/even)
private double currentRMS=-1.0; // calculated RMS for the currentVector->currentfX private double currentRMS=-1.0; // calculated RMS for the currentVector->currentfX
private double currentRMSPure=-1.0; // calculated RMS for the currentVector->currentfX private double currentRMSPure=-1.0; // calculated RMS for the currentVector->currentfX
private double nextRMS=-1.0; // calculated RMS for the nextVector->nextfX private double nextRMS=-1.0; // calculated RMS for the nextVector->nextfX
private double nextRMSPure=-1.0; // calculated RMS for the nextVector->nextfX private double nextRMSPure=-1.0; // calculated RMS for the nextVector->nextfX
private double firstRMS=-1.0; // RMS before current series of LMA started private double firstRMS=-1.0; // RMS before current series of LMA started
private double firstRMSPure=-1.0; // RMS before current series of LMA started private double firstRMSPure=-1.0; // RMS before current series of LMA started
private double lambdaStepUp= 8.0; // multiply lambda by this if result is worse private double lambdaStepUp= 8.0; // multiply lambda by this if result is worse
private double lambdaStepDown= 0.5; // multiply lambda by this if result is better private double lambdaStepDown= 0.5; // multiply lambda by this if result is better
private double thresholdFinish=0.001; // (copied from series) stop iterations if 2 last steps had less improvement (but not worsening ) private double thresholdFinish=0.001; // (copied from series) stop iterations if 2 last steps had less improvement (but not worsening )
private int numIterations= 100; // maximal number of iterations private int numIterations= 100; // maximal number of iterations
private double maxLambda= 100.0; // max lambda to fail private double maxLambda= 100.0; // max lambda to fail
private double lambda=0.001; // copied from series private double lambda=0.001; // copied from series
private double [] lastImprovements= {-1.0,-1.0}; // {last improvement, previous improvement}. If both >0 and < thresholdFinish - done private double [] lastImprovements= {-1.0,-1.0}; // {last improvement, previous improvement}. If both >0 and < thresholdFinish - done
private int iterationStepNumber=0; private int iterationStepNumber=0;
private boolean stopEachStep= true; // open dialog after each fitting step private boolean stopEachStep= true; // open dialog after each fitting step
private boolean stopOnFailure= true; // open dialog when fitting series failed private boolean stopOnFailure= true; // open dialog when fitting series failed
private boolean showParams= false; // show modified parameters private boolean showParams= false; // show modified parameters
private boolean showDisabledParams = false; private boolean showDisabledParams = false;
private boolean showCorrectionParams = false; private boolean showCorrectionParams = false;
private long startTime=0; private boolean keepCorrectionParameters = true;
private AtomicInteger stopRequested=null; // 1 - stop now, 2 - when convenient private long startTime=0;
private boolean saveSeries=false; // just for the dialog private AtomicInteger stopRequested=null; // 1 - stop now, 2 - when convenient
private boolean saveSeries=false; // just for the dialog
private boolean showMotors = true;
private boolean [] showMeasCalc = {true,true,true}; private boolean showMotors = true;
private boolean [] showColors = {true,true,true}; private boolean [] showMeasCalc = {true,true,true};
private boolean [] showDirs = {true,true}; private boolean [] showColors = {true,true,true};
private boolean [] showSamples = null; private boolean [] showDirs = {true,true};
private boolean showAllSamples = true; private boolean [] showSamples = null;
private boolean showIgnoredData= false; private boolean showAllSamples = true;
private boolean showRad = true; private boolean showIgnoredData= false;
private boolean [][][][][] sampleMask=null; private boolean showRad = true;
private boolean [][][][][] sampleMask=null;
private boolean correct_measurement_ST=true;
private boolean updateWeightWhileFitting=false; private boolean correct_measurement_ST=true;
private boolean updateWeightWhileFitting=false;
public int debugLevel;
public boolean debugDerivatives; public int debugLevel;
public boolean debugDerivativesFxDxDy=false; public boolean debugDerivatives;
public boolean debugDerivativesFxDxDy=false;
private double k_red=0.7;
private double k_blue=0.4; private double k_red=0.7;
private double k_blue=0.4;
private double qb_scan_below=-20.0; // um
private double qb_scan_above= 60.0; // um private double qb_scan_below=-20.0; // um
private double qb_scan_step= 0.5; // um private double qb_scan_above= 60.0; // um
private double qb_scan_step= 0.5; // um
private boolean qb_use_corrected=true;
private boolean qb_invert=true; private boolean qb_use_corrected=true;
private boolean qb_invert=true;
private boolean rslt_show_z_axial=true;
private boolean rslt_show_z_individual=true; private boolean rslt_show_z_axial=true;
private boolean rslt_show_f_axial=true; private boolean rslt_show_z_individual=true;
private boolean rslt_show_f_individual=true; private boolean rslt_show_f_axial=true;
private double rslt_scan_below=-10.0; private boolean rslt_show_f_individual=true;
private double rslt_scan_above= 10.0; private double rslt_scan_below=-10.0;
private double rslt_scan_step= 5.0; private double rslt_scan_above= 10.0;
private boolean rslt_mtf50_mode= true; private double rslt_scan_step= 5.0;
private boolean [] rslt_show_chn={true,true,true,true,true,true}; private boolean rslt_mtf50_mode= true;
private boolean [] rslt_show_chn={true,true,true,true,true,true};
// public double fwhm_to_mtf50=500.0; // put actual number // public double fwhm_to_mtf50=500.0; // put actual number
public double fwhm_to_mtf50=2*Math.log(2.0)/Math.PI*1000; //pi/0.004 public double fwhm_to_mtf50=2*Math.log(2.0)/Math.PI*1000; //pi/0.004
public void setDebugLevel(int debugLevel){ public void setDebugLevel(int debugLevel){
this.debugLevel=debugLevel; this.debugLevel=debugLevel;
} }
public class LMAArrays { // reuse from Distortions? public class LMAArrays { // reuse from Distortions?
public double [][] jTByJ= null; // jacobian multiplied by Jacobian transposed public double [][] jTByJ= null; // jacobian multiplied by Jacobian transposed
public double [] jTByDiff=null; // jacobian multiplied difference vector public double [] jTByDiff=null; // jacobian multiplied difference vector
public LMAArrays clone() { public LMAArrays clone() {
LMAArrays lma=new LMAArrays(); LMAArrays lma=new LMAArrays();
lma.jTByJ = this.jTByJ.clone(); lma.jTByJ = this.jTByJ.clone();
for (int i=0;i<this.jTByJ.length;i++) lma.jTByJ[i]=this.jTByJ[i].clone(); for (int i=0;i<this.jTByJ.length;i++) lma.jTByJ[i]=this.jTByJ[i].clone();
lma.jTByDiff=this.jTByDiff.clone(); lma.jTByDiff=this.jTByDiff.clone();
return lma; return lma;
} }
} }
public enum MECH_PAR { public enum MECH_PAR {
K0, // Average motor center travel","um/step","0.0124"}, K0, // Average motor center travel","um/step","0.0124"},
KD1, // M1 and M2 travel disbalance","um/step","0.0"}, KD1, // M1 and M2 travel disbalance","um/step","0.0"},
KD3, // M3 to average of M1 and M2 travel disbalance","um/step","0.0"}, KD3, // M3 to average of M1 and M2 travel disbalance","um/step","0.0"},
...@@ -184,20 +187,20 @@ public class FocusingField { ...@@ -184,20 +187,20 @@ public class FocusingField {
z0, // center shift, positive away form the lens","um","0.0"}, z0, // center shift, positive away form the lens","um","0.0"},
tx, // horizontal tilt", "um/pix","0.0"}, tx, // horizontal tilt", "um/pix","0.0"},
ty // vertical tilt", "um/pix","0.0"}}; ty // vertical tilt", "um/pix","0.0"}};
} }
public static double getPixelMM(){return PIXEL_SIZE;} public static double getPixelMM(){return PIXEL_SIZE;}
public static double getPixelUM(){return PIXEL_SIZE*1000;} public static double getPixelUM(){return PIXEL_SIZE*1000;}
public int flattenIndex(int i, int j){return j+i*sampleCoord[0].length;} public int flattenIndex(int i, int j){return j+i*sampleCoord[0].length;}
public int getNumSamples(){return sampleCoord.length*sampleCoord[0].length;} public int getNumSamples(){return sampleCoord.length*sampleCoord[0].length;}
public int getSampleWidth(){return sampleCoord[0].length;} public int getSampleWidth(){return sampleCoord[0].length;}
public double [][] flattenSampleCoord(){ public double [][] flattenSampleCoord(){
///sampleCoord ///sampleCoord
double [][] flatSampleCoord=new double [sampleCoord.length*sampleCoord[0].length][2]; double [][] flatSampleCoord=new double [sampleCoord.length*sampleCoord[0].length][2];
int index=0; int index=0;
for (int i=0;i<sampleCoord.length;i++) for (int j=0;j<sampleCoord[0].length;j++) flatSampleCoord[index++]= sampleCoord[i][j]; for (int i=0;i<sampleCoord.length;i++) for (int j=0;j<sampleCoord[0].length;j++) flatSampleCoord[index++]= sampleCoord[i][j];
return flatSampleCoord; // last dimension is not cloned return flatSampleCoord; // last dimension is not cloned
} }
public class MeasuredSample{ public class MeasuredSample{
public int [] motors = new int[3]; public int [] motors = new int[3];
public String timestamp; public String timestamp;
public double px; public double px;
...@@ -230,8 +233,8 @@ public class FocusingField { ...@@ -230,8 +233,8 @@ public class FocusingField {
this.dPxyc[1]=dPyc; this.dPxyc[1]=dPyc;
this.sampleIndex=sampleIndex; this.sampleIndex=sampleIndex;
} }
} }
public boolean configureDataVector(String title, boolean forcenew){ public boolean configureDataVector(String title, boolean forcenew){
if ((fieldFitting == null) && !forcenew){ if ((fieldFitting == null) && !forcenew){
forcenew=true; forcenew=true;
} }
...@@ -313,13 +316,13 @@ public class FocusingField { ...@@ -313,13 +316,13 @@ public class FocusingField {
this.savedVector=fieldFitting.createParameterVector(sagittalMaster); this.savedVector=fieldFitting.createParameterVector(sagittalMaster);
// initialVector // initialVector
return true; return true;
} }
// includes deselected channels // includes deselected channels
public void setDataVector(MeasuredSample [] vector){ // remove unused channels if any public void setDataVector(MeasuredSample [] vector){ // remove unused channels if any
if (debugLevel>1) System.out.println("+++++ (Re)calculating sample weights +++++"); if (debugLevel>1) System.out.println("+++++ (Re)calculating sample weights +++++");
boolean [] chanSel=fieldFitting.getSelectedChannels(); boolean [] chanSel=fieldFitting.getSelectedChannels();
int numSamples=0; int numSamples=0;
...@@ -330,7 +333,7 @@ public class FocusingField { ...@@ -330,7 +333,7 @@ public class FocusingField {
int corrLength=fieldFitting.getNumberOfCorrParameters(); int corrLength=fieldFitting.getNumberOfCorrParameters();
dataValues = new double [dataVector.length+corrLength]; dataValues = new double [dataVector.length+corrLength];
dataWeights = new double [dataVector.length+corrLength]; dataWeights = new double [dataVector.length+corrLength];
// sumWeights=0.0; // sumWeights=0.0;
int mode=weighMode; int mode=weighMode;
double kw= (weightRadius>0.0)?(-0.5*getPixelMM()*getPixelMM()/(weightRadius*weightRadius)):0; double kw= (weightRadius>0.0)?(-0.5*getPixelMM()*getPixelMM()/(weightRadius*weightRadius)):0;
//weightRadius //weightRadius
...@@ -356,11 +359,11 @@ public class FocusingField { ...@@ -356,11 +359,11 @@ public class FocusingField {
dataValues[i+dataVector.length]=0.0; // correction target is always 0 dataValues[i+dataVector.length]=0.0; // correction target is always 0
dataWeights[i+dataVector.length]=1.0; // improve? dataWeights[i+dataVector.length]=1.0; // improve?
} }
} }
// for compatibility with Distortions class\ // for compatibility with Distortions class\
public void commitParameterVector(double [] vector){ public void commitParameterVector(double [] vector){
fieldFitting.commitParameterVector(vector,sagittalMaster); fieldFitting.commitParameterVector(vector,sagittalMaster);
// recalculate measured S,T (depend on center) if center is among fitted parameters // recalculate measured S,T (depend on center) if center is among fitted parameters
boolean [] centerSelect=fieldFitting.getCenterSelect(); boolean [] centerSelect=fieldFitting.getCenterSelect();
...@@ -378,15 +381,15 @@ public class FocusingField { ...@@ -378,15 +381,15 @@ public class FocusingField {
} }
} }
} }
public double [] createFXandJacobian( double [] vector, boolean createJacobian){ public double [] createFXandJacobian( double [] vector, boolean createJacobian){
commitParameterVector(vector); commitParameterVector(vector);
return createFXandJacobian(createJacobian); return createFXandJacobian(createJacobian);
} }
public double [] createFXandJacobian(boolean createJacobian){ public double [] createFXandJacobian(boolean createJacobian){
int numCorrPar=fieldFitting.getNumberOfCorrParameters(); int numCorrPar=fieldFitting.getNumberOfCorrParameters();
double [] fx=new double[dataVector.length + numCorrPar ]; double [] fx=new double[dataVector.length + numCorrPar ];
double [][] derivs=null; double [][] derivs=null;
...@@ -431,15 +434,6 @@ public class FocusingField { ...@@ -431,15 +434,6 @@ public class FocusingField {
// jacobian[i][n]=derivs[selChanIndices[ms.channel]][i]; // jacobian[i][n]=derivs[selChanIndices[ms.channel]][i];
jacobian[i][n]=thisDerivs[i]; jacobian[i][n]=thisDerivs[i];
} }
/*
if ((fieldFitting.sampleCorrChnParIndex!=null) && (fieldFitting.sampleCorrChnParIndex[ms.channel]!=null)){
for (int i=0;i<fieldFitting.getNumCurvars()[0];i++){
if (fieldFitting.sampleCorrChnParIndex[ms.channel][i]>=0){
jacobian[i][n]
}
}
}
*/
//TODO: correct /dpx, /dpy to compensate for measured S,T calcualtion //TODO: correct /dpx, /dpy to compensate for measured S,T calcualtion
boolean [] centerSelect=fieldFitting.getCenterSelect(); boolean [] centerSelect=fieldFitting.getCenterSelect();
if (correct_measurement_ST && (centerSelect[0] || centerSelect[1])){ // do not do that if both X and Y are disabled if (correct_measurement_ST && (centerSelect[0] || centerSelect[1])){ // do not do that if both X and Y are disabled
...@@ -460,10 +454,10 @@ public class FocusingField { ...@@ -460,10 +454,10 @@ public class FocusingField {
for (int i=0;i<numSamples;i++){ for (int i=0;i<numSamples;i++){
double f=0.0; double f=0.0;
for (int j=0;j<numSamples;j++){ for (int j=0;j<numSamples;j++){
f+=fieldFitting.sampleCorr[pindex+j]*fieldFitting.sampleCorrCrossWeights[chn][np][i][j]; f+=fieldFitting.sampleCorrVector[pindex+j]*fieldFitting.sampleCorrCrossWeights[chn][np][i][j];
} }
fx[index]=f; fx[index]=f;
// f+=fieldFitting.sampleCorr[pindex+i] // f+=fieldFitting.sampleCorrVector[pindex+i]
if (createJacobian) { if (createJacobian) {
for (int j=0;j<numSamples;j++){ for (int j=0;j<numSamples;j++){
jacobian[numRegPars+pindex+j][index]=fieldFitting.sampleCorrCrossWeights[chn][np][i][j]; jacobian[numRegPars+pindex+j][index]=fieldFitting.sampleCorrCrossWeights[chn][np][i][j];
...@@ -477,9 +471,9 @@ public class FocusingField { ...@@ -477,9 +471,9 @@ public class FocusingField {
} }
} }
return fx; return fx;
} }
public double getRMS(double [] fx, boolean pure){ public double getRMS(double [] fx, boolean pure){
int len=pure?dataVector.length:fx.length; int len=pure?dataVector.length:fx.length;
double sum=0.0; double sum=0.0;
double sum_w=0.0; double sum_w=0.0;
...@@ -500,40 +494,40 @@ public class FocusingField { ...@@ -500,40 +494,40 @@ public class FocusingField {
sum/=sum_w; sum/=sum_w;
} }
return Math.sqrt(sum); return Math.sqrt(sum);
} }
public MeasuredSample [] createDataVector(){ public MeasuredSample [] createDataVector(){
return createDataVector( return createDataVector(
true, // boolean updateSelection, true, // boolean updateSelection,
currentPX0, // double centerPX, currentPX0, // double centerPX,
currentPY0); //double centerPY currentPY0); //double centerPY
} }
public MeasuredSample [] createDataVector( public MeasuredSample [] createDataVector(
boolean updateSelection, boolean updateSelection,
double centerPX, double centerPX,
double centerPY double centerPY
){ // use this data ){ // use this data
return createDataVector( return createDataVector(
updateSelection, updateSelection,
centerPX, centerPX,
centerPY, centerPY,
(this.useMinMeas?this.minMeas:null), // pixels (this.useMinMeas?this.minMeas:null), // pixels
(this.useMaxMeas?this.maxMeas:null), // pixels (this.useMaxMeas?this.maxMeas:null), // pixels
(this.useThresholdMax?this.thresholdMax:null)); // pixels (this.useThresholdMax?this.thresholdMax:null)); // pixels
} }
/** /**
* Generate of usable measurement samples * Generate of usable measurement samples
* @param minMeas minimal measurement PSF radius (in pixels) - correction that increases result * @param minMeas minimal measurement PSF radius (in pixels) - correction that increases result
* resolution in "sharp" areas (to compensate for measurement error). Individual for each of * resolution in "sharp" areas (to compensate for measurement error). Individual for each of
* the 6 color/direction components. * the 6 color/direction components.
* @param updateSelection when true - updates selection of "good" samples, when false - reuses existent one * @param updateSelection when true - updates selection of "good" samples, when false - reuses existent one
* @param maxMeas maximal measurement PSF radius (in pixels) - correction that decreases result * @param maxMeas maximal measurement PSF radius (in pixels) - correction that decreases result
* resolution out-of-focus areas to compensate for the limited size of the PSF window. * resolution out-of-focus areas to compensate for the limited size of the PSF window.
* Individual for each of the 6 color/direction components. * Individual for each of the 6 color/direction components.
* @param thresholdMax maximal PSF radius to consider data usable * @param thresholdMax maximal PSF radius to consider data usable
* @return array of the MeasuredSample instances, including motors, PSF radius, channel and value * @return array of the MeasuredSample instances, including motors, PSF radius, channel and value
*/ */
/* /*
Need to find partial derivatives of each of the 3 coefficients: c2, s2 and cs for both px0 and py0 Need to find partial derivatives of each of the 3 coefficients: c2, s2 and cs for both px0 and py0
r2 = (x-x0)^2+ (y-y0)^2 r2 = (x-x0)^2+ (y-y0)^2
...@@ -569,8 +563,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -569,8 +563,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
d_cs/dx0= delta_y*(2*delta_x^2-r2)/r2^2 d_cs/dx0= delta_y*(2*delta_x^2-r2)/r2^2
d_cs/dy0= delta_x*(2*delta_y^2-r2)/r2^2 d_cs/dy0= delta_x*(2*delta_y^2-r2)/r2^2
*/ */
public MeasuredSample [] createDataVector( public MeasuredSample [] createDataVector(
boolean updateSelection, boolean updateSelection,
double centerPX, double centerPX,
double centerPY, double centerPY,
...@@ -602,7 +596,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -602,7 +596,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
2*d_cs/dx0= 2*delta_y*(2*delta_x^2-r2)/r2^2 2*d_cs/dx0= 2*delta_y*(2*delta_x^2-r2)/r2^2
2*d_cs/dy0= 2*delta_x*(2*delta_y^2-r2)/r2^2 2*d_cs/dy0= 2*delta_x*(2*delta_y^2-r2)/r2^2
*/ */
double [][][] cosSin2Tab=new double[sampleCoord.length][sampleCoord[0].length][3]; double [][][] cosSin2Tab=new double[sampleCoord.length][sampleCoord[0].length][3];
double [][][] debugCosSin2Tab_dx=null; double [][][] debugCosSin2Tab_dx=null;
double [][][] debugCosSin2Tab_dy=null; double [][][] debugCosSin2Tab_dy=null;
...@@ -883,7 +877,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -883,7 +877,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
if (debugLevel>3) System.out.println(); if (debugLevel>3) System.out.println();
if (debugLevel>0) System.out.println("createDataVector -> "+sampleList.size()+" elements"); if (debugLevel>0) System.out.println("createDataVector -> "+sampleList.size()+" elements");
return sampleList.toArray(new MeasuredSample[0]); return sampleList.toArray(new MeasuredSample[0]);
} }
/** /**
* Calculate differences vector * Calculate differences vector
* @param fX vector of calculated pixelX,pixelY on the sensors * @param fX vector of calculated pixelX,pixelY on the sensors
...@@ -1086,12 +1080,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1086,12 +1080,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
// this.savedJacobian=this.jacobian; // this.savedJacobian=this.jacobian;
this.savedLMAArrays=lMAArrays.clone(); this.savedLMAArrays=lMAArrays.clone();
this.jacobian=null; // not needed, just to catch bugs this.jacobian=null; // not needed, just to catch bugs
this.nextfX=createFXandJacobian(this.nextVector,true); this.nextfX=createFXandJacobian(this.nextVector,true);
this.lMAArrays=calculateJacobianArrays(this.nextfX); this.lMAArrays=calculateJacobianArrays(this.nextfX);
this.nextRMS= calcErrorDiffY(this.nextfX,false); this.nextRMS= calcErrorDiffY(this.nextfX,false);
this.nextRMSPure= calcErrorDiffY(this.nextfX,true); this.nextRMSPure= calcErrorDiffY(this.nextfX,true);
this.lastImprovements[1]=this.lastImprovements[0]; this.lastImprovements[1]=this.lastImprovements[0];
this.lastImprovements[0]=this.currentRMS-this.nextRMS; this.lastImprovements[0]=this.currentRMS-this.nextRMS;
if (debugLevel>2) { if (debugLevel>2) {
...@@ -1142,9 +1136,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1142,9 +1136,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
System.out.println("stepLevenbergMarquardtFirst("+debugLevel+")=>"+status[0]+","+status[1]); System.out.println("stepLevenbergMarquardtFirst("+debugLevel+")=>"+status[0]+","+status[1]);
} }
return status; return status;
} }
public void stepLevenbergMarquardtAction(int debugLevel){// public void stepLevenbergMarquardtAction(int debugLevel){//
this.iterationStepNumber++; this.iterationStepNumber++;
// apply/revert,modify lambda // apply/revert,modify lambda
if (debugLevel>1) { if (debugLevel>1) {
...@@ -1165,16 +1159,18 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1165,16 +1159,18 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
this.lambda*=this.lambdaStepUp; this.lambda*=this.lambdaStepUp;
this.lMAArrays=this.savedLMAArrays; // restore Jt*J and Jt*diff this.lMAArrays=this.savedLMAArrays; // restore Jt*J and Jt*diff
} }
} }
/** /**
* Dialog to select Levenberg-Marquardt algorithm and related parameters * Dialog to select Levenberg-Marquardt algorithm and related parameters
* @return true if OK, false if canceled * @return true if OK, false if canceled
*/ */
public boolean selectLMAParameters(){ public boolean selectLMAParameters(){
// int numSeries=fittingStrategy.getNumSeries(); // int numSeries=fittingStrategy.getNumSeries();
boolean resetCorrections=false;
GenericDialog gd = new GenericDialog("Levenberg-Marquardt algorithm parameters for cameras distortions/locations"); GenericDialog gd = new GenericDialog("Levenberg-Marquardt algorithm parameters for cameras distortions/locations");
gd.addCheckbox("Debug df/dX0, df/dY0", false); gd.addCheckbox("Debug df/dX0, df/dY0", false);
gd.addCheckbox("Keep current correction parameters", this.keepCorrectionParameters);
// gd.addNumericField("Iteration number to start (0.."+(numSeries-1)+")", this.seriesNumber, 0); // gd.addNumericField("Iteration number to start (0.."+(numSeries-1)+")", this.seriesNumber, 0);
gd.addNumericField("Initial LMA Lambda ", this.lambda, 5); gd.addNumericField("Initial LMA Lambda ", this.lambda, 5);
gd.addNumericField("Multiply lambda on success", this.lambdaStepDown, 5); gd.addNumericField("Multiply lambda on success", this.lambdaStepDown, 5);
...@@ -1192,6 +1188,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1192,6 +1188,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
gd.addCheckbox("Show disabled parameters", this.showDisabledParams); gd.addCheckbox("Show disabled parameters", this.showDisabledParams);
gd.addCheckbox("Show per-sample correction parameters", this.showCorrectionParams); gd.addCheckbox("Show per-sample correction parameters", this.showCorrectionParams);
gd.addCheckbox("Reset all per-sample corrections to zero", resetCorrections);
// gd.addCheckbox("Show debug images before correction",this.showThisImages); // gd.addCheckbox("Show debug images before correction",this.showThisImages);
// gd.addCheckbox("Show debug images after correction", this.showNextImages); // gd.addCheckbox("Show debug images after correction", this.showNextImages);
...@@ -1200,6 +1197,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1200,6 +1197,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
gd.showDialog(); gd.showDialog();
if (gd.wasCanceled()) return false; if (gd.wasCanceled()) return false;
this.debugDerivativesFxDxDy=gd.getNextBoolean(); this.debugDerivativesFxDxDy=gd.getNextBoolean();
this.keepCorrectionParameters = gd.getNextBoolean();
// this.seriesNumber= (int) gd.getNextNumber(); // this.seriesNumber= (int) gd.getNextNumber();
this.lambda= gd.getNextNumber(); this.lambda= gd.getNextNumber();
this.lambdaStepDown= gd.getNextNumber(); this.lambdaStepDown= gd.getNextNumber();
...@@ -1218,10 +1216,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1218,10 +1216,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
// this.showNextImages= gd.getNextBoolean(); // this.showNextImages= gd.getNextBoolean();
// this.threadsMax= (int) gd.getNextNumber(); // this.threadsMax= (int) gd.getNextNumber();
// this.threadedLMA= gd.getNextBoolean(); // this.threadedLMA= gd.getNextBoolean();
resetCorrections= gd.getNextBoolean();
if (resetCorrections) fieldFitting.resetSampleCorr();
return true; return true;
} }
public void listParameters(String title, String path){ public void listParameters(String title, String path){
String header="State\tDescription\tValue\tUnits"; String header="State\tDescription\tValue\tUnits";
StringBuffer sb = new StringBuffer(); StringBuffer sb = new StringBuffer();
for (String s:this.fieldFitting.getParameterValueStrings(true,true)){ //this.showDisabledParams)){ // for (String s:this.fieldFitting.getParameterValueStrings(true,true)){ //this.showDisabledParams)){ //
...@@ -1234,9 +1234,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1234,9 +1234,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} else { } else {
new TextWindow(title, header, sb.toString(), 800,1000); new TextWindow(title, header, sb.toString(), 800,1000);
} }
} }
public void listData(String title, String path){ public void listData(String title, String path){
if ((showSamples==null) || (showSamples.length!=sampleCoord.length*sampleCoord[0].length)){ if ((showSamples==null) || (showSamples.length!=sampleCoord.length*sampleCoord[0].length)){
showSamples=new boolean [sampleCoord.length*sampleCoord[0].length]; showSamples=new boolean [sampleCoord.length*sampleCoord[0].length];
for (int i=0;i<showSamples.length;i++) showSamples[i]=false; for (int i=0;i<showSamples.length;i++) showSamples[i]=false;
...@@ -1292,9 +1292,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1292,9 +1292,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
localShowSamples, localShowSamples,
showIgnoredData, showIgnoredData,
showRad); showRad);
} }
public void listData(String title, public void listData(String title,
String path, String path,
boolean showMotors, boolean showMotors,
boolean []showMeasCalc, boolean []showMeasCalc,
...@@ -1512,12 +1512,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1512,12 +1512,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
new TextWindow(title, header, sb.toString(), 800,1000); new TextWindow(title, header, sb.toString(), 800,1000);
} }
} }
public void showCurvCorr(){ public void showCurvCorr(){
fieldFitting.showCurvCorr("curv_corr"); fieldFitting.showCurvCorr("curv_corr");
} }
public void listCombinedResults(){ public void listCombinedResults(){
// private boolean rslt_show_z_axial=true; // private boolean rslt_show_z_axial=true;
// private boolean rslt_show_z_individual=true; // private boolean rslt_show_z_individual=true;
// private boolean rslt_show_f_axial=true; // private boolean rslt_show_f_axial=true;
...@@ -1583,9 +1583,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1583,9 +1583,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
center_z[1]+rslt_scan_above, //double scan_above, center_z[1]+rslt_scan_above, //double scan_above,
rslt_scan_step, //double scan_step, rslt_scan_step, //double scan_step,
rslt_mtf50_mode); //boolean freq_mode) rslt_mtf50_mode); //boolean freq_mode)
} }
public void listCombinedResults( public void listCombinedResults(
String title, String title,
String path, String path,
boolean [] show_chn, boolean [] show_chn,
...@@ -1676,10 +1676,10 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1676,10 +1676,10 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} else { } else {
new TextWindow(title, header, sb.toString(), 800,1000); new TextWindow(title, header, sb.toString(), 800,1000);
} }
} }
public void listScanQB(){ public void listScanQB(){
double [] center_z=fieldFitting.getZCenters(); double [] center_z=fieldFitting.getZCenters();
double best_qb_axial= fieldFitting.getBestQualB( double best_qb_axial= fieldFitting.getBestQualB(
...@@ -1725,9 +1725,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1725,9 +1725,9 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
this.k_blue, //double kb, this.k_blue, //double kb,
this.qb_use_corrected, //boolean corrected, this.qb_use_corrected, //boolean corrected,
this.qb_invert); //boolean freq_mode) this.qb_invert); //boolean freq_mode)
} }
public void listScanQB( public void listScanQB(
String title, String title,
String path, String path,
double min_z, // absolute double min_z, // absolute
...@@ -1766,10 +1766,10 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1766,10 +1766,10 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} else { } else {
new TextWindow(title, header, sb.toString(), 800,1000); new TextWindow(title, header, sb.toString(), 800,1000);
} }
} }
public boolean dialogLMAStep(boolean [] state){ public boolean dialogLMAStep(boolean [] state){
String [] states={ String [] states={
"Worse, increase lambda", "Worse, increase lambda",
"Better, decrease lambda", "Better, decrease lambda",
...@@ -1836,11 +1836,11 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1836,11 +1836,11 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
// this.showNextImages= gd.getNextBoolean(); // this.showNextImages= gd.getNextBoolean();
this.saveSeries=true; this.saveSeries=true;
return gd.wasOKed(); return gd.wasOKed();
} }
public boolean LevenbergMarquardt(boolean openDialog, int debugLevel){ public boolean LevenbergMarquardt(boolean openDialog, int debugLevel){
double savedLambda=this.lambda; double savedLambda=this.lambda;
this.debugLevel=debugLevel; this.debugLevel=debugLevel;
if (openDialog && !selectLMAParameters()) return false; if (openDialog && !selectLMAParameters()) return false;
...@@ -1940,7 +1940,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1940,7 +1940,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
// if (wasLastSeries) break; // if (wasLastSeries) break;
// } // while (this.fittingStrategy.isSeriesValid(this.seriesNumber)){ // TODO: Add "stop" tag to series // } // while (this.fittingStrategy.isSeriesValid(this.seriesNumber)){ // TODO: Add "stop" tag to series
if (debugLevel>0) System.out.println("LevenbergMarquardt(): all done"+ if (debugLevel>0) System.out.println("LevenbergMarquardt(): all done"+
", step="+ this.iterationStepNumber+ ", step="+ this.iterationStepNumber+
", RMS="+this.currentRMS+ ", RMS="+this.currentRMS+
" ("+this.firstRMS+") "+ " ("+this.firstRMS+") "+
" at "+ IJ.d2s(0.000000001*(System.nanoTime()-this.startTime),3)); " at "+ IJ.d2s(0.000000001*(System.nanoTime()-this.startTime),3));
...@@ -1948,7 +1948,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -1948,7 +1948,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
commitParameterVector(this.savedVector); commitParameterVector(this.savedVector);
return true; // all series done return true; // all series done
} }
...@@ -2116,6 +2116,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2116,6 +2116,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
hConfig.setThrowExceptionOnMissing(false); // default value, will return null on missing hConfig.setThrowExceptionOnMissing(false); // default value, will return null on missing
comment= hConfig.getString("comment","no comments"); comment= hConfig.getString("comment","no comments");
// if ((comment.length()>10) && comment.substring(0,9).equals("<![CDATA[")) comment=comment.substring(9,comment.length()-3);
serialNumber= hConfig.getString("serialNumber","???"); serialNumber= hConfig.getString("serialNumber","???");
lensSerial= hConfig.getString("lensSerial","???"); lensSerial= hConfig.getString("lensSerial","???");
pX0_distortions=Double.parseDouble(hConfig.getString("lens_center_x","0.0")); pX0_distortions=Double.parseDouble(hConfig.getString("lens_center_x","0.0"));
...@@ -2154,7 +2156,11 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2154,7 +2156,11 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
String path){ // x,y,r String path){ // x,y,r
XMLConfiguration hConfig=new XMLConfiguration(); XMLConfiguration hConfig=new XMLConfiguration();
hConfig.setRootElementName("focusingHistory"); hConfig.setRootElementName("focusingHistory");
if (comment!=null) hConfig.addProperty("comment",comment); if (comment!=null){
String comment_esc=comment.replace(",","\\,");
// hConfig.addProperty("comment","<![CDATA["+comment_esc+ "]]>");
hConfig.addProperty("comment",comment_esc);
}
if (serialNumber!=null) hConfig.addProperty("serialNumber",serialNumber); if (serialNumber!=null) hConfig.addProperty("serialNumber",serialNumber);
if (lensSerial!=null) hConfig.addProperty("lensSerial",lensSerial); if (lensSerial!=null) hConfig.addProperty("lensSerial",lensSerial);
hConfig.addProperty("lens_center_x",pX0_distortions); // distortions center, not aberrations! hConfig.addProperty("lens_center_x",pX0_distortions); // distortions center, not aberrations!
...@@ -2206,7 +2212,10 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2206,7 +2212,10 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
private double [][] sampleCorrPullZero=new double[6][]; // 1.0 - only difference from neighbors matters, 0.0 - only difference from 0 private double [][] sampleCorrPullZero=new double[6][]; // 1.0 - only difference from neighbors matters, 0.0 - only difference from 0
private double [] sampleCorrRadius=null; private double [] sampleCorrRadius=null;
private double [][][][] sampleCorrCrossWeights= new double[6][][][]; private double [][][][] sampleCorrCrossWeights= new double[6][][][];
private double [] sampleCorr=null; private double [] sampleCorrVector=null; // currently adjusted per-sample parameters
private double [][][] correctionParameters=new double[6][][]; // all
public int numberOfLocations=0;
private int [][] sampleCorrChnParIndex=null; private int [][] sampleCorrChnParIndex=null;
private boolean [] dflt_sampleCorrSelect= {false,false,false,false}; private boolean [] dflt_sampleCorrSelect= {false,false,false,false};
private double [] dflt_sampleCorrCost= {0.2,50.0,1.0,1.0}; private double [] dflt_sampleCorrCost= {0.2,50.0,1.0,1.0};
...@@ -2217,6 +2226,46 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2217,6 +2226,46 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
"Green, sagittal","Green, tangential", "Green, sagittal","Green, tangential",
"Blue, sagittal","Blue, tangential"}; "Blue, sagittal","Blue, tangential"};
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"centerSelect_X",centerSelect[0]+"");
properties.setProperty(prefix+"centerSelect_Y",centerSelect[1]+"");
mechanicalFocusingModel.setProperties(prefix+"mechanicalFocusingModel.",properties);
for (int i=0;i<curvatureModel.length;i++){
if (curvatureModel[i]!=null) curvatureModel[i].setProperties(prefix+"curvatureModel_"+i+".",properties);
}
if (channelSelect!=null) for (int i=0;i<channelSelect.length;i++){
properties.setProperty(prefix+"channelSelect_"+i,channelSelect[i]+"");
}
if (mechanicalSelect!=null) for (int i=0;i<mechanicalSelect.length;i++){
properties.setProperty(prefix+"mechanicalSelect_"+i,mechanicalSelect[i]+"");
}
for (int chn=0;chn<curvatureSelect.length;chn++) if (curvatureSelect[chn]!=null) for (int i=0;i<curvatureSelect[chn].length;i++){
properties.setProperty(prefix+"curvatureSelect_"+chn+"_"+i,curvatureSelect[chn][i]+"");
}
for (int chn=0;chn<sampleCorrSelect.length;chn++) if (sampleCorrSelect[chn]!=null) for (int i=0;i<sampleCorrSelect[chn].length;i++){
properties.setProperty(prefix+"sampleCorrSelect_"+chn+"_"+i,sampleCorrSelect[chn][i]+"");
}
for (int chn=0;chn<sampleCorrCost.length;chn++) if (sampleCorrCost[chn]!=null) for (int i=0;i<sampleCorrCost[chn].length;i++){
properties.setProperty(prefix+"sampleCorrCost_"+chn+"_"+i,sampleCorrCost[chn][i]+"");
}
for (int chn=0;chn<sampleCorrSigma.length;chn++) if (sampleCorrSigma[chn]!=null) for (int i=0;i<sampleCorrSigma[chn].length;i++){
properties.setProperty(prefix+"sampleCorrSigma_"+chn+"_"+i,sampleCorrSigma[chn][i]+"");
}
for (int chn=0;chn<sampleCorrPullZero.length;chn++) if (sampleCorrPullZero[chn]!=null) for (int i=0;i<sampleCorrPullZero[chn].length;i++){
properties.setProperty(prefix+"sampleCorrPullZero_"+chn+"_"+i,sampleCorrPullZero[chn][i]+"");
}
/*
private double [][] sampleCorrCost= new double[6][]; // equivalent cost of one unit of parameter value (in result units, um)
private double [][] sampleCorrSigma= new double[6][]; // sigma (in mm) for neighbors influence
private double [][] sampleCorrPullZero=new double[6][]; // 1.0 - only difference from neighbors matters, 0.0 - only difference from 0
*/
}
public double [] getSampleRadiuses(){ // distance from the current center to each each sample public double [] getSampleRadiuses(){ // distance from the current center to each each sample
return sampleCorrRadius; return sampleCorrRadius;
} }
...@@ -2224,24 +2273,18 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2224,24 +2273,18 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
int width=getSampleWidth(); int width=getSampleWidth();
int numSamples=getNumSamples(); int numSamples=getNumSamples();
String [] chnShortNames={"RS","RT","GS","GT","BRS","BT"}; String [] chnShortNames={"RS","RT","GS","GT","BRS","BT"};
if ((sampleCorr==null) || (sampleCorr.length==0)) {
String msg="No correction parameters are enabled";
IJ.showMessage(msg);
System.out.println(msg);
return;
}
int numCorrPar=0; int numCorrPar=0;
int maxNumPars=0; int maxNumPars=0;
for (int chn=0;chn<sampleCorrChnParIndex.length;chn++) for (int chn=0;chn<correctionParameters.length;chn++)
if (sampleCorrChnParIndex[chn]!=null) if (correctionParameters[chn]!=null)
for (int np=0;np<sampleCorrChnParIndex[chn].length;np++) for (int np=0;np<correctionParameters[chn].length;np++)
if (sampleCorrChnParIndex[chn][np]>=0) { if (correctionParameters[chn][np]!=null) {
numCorrPar++; numCorrPar++;
if (np>maxNumPars) maxNumPars=np; if (np>maxNumPars) maxNumPars=np;
} }
maxNumPars++; maxNumPars++;
if (numCorrPar==0){ if (numCorrPar==0){
String msg="Still no correction parameters are enabled"; String msg="No correction parameters are enabled";
IJ.showMessage(msg); IJ.showMessage(msg);
System.out.println(msg); System.out.println(msg);
return; return;
...@@ -2249,25 +2292,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2249,25 +2292,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
double [][] pixels=new double [numCorrPar][numSamples]; double [][] pixels=new double [numCorrPar][numSamples];
String [] titles=new String[numCorrPar]; String [] titles=new String[numCorrPar];
int index=0; int index=0;
/*
for (int chn=0;chn<sampleCorrChnParIndex.length;chn++)
if (sampleCorrChnParIndex[chn]!=null)
for (int np=0;np<sampleCorrChnParIndex[chn].length;np++)
if (sampleCorrChnParIndex[chn][np]>=0) {
titles[index]=chnShortNames[chn]+"-"+curvatureModel[chn].getZName(np);
for (int nSample=0;nSample<numSamples;nSample++) {
pixels[index][nSample]=sampleCorr[sampleCorrChnParIndex[chn][np]+nSample];
}
index++;
}
*/
for (int np=0;np<maxNumPars;np++) for (int np=0;np<maxNumPars;np++)
for (int chn=0;chn<sampleCorrChnParIndex.length;chn++) for (int chn=0;chn<correctionParameters.length;chn++)
if ((sampleCorrChnParIndex[chn]!=null) && (sampleCorrChnParIndex[chn].length>np) && (sampleCorrChnParIndex[chn][np]>=0)) { if ((correctionParameters[chn]!=null) && (correctionParameters[chn].length>np) && (correctionParameters[chn][np]!=null)) {
titles[index]=chnShortNames[chn]+"-"+curvatureModel[chn].getZName(np); titles[index]=chnShortNames[chn]+"-"+curvatureModel[chn].getZName(np);
for (int nSample=0;nSample<numSamples;nSample++) { for (int nSample=0;nSample<numSamples;nSample++) {
pixels[index][nSample]=sampleCorr[sampleCorrChnParIndex[chn][np]+nSample]; pixels[index][nSample]=correctionParameters[chn][np][nSample];
} }
index++; index++;
} }
...@@ -2489,7 +2519,10 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2489,7 +2519,10 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
int fromChn=individualChannels?0:firstChn; int fromChn=individualChannels?0:firstChn;
int toChn=individualChannels?channelSelect.length:(firstChn+1); int toChn=individualChannels?channelSelect.length:(firstChn+1);
boolean resetCorrections=false;
GenericDialog gd = new GenericDialog(title); GenericDialog gd = new GenericDialog(title);
gd.addCheckbox("Reset all per-sample corrections to zero", resetCorrections);
int numParsZR[] = getNumCurvars(); // [0] - Z, [1] - r, int numParsZR[] = getNumCurvars(); // [0] - Z, [1] - r,
for (int nChn=fromChn;nChn<toChn;nChn++) if (channelSelect[nChn]){ for (int nChn=fromChn;nChn<toChn;nChn++) if (channelSelect[nChn]){
...@@ -2507,6 +2540,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2507,6 +2540,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
gd.showDialog(); gd.showDialog();
if (gd.wasCanceled()) return false; if (gd.wasCanceled()) return false;
if (gd.wasOKed()) { // selected non-default "Apply" if (gd.wasOKed()) { // selected non-default "Apply"
resetCorrections= gd.getNextBoolean();
for (int nChn=fromChn;nChn<toChn;nChn++) if (channelSelect[nChn]){ for (int nChn=fromChn;nChn<toChn;nChn++) if (channelSelect[nChn]){
for (int i=0;i<sampleCorrSelect[nChn].length;i++) if (disabledPars || curvatureSelect[nChn][i*numParsZR[1]]){ for (int i=0;i<sampleCorrSelect[nChn].length;i++) if (disabledPars || curvatureSelect[nChn][i*numParsZR[1]]){
sampleCorrSelect[nChn][i]= gd.getNextBoolean(); sampleCorrSelect[nChn][i]= gd.getNextBoolean();
...@@ -2528,27 +2562,86 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2528,27 +2562,86 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
} }
} }
if (resetCorrections) resetSampleCorr();
return true; return true;
} }
// once per data set
public void resetSampleCorr(){
for (int i=0; i<correctionParameters.length;i++) correctionParameters[i]=null;
}
public double [] getCorrVector(){
//numberOfLocations
int numPars=0;
for (int nChn=0; nChn< sampleCorrChnParIndex.length;nChn++) {
if (sampleCorrChnParIndex[nChn]!=null){
for (int nPar=0;nPar< sampleCorrChnParIndex[nChn].length;nPar++) {
if (sampleCorrChnParIndex[nChn][nPar]>=0){
numPars+=numberOfLocations;
}
}
}
}
sampleCorrVector=new double [numPars];
for (int nChn=0; nChn< sampleCorrChnParIndex.length;nChn++) {
if (sampleCorrChnParIndex[nChn]!=null){
for (int nPar=0;nPar< sampleCorrChnParIndex[nChn].length;nPar++) {
if (sampleCorrChnParIndex[nChn][nPar]>=0){
for (int i=0;i<numberOfLocations;i++){
if ((correctionParameters[nChn]!=null) && (correctionParameters[nChn][nPar]!=null))
sampleCorrVector[sampleCorrChnParIndex[nChn][nPar]+i]=correctionParameters[nChn][nPar][i];
else
sampleCorrVector[sampleCorrChnParIndex[nChn][nPar]+i]=0.0;
}
}
}
}
}
return sampleCorrVector;
}
public void commitCorrVector(){
commitCorrVector(sampleCorrVector);
}
public void commitCorrVector(double [] vector){
for (int nChn=0; nChn< sampleCorrChnParIndex.length;nChn++) {
if (sampleCorrChnParIndex[nChn]!=null){
for (int nPar=0;nPar< sampleCorrChnParIndex[nChn].length;nPar++) {
if (sampleCorrChnParIndex[nChn][nPar]>=0){
if(correctionParameters[nChn]==null)
correctionParameters[nChn]=new double [sampleCorrChnParIndex[nChn].length][];
if(correctionParameters[nChn][nPar]==null)
correctionParameters[nChn][nPar]=new double [numberOfLocations];
for (int i=0;i<numberOfLocations;i++){
correctionParameters[nChn][nPar][i]=vector[sampleCorrChnParIndex[nChn][nPar]+i];
}
}
}
}
}
}
/** /**
* create matrix of weights of the other parameters influence * create matrix of weights of the other parameters influence
* @param sampleCoordinates [sample number]{x,y} - flattened array of sample coordinates * @param sampleCoordinates [sample number]{x,y} - flattened array of sample coordinates
* Run in the beginning of fitting series (zeroes the values) * Run in the beginning of fitting series (zeroes the values)
*/ */
// once per fitting series (or parameter change
public void initSampleCorr(double [][] sampleCoordinates){ public void initSampleCorrVector(double [][] sampleCoordinates){
int numSamples=sampleCoordinates.length; numberOfLocations=sampleCoordinates.length;
// int numSamples=sampleCoordinates.length;
for (int nChn=0; nChn< sampleCorrSelect.length;nChn++) { for (int nChn=0; nChn< sampleCorrSelect.length;nChn++) {
if (channelSelect[nChn]){ if (channelSelect[nChn]){
int numPars=sampleCorrSelect[nChn].length; int numPars=sampleCorrSelect[nChn].length;
sampleCorrCrossWeights[nChn]=new double[numPars][][]; sampleCorrCrossWeights[nChn]=new double[numPars][][];
for (int nPar=0;nPar<numPars;nPar++){ for (int nPar=0;nPar<numPars;nPar++){
if (sampleCorrSelect[nChn][nPar]){ if (sampleCorrSelect[nChn][nPar]){
sampleCorrCrossWeights[nChn][nPar]=new double[numSamples][numSamples]; sampleCorrCrossWeights[nChn][nPar]=new double[numberOfLocations][numberOfLocations];
double k=-getPixelMM()*getPixelMM()/(sampleCorrSigma[nChn][nPar]*sampleCorrSigma[nChn][nPar]); double k=-getPixelMM()*getPixelMM()/(sampleCorrSigma[nChn][nPar]*sampleCorrSigma[nChn][nPar]);
for (int i=0;i<numSamples;i++){ for (int i=0;i<numberOfLocations;i++){
double sw=0.0; double sw=0.0;
for (int j=0;j<numSamples;j++) { for (int j=0;j<numberOfLocations;j++) {
if (i!=j){ if (i!=j){
double dx=sampleCoordinates[i][0]-sampleCoordinates[i][0]; double dx=sampleCoordinates[i][0]-sampleCoordinates[i][0];
double dy=sampleCoordinates[i][1]-sampleCoordinates[i][1]; double dy=sampleCoordinates[i][1]-sampleCoordinates[i][1];
...@@ -2559,7 +2652,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2559,7 +2652,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
if ((sampleCorrPullZero[nChn][nPar]==0) ||(sampleCorrCost[nChn][nPar]==0)) sw=0.0; if ((sampleCorrPullZero[nChn][nPar]==0) ||(sampleCorrCost[nChn][nPar]==0)) sw=0.0;
else if (sw!=0.0) sw=-sampleCorrCost[nChn][nPar]*sampleCorrPullZero[nChn][nPar]/sw; else if (sw!=0.0) sw=-sampleCorrCost[nChn][nPar]*sampleCorrPullZero[nChn][nPar]/sw;
for (int j=0;j<numSamples;j++) { for (int j=0;j<numberOfLocations;j++) {
if (i!=j){ if (i!=j){
sampleCorrCrossWeights[nChn][nPar][i][j]*=sw; sampleCorrCrossWeights[nChn][nPar][i][j]*=sw;
} else { } else {
...@@ -2593,11 +2686,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2593,11 +2686,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
} }
// currently all correction parameters are initialized as zeros. // currently all correction parameters are initialized as zeros.
sampleCorr=new double [numPars]; getCorrVector();
for (int i=0;i<numPars;i++)sampleCorr[i]=0.0; // sampleCorrVector=new double [numPars];
sampleCorrRadius=new double [numSamples]; // for (int i=0;i<numPars;i++)sampleCorrVector[i]=0.0;
sampleCorrRadius=new double [numberOfLocations];
//pXY //pXY
for (int i=0;i<numSamples;i++){ for (int i=0;i<numberOfLocations;i++){
double dx=sampleCoordinates[i][0]-pXY[0]; double dx=sampleCoordinates[i][0]-pXY[0];
double dy=sampleCoordinates[i][1]-pXY[0]; double dy=sampleCoordinates[i][1]-pXY[0];
sampleCorrRadius[i]=getPixelMM()*Math.sqrt(dx*dx+dy*dy); sampleCorrRadius[i]=getPixelMM()*Math.sqrt(dx*dx+dy*dy);
...@@ -2605,12 +2699,20 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2605,12 +2699,20 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
public double [] getCorrPar(int chn, int sampleIndex){ public double [] getCorrPar(int chn, int sampleIndex){
if ((sampleCorrChnParIndex==null) || (sampleCorrChnParIndex[chn]==null)) return null; /* if ((sampleCorrChnParIndex==null) || (sampleCorrChnParIndex[chn]==null)) return null;
double [] corr =new double [sampleCorrChnParIndex[chn].length]; double [] corr =new double [sampleCorrChnParIndex[chn].length];
for (int i=0;i<corr.length;i++){ for (int i=0;i<corr.length;i++){
if (sampleCorrChnParIndex[chn][i]<0) corr[i]=0.0; if (sampleCorrChnParIndex[chn][i]<0) corr[i]=0.0;
else corr[i]=sampleCorr[sampleCorrChnParIndex[chn][i]+sampleIndex]; else corr[i]=sampleCorrVector[sampleCorrChnParIndex[chn][i]+sampleIndex];
} }
*/
if (correctionParameters[chn]==null) return null;
double [] corr =new double [correctionParameters[chn].length];
for (int i=0;i<corr.length;i++){
if (correctionParameters[chn][i] !=null) corr[i]=correctionParameters[chn][i][sampleIndex];
else corr[i]=0.0;
}
return corr; return corr;
} }
...@@ -2751,7 +2853,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2751,7 +2853,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
disabledCorrectionPars)) return false; disabledCorrectionPars)) return false;
// initSampleCorr(flattenSampleCoord()); // initSampleCorr(flattenSampleCoord());
} }
initSampleCorr(flattenSampleCoord()); // run always regardless of configured or not (to create zero-length array of corr) // will modify
initSampleCorrVector(flattenSampleCoord()); // run always regardless of configured or not (to create zero-length array of corr)
return true; return true;
} }
ArrayList<String> getParameterValueStrings(boolean showDisabled, boolean showCorrection){ ArrayList<String> getParameterValueStrings(boolean showDisabled, boolean showCorrection){
...@@ -2804,12 +2907,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2804,12 +2907,12 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
if (showCorrection && (getNumberOfCorrParameters()>0)){ if (showCorrection && (getNumberOfCorrParameters()>0)){
parList.add("\t ===== Per-sample correction parameters =====\t\t"); parList.add("\t ===== Per-sample correction parameters =====\t\t");
for (int n=0;n<sampleCorrChnParIndex.length;n++) if (sampleCorrChnParIndex[n]!=null){ for (int n=0;n<correctionParameters.length;n++) if (correctionParameters[n]!=null){
for (int np=0;np<sampleCorrChnParIndex[n].length;np++) if (sampleCorrChnParIndex[n][np]>=0){ for (int np=0;np<correctionParameters[n].length;np++) if (correctionParameters[n][np]!=null){
int numSamples=sampleCorrCrossWeights[n][np].length; // int numSamples=sampleCorrCrossWeights[n][np].length;
parList.add("\t ----- correction parameters for \""+ getDescription(n)+" "+curvatureModel[n].getZDescription(np)+"\" -----\t\t"); parList.add("\t ----- correction parameters for \""+ getDescription(n)+" "+curvatureModel[n].getZDescription(np)+"\" -----\t\t");
for (int i=0;i<numSamples;i++){ for (int i=0;i<numberOfLocations;i++){
parList.add(i+"\t"+curvatureModel[n].getZDescription(np)+":\t"+sampleCorr[sampleCorrChnParIndex[n][np]+i]+"\t"); parList.add(i+"\t"+curvatureModel[n].getZDescription(np)+":\t"+correctionParameters[n][np][i]+"\t");
} }
} }
} }
...@@ -2892,8 +2995,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2892,8 +2995,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
return true; return true;
} }
public int getNumberOfCorrParameters(){ public int getNumberOfCorrParameters(){ // selected for fitting
return (sampleCorr!=null)?sampleCorr.length:0; return (sampleCorrVector!=null)?sampleCorrVector.length:0;
} }
public int getNumberOfParameters(boolean sagittalMaster){ public int getNumberOfParameters(boolean sagittalMaster){
...@@ -2954,7 +3057,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2954,7 +3057,7 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
} }
int nCorrPars=getNumberOfCorrParameters(); int nCorrPars=getNumberOfCorrParameters();
for (int i=0;i<nCorrPars;i++) pars[np++]=sampleCorr[i]; for (int i=0;i<nCorrPars;i++) pars[np++]=sampleCorrVector[i];
return pars; return pars;
} }
...@@ -2982,7 +3085,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -2982,7 +3085,8 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
} }
// copy correction parameters // copy correction parameters
int nCorrPars=getNumberOfCorrParameters(); int nCorrPars=getNumberOfCorrParameters();
for (int i=0;i<nCorrPars;i++) sampleCorr[i]=pars[np++]; for (int i=0;i<nCorrPars;i++) sampleCorrVector[i]=pars[np++];
commitCorrVector();
// copy center parameters to dependent // copy center parameters to dependent
// copy if master is selected, regardless of is dependent selected or not // copy if master is selected, regardless of is dependent selected or not
...@@ -3197,6 +3301,22 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -3197,6 +3301,22 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
public MechanicalFocusingModel(){ // add arguments? public MechanicalFocusingModel(){ // add arguments?
initDefaults(); initDefaults();
} }
public void setProperties(String prefix,Properties properties){
if (paramValues==null) {
for (int i=0;i<paramValues.length;i++){
properties.setProperty(prefix+descriptions[i][0],paramValues[i]+"");
}
}
}
public void getProperties(String prefix,Properties properties){
if ((paramValues==null) || (paramValues.length!=descriptions.length))
initDefaults();
for (int i=0;i<paramValues.length;i++){
if (properties.getProperty(prefix+descriptions[i][0])!=null)
paramValues[i]=Double.parseDouble(properties.getProperty(prefix+descriptions[i][0]));
}
}
public void initDefaults(){ public void initDefaults(){
paramValues=new double [descriptions.length]; paramValues=new double [descriptions.length];
for (int i=0;i<descriptions.length;i++) paramValues[i]=Double.parseDouble(descriptions[i][3]); for (int i=0;i<descriptions.length;i++) paramValues[i]=Double.parseDouble(descriptions[i][3]);
...@@ -3456,6 +3576,46 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2 ...@@ -3456,6 +3576,46 @@ d_s2/d_x0= 2*delta_x*delta_y^2/r2^2
this.modelParams=new double [distanceParametersNumber][radialParametersNumber]; this.modelParams=new double [distanceParametersNumber][radialParametersNumber];
setDefaults(); setDefaults();
} }
public void setProperties(String prefix,Properties properties){
properties.setProperty(prefix+"distanceParametersNumber",modelParams.length+"");
properties.setProperty(prefix+"radialParametersNumber",modelParams[0].length+"");
properties.setProperty(prefix+"pX0",pX0+"");
properties.setProperty(prefix+"pY0",pY0+"");
for (int i=0;i<modelParams.length;i++) for (int j=0;j<modelParams[i].length;j++){
properties.setProperty(prefix+"modelParams"+i+"_"+j,modelParams[i][j]+"");
}
}
public void getProperties(String prefix,Properties properties){
int numZPars,numRPars;
if (properties.getProperty(prefix+"pX0")!=null)
pX0=Double.parseDouble(properties.getProperty(prefix+"pX0"));
if (properties.getProperty(prefix+"pY0")!=null)
pX0=Double.parseDouble(properties.getProperty(prefix+"pY0"));
if (modelParams!=null){
numZPars=modelParams.length;
numRPars=modelParams[0].length;
} else {
numZPars=dflt_distanceParametersNumber;
numRPars=dflt_radialParametersNumber;
}
if (properties.getProperty(prefix+"distanceParametersNumber")!=null)
numZPars=Integer.parseInt(properties.getProperty(prefix+"distanceParametersNumber"));
if (properties.getProperty(prefix+"radialParametersNumber")!=null)
numRPars=Integer.parseInt(properties.getProperty(prefix+"radialParametersNumber"));
if ((modelParams!=null) || (modelParams.length!=numZPars)|| (modelParams[0].length!=numRPars)){
modelParams=new double [numZPars][numRPars];
setDefaults();
}
for (int i=0;i<modelParams.length;i++) for (int j=0;j<modelParams[i].length;j++){
if (properties.getProperty(prefix+"modelParams"+i+"_"+j)!=null) {
modelParams[i][j]=Double.parseDouble(properties.getProperty(prefix+"modelParams"+i+"_"+j));
}
}
}
public void setCenter(double pX, double pY){ public void setCenter(double pX, double pY){
pX0=pX; pX0=pX;
pY0=pY; pY0=pY;
...@@ -3772,3 +3932,6 @@ ar1 - ar[4] ...@@ -3772,3 +3932,6 @@ ar1 - ar[4]
} }
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment