Commit 367449b7 authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Working on the model of the PSF dependence on the distance, height,

color channel and direction (S,T) to match measurements. And to
simultaneously determine mechanical properties of the setup.
parent 37ef16f3
Loading
Loading
Loading
Loading
+110 −19
Original line number Diff line number Diff line
@@ -34,26 +34,18 @@ import ij.text.TextWindow;
import java.awt.*;
import java.awt.event.*;
import java.io.*; // FIle
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import javax.swing.*; // TODO: modify methods that depend on it, use class CalibrationFileManagement
import java.util.*; 
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
//import FocusingField.MeasuredSample;
import Jama.Matrix;  // Download here: http://math.nist.gov/javanumerics/jama/
public class Aberration_Calibration extends PlugInFrame implements ActionListener {
@@ -530,7 +522,7 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
	
	public static LensAdjustment.FocusMeasurementParameters FOCUS_MEASUREMENT_PARAMETERS= new LensAdjustment.FocusMeasurementParameters(MOTORS.curpos);
	public static CalibrationHardwareInterface.GoniometerMotors GONIOMETER_MOTORS= new CalibrationHardwareInterface.GoniometerMotors();
	
	public static FocusingField FOCUSING_FIELD=null;
	//GoniometerParameters
	public static Goniometer.GoniometerParameters GONIOMETER_PARAMETERS= new Goniometer.GoniometerParameters(GONIOMETER_MOTORS);
	
@@ -767,9 +759,13 @@ if (MORE_BUTTONS) {
		panelFocusing = new Panel();
		panelFocusing.setLayout(new GridLayout(1, 0, 5, 5));
		addButton("Configure Focusing",panelFocusing,color_configure);
		if (MORE_BUTTONS) {		
			addButton("Head Orientation",panelFocusing);
		}
		addButton("Lens Center",panelFocusing,color_process);
		if (MORE_BUTTONS) {		
			addButton("Find Grid",panelFocusing,color_lenses);
		}
        addButton("Select WOI",panelFocusing,color_lenses);
        addButton("Reset Histories",panelFocusing,color_lenses);
        addButton("Motors Home",panelFocusing,color_lenses);
@@ -781,6 +777,12 @@ if (MORE_BUTTONS) {
		addButton("Temp. Scan",panelFocusing,color_process);
		//
		addButton("List History",panelFocusing,color_report);
		addButton("Save History",panelFocusing,color_debug);
		addButton("Restore History",panelFocusing,color_debug);
		addButton("Modify LMA",panelFocusing,color_debug);
		addButton("LMA History",panelFocusing,color_debug);
		addButton("List curv pars",panelFocusing,color_debug);
		addButton("List curv data",panelFocusing,color_debug);
		addButton("Show PSF",panelFocusing,color_report);
		add(panelFocusing);
	//panelGoniometer
@@ -2643,7 +2645,7 @@ if (MORE_BUTTONS) {
            	// /getPointersXY(ImagePlus imp, int numPointers){               if
            	// calculate distortion grid for it
            	matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Filed calibration - different image. 
            	matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Field calibration - different image. 
            	matchSimulatedPattern.invalidateFocusMask();
            	int numAbsolutePoints=matchSimulatedPattern.calculateDistortions(
            			DISTORTION, //
@@ -3577,7 +3579,7 @@ if (MORE_BUTTONS) {
			// reset matchSimulatedPattern, so it will start from scratch
			matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize); // new instance, all reset
			// next 2 lines are not needed for the new instance, but can be used alternatively if keeipg it
			   matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Filed calibration - different image. 
			   matchSimulatedPattern.invalidateFlatFieldForGrid(); //Reset Flat Field calibration - different image. 
			   matchSimulatedPattern.invalidateFocusMask();
			
@@ -4252,6 +4254,90 @@ if (MORE_BUTTONS) {
					);
			return;
		}
/* ======================================================================== */
		if       (label.equals("Save History")) {
			DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
			double pX0=FOCUS_MEASUREMENT_PARAMETERS.result_PX0;
			double pY0=FOCUS_MEASUREMENT_PARAMETERS.result_PY0;
			double [][][] sampleCoord=FOCUS_MEASUREMENT_PARAMETERS.sampleCoordinates( //{x,y,r}
					pX0,   // lens center on the sensor
					pY0);
			// set file path
			String path=null;
			String dir=getResultsPath(FOCUS_MEASUREMENT_PARAMETERS);
			File dFile=new File(dir);
			if (!dFile.isDirectory() &&  !dFile.mkdirs()) {
				String msg="Failed to create directory "+dir;
				IJ.showMessage(msg);
				throw new IllegalArgumentException (msg);
			}
			String lensPrefix="";
			if (FOCUS_MEASUREMENT_PARAMETERS.includeLensSerial && (FOCUS_MEASUREMENT_PARAMETERS.lensSerial.length()>0)){
				lensPrefix=String.format("LENS%S-S%02d-",FOCUS_MEASUREMENT_PARAMETERS.lensSerial,FOCUS_MEASUREMENT_PARAMETERS.manufacturingState);
			}
			path=dFile+Prefs.getFileSeparator()+lensPrefix+CAMERAS.getLastTimestampUnderscored()+".history-xml";
			FOCUSING_FIELD= new FocusingField(
					FOCUS_MEASUREMENT_PARAMETERS.serialNumber,
					FOCUS_MEASUREMENT_PARAMETERS.lensSerial, // String lensSerial, // if null - do not add average
					FOCUS_MEASUREMENT_PARAMETERS.comment, // String comment,
					pX0,
					pY0,
					sampleCoord,
					this.SYNC_COMMAND.stopRequested);
			System.out.println("Saving measurement history to "+path);
			MOTORS.addCurrentHistoryToFocusingField(FOCUSING_FIELD);
			FOCUSING_FIELD.saveXML(path);
			return;
		}
/* ======================================================================== */
		if       (label.equals("Restore History")) {
			DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
			FOCUSING_FIELD=new FocusingField(
					true, // boolean smart,       // do not open dialog if default matches 
					"",//); //String defaultPath); //			AtomicInteger stopRequested
					this.SYNC_COMMAND.stopRequested);
			System.out.println("Loaded FocusingField");
			FOCUSING_FIELD.configureDataVector("Configure curvature",true);
			FOCUSING_FIELD.setDataVector(FOCUSING_FIELD.createDataVector());
			double []focusing_fx=FOCUSING_FIELD.createFXandJacobian(true);
			double rms= FOCUSING_FIELD.getRMS(focusing_fx);
			System.out.println("rms="+rms);
			return;
		}
/* ======================================================================== */
		if       (label.equals("Modify LMA")) {
			DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
			if (FOCUSING_FIELD==null) return;
			FOCUSING_FIELD.configureDataVector("Re-configure curvature parameters",false);
			FOCUSING_FIELD.setDataVector(FOCUSING_FIELD.createDataVector());
			return;
		}
/* ======================================================================== */
		if       (label.equals("LMA History")) {
			DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
			if (FOCUSING_FIELD==null) return;
			FOCUSING_FIELD.LevenbergMarquardt(true, DEBUG_LEVEL); //boolean openDialog, int debugLevel){
			return;
		}
/* ======================================================================== */
		if       (label.equals("List curv pars")) {
			DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
			if (FOCUSING_FIELD==null) return;
			FOCUSING_FIELD.listParameters("Field curvature measurement parameters",null); // to screen
			return;
		}
/* ======================================================================== */
		if       (label.equals("List curv data")) {
			DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
			if (FOCUSING_FIELD==null) return;
			FOCUSING_FIELD.listData("Field curvature measurement data",null); // to screen
			return;
		}
//"LMA History"		
		
/* ======================================================================== */
		if       (label.equals("Show PSF")) {
			
@@ -8010,7 +8096,7 @@ if (MORE_BUTTONS) {
			LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
			
			
			GenericDialog gd=new GenericDialog("Pattern Flat Filed parameters");
			GenericDialog gd=new GenericDialog("Pattern Flat Field parameters");
			gd.addNumericField("Fitting series number (to select images), negative - use all enabled images", -1,0);
			gd.addNumericField("Reference station number (unity target brightness)", 0,0);
			gd.addNumericField("Shrink sensor mask",    100.0, 1,6,"sensor pix");
@@ -10100,7 +10186,7 @@ if (MORE_BUTTONS) {
				for (int jj=0;jj<sampleCoord[0].length;jj++){
					int index=ii*sampleCoord[0].length+jj;
					imp_psf.setProperty("pX_"+index, ""+sampleCoord[ii][jj][0]);
					imp_psf.setProperty("pX_"+index, ""+sampleCoord[ii][jj][0]);
					imp_psf.setProperty("pY_"+index, ""+sampleCoord[ii][jj][1]);
					if (fullResults[ii][jj]!=null){
						for (int cc=0;cc<fullResults[ii][jj].length;cc++) if (fullResults[ii][jj][cc]!=null){
							imp_psf.setProperty("R50_"+cc+"_"+index, ""+fullResults[ii][jj][cc][0]);
@@ -10196,6 +10282,11 @@ if (MORE_BUTTONS) {
					double r=Math.sqrt(x*x+y*y);			
					double ca=(sampleCoord[i][j][0]-x0)/r;
					double sa=(sampleCoord[i][j][1]-y0)/r;
//					System.out.println("extractPSFMetrics.. color="+color+" i="+i+" j="+j+" cos="+ca+" sin="+sa+
//							" psf_cutoffEnergy="+focusMeasurementParameters.psf_cutoffEnergy+
//							" psf_cutoffLevel="+focusMeasurementParameters.psf_cutoffLevel+
//							" psf_minArea="+focusMeasurementParameters.psf_minArea+
//							" psf_blurSigma="+focusMeasurementParameters.psf_blurSigma);
					double [] tanRad=		   matchSimulatedPattern.tangetRadialSizes(
							   ca, // cosine of the center to sample vector
							   sa, // sine of the center to sample vector
@@ -11739,7 +11830,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
    }
// images cap[ture in portrait mode, opened in landscape mode (rotated CCW90 from original)
// returns valid images for sub-bands: top, middle and bottom:   mask bits 1- top (left) valid, 2 - middle valid, 4 - bottom (right) vlaid     
    private int calcValidFlatFiledMask(FlatFieldParameters flatFieldParameters, int [] ranges, ImagePlus imp){
    private int calcValidFlatFieldMask(FlatFieldParameters flatFieldParameters, int [] ranges, ImagePlus imp){
    	int mask=0, maskO=0, maskU=0;
    	int [] mranges=ranges.clone();
    	mranges[0]=flatFieldParameters.margins[0];
@@ -11864,7 +11955,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
          		ip=imp_single.getChannelProcessor();
// currently all images in all channels should be the same width          		
        	    if (weightMasks[0]==null)initFlatFieldArrays (imp_single.getWidth(), weightMasks, ranges, weights);
        	    int diagMask= calcValidFlatFiledMask(flatFieldParameters, ranges,  imp_single);
        	    int diagMask= calcValidFlatFieldMask(flatFieldParameters, ranges,  imp_single);
        	    int validBandsMask = diagMask & 7;
        	    String imageExpStatus="";
        	    for (int n=0;n<3;n++) {
+126 −6
Original line number Diff line number Diff line
@@ -31,9 +31,12 @@ import ij.process.FloatProcessor;
import ij.process.ImageProcessor;
import ij.text.TextWindow;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@@ -50,6 +53,8 @@ import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.XMLConfiguration;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.SAXException;
@@ -2513,7 +2518,7 @@ public class CalibrationHardwareInterface {
    public FocusingSharpness focusingSharpness=new FocusingSharpness(1000);
    public int debugLevel=1;
    public String motorsStatePath="lensAdjustmentMotorPosition.xml"; // will be saved in ~/.imagej/
    public String prefsDirectory=Prefs.getPrefsDir()+Prefs.getFileSeparator(); // "~/.imagej/" 
    public String prefsDirectory=null; // prefs.getPrefsDir()+Prefs.getFileSeparator(); // "~/.imagej/" - too early !!! 
    private Properties motorProperties=new Properties();
    public boolean interactiveRestore=true; // ask for confirmation to restore motor position
    public boolean stateValid=false;
@@ -2528,6 +2533,12 @@ public class CalibrationHardwareInterface {
    public double getMicronsPerStep(){return  1000.0*this.threadPitch*this.linearReductionRatio/stepsPerRevolution;}
    public void   setLinearReductionRatio(double lrr){this.linearReductionRatio=lrr;}
    
    public String getPrefsDir(){
    	if (prefsDirectory==null) prefsDirectory=Prefs.getPrefsDir();
    	if (prefsDirectory!=null) prefsDirectory+=Prefs.getFileSeparator(); // "~/.imagej/"
    	return prefsDirectory;
    }

    public boolean isInitialized(){
    	return this.stateValid;
    }
@@ -2568,7 +2579,7 @@ public class CalibrationHardwareInterface {
    public void saveMotorState() throws IOException{
    	if (!this.stateValid) return; // do not save until allowed 
    	for (int i=0;i<curpos.length;i++) this.motorProperties.setProperty("motor"+(i+1),this.curpos[i]+"");
    	String path=this.prefsDirectory+this.motorsStatePath;
    	String path=this.getPrefsDir()+this.motorsStatePath;
    	OutputStream os;
    	try {
    		os = new FileOutputStream(path);
@@ -2600,7 +2611,7 @@ public class CalibrationHardwareInterface {
    }
    
    public int [] loadMotorState() throws IOException{
    	String path=this.prefsDirectory+this.motorsStatePath;
    	String path=this.getPrefsDir()+this.motorsStatePath;
    	InputStream is;
    	try {
    		is = new FileInputStream(path);
@@ -2756,7 +2767,7 @@ public class CalibrationHardwareInterface {
        	if (this.debugLevel>2) System.out.println("--savedPosition="+((savedPosition==null)?"null":("{"+savedPosition[0]+","+savedPosition[1]+","+savedPosition[2]+"}")));
			if (this.interactiveRestore){
	    		gd = new GenericDialog("Missing motor position file");
	    		gd.addMessage("No motor position file ("+this.prefsDirectory+this.motorsStatePath+") found.");
	    		gd.addMessage("No motor position file ("+this.getPrefsDir()+this.motorsStatePath+") found.");
	    		gd.addMessage("If you run the program for the first time it is normal, you may click \"OK\" and the new file will be created");
	    		gd.addMessage("If you select \"Cancel\" the current command will be aborted, you may check the file and restart the program.");
	    	    gd.showDialog();
@@ -3056,6 +3067,28 @@ public class CalibrationHardwareInterface {
    			result_lastKT,
    			result_allHistoryKT);
    }
	public void saveHistoryXML(
			String path,
    		String serialNumber,
			String lensSerial, // if null - do not add average
    		String comment,
			double pX0,
			double pY0,
			double [][][] sampleCoord){ // x,y,r
		this.focusingHistory.saveXML(
    			path,
        		serialNumber,
    			lensSerial, // if null - do not add average
        		comment,
    			pX0,
    			pY0,
    			sampleCoord);
	}
    
	public void addCurrentHistoryToFocusingField(FocusingField focusingField){
		this.focusingHistory.addCurrentHistory(focusingField);
	}
	
    public int historySize(){
    	return this.focusingHistory.history.size();
    }
@@ -5437,7 +5470,94 @@ if (debugLevel>=debugThreshold) System.out.println(i+" "+diff[0]+" "+diff[1]+" "
    				Double.NaN);
    	}
    	
    	public void addCurrentHistory(
    			FocusingField focusingField)
    	{
    		for (int i=0;i<this.history.size();i++){
    			FocusingState focusingState=this.history.get(i);
    			focusingField.addSample(
    					focusingState.getTimestamp(),
    					focusingState.getTemperature(),
    					focusingState.motorsPos,
    					focusingState.getSamples());
    		}        	 

    	}

    	public void saveXML(
    			String path,
        		String serialNumber,
    			String lensSerial, // if null - do not add average
        		String comment,
    			double pX0,
    			double pY0,
    			double [][][] sampleCoord){ // x,y,r
    		String sep=" "; //",";
    		ArrayList<String> nodeList=new ArrayList<String>(); 
        	XMLConfiguration hConfig=new XMLConfiguration();
        	hConfig.setRootElementName("focusingHistory");
        	if (comment!=null)      hConfig.addProperty("comment",comment);
        	if (serialNumber!=null) hConfig.addProperty("serialNumber",serialNumber);
        	if (lensSerial!=null)   hConfig.addProperty("lensSerial",lensSerial);
        	 hConfig.addProperty("lens_center_x",pX0);
        	 hConfig.addProperty("lens_center_y",pY0);
        	 if ((sampleCoord!=null) && (sampleCoord.length>0) && (sampleCoord[0] != null) && (sampleCoord[0].length>0)){
        		 hConfig.addProperty("samples_x",sampleCoord[0].length);
        		 hConfig.addProperty("samples_y",sampleCoord.length);
        		 for (int i=0;i<sampleCoord.length;i++)
        			 for (int j=0;j<sampleCoord[i].length;j++){
//                		 double coord[] = {sampleCoord[i][j][0],sampleCoord[i][j][1]};
                		 hConfig.addProperty("sample_"+i+"_"+j,sampleCoord[i][j][0]+sep+sampleCoord[i][j][1]);
        			 }
        	 }
        	 hConfig.addProperty("measurements",this.history.size());
        	 for (int i=0;i<this.history.size();i++){
        		 FocusingState focusingState=this.history.get(i);
        		 String prefix="measurement_"+i+".";
        		 if (focusingState.getTimestamp()!=null)
        			 hConfig.addProperty(prefix+"timestamp",focusingState.getTimestamp());
        		 hConfig.addProperty(prefix+"temperature",focusingState.getTemperature());
        		 hConfig.addProperty(prefix+"motors",focusingState.motorsPos[0]+sep+focusingState.motorsPos[1]+sep+focusingState.motorsPos[2]); // array of 3
        		 double [][][][] samples=focusingState.getSamples();
        		 nodeList.clear();
        		 if ((samples!=null) && (samples.length>0) && (samples[0]!=null) && (samples[0].length>0)){
        			 for (int ii=0;ii<samples.length;ii++) for (int jj=0;jj<samples[ii].length;jj++){
        				 if ((samples[ii][jj]!=null) && (samples[ii][jj].length>0)) {
        					 String sdata=ii+sep+jj;
        					 for (int cc=0;cc<samples[ii][jj].length;cc++) {
        						 double rt=samples[ii][jj][cc][0]/Math.sqrt((1+samples[ii][jj][cc][1]*samples[ii][jj][cc][1])/2.0); // tangential;
        						 double rs=rt*samples[ii][jj][cc][1]; // saggital
        						 sdata += sep+rs+ // saggital
        								  sep+rt; // tangential
//        						 double [] samples_st={
//        								 samples[ii][jj][cc][0], // saggital
//        								 samples[ii][jj][cc][0]/samples[ii][jj][cc][1] // tangential (was ratio)
//        						 };
        						 if ((samples[ii][jj]!=null) && (samples[ii][jj][cc]!=null)) {
//        							 hConfig.addProperty(prefix+"y"+ii+".x"+jj+".c"+cc,samples_st); // array of 2
//        							 nodeList.add(sdata);
        						 }
        					 }
							 nodeList.add(sdata);
        				 }
        			 }
					 hConfig.addProperty(prefix+"sample",nodeList);
        		 }        	 
        	 }
         	File file=new File (path);
         	BufferedWriter writer;
 			try {
 				writer = new BufferedWriter(new FileWriter(file));
 	        	hConfig.save(writer);
 			} catch (IOException e) {
 				// TODO Auto-generated catch block
 				e.printStackTrace();
 			} catch (ConfigurationException e) {
 				// TODO Auto-generated catch block
 				e.printStackTrace();
 			}
        	 
    	}
     	public void list(
    			String path,
        		String serialNumber,