Commit 50de1233 authored by Andrey Filippov's avatar Andrey Filippov

preparing for the goniometer with LWIR

parent 47b15645
...@@ -60,25 +60,16 @@ import java.util.regex.Pattern; ...@@ -60,25 +60,16 @@ import java.util.regex.Pattern;
// TODO: modify methods that depend on it, use class CalibrationFileManagement // TODO: modify methods that depend on it, use class CalibrationFileManagement
import javax.swing.JFileChooser; import javax.swing.JFileChooser;
import com.elphel.imagej.calibration.CalibrationFileManagement.MultipleExtensionsFileFilter;
import com.elphel.imagej.calibration.CalibrationHardwareInterface.CamerasInterface;
import com.elphel.imagej.calibration.CalibrationHardwareInterface.FocusingMotors;
import com.elphel.imagej.calibration.CalibrationHardwareInterface.GoniometerMotors;
import com.elphel.imagej.calibration.CalibrationHardwareInterface.LaserPointers;
import com.elphel.imagej.calibration.CalibrationHardwareInterface.PowerControl;
import com.elphel.imagej.calibration.CalibrationHardwareInterface.UVLEDandLasers;
import com.elphel.imagej.calibration.Distortions.RefineParameters;
import com.elphel.imagej.calibration.SimulationPattern.SimulParameters;
import com.elphel.imagej.cameras.EyesisCameraParameters; import com.elphel.imagej.cameras.EyesisCameraParameters;
import com.elphel.imagej.cameras.SFEPhases; import com.elphel.imagej.cameras.SFEPhases;
import com.elphel.imagej.cameras.SFEPhases.Defect;
import com.elphel.imagej.cameras.SFEPhases.SensorDefects;
import com.elphel.imagej.common.DoubleFHT; import com.elphel.imagej.common.DoubleFHT;
import com.elphel.imagej.common.DoubleGaussianBlur; import com.elphel.imagej.common.DoubleGaussianBlur;
import com.elphel.imagej.common.PolynomialApproximation; import com.elphel.imagej.common.PolynomialApproximation;
import com.elphel.imagej.common.ShowDoubleFloatArrays; import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.common.WindowTools; import com.elphel.imagej.common.WindowTools;
import com.elphel.imagej.jp4.JP46_Reader_camera; import com.elphel.imagej.jp4.JP46_Reader_camera;
import com.elphel.imagej.lwir.LwirReader;
import com.elphel.imagej.lwir.LwirReaderParameters;
import Jama.Matrix; // Download here: http://math.nist.gov/javanumerics/jama/ import Jama.Matrix; // Download here: http://math.nist.gov/javanumerics/jama/
import ij.IJ; import ij.IJ;
...@@ -110,6 +101,7 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene ...@@ -110,6 +101,7 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene
private Panel panelCurvature; private Panel panelCurvature;
private Panel panelGoniometer; private Panel panelGoniometer;
private Panel panelPixelMapping, panelStereo,panelStereo1; private Panel panelPixelMapping, panelStereo,panelStereo1;
private Panel panelLWIR;
private ShowDoubleFloatArrays SDFA_INSTANCE; // just for debugging? private ShowDoubleFloatArrays SDFA_INSTANCE; // just for debugging?
JP46_Reader_camera JP4_INSTANCE; JP46_Reader_camera JP4_INSTANCE;
...@@ -271,6 +263,9 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene ...@@ -271,6 +263,9 @@ public class Aberration_Calibration extends PlugInFrame implements ActionListene
); );
public static LwirReader LWIR_READER = null;
public static ProcessCalibrationFilesParameters PROCESS_PARAMETERS = new ProcessCalibrationFilesParameters( public static ProcessCalibrationFilesParameters PROCESS_PARAMETERS = new ProcessCalibrationFilesParameters(
"jp46", // sourceFileExtension, "jp46", // sourceFileExtension,
"tiff", // kernelFileExtension, "tiff", // kernelFileExtension,
...@@ -614,6 +609,11 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi ...@@ -614,6 +609,11 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
public static EyesisAberrations EYESIS_ABERRATIONS; // need Distortions to be set up public static EyesisAberrations EYESIS_ABERRATIONS; // need Distortions to be set up
public static Goniometer GONIOMETER=null; public static Goniometer GONIOMETER=null;
public static LwirReaderParameters LWIR_PARAMETERS=new LwirReaderParameters();
// new CalibrationHardwareInterface.LaserPointers(); // new CalibrationHardwareInterface.LaserPointers();
public class SyncCommand{ public class SyncCommand{
public boolean isRunning= false; public boolean isRunning= false;
...@@ -634,7 +634,7 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi ...@@ -634,7 +634,7 @@ public static MatchSimulatedPattern.DistortionParameters DISTORTION =new MatchSi
addKeyListener(IJ.getInstance()); addKeyListener(IJ.getInstance());
// setLayout(new GridLayout(ADVANCED_MODE?8:5, 1)); // setLayout(new GridLayout(ADVANCED_MODE?8:5, 1));
// setLayout(new GridLayout(ADVANCED_MODE?9:6, 1)); // setLayout(new GridLayout(ADVANCED_MODE?9:6, 1));
setLayout(new GridLayout(ADVANCED_MODE?20:20, 1)); setLayout(new GridLayout(ADVANCED_MODE?21:21, 1));
Color color_configure= new Color(200, 200,160); Color color_configure= new Color(200, 200,160);
Color color_process= new Color(180, 180, 240); Color color_process= new Color(180, 180, 240);
Color color_conf_process= new Color(180, 240, 240); Color color_conf_process= new Color(180, 240, 240);
...@@ -983,9 +983,19 @@ if (MORE_BUTTONS) { ...@@ -983,9 +983,19 @@ if (MORE_BUTTONS) {
addButton("Create Ambiguity",panelStereo1); addButton("Create Ambiguity",panelStereo1);
addButton("Initial Resolve",panelStereo1); addButton("Initial Resolve",panelStereo1);
addButton("Ambiguity Resolve",panelStereo1); addButton("Ambiguity Resolve",panelStereo1);
add(panelStereo1); add(panelStereo1);
panelLWIR= new Panel();
panelLWIR.setLayout(new GridLayout(1, 0, 5, 5)); // rows, columns, vgap, hgap
addButton("LWIR Configure", panelLWIR,color_configure);
addButton("LWIR_TEST", panelLWIR, color_conf_process);
addButton("LWIR_ACQUIRE", panelLWIR, color_conf_process);
addButton("Configure Goniometer", panelLWIR,color_configure);
addButton("Goniometer Move", panelLWIR,color_debug);
addButton("LWIR Goniometer", panelLWIR,color_conf_process);
add(panelLWIR);
pack(); pack();
GUI.center(this); GUI.center(this);
setVisible(true); setVisible(true);
...@@ -1094,6 +1104,23 @@ if (MORE_BUTTONS) { ...@@ -1094,6 +1104,23 @@ if (MORE_BUTTONS) {
if (DEBUG_LEVEL>0) System.out.println("--- Free memory="+runtime.freeMemory()+" (of "+runtime.totalMemory()+")"); if (DEBUG_LEVEL>0) System.out.println("--- Free memory="+runtime.freeMemory()+" (of "+runtime.totalMemory()+")");
if (label==null) return; if (label==null) return;
String LOG_LEVEL;
switch (MASTER_DEBUG_LEVEL) {
case -2: LOG_LEVEL = "FATAL"; break;
case -1: LOG_LEVEL = "ERROR"; break;
case 0: LOG_LEVEL = "WARN"; break;
case 1: LOG_LEVEL = "INFO"; break;
case 2: LOG_LEVEL = "DEBUG"; break;
default: LOG_LEVEL = "OFF";
}
boolean LOG_LEVEL_SET = loci.common.DebugTools.enableLogging(LOG_LEVEL);
if (!LOG_LEVEL_SET) { // only first time true
loci.common.DebugTools.setRootLevel(LOG_LEVEL);
}
System.out.println("DEBUG_LEVEL = "+DEBUG_LEVEL+", MASTER_DEBUG_LEVEL = "+MASTER_DEBUG_LEVEL+
" LOG_LEVEL="+LOG_LEVEL+"LOG_LEVEL_SET="+LOG_LEVEL_SET);
if (FOCUSING_FIELD!=null) FOCUSING_FIELD.setThreads(THREADS_MAX); if (FOCUSING_FIELD!=null) FOCUSING_FIELD.setThreads(THREADS_MAX);
/* ======================================================================== */ /* ======================================================================== */
if (label.equals("Configure Globals")) { if (label.equals("Configure Globals")) {
...@@ -1172,334 +1199,11 @@ if (MORE_BUTTONS) { ...@@ -1172,334 +1199,11 @@ if (MORE_BUTTONS) {
return; return;
/* ======================================================================== */ /* ======================================================================== */
} else if (label.equals("Restore") || label.equals("Restore no autoload")) { } else if (label.equals("Restore") || label.equals("Restore no autoload")) {
boolean noAuto=label.equals("Restore no autoload"); restore(label.equals("Restore no autoload"));
ABERRATIONS_PARAMETERS.autoRestore=false;
String confPath=loadProperties(null,PROCESS_PARAMETERS.kernelsDirectory,PROCESS_PARAMETERS.useXML, PROPERTIES);
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
if (ABERRATIONS_PARAMETERS.autoRestore && !noAuto){
if (DEBUG_LEVEL>0)System.out.println("Auto-loading configuration files");
if (LENS_DISTORTIONS==null) {
LENS_DISTORTIONS=new Distortions(LENS_DISTORTION_PARAMETERS,PATTERN_PARAMETERS,REFINE_PARAMETERS,this.SYNC_COMMAND.stopRequested);
}
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
boolean dcdUpdated=autoLoadFiles(
ABERRATIONS_PARAMETERS,
LENS_DISTORTIONS, // should be initialized, after update DISTORTION_CALIBRATION_DATA from this
PATTERN_PARAMETERS,
EYESIS_CAMERA_PARAMETERS, //EyesisCameraParameters eyesisCameraParameters,
UPDATE_STATUS,
DEBUG_LEVEL
);
if (dcdUpdated) DISTORTION_CALIBRATION_DATA=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData;
if (ABERRATIONS_PARAMETERS.autoReCalibrate){
if (LENS_DISTORTIONS.fittingStrategy==null) {
IJ.showMessage("Can not recalibrate grids - LENS_DISTORTION.fittingStrategy is not set");
return;
}
if (DEBUG_LEVEL>0)System.out.println("=== Re-calibrating grids ===");
int numMatched=LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
5.0, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //boolean processAll, // if true - process all images, false - only disabeld
false, //?
false, //processBlind,
-1, // imageNumber,
true, // useSetData - use imageSets data if available (false - use camera data)
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
System.out.println("Number of matched images: "+numMatched);
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
LENS_DISTORTIONS.updateStatus=UPDATE_STATUS;
LENS_DISTORTIONS.fittingStrategy.debugLevel=DEBUG_LEVEL;
LENS_DISTORTIONS.markBadNodces(
-1,// series - all images
DEBUG_LEVEL);
}
if ((LENS_DISTORTIONS.fittingStrategy != null) && ABERRATIONS_PARAMETERS.autoFilter) { // trying to fix restore
if (DEBUG_LEVEL>0) System.out.println("LENS_DISTORTIONS.fittingStrategy != null -> Extra after loading");
int minGridsNoPointer=1000;
int [] numImages=DISTORTION_CALIBRATION_DATA.filterImages(
false, // resetHinted,
0, // 2, // minPointers,
0.4, // minGridPeriod,
true, // disableNoVignetting,
minGridsNoPointer); //minGridsNoPointer);
System.out.println("Number of enabled grid images: "+numImages[0]+
", of them new: "+numImages[1]+
", disabled without vignetting info: "+numImages[2]+
", disabled having less than "+minGridsNoPointer+" nodes and no matched pointers: "+numImages[3]+
", disabled with no lasers and enableNoLaser==false (like 2 bottom cameras - check all stations):" +numImages[4]);
if (DISTORTION_CALIBRATION_DATA.gIS==null) {
int numImageSets=DISTORTION_CALIBRATION_DATA.buildImageSets(false); // from scratch
if (DEBUG_LEVEL>0) System.out.println("Image set was empty, built a new one with "+numImageSets+" image sets (\"panoramas\"): ");
DISTORTION_CALIBRATION_DATA.updateSetOrientation(null); // restore orientation from (enabled) image files
if (DEBUG_LEVEL>0) System.out.println("Setting sets orientation from per-grid image data");
}
}
restoreFocusingHistory(false);
}
return; return;
/* ======================================================================== */ /* ======================================================================== */
} else if (label.equals("Process Calibration Files")) { } else if (label.equals("Process Calibration Files")) {
if (!showProcessCalibrationFilesDialog(PROCESS_PARAMETERS)) return; processCalibrationFiles();
boolean noMessageBoxes=false; //TODO: move to configuration
long startTime=System.nanoTime();
long tmpTime;
String resultPath;
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
int loop_debug_level=1;
String [][][] filePaths=null;
int dirNum, fileNum;
ImageStack stack;
ImagePlus imp_psf;
File file;
String fileName;
if (PROCESS_PARAMETERS.processSourceImages) {
if ((PROCESS_PARAMETERS.sourceSuperDirectory==null) || (PROCESS_PARAMETERS.sourceSuperDirectory.length()==0)) {
fileName= selectSourceDirectory(PROCESS_PARAMETERS.sourceSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.sourceSuperDirectory=fileName;
}
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
filePaths=prepareCalibrationFilesList(PROCESS_PARAMETERS);
if (filePaths==null) {
IJ.showMessage("Error","No files to process\nProcess canceled");
return;
}
startTime=System.nanoTime(); // restart timer after possible interactive dialogs
for (dirNum=0;dirNum<filePaths.length; dirNum++) {
if (filePaths[dirNum]!=null){
if (DEBUG_LEVEL>1) System.out.println("======= directory number="+dirNum+", number of files="+filePaths[dirNum].length+" ========");
for (fileNum=0;fileNum<filePaths[dirNum].length; fileNum++) {
if (DEBUG_LEVEL>1) System.out.println(filePaths[dirNum][fileNum][0] +" ==> "+filePaths[dirNum][fileNum][1]);
imp_sel=JP4_INSTANCE.open(
"", // path,
filePaths[dirNum][fileNum][0],
"", //arg - not used in JP46 reader
true, // un-apply camera color gains
imp_sel); // reuse the same image window
// Remove for old method?
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
matchSimulatedPattern.calculateDistortions(
DISTORTION, //
PATTERN_DETECT,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
null, // LaserPointer laserPointer, // LaserPointer object or null
true, // don't care -removeOutOfGridPointers
null, // double [][][] hintGrid, // predicted grid array (or null)
0, // double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
THREADS_MAX,
UPDATE_STATUS,
DEBUG_LEVEL,
DISTORTION.loop_debug_level, // debug level
noMessageBoxes);
SIM_ARRAY= (new SimulationPattern(SIMUL)).simulateGridAll (
imp_sel.getWidth(),
imp_sel.getHeight(),
matchSimulatedPattern,
2, // gridFrac, // number of grid steps per pattern full period
SIMUL,
THREADS_MAX,
UPDATE_STATUS,
DEBUG_LEVEL,
DISTORTION.loop_debug_level); // debug level
createPSFMap(
matchSimulatedPattern,
matchSimulatedPattern.applyFlatField (imp_sel), // if grid is flat-field calibrated, apply it
null, // int [][][] sampleList, // optional (or null) 2-d array: list of coordinate pairs (2d - to match existent PSF_KERNEL_MAP structure)
MULTIFILE_PSF.overexposedMaxFraction,
SIMUL, //simulation parameters
MAP_FFT_SIZE, // scanImageForPatterns:FFT size
PATTERN_DETECT,
FFT_OVERLAP, // scanImageForPatterns:high-pass gaussian filter sigma when correlating power spectrum
FFT_SIZE, // maximal distance between maximum on spectrum and predicted maximum on autocorrelation of gamma(|spectrum|)
COMPONENTS,
PSF_SUBPIXEL, // maximal iterations when looking for local maximum
OTF_FILTER,
PSF_PARS, // step of the new map (should be multiple of map step)
PSF_PARS.minDefinedArea,
INVERSE.dSize, // size of square used in the new map (should be multiple of map step)
THREADS_MAX,
UPDATE_STATUS,
loop_debug_level);// debug level used inside loops
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
stack=mergeKernelsToStack(PSF_KERNEL_MAP);
if (stack!=null) {
imp_psf = new ImagePlus(filePaths[dirNum][fileNum][1], stack);
// if (DEBUG_LEVEL>1) imp_psf.show();
if (DEBUG_LEVEL>1) System.out.println("Saving result to"+filePaths[dirNum][fileNum][1]+ " at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
FileSaver fs=new FileSaver(imp_psf);
fs.saveAsTiffStack(filePaths[dirNum][fileNum][1]);
} else {
System.out.println("File "+filePaths[dirNum][fileNum][1]+ " has no useful PSF kernels - at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
}
}
}
}
}
if (PROCESS_PARAMETERS.combinePSFfiles) {
tmpTime=System.nanoTime();
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
filePaths=preparePartialKernelsFilesList(PROCESS_PARAMETERS);
startTime-=(System.nanoTime()-tmpTime); // do not count time used for selection of files
if (filePaths==null) {
IJ.showMessage("Error","No partila kernel files to process, finished in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+ " seconds");
return;
}
String [] filenames;
for (dirNum=0;dirNum<filePaths.length; dirNum++) {
if ((filePaths[dirNum]!=null) && (filePaths[dirNum].length!=0)){
resultPath=filePaths[dirNum][0][1];
filenames=new String[filePaths[dirNum].length];
for (fileNum=0;fileNum<filenames.length;fileNum++) filenames[fileNum]=filePaths[dirNum][fileNum][0];
if (!combinePSFKernels (
INTERPOLATE,
MULTIFILE_PSF,
filenames,
resultPath,
SDFA_INSTANCE,
imp_sel, // re-use global
true, // saveResult,
false, // showResult,
UPDATE_STATUS,
DEBUG_LEVEL)) continue; // return; // no overlap, bad result kernel
}
}
}
if (PROCESS_PARAMETERS.interpolatePSFkernel) {
tmpTime=System.nanoTime();
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
IJ.showMessage("Notice","partialKernelsSuperDirectory="+PROCESS_PARAMETERS.partialKernelsSuperDirectory);
startTime-=(System.nanoTime()-tmpTime); // do not count time used for selection of files
filePaths=prepareInterpolateKernelsList(PROCESS_PARAMETERS);
for (fileNum=0;fileNum<filePaths.length;fileNum++) if ((filePaths[fileNum]!=null) && (filePaths[fileNum].length>0)) {
file=new File(filePaths[fileNum][0][0]);
if (!file.exists()) {
if (DEBUG_LEVEL>1) System.out.println("Raw PSF kernel stack file "+filePaths[fileNum][0][0]+" does not exist");
continue;
}
imp_psf=new ImagePlus(filePaths[fileNum][0][0]);
if (imp_psf.getStackSize()<3) {
System.out.println("Need a 3-layer stack with raw PSF kernels");
continue;
}
stack= interpolateKernelStack(imp_psf.getStack(), // Image stack, each slice consists of square kernels of one channel
INTERPOLATE,
UPDATE_STATUS); // update status info
imp_psf = new ImagePlus(filePaths[fileNum][0][1], stack);
if (DEBUG_LEVEL>2) {
imp_psf.getProcessor().resetMinAndMax(); // imp_psf will be reused
imp_psf.show();
}
if (DEBUG_LEVEL>1) System.out.println("Saving interpolation result to"+filePaths[fileNum][0][1]+ " at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
FileSaver fs=new FileSaver(imp_psf);
fs.saveAsTiffStack(filePaths[fileNum][0][1]);
}
}
if (PROCESS_PARAMETERS.invertKernels) {
tmpTime=System.nanoTime();
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
if ((PROCESS_PARAMETERS.kernelsDirectory==null) || (PROCESS_PARAMETERS.kernelsDirectory.length()==0)) {
fileName= selectKernelsDirectory(PROCESS_PARAMETERS.kernelsDirectory);
if (fileName!=null) PROCESS_PARAMETERS.kernelsDirectory=fileName;
}
startTime-=(System.nanoTime()-tmpTime); // do not count time used fro selection of files
filePaths=prepareInvertGaussianKernelsList(PROCESS_PARAMETERS, PROCESS_PARAMETERS.rpsfPrefix );
for (fileNum=0;fileNum<filePaths.length;fileNum++) if ((filePaths[fileNum]!=null) && (filePaths[fileNum].length>0)) {
file=new File(filePaths[fileNum][0][0]);
if (!file.exists()) {
if (DEBUG_LEVEL>0) System.out.println("Interpolated PSF kernel stack file "+filePaths[fileNum][0][0]+" does not exist");
continue;
}
imp_psf=new ImagePlus(filePaths[fileNum][0][0]);
if (imp_psf.getStackSize()<3) {
System.out.println("Need a 3-layer stack with interpolated PSF kernels");
continue;
}
stack= reversePSFKernelStack(imp_psf.getStack(), // stack of 3 32-bit (float) images, made of square kernels
INVERSE,
THREADS_MAX, // size (side of square) of reverse PSF kernel
UPDATE_STATUS); // update status info
imp_psf = new ImagePlus(filePaths[fileNum][0][1], stack);
if (DEBUG_LEVEL>2) {
imp_psf.getProcessor().resetMinAndMax(); // imp_psf will be reused
imp_psf.show();
}
if (DEBUG_LEVEL>0) System.out.println("Saving PSF inversion result to"+filePaths[fileNum][0][1]+ " at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
FileSaver fs=new FileSaver(imp_psf);
fs.saveAsTiffStack(filePaths[fileNum][0][1]);
}
}
if (PROCESS_PARAMETERS.gaussianKernels) {
tmpTime=System.nanoTime();
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
if ((PROCESS_PARAMETERS.kernelsDirectory==null) || (PROCESS_PARAMETERS.kernelsDirectory.length()==0)) {
fileName= selectKernelsDirectory(PROCESS_PARAMETERS.kernelsDirectory);
if (fileName!=null) PROCESS_PARAMETERS.kernelsDirectory=fileName;
}
startTime-=(System.nanoTime()-tmpTime); // do not count time used fro selection of files
filePaths=prepareInvertGaussianKernelsList(PROCESS_PARAMETERS, PROCESS_PARAMETERS.gaussianPrefix);
for (fileNum=0;fileNum<filePaths.length;fileNum++) if ((filePaths[fileNum]!=null) && (filePaths[fileNum].length>0)) {
file=new File(filePaths[fileNum][0][0]);
if (!file.exists()) {
if (DEBUG_LEVEL>0) System.out.println("Interpolated PSF kernel stack file "+filePaths[fileNum][0][0]+" does not exist");
continue;
}
imp_psf=new ImagePlus(filePaths[fileNum][0][0]);
if (imp_psf.getStackSize()<3) {
System.out.println("Need a 3-layer stack with interpolated PSF kernels");
continue;
}
stack= generateGaussianStackFromDirect(imp_psf.getStack(), // stack of 3 32-bit (float) images, made of square kernels
INVERSE,
UPDATE_STATUS); // update status info
imp_psf = new ImagePlus(filePaths[fileNum][0][1], stack);
if (DEBUG_LEVEL>2) {
imp_psf.getProcessor().resetMinAndMax(); // imp_psf will be reused
imp_psf.show();
}
if (DEBUG_LEVEL>0) System.out.println("Saving Gaussian kernels result to"+filePaths[fileNum][0][1]+ " at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
FileSaver fs=new FileSaver(imp_psf);
fs.saveAsTiffStack(filePaths[fileNum][0][1]);
}
}
System.out.println("Processing done in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+ " seconds");
if (PROCESS_PARAMETERS.saveSettings) saveProperties(PROCESS_PARAMETERS.kernelsDirectory+Prefs.getFileSeparator()+"calibration_settings",null,PROCESS_PARAMETERS.useXML, PROPERTIES);
return; return;
/* ======================================================================== */ /* ======================================================================== */
...@@ -9697,6 +9401,110 @@ if (MORE_BUTTONS) { ...@@ -9697,6 +9401,110 @@ if (MORE_BUTTONS) {
} }
return; return;
} }
/* ======================================================================== */
if (label.equals("LWIR Configure")) {
LWIR_PARAMETERS.showJDialog();
return;
}
/* ======================================================================== */
//
if (label.equals("LWIR_TEST")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
// public static LwirReader LWIR_READER = null;
if (LWIR_READER == null) {
LWIR_READER = new LwirReader(LWIR_PARAMETERS);
}
ImagePlus [][] imps = LWIR_READER.readAllMultiple(
10, // final int num_frames,
// true, // use LWIR telemetry
true, // final boolean show,
false); // true); // final boolean scale)
for (ImagePlus imp: imps[0]) {
imp.show();
}
System.out.println("LWIR_TEST: got "+imps.length+" image sets");
ImagePlus [][] imps_sync = LWIR_READER.matchSets(imps, 0.001, 3); // double max_mismatch)
if (imps_sync != null) {
ImagePlus [] imps_avg = LWIR_READER.averageMultiFrames(imps_sync);
for (ImagePlus imp: imps_avg) {
imp.show();
}
}
return;
}
/* ======================================================================== */
if (label.equals("LWIR_ACQUIRE")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
// public static LwirReader LWIR_READER = null;
if (LWIR_READER == null) {
LWIR_READER = new LwirReader(LWIR_PARAMETERS);
}
ImagePlus [] imps = LWIR_READER.acquire("/data_ssd/imagej-elphel/attic/camera_img/test-calib"); // directory to save
if (imps != null) {
// for (ImagePlus imp: imps) {
// imp.show();
// }
}
return;
}
/* ======================================================================== */
if (label.equals("Goniometer LWIR")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
// CAMERAS.setNumberOfThreads(THREADS_MAX);
// CAMERAS.debugLevel=DEBUG_LEVEL;
if (GONIOMETER==null) {
GONIOMETER= new Goniometer(
LWIR_READER,
// CAMERAS, // CalibrationHardwareInterface.CamerasInterface cameras,
DISTORTION, //MatchSimulatedPattern.DistortionParameters distortion,
PATTERN_DETECT, //MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
EYESIS_CAMERA_PARAMETERS, //EyesisCameraParameters eyesisCameraParameters,
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointers
SIMUL, //SimulationPattern.SimulParameters simulParametersDefault,
GONIOMETER_PARAMETERS, //LensAdjustment.FocusMeasurementParameters focusMeasurementParameters,
DISTORTION_PROCESS_CONFIGURATION
);
if (DEBUG_LEVEL>1){
System.out.println("Initiaslizing Goniometer class");
}
} else if (DEBUG_LEVEL>1){
System.out.println("GONIOMETER was initialized");
}
// calculate angular size of the target as visible from the camera
double distanceToTarget=GONIOMETER_PARAMETERS.targetDistance;
double patternWidth= PATTERN_PARAMETERS.patternWidth;
double patternHeight=PATTERN_PARAMETERS.patternHeight;
double targetAngleHorizontal=360*Math.atan(patternWidth/2/distanceToTarget)/Math.PI;
double targetAngleVertical= 360*Math.atan(patternHeight/2/distanceToTarget)/Math.PI;
if (DEBUG_LEVEL>0) System.out.println(
"Using:\n"+
"Distance from target: "+IJ.d2s(distanceToTarget,1)+" mm\n"+
" Taget width: "+IJ.d2s(patternWidth,1)+" mm\n"+
" Taget height: "+IJ.d2s(patternHeight,1)+" mm\n"+
"Taget angular size horizontal: "+IJ.d2s(targetAngleHorizontal,1)+" degrees\n"+
"Taget angular size vertical: "+IJ.d2s(targetAngleVertical,1)+" degrees\n"
);
GONIOMETER.debugLevel=DEBUG_LEVEL;
/// POWER_CONTROL.lightsOnWithDelay();
boolean goniometerScanOK=GONIOMETER.scanAndAcquire(
targetAngleHorizontal,
targetAngleVertical,
this.SYNC_COMMAND.stopRequested,
UPDATE_STATUS);
System.out.println ("GONIOMETER.scanAndAcquireI() "+(goniometerScanOK?"finished OK":"failed"));
/// POWER_CONTROL.lightsOff();
return;
}
/* ======================================================================== */ /* ======================================================================== */
...@@ -9706,6 +9514,347 @@ if (MORE_BUTTONS) { ...@@ -9706,6 +9514,347 @@ if (MORE_BUTTONS) {
} }
/* ===== Other methods ==================================================== */ /* ===== Other methods ==================================================== */
/* ======================================================================== */
/* ======================================================================== */
/* ======================================================================== */
/* ======================================================================== */
public void processCalibrationFiles() {
if (!showProcessCalibrationFilesDialog(PROCESS_PARAMETERS)) return;
boolean noMessageBoxes=false; //TODO: move to configuration
long startTime=System.nanoTime();
long tmpTime;
String resultPath;
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
int loop_debug_level=1;
String [][][] filePaths=null;
int dirNum, fileNum;
ImageStack stack;
ImagePlus imp_psf;
File file;
String fileName;
if (PROCESS_PARAMETERS.processSourceImages) {
if ((PROCESS_PARAMETERS.sourceSuperDirectory==null) || (PROCESS_PARAMETERS.sourceSuperDirectory.length()==0)) {
fileName= selectSourceDirectory(PROCESS_PARAMETERS.sourceSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.sourceSuperDirectory=fileName;
}
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
filePaths=prepareCalibrationFilesList(PROCESS_PARAMETERS);
if (filePaths==null) {
IJ.showMessage("Error","No files to process\nProcess canceled");
return;
}
startTime=System.nanoTime(); // restart timer after possible interactive dialogs
for (dirNum=0;dirNum<filePaths.length; dirNum++) {
if (filePaths[dirNum]!=null){
if (DEBUG_LEVEL>1) System.out.println("======= directory number="+dirNum+", number of files="+filePaths[dirNum].length+" ========");
for (fileNum=0;fileNum<filePaths[dirNum].length; fileNum++) {
if (DEBUG_LEVEL>1) System.out.println(filePaths[dirNum][fileNum][0] +" ==> "+filePaths[dirNum][fileNum][1]);
imp_sel=JP4_INSTANCE.open(
"", // path,
filePaths[dirNum][fileNum][0],
"", //arg - not used in JP46 reader
true, // un-apply camera color gains
imp_sel); // reuse the same image window
//Remove for old method?
matchSimulatedPattern= new MatchSimulatedPattern(DISTORTION.FFTSize);
matchSimulatedPattern.calculateDistortions(
DISTORTION, //
PATTERN_DETECT,
SIMUL,
COMPONENTS.equalizeGreens,
imp_sel,
null, // LaserPointer laserPointer, // LaserPointer object or null
true, // don't care -removeOutOfGridPointers
null, // double [][][] hintGrid, // predicted grid array (or null)
0, // double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
THREADS_MAX,
UPDATE_STATUS,
DEBUG_LEVEL,
DISTORTION.loop_debug_level, // debug level
noMessageBoxes);
SIM_ARRAY= (new SimulationPattern(SIMUL)).simulateGridAll (
imp_sel.getWidth(),
imp_sel.getHeight(),
matchSimulatedPattern,
2, // gridFrac, // number of grid steps per pattern full period
SIMUL,
THREADS_MAX,
UPDATE_STATUS,
DEBUG_LEVEL,
DISTORTION.loop_debug_level); // debug level
createPSFMap(
matchSimulatedPattern,
matchSimulatedPattern.applyFlatField (imp_sel), // if grid is flat-field calibrated, apply it
null, // int [][][] sampleList, // optional (or null) 2-d array: list of coordinate pairs (2d - to match existent PSF_KERNEL_MAP structure)
MULTIFILE_PSF.overexposedMaxFraction,
SIMUL, //simulation parameters
MAP_FFT_SIZE, // scanImageForPatterns:FFT size
PATTERN_DETECT,
FFT_OVERLAP, // scanImageForPatterns:high-pass gaussian filter sigma when correlating power spectrum
FFT_SIZE, // maximal distance between maximum on spectrum and predicted maximum on autocorrelation of gamma(|spectrum|)
COMPONENTS,
PSF_SUBPIXEL, // maximal iterations when looking for local maximum
OTF_FILTER,
PSF_PARS, // step of the new map (should be multiple of map step)
PSF_PARS.minDefinedArea,
INVERSE.dSize, // size of square used in the new map (should be multiple of map step)
THREADS_MAX,
UPDATE_STATUS,
loop_debug_level);// debug level used inside loops
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
stack=mergeKernelsToStack(PSF_KERNEL_MAP);
if (stack!=null) {
imp_psf = new ImagePlus(filePaths[dirNum][fileNum][1], stack);
// if (DEBUG_LEVEL>1) imp_psf.show();
if (DEBUG_LEVEL>1) System.out.println("Saving result to"+filePaths[dirNum][fileNum][1]+ " at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
FileSaver fs=new FileSaver(imp_psf);
fs.saveAsTiffStack(filePaths[dirNum][fileNum][1]);
} else {
System.out.println("File "+filePaths[dirNum][fileNum][1]+ " has no useful PSF kernels - at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
}
}
}
}
}
if (PROCESS_PARAMETERS.combinePSFfiles) {
tmpTime=System.nanoTime();
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
filePaths=preparePartialKernelsFilesList(PROCESS_PARAMETERS);
startTime-=(System.nanoTime()-tmpTime); // do not count time used for selection of files
if (filePaths==null) {
IJ.showMessage("Error","No partila kernel files to process, finished in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+ " seconds");
return;
}
String [] filenames;
for (dirNum=0;dirNum<filePaths.length; dirNum++) {
if ((filePaths[dirNum]!=null) && (filePaths[dirNum].length!=0)){
resultPath=filePaths[dirNum][0][1];
filenames=new String[filePaths[dirNum].length];
for (fileNum=0;fileNum<filenames.length;fileNum++) filenames[fileNum]=filePaths[dirNum][fileNum][0];
if (!combinePSFKernels (
INTERPOLATE,
MULTIFILE_PSF,
filenames,
resultPath,
SDFA_INSTANCE,
imp_sel, // re-use global
true, // saveResult,
false, // showResult,
UPDATE_STATUS,
DEBUG_LEVEL)) continue; // return; // no overlap, bad result kernel
}
}
}
if (PROCESS_PARAMETERS.interpolatePSFkernel) {
tmpTime=System.nanoTime();
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
IJ.showMessage("Notice","partialKernelsSuperDirectory="+PROCESS_PARAMETERS.partialKernelsSuperDirectory);
startTime-=(System.nanoTime()-tmpTime); // do not count time used for selection of files
filePaths=prepareInterpolateKernelsList(PROCESS_PARAMETERS);
for (fileNum=0;fileNum<filePaths.length;fileNum++) if ((filePaths[fileNum]!=null) && (filePaths[fileNum].length>0)) {
file=new File(filePaths[fileNum][0][0]);
if (!file.exists()) {
if (DEBUG_LEVEL>1) System.out.println("Raw PSF kernel stack file "+filePaths[fileNum][0][0]+" does not exist");
continue;
}
imp_psf=new ImagePlus(filePaths[fileNum][0][0]);
if (imp_psf.getStackSize()<3) {
System.out.println("Need a 3-layer stack with raw PSF kernels");
continue;
}
stack= interpolateKernelStack(imp_psf.getStack(), // Image stack, each slice consists of square kernels of one channel
INTERPOLATE,
UPDATE_STATUS); // update status info
imp_psf = new ImagePlus(filePaths[fileNum][0][1], stack);
if (DEBUG_LEVEL>2) {
imp_psf.getProcessor().resetMinAndMax(); // imp_psf will be reused
imp_psf.show();
}
if (DEBUG_LEVEL>1) System.out.println("Saving interpolation result to"+filePaths[fileNum][0][1]+ " at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
FileSaver fs=new FileSaver(imp_psf);
fs.saveAsTiffStack(filePaths[fileNum][0][1]);
}
}
if (PROCESS_PARAMETERS.invertKernels) {
tmpTime=System.nanoTime();
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
if ((PROCESS_PARAMETERS.kernelsDirectory==null) || (PROCESS_PARAMETERS.kernelsDirectory.length()==0)) {
fileName= selectKernelsDirectory(PROCESS_PARAMETERS.kernelsDirectory);
if (fileName!=null) PROCESS_PARAMETERS.kernelsDirectory=fileName;
}
startTime-=(System.nanoTime()-tmpTime); // do not count time used fro selection of files
filePaths=prepareInvertGaussianKernelsList(PROCESS_PARAMETERS, PROCESS_PARAMETERS.rpsfPrefix );
for (fileNum=0;fileNum<filePaths.length;fileNum++) if ((filePaths[fileNum]!=null) && (filePaths[fileNum].length>0)) {
file=new File(filePaths[fileNum][0][0]);
if (!file.exists()) {
if (DEBUG_LEVEL>0) System.out.println("Interpolated PSF kernel stack file "+filePaths[fileNum][0][0]+" does not exist");
continue;
}
imp_psf=new ImagePlus(filePaths[fileNum][0][0]);
if (imp_psf.getStackSize()<3) {
System.out.println("Need a 3-layer stack with interpolated PSF kernels");
continue;
}
stack= reversePSFKernelStack(imp_psf.getStack(), // stack of 3 32-bit (float) images, made of square kernels
INVERSE,
THREADS_MAX, // size (side of square) of reverse PSF kernel
UPDATE_STATUS); // update status info
imp_psf = new ImagePlus(filePaths[fileNum][0][1], stack);
if (DEBUG_LEVEL>2) {
imp_psf.getProcessor().resetMinAndMax(); // imp_psf will be reused
imp_psf.show();
}
if (DEBUG_LEVEL>0) System.out.println("Saving PSF inversion result to"+filePaths[fileNum][0][1]+ " at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
FileSaver fs=new FileSaver(imp_psf);
fs.saveAsTiffStack(filePaths[fileNum][0][1]);
}
}
if (PROCESS_PARAMETERS.gaussianKernels) {
tmpTime=System.nanoTime();
if ((PROCESS_PARAMETERS.partialKernelsSuperDirectory==null) || (PROCESS_PARAMETERS.partialKernelsSuperDirectory.length()==0)) {
fileName= selectPartialKernelsDirectory(PROCESS_PARAMETERS.partialKernelsSuperDirectory);
if (fileName!=null) PROCESS_PARAMETERS.partialKernelsSuperDirectory=fileName;
}
if ((PROCESS_PARAMETERS.kernelsDirectory==null) || (PROCESS_PARAMETERS.kernelsDirectory.length()==0)) {
fileName= selectKernelsDirectory(PROCESS_PARAMETERS.kernelsDirectory);
if (fileName!=null) PROCESS_PARAMETERS.kernelsDirectory=fileName;
}
startTime-=(System.nanoTime()-tmpTime); // do not count time used fro selection of files
filePaths=prepareInvertGaussianKernelsList(PROCESS_PARAMETERS, PROCESS_PARAMETERS.gaussianPrefix);
for (fileNum=0;fileNum<filePaths.length;fileNum++) if ((filePaths[fileNum]!=null) && (filePaths[fileNum].length>0)) {
file=new File(filePaths[fileNum][0][0]);
if (!file.exists()) {
if (DEBUG_LEVEL>0) System.out.println("Interpolated PSF kernel stack file "+filePaths[fileNum][0][0]+" does not exist");
continue;
}
imp_psf=new ImagePlus(filePaths[fileNum][0][0]);
if (imp_psf.getStackSize()<3) {
System.out.println("Need a 3-layer stack with interpolated PSF kernels");
continue;
}
stack= generateGaussianStackFromDirect(imp_psf.getStack(), // stack of 3 32-bit (float) images, made of square kernels
INVERSE,
UPDATE_STATUS); // update status info
imp_psf = new ImagePlus(filePaths[fileNum][0][1], stack);
if (DEBUG_LEVEL>2) {
imp_psf.getProcessor().resetMinAndMax(); // imp_psf will be reused
imp_psf.show();
}
if (DEBUG_LEVEL>0) System.out.println("Saving Gaussian kernels result to"+filePaths[fileNum][0][1]+ " at "+ IJ.d2s(0.000000001*(System.nanoTime()-startTime),3));
FileSaver fs=new FileSaver(imp_psf);
fs.saveAsTiffStack(filePaths[fileNum][0][1]);
}
}
System.out.println("Processing done in "+IJ.d2s(0.000000001*(System.nanoTime()-startTime),3)+ " seconds");
if (PROCESS_PARAMETERS.saveSettings) saveProperties(PROCESS_PARAMETERS.kernelsDirectory+Prefs.getFileSeparator()+"calibration_settings",null,PROCESS_PARAMETERS.useXML, PROPERTIES);
return;
}
public void restore(boolean noAuto)
{
// boolean noAuto=label.equals("Restore no autoload");
ABERRATIONS_PARAMETERS.autoRestore=false;
String confPath=loadProperties(null,PROCESS_PARAMETERS.kernelsDirectory,PROCESS_PARAMETERS.useXML, PROPERTIES);
DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
if (ABERRATIONS_PARAMETERS.autoRestore && !noAuto){
if (DEBUG_LEVEL>0)System.out.println("Auto-loading configuration files");
if (LENS_DISTORTIONS==null) {
LENS_DISTORTIONS=new Distortions(LENS_DISTORTION_PARAMETERS,PATTERN_PARAMETERS,REFINE_PARAMETERS,this.SYNC_COMMAND.stopRequested);
}
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
boolean dcdUpdated=autoLoadFiles(
ABERRATIONS_PARAMETERS,
LENS_DISTORTIONS, // should be initialized, after update DISTORTION_CALIBRATION_DATA from this
PATTERN_PARAMETERS,
EYESIS_CAMERA_PARAMETERS, //EyesisCameraParameters eyesisCameraParameters,
UPDATE_STATUS,
DEBUG_LEVEL
);
if (dcdUpdated) DISTORTION_CALIBRATION_DATA=LENS_DISTORTIONS.fittingStrategy.distortionCalibrationData;
if (ABERRATIONS_PARAMETERS.autoReCalibrate){
if (LENS_DISTORTIONS.fittingStrategy==null) {
IJ.showMessage("Can not recalibrate grids - LENS_DISTORTION.fittingStrategy is not set");
return;
}
if (DEBUG_LEVEL>0)System.out.println("=== Re-calibrating grids ===");
int numMatched=LENS_DISTORTIONS.applyHintedGrids(
LASER_POINTERS, // MatchSimulatedPattern.LaserPointer laserPointer, // LaserPointer object that specifies actual laser poiners on the target
DISTORTION_PROCESS_CONFIGURATION.removeOutOfGridPointers, // boolean removeOutOfGridPointers,
5.0, //double hintGridTolerance, // alllowed mismatch (fraction of period) or 0 - orientation only
true, //boolean processAll, // if true - process all images, false - only disabeld
false, //?
false, //processBlind,
-1, // imageNumber,
true, // useSetData - use imageSets data if available (false - use camera data)
THREADS_MAX, //int threadsMax,
UPDATE_STATUS, // boolean updateStatus,
DISTORTION.loop_debug_level, // int mspDebugLevel,
MASTER_DEBUG_LEVEL, //int global_debug_level, // DEBUG_LEVEL
MASTER_DEBUG_LEVEL //int debug_level // debug level used inside loops
);
System.out.println("Number of matched images: "+numMatched);
LENS_DISTORTIONS.debugLevel=DEBUG_LEVEL;
LENS_DISTORTIONS.updateStatus=UPDATE_STATUS;
LENS_DISTORTIONS.fittingStrategy.debugLevel=DEBUG_LEVEL;
LENS_DISTORTIONS.markBadNodces(
-1,// series - all images
DEBUG_LEVEL);
}
if ((LENS_DISTORTIONS.fittingStrategy != null) && ABERRATIONS_PARAMETERS.autoFilter) { // trying to fix restore
if (DEBUG_LEVEL>0) System.out.println("LENS_DISTORTIONS.fittingStrategy != null -> Extra after loading");
int minGridsNoPointer=1000;
int [] numImages=DISTORTION_CALIBRATION_DATA.filterImages(
false, // resetHinted,
0, // 2, // minPointers,
0.4, // minGridPeriod,
true, // disableNoVignetting,
minGridsNoPointer); //minGridsNoPointer);
System.out.println("Number of enabled grid images: "+numImages[0]+
", of them new: "+numImages[1]+
", disabled without vignetting info: "+numImages[2]+
", disabled having less than "+minGridsNoPointer+" nodes and no matched pointers: "+numImages[3]+
", disabled with no lasers and enableNoLaser==false (like 2 bottom cameras - check all stations):" +numImages[4]);
if (DISTORTION_CALIBRATION_DATA.gIS==null) {
int numImageSets=DISTORTION_CALIBRATION_DATA.buildImageSets(false); // from scratch
if (DEBUG_LEVEL>0) System.out.println("Image set was empty, built a new one with "+numImageSets+" image sets (\"panoramas\"): ");
DISTORTION_CALIBRATION_DATA.updateSetOrientation(null); // restore orientation from (enabled) image files
if (DEBUG_LEVEL>0) System.out.println("Setting sets orientation from per-grid image data");
}
}
restoreFocusingHistory(false);
}
return;
}
public void viewCSVFile(){ public void viewCSVFile(){
String [] extensions={".csv","CSV"}; String [] extensions={".csv","CSV"};
CalibrationFileManagement.MultipleExtensionsFileFilter parFilter = new CalibrationFileManagement.MultipleExtensionsFileFilter("",extensions,"CSV table *.csv files"); CalibrationFileManagement.MultipleExtensionsFileFilter parFilter = new CalibrationFileManagement.MultipleExtensionsFileFilter("",extensions,"CSV table *.csv files");
...@@ -14819,6 +14968,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) { ...@@ -14819,6 +14968,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
boolean select_ABERRATIONS_PARAMETERS=!select; boolean select_ABERRATIONS_PARAMETERS=!select;
boolean select_FOCUSING_FIELD=!select; boolean select_FOCUSING_FIELD=!select;
boolean select_POWER_CONTROL=!select; boolean select_POWER_CONTROL=!select;
boolean select_LWIR=!select;
if (select) { if (select) {
GenericDialog gd = new GenericDialog("Select parameters to save"); GenericDialog gd = new GenericDialog("Select parameters to save");
gd.addMessage("===== Individual parameters ======"); gd.addMessage("===== Individual parameters ======");
...@@ -14859,6 +15009,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) { ...@@ -14859,6 +15009,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
gd.addCheckbox("ABERRATIONS_PARAMETERS",select_ABERRATIONS_PARAMETERS); gd.addCheckbox("ABERRATIONS_PARAMETERS",select_ABERRATIONS_PARAMETERS);
gd.addCheckbox("FOCUSING_FIELD",select_FOCUSING_FIELD); gd.addCheckbox("FOCUSING_FIELD",select_FOCUSING_FIELD);
gd.addCheckbox("POWER_CONTROL",select_POWER_CONTROL); gd.addCheckbox("POWER_CONTROL",select_POWER_CONTROL);
gd.addCheckbox("LWIR",select_LWIR);
WindowTools.addScrollBars(gd); WindowTools.addScrollBars(gd);
gd.showDialog(); gd.showDialog();
...@@ -14900,6 +15051,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) { ...@@ -14900,6 +15051,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
select_ABERRATIONS_PARAMETERS=gd.getNextBoolean(); select_ABERRATIONS_PARAMETERS=gd.getNextBoolean();
select_FOCUSING_FIELD=gd.getNextBoolean(); select_FOCUSING_FIELD=gd.getNextBoolean();
select_POWER_CONTROL=gd.getNextBoolean(); select_POWER_CONTROL=gd.getNextBoolean();
select_LWIR=gd.getNextBoolean();
} }
if (select_MASTER_DEBUG_LEVEL) properties.setProperty("MASTER_DEBUG_LEVEL", MASTER_DEBUG_LEVEL+""); if (select_MASTER_DEBUG_LEVEL) properties.setProperty("MASTER_DEBUG_LEVEL", MASTER_DEBUG_LEVEL+"");
...@@ -14939,6 +15091,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) { ...@@ -14939,6 +15091,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
if (select_ABERRATIONS_PARAMETERS) ABERRATIONS_PARAMETERS.setProperties("ABERRATIONS_PARAMETERS.", properties); if (select_ABERRATIONS_PARAMETERS) ABERRATIONS_PARAMETERS.setProperties("ABERRATIONS_PARAMETERS.", properties);
if ((select_FOCUSING_FIELD) && (FOCUSING_FIELD!=null)) FOCUSING_FIELD.setProperties("FOCUSING_FIELD.", properties); if ((select_FOCUSING_FIELD) && (FOCUSING_FIELD!=null)) FOCUSING_FIELD.setProperties("FOCUSING_FIELD.", properties);
if (select_POWER_CONTROL) POWER_CONTROL.setProperties("POWER_CONTROL.", properties); if (select_POWER_CONTROL) POWER_CONTROL.setProperties("POWER_CONTROL.", properties);
if (select_LWIR) LWIR_PARAMETERS.setProperties("LWIR.", properties);
if (select) properties.remove("selected"); if (select) properties.remove("selected");
} }
...@@ -14981,6 +15134,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) { ...@@ -14981,6 +15134,7 @@ private double [][] jacobianByJacobian(double [][] jacobian, boolean [] mask) {
ABERRATIONS_PARAMETERS.getProperties("ABERRATIONS_PARAMETERS.", properties); ABERRATIONS_PARAMETERS.getProperties("ABERRATIONS_PARAMETERS.", properties);
if (FOCUSING_FIELD!=null) FOCUSING_FIELD.getProperties("FOCUSING_FIELD.", properties,false); // false -> overwrite distortions center if (FOCUSING_FIELD!=null) FOCUSING_FIELD.getProperties("FOCUSING_FIELD.", properties,false); // false -> overwrite distortions center
POWER_CONTROL.getProperties("POWER_CONTROL.", properties); POWER_CONTROL.getProperties("POWER_CONTROL.", properties);
LWIR_PARAMETERS.getProperties("LWIR.", properties);
} }
private String selectSourceDirectory(String defaultPath) { private String selectSourceDirectory(String defaultPath) {
...@@ -3,13 +3,13 @@ package com.elphel.imagej.calibration; ...@@ -3,13 +3,13 @@ package com.elphel.imagej.calibration;
** -----------------------------------------------------------------------------** ** -----------------------------------------------------------------------------**
** Goniometer.java ** Goniometer.java
** **
** Measurements in the "goniometer" machine ** Measurements in the "goniometer" machine
** **
** **
** Copyright (C) 2010 Elphel, Inc. ** Copyright (C) 2010 Elphel, Inc.
** **
** -----------------------------------------------------------------------------** ** -----------------------------------------------------------------------------**
** **
** Goniometer.java is free software: you can redistribute it and/or modify ** Goniometer.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
...@@ -29,12 +29,10 @@ package com.elphel.imagej.calibration; ...@@ -29,12 +29,10 @@ package com.elphel.imagej.calibration;
import java.util.Properties; import java.util.Properties;
import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicInteger;
import com.elphel.imagej.calibration.CalibrationHardwareInterface.CamerasInterface;
import com.elphel.imagej.calibration.CalibrationHardwareInterface.GoniometerMotors;
import com.elphel.imagej.calibration.SimulationPattern.SimulParameters;
import com.elphel.imagej.cameras.EyesisCameraParameters; import com.elphel.imagej.cameras.EyesisCameraParameters;
import com.elphel.imagej.common.ShowDoubleFloatArrays; import com.elphel.imagej.common.ShowDoubleFloatArrays;
import com.elphel.imagej.common.WindowTools; import com.elphel.imagej.common.WindowTools;
import com.elphel.imagej.lwir.LwirReader;
import ij.IJ; import ij.IJ;
import ij.ImagePlus; import ij.ImagePlus;
...@@ -53,6 +51,7 @@ horizontal axis: ...@@ -53,6 +51,7 @@ horizontal axis:
// for // for
// debugging // debugging
public CalibrationHardwareInterface.CamerasInterface cameras = null; public CalibrationHardwareInterface.CamerasInterface cameras = null;
LwirReader lwirReader = null;
// public CalibrationHardwareInterface.LaserPointers lasers = null; // public CalibrationHardwareInterface.LaserPointers lasers = null;
// public static CalibrationHardwareInterface.FocusingMotors motorsS=null; // public static CalibrationHardwareInterface.FocusingMotors motorsS=null;
// public DistortionProcessConfiguration // public DistortionProcessConfiguration
...@@ -81,7 +80,6 @@ horizontal axis: ...@@ -81,7 +80,6 @@ horizontal axis:
public Goniometer(CalibrationHardwareInterface.CamerasInterface cameras, public Goniometer(CalibrationHardwareInterface.CamerasInterface cameras,
MatchSimulatedPattern.DistortionParameters distortionParametersDefault, MatchSimulatedPattern.DistortionParameters distortionParametersDefault,
// MatchSimulatedPattern.DistortionParameters distortion,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters, MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
EyesisCameraParameters eyesisCameraParameters, EyesisCameraParameters eyesisCameraParameters,
MatchSimulatedPattern.LaserPointer laserPointers, MatchSimulatedPattern.LaserPointer laserPointers,
...@@ -98,9 +96,34 @@ horizontal axis: ...@@ -98,9 +96,34 @@ horizontal axis:
this.simulParametersDefault=simulParametersDefault; this.simulParametersDefault=simulParametersDefault;
this.goniometerParameters=goniometerParameters; this.goniometerParameters=goniometerParameters;
this.distortionProcessConfiguration=distortionProcessConfiguration; this.distortionProcessConfiguration=distortionProcessConfiguration;
}
public Goniometer(
LwirReader lwirReader,
// CalibrationHardwareInterface.CamerasInterface cameras,
MatchSimulatedPattern.DistortionParameters distortionParametersDefault,
MatchSimulatedPattern.PatternDetectParameters patternDetectParameters,
EyesisCameraParameters eyesisCameraParameters,
MatchSimulatedPattern.LaserPointer laserPointers,
SimulationPattern.SimulParameters simulParametersDefault,
Goniometer.GoniometerParameters goniometerParameters,
DistortionProcessConfiguration distortionProcessConfiguration
) {
this.lwirReader= lwirReader;
// this.cameras = cameras;
this.distortionParametersDefault = distortionParametersDefault;
// this.distortion = distortion;
this.patternDetectParameters=patternDetectParameters;
this.eyesisCameraParameters = eyesisCameraParameters;
this.laserPointers = laserPointers;
this.simulParametersDefault=simulParametersDefault;
this.goniometerParameters=goniometerParameters;
this.distortionProcessConfiguration=distortionProcessConfiguration;
} }
//goniometerMotors //goniometerMotors
private enum MOT_ACT { private enum MOT_ACT {
MOVE_SPEC, MOVE_SPEC,
...@@ -118,7 +141,7 @@ horizontal axis: ...@@ -118,7 +141,7 @@ horizontal axis:
"Rotate to clockwise 200 degrees", "Rotate to clockwise 200 degrees",
"Rotate to counter-clockwise 200 degrees", "Rotate to counter-clockwise 200 degrees",
"set current position as new home"}; "set current position as new home"};
public boolean manualMove( public boolean manualMove(
AtomicInteger stopRequested, // 1 - stop now, 2 - when convenient AtomicInteger stopRequested, // 1 - stop now, 2 - when convenient
...@@ -126,7 +149,7 @@ horizontal axis: ...@@ -126,7 +149,7 @@ horizontal axis:
int tiltMotor=2; // 0-1-2 int tiltMotor=2; // 0-1-2
int axialMotor=1; // 0-1-2 int axialMotor=1; // 0-1-2
boolean needsInit=false; boolean needsInit=false;
int [] currentMotors=this.goniometerParameters.goniometerMotors.getCurrentPositions(); int [] currentMotors=this.goniometerParameters.goniometerMotors.getCurrentPositions();
double currentTilt=currentMotors[tiltMotor]/this.goniometerParameters.goniometerMotors.stepsPerDegreeTilt; double currentTilt=currentMotors[tiltMotor]/this.goniometerParameters.goniometerMotors.stepsPerDegreeTilt;
double currentAxial=currentMotors[axialMotor]/this.goniometerParameters.goniometerMotors.stepsPerDegreeAxial; double currentAxial=currentMotors[axialMotor]/this.goniometerParameters.goniometerMotors.stepsPerDegreeAxial;
...@@ -137,7 +160,7 @@ horizontal axis: ...@@ -137,7 +160,7 @@ horizontal axis:
"Current position:\n"+ "Current position:\n"+
"Tilt: "+IJ.d2s(currentTilt,1)+" degrees ("+currentMotors[tiltMotor]+" steps)\n"+ "Tilt: "+IJ.d2s(currentTilt,1)+" degrees ("+currentMotors[tiltMotor]+" steps)\n"+
"Axial: "+IJ.d2s(currentAxial,1)+" degrees ("+currentMotors[axialMotor]+" steps)\n"); "Axial: "+IJ.d2s(currentAxial,1)+" degrees ("+currentMotors[axialMotor]+" steps)\n");
GenericDialog gd = new GenericDialog("User interrupt"); GenericDialog gd = new GenericDialog("User interrupt");
gd.addRadioButtonGroup("Select action", options, 7, 1, options[0]); gd.addRadioButtonGroup("Select action", options, 7, 1, options[0]);
...@@ -222,13 +245,15 @@ horizontal axis: ...@@ -222,13 +245,15 @@ horizontal axis:
if (!OK) System.out.println("motorsMove()->false"); if (!OK) System.out.println("motorsMove()->false");
return true; // OK; // So will re-open dialog even after abort return true; // OK; // So will re-open dialog even after abort
} }
public boolean scanAndAcquire( public boolean scanAndAcquire(
double targetAngleHorizontal, double targetAngleHorizontal,
double targetAngleVertical, double targetAngleVertical,
AtomicInteger stopRequested, // 1 - stop now, 2 - when convenient AtomicInteger stopRequested, // 1 - stop now, 2 - when convenient
boolean updateStatus boolean updateStatus
){ ){
int tiltMotor=2; // 0-1-2 int tiltMotor=2; // 0-1-2
int axialMotor=1; // 0-1-2 int axialMotor=1; // 0-1-2
int [] motors=this.goniometerParameters.goniometerMotors.updateMotorsPosition(); int [] motors=this.goniometerParameters.goniometerMotors.updateMotorsPosition();
...@@ -236,28 +261,28 @@ horizontal axis: ...@@ -236,28 +261,28 @@ horizontal axis:
double thisAxial=motors[axialMotor]/this.goniometerParameters.goniometerMotors.stepsPerDegreeAxial; double thisAxial=motors[axialMotor]/this.goniometerParameters.goniometerMotors.stepsPerDegreeAxial;
double scanOverlapVertical=this.goniometerParameters.scanOverlapVertical; double scanOverlapVertical=this.goniometerParameters.scanOverlapVertical;
double scanOverlapHorizontal=this.goniometerParameters.scanOverlapHorizontal; double scanOverlapHorizontal=this.goniometerParameters.scanOverlapHorizontal;
boolean reverseAxial=(this.goniometerParameters.scanLimitAxialStart>this.goniometerParameters.scanLimitAxialEnd); boolean reverseAxial=(this.goniometerParameters.scanLimitAxialStart>this.goniometerParameters.scanLimitAxialEnd);
double scanLimitAxialLow= reverseAxial?this.goniometerParameters.scanLimitAxialEnd:this.goniometerParameters.scanLimitAxialStart; double scanLimitAxialLow= reverseAxial?this.goniometerParameters.scanLimitAxialEnd:this.goniometerParameters.scanLimitAxialStart;
double scanLimitAxialHigh= reverseAxial?this.goniometerParameters.scanLimitAxialStart:this.goniometerParameters.scanLimitAxialEnd; double scanLimitAxialHigh= reverseAxial?this.goniometerParameters.scanLimitAxialStart:this.goniometerParameters.scanLimitAxialEnd;
boolean zenithToNadir=this.goniometerParameters.scanLatitudeHigh<this.goniometerParameters.scanLatitudeLow; boolean zenithToNadir=this.goniometerParameters.scanLatitudeHigh<this.goniometerParameters.scanLatitudeLow;
double scanLatitudeHigh=zenithToNadir? this.goniometerParameters.scanLatitudeLow: this.goniometerParameters.scanLatitudeHigh; double scanLatitudeHigh=zenithToNadir? this.goniometerParameters.scanLatitudeLow: this.goniometerParameters.scanLatitudeHigh;
double scanLatitudeLow= zenithToNadir? this.goniometerParameters.scanLatitudeHigh:this.goniometerParameters.scanLatitudeLow; double scanLatitudeLow= zenithToNadir? this.goniometerParameters.scanLatitudeHigh:this.goniometerParameters.scanLatitudeLow;
double scanStepTilt= targetAngleVertical* (1.0-scanOverlapVertical); double scanStepTilt= targetAngleVertical* (1.0-scanOverlapVertical);
double scanStepAxial=targetAngleHorizontal*(1.0-scanOverlapHorizontal); // valid at equator double scanStepAxial=targetAngleHorizontal*(1.0-scanOverlapHorizontal); // valid at equator
if (this.debugLevel>1) System.out.println("scanStepTilt="+IJ.d2s(scanStepTilt,2)+", scanStepAxial="+IJ.d2s(scanStepAxial,2)); if (this.debugLevel>1) System.out.println("scanStepTilt="+IJ.d2s(scanStepTilt,2)+", scanStepAxial="+IJ.d2s(scanStepAxial,2));
int numTiltSteps=(int) Math.ceil((scanLatitudeHigh-scanLatitudeLow)/scanStepTilt); // includes first and last int numTiltSteps=(int) Math.ceil((scanLatitudeHigh-scanLatitudeLow)/scanStepTilt); // includes first and last
if (numTiltSteps>0){ // increase vertical overlap to make it same for all images if (numTiltSteps>0){ // increase vertical overlap to make it same for all images
scanStepTilt=(scanLatitudeHigh-scanLatitudeLow)/numTiltSteps; scanStepTilt=(scanLatitudeHigh-scanLatitudeLow)/numTiltSteps;
scanOverlapVertical=1.0-(scanStepTilt/targetAngleVertical); scanOverlapVertical=1.0-(scanStepTilt/targetAngleVertical);
} }
if (this.debugLevel>1) System.out.println("Updated scanStepTilt="+IJ.d2s(scanStepTilt,2)+", scanOverlapVertical="+IJ.d2s(scanOverlapVertical,2)); if (this.debugLevel>1) System.out.println("Updated scanStepTilt="+IJ.d2s(scanStepTilt,2)+", scanOverlapVertical="+IJ.d2s(scanOverlapVertical,2));
double [] tilts=new double [numTiltSteps]; double [] tilts=new double [numTiltSteps];
double [][] rots= new double [numTiltSteps][]; double [][] rots= new double [numTiltSteps][];
...@@ -276,11 +301,10 @@ horizontal axis: ...@@ -276,11 +301,10 @@ horizontal axis:
double cosMinAbsTilt=Math.cos(minAbsTilt*Math.PI/180.0); double cosMinAbsTilt=Math.cos(minAbsTilt*Math.PI/180.0);
if (this.debugLevel>2) System.out.println("tilt="+IJ.d2s(tilt,2)+"tiltL="+IJ.d2s(tiltL,2)+", tiltH="+IJ.d2s(tiltH,2)+ if (this.debugLevel>2) System.out.println("tilt="+IJ.d2s(tilt,2)+"tiltL="+IJ.d2s(tiltL,2)+", tiltH="+IJ.d2s(tiltH,2)+
", minAbsTilt="+IJ.d2s(minAbsTilt,2)+", cosMinAbsTilt="+IJ.d2s(cosMinAbsTilt,2)); ", minAbsTilt="+IJ.d2s(minAbsTilt,2)+", cosMinAbsTilt="+IJ.d2s(cosMinAbsTilt,2));
// double axialRange=
double scanStep=scanStepAxial; double scanStep=scanStepAxial;
double overlap=scanOverlapHorizontal; double overlap=scanOverlapHorizontal;
int numAxialSteps=(int) Math.ceil((scanLimitAxialHigh-scanLimitAxialLow)*cosMinAbsTilt/scanStepAxial); int numAxialSteps=(int) Math.ceil((scanLimitAxialHigh-scanLimitAxialLow)*cosMinAbsTilt/scanStepAxial);
// Correction for bottom rollers that block view - if tilt is above 60degrees (positive - looking higher). The clear angle is ~36% // Correction for bottom rollers that block view - if tilt is above 60degrees (positive - looking higher). The clear angle is ~36%
if (tilts[i]>this.bottomRollerTilt){ if (tilts[i]>this.bottomRollerTilt){
int numForRollers=(int) Math.ceil((scanLimitAxialHigh-scanLimitAxialLow)/(this.bottomRollersClearance*(1.0-scanOverlapHorizontal))); int numForRollers=(int) Math.ceil((scanLimitAxialHigh-scanLimitAxialLow)/(this.bottomRollersClearance*(1.0-scanOverlapHorizontal)));
...@@ -292,12 +316,10 @@ horizontal axis: ...@@ -292,12 +316,10 @@ horizontal axis:
numAxialSteps=numForRollers; numAxialSteps=numForRollers;
} }
} }
// spread evenly // spread evenly
if (numAxialSteps>0){ // increase vertical overlap to make it same for all images if (numAxialSteps>0){ // increase vertical overlap to make it same for all images
// scanStep=(scanLimitAxialHigh-scanLimitAxialLow)*cosMinAbsTilt/numAxialSteps;
// overlap=1.0-(scanStep/targetAngleHorizontal);
scanStep=(scanLimitAxialHigh-scanLimitAxialLow)/numAxialSteps; scanStep=(scanLimitAxialHigh-scanLimitAxialLow)/numAxialSteps;
overlap=1.0-(scanStep*cosMinAbsTilt/targetAngleHorizontal); overlap=1.0-(scanStep*cosMinAbsTilt/targetAngleHorizontal);
} }
...@@ -322,14 +344,8 @@ horizontal axis: ...@@ -322,14 +344,8 @@ horizontal axis:
System.out.println(); System.out.println();
} }
} }
// return true;
// motorsSimultaneous
// show current tilt/axial
// double absTiltRange=Math.abs(this.goniometerParameters.scanLimitTiltStart-this.goniometerParameters.scanLimitTiltStart);
GenericDialog gd = new GenericDialog("Start scanning"); GenericDialog gd = new GenericDialog("Start scanning");
// this.serialNumber, // camera serial number string
gd.addMessage("About to start scanning and recording images, parameters are set in the \"Configure Goniometer\" dialog"); gd.addMessage("About to start scanning and recording images, parameters are set in the \"Configure Goniometer\" dialog");
gd.addMessage("Please make sure goniometer motors are set that 0,0 corresponds to the camera in the initial position -"); gd.addMessage("Please make sure goniometer motors are set that 0,0 corresponds to the camera in the initial position -");
gd.addMessage("vertical and cables are not entangled, camera exposure is set correctly."); gd.addMessage("vertical and cables are not entangled, camera exposure is set correctly.");
...@@ -343,7 +359,7 @@ horizontal axis: ...@@ -343,7 +359,7 @@ horizontal axis:
if (this.lastScanStep>=0){ if (this.lastScanStep>=0){
gd.addMessage("Last scan finished at stop "+this.lastScanStep); gd.addMessage("Last scan finished at stop "+this.lastScanStep);
if (this.lastScanStep<(numStops-1)) startStep= this.lastScanStep+1; if (this.lastScanStep<(numStops-1)) startStep= this.lastScanStep+1;
} }
gd.addMessage(""); gd.addMessage("");
gd.addMessage("Current position is:"); gd.addMessage("Current position is:");
...@@ -364,7 +380,7 @@ horizontal axis: ...@@ -364,7 +380,7 @@ horizontal axis:
} }
// overwrite some distortionProcessConfiguration parameters (show, save, ...?) from GoniometerParameters // overwrite some distortionProcessConfiguration parameters (show, save, ...?) from GoniometerParameters
this.distortionProcessConfiguration.sourceDirectory=src_dir; this.distortionProcessConfiguration.sourceDirectory=src_dir;
// just for now - setting motor debug 1 higher than this // just for now - setting motor debug 1 higher than this
this.goniometerParameters.goniometerMotors.debugLevel=this.debugLevel+1; this.goniometerParameters.goniometerMotors.debugLevel=this.debugLevel+1;
long startTime = System.nanoTime(); long startTime = System.nanoTime();
String status; String status;
...@@ -389,7 +405,6 @@ horizontal axis: ...@@ -389,7 +405,6 @@ horizontal axis:
if (this.debugLevel>0) System.out.println(status); if (this.debugLevel>0) System.out.println(status);
if (updateStatus) IJ.showStatus(status); if (updateStatus) IJ.showStatus(status);
this.goniometerParameters.motorsSimultaneous=false; // not yet implemented this.goniometerParameters.motorsSimultaneous=false; // not yet implemented
// if (!this.goniometerParameters.motorsSimultaneous){
OK= this.goniometerParameters.goniometerMotors.moveMotorSetETA(tiltMotor, tiltMotorPosition); OK= this.goniometerParameters.goniometerMotors.moveMotorSetETA(tiltMotor, tiltMotorPosition);
if (!OK) { if (!OK) {
String msg="Could not set motor "+(tiltMotor+1)+" to move to "+tiltMotorPosition+" - may be out of limit"; String msg="Could not set motor "+(tiltMotor+1)+" to move to "+tiltMotorPosition+" - may be out of limit";
...@@ -432,11 +447,20 @@ horizontal axis: ...@@ -432,11 +447,20 @@ horizontal axis:
return false; return false;
} }
// update motor positions in the image properties, acquire and save images. // update motor positions in the image properties, acquire and save images.
// TODO: Make acquisition/decoding/laser identification multi-threaded // TODO: Make acquisition/decoding/laser identification multi-threaded
this.cameras.setMotorsPosition(this.goniometerParameters.goniometerMotors.getTargetPositions()); // Used target, not current to prevent minor variations
this.cameras.reportTiming=debugTiming; if (cameras != null) {
this.cameras.setMotorsPosition(this.goniometerParameters.goniometerMotors.getTargetPositions()); // Used target, not current to prevent minor variations
this.cameras.reportTiming=debugTiming;
this.cameras.acquire(this.distortionProcessConfiguration.sourceDirectory,true, updateStatus); // true - use lasers, updateStatus - make false?
} else if (lwirReader != null) {
this.lwirReader.setMotorsPosition(this.goniometerParameters.goniometerMotors.getTargetPositions()); // Used target, not current to prevent minor variations
this.lwirReader.reportTiming=debugTiming;
this.lwirReader.acquire(this.distortionProcessConfiguration.sourceDirectory); // true - use lasers, updateStatus - make false?
} else {
System.out.println("Neignter traditional camera/rig, no LWIR rig are initialized, dry run");
}
this.cameras.acquire(this.distortionProcessConfiguration.sourceDirectory,true, updateStatus); // true - use lasers, updateStatus - make false?
this.lastScanStep++; this.lastScanStep++;
if (stopRequested.get()>1){ if (stopRequested.get()>1){
if (this.debugLevel>0) System.out.println("User interrupt"); if (this.debugLevel>0) System.out.println("User interrupt");
...@@ -523,7 +547,7 @@ horizontal axis: ...@@ -523,7 +547,7 @@ horizontal axis:
return true; return true;
} }
public boolean testHintedTarget ( public boolean testHintedTarget (
ImagePlus[] images, ImagePlus[] images,
Distortions lensDistortions, // should not be null Distortions lensDistortions, // should not be null
...@@ -551,7 +575,7 @@ horizontal axis: ...@@ -551,7 +575,7 @@ horizontal axis:
// String imgTitle=images[nImg].getTitle(); // String imgTitle=images[nImg].getTitle();
pointersArray[nImg]=0; pointersArray[nImg]=0;
if (images[nImg].getProperty("POINTERS")!=null) pointersArray[nImg]=Integer.parseInt((String) (images[nImg].getProperty("POINTERS"))); if (images[nImg].getProperty("POINTERS")!=null) pointersArray[nImg]=Integer.parseInt((String) (images[nImg].getProperty("POINTERS")));
choices[index]=index+" sub-camera:"+subCam+" "+images[nImg].getTitle()+" - "+pointersArray[nImg]+" pointers"; choices[index]=index+" sub-camera:"+subCam+" "+images[nImg].getTitle()+" - "+pointersArray[nImg]+" pointers";
// if (this.debugLevel>1)System.out.println ("Adding image, nImg="+nImg); // if (this.debugLevel>1)System.out.println ("Adding image, nImg="+nImg);
// if (this.debugLevel>1)System.out.println ("Adding image "+images[nImg].getTitle()+": "+choices[index]); // if (this.debugLevel>1)System.out.println ("Adding image "+images[nImg].getTitle()+": "+choices[index]);
...@@ -564,7 +588,7 @@ horizontal axis: ...@@ -564,7 +588,7 @@ horizontal axis:
if (distortionCalibrationData.getNumStations()>1) { if (distortionCalibrationData.getNumStations()>1) {
gd.addNumericField("Station number (0.."+(distortionCalibrationData.getNumStations()-1)+")", stationNumber, 0); gd.addNumericField("Station number (0.."+(distortionCalibrationData.getNumStations()-1)+")", stationNumber, 0);
} }
gd.showDialog(); gd.showDialog();
if (gd.wasCanceled()) return false; if (gd.wasCanceled()) return false;
index= gd.getNextChoiceIndex(); index= gd.getNextChoiceIndex();
...@@ -576,7 +600,7 @@ horizontal axis: ...@@ -576,7 +600,7 @@ horizontal axis:
} }
int nImg=indices[index]; int nImg=indices[index];
int subCam= distortionCalibrationData.getImageChannel(images[nImg]); int subCam= distortionCalibrationData.getImageChannel(images[nImg]);
// int stationNumber= distortionCalibrationData.getImageStation(numGridImage), // station number // int stationNumber= distortionCalibrationData.getImageStation(numGridImage), // station number
double timeStamp= distortionCalibrationData.getImageTimestamp(images[nImg]); double timeStamp= distortionCalibrationData.getImageTimestamp(images[nImg]);
...@@ -600,7 +624,7 @@ horizontal axis: ...@@ -600,7 +624,7 @@ horizontal axis:
IJ.showMessage("Warning",msg); IJ.showMessage("Warning",msg);
} }
if ((Double.isNaN(goniometerTiltAxial[0])) || (Double.isNaN(goniometerTiltAxial[1]))) return false; if ((Double.isNaN(goniometerTiltAxial[0])) || (Double.isNaN(goniometerTiltAxial[1]))) return false;
double [][][] hintGrid=lensDistortions.estimateGridOnSensor( double [][][] hintGrid=lensDistortions.estimateGridOnSensor(
stationNumber, // station number stationNumber, // station number
subCam, subCam,
...@@ -617,8 +641,8 @@ horizontal axis: ...@@ -617,8 +641,8 @@ horizontal axis:
return false; return false;
} }
if (this.debugLevel>1) lensDistortions.showHintGrid(hintGrid); if (this.debugLevel>1) lensDistortions.showHintGrid(hintGrid);
MatchSimulatedPattern matchSimulatedPattern = new MatchSimulatedPattern(this.distortionParametersDefault.FFTSize); // new instance, all reset MatchSimulatedPattern matchSimulatedPattern = new MatchSimulatedPattern(this.distortionParametersDefault.FFTSize); // new instance, all reset
// next 2 lines are not needed for the new instance, but can be // next 2 lines are not needed for the new instance, but can be
// used alternatively if keeping it // used alternatively if keeping it
...@@ -626,8 +650,8 @@ horizontal axis: ...@@ -626,8 +650,8 @@ horizontal axis:
matchSimulatedPattern.invalidateFocusMask(); matchSimulatedPattern.invalidateFocusMask();
matchSimulatedPattern.debugLevel = debug_level; matchSimulatedPattern.debugLevel = debug_level;
ImagePlus imp_eq = matchSimulatedPattern.applyFlatField(images[nImg]); // current image with grid flat-field correction ImagePlus imp_eq = matchSimulatedPattern.applyFlatField(images[nImg]); // current image with grid flat-field correction
//TODO: it shows always 4 pointers (if>0) - the array is sparse //TODO: it shows always 4 pointers (if>0) - the array is sparse
// public int getNumberOfPointers (int sensorNum){ // public int getNumberOfPointers (int sensorNum){
// public int getNumberOfPointers (ImagePlus imp){ // public int getNumberOfPointers (ImagePlus imp){
...@@ -667,11 +691,11 @@ horizontal axis: ...@@ -667,11 +691,11 @@ horizontal axis:
if (debug_level > 0) System.out.println("Warning: " + msg); if (debug_level > 0) System.out.println("Warning: " + msg);
if (debug_level > 2) IJ.showMessage("Warning", msg); if (debug_level > 2) IJ.showMessage("Warning", msg);
} }
return true; return true;
} }
/* /*
* private showDoubleFloatArrays SDFA_INSTANCE= new showDoubleFloatArrays(); // just for debugging? * private showDoubleFloatArrays SDFA_INSTANCE= new showDoubleFloatArrays(); // just for debugging?
this.SDFA_INSTANCE.showArrays(gridXYZCorr, getGridWidth(), getGridHeight(), true, "Grid corrections", titles); this.SDFA_INSTANCE.showArrays(gridXYZCorr, getGridWidth(), getGridHeight(), true, "Grid corrections", titles);
...@@ -684,7 +708,7 @@ horizontal axis: ...@@ -684,7 +708,7 @@ horizontal axis:
(this.distortionCalibrationData.isSubcameraParameter(parIndex)?(" s"+subCam):"com "), (this.distortionCalibrationData.isSubcameraParameter(parIndex)?(" s"+subCam):"com "),
this.definedModes, this.definedModes[this.parameterMode[numSeries][i]]); this.definedModes, this.definedModes[this.parameterMode[numSeries][i]]);
* *
* this.parameterMode[numSeries][i]=gd.getNextChoiceIndex(); * this.parameterMode[numSeries][i]=gd.getNextChoiceIndex();
PatternParameters patternParameters, // should not be null PatternParameters patternParameters, // should not be null
boolean equalizeGreens, boolean equalizeGreens,
...@@ -692,7 +716,7 @@ horizontal axis: ...@@ -692,7 +716,7 @@ horizontal axis:
boolean updateStatus, boolean updateStatus,
int debug_level) {// debug level used inside loops int debug_level) {// debug level used inside loops
* *
* *
*/ */
public MatchSimulatedPattern.DistortionParameters modifyDistortionParameters(){ public MatchSimulatedPattern.DistortionParameters modifyDistortionParameters(){
...@@ -715,7 +739,7 @@ horizontal axis: ...@@ -715,7 +739,7 @@ horizontal axis:
distortionParameters.searchOverlap=this.goniometerParameters.searchOverlap; distortionParameters.searchOverlap=this.goniometerParameters.searchOverlap;
return distortionParameters; return distortionParameters;
} }
public SimulationPattern.SimulParameters modifySimulParameters(){ public SimulationPattern.SimulParameters modifySimulParameters(){
SimulationPattern.SimulParameters simulParameters = this.simulParametersDefault.clone(); SimulationPattern.SimulParameters simulParameters = this.simulParametersDefault.clone();
simulParameters.smallestSubPix = this.goniometerParameters.smallestSubPix; simulParameters.smallestSubPix = this.goniometerParameters.smallestSubPix;
...@@ -723,7 +747,7 @@ horizontal axis: ...@@ -723,7 +747,7 @@ horizontal axis:
simulParameters.subdiv = this.goniometerParameters.subdiv; simulParameters.subdiv = this.goniometerParameters.subdiv;
return simulParameters; return simulParameters;
} }
public double[] estimateOrientation( public double[] estimateOrientation(
ImagePlus[] images, // last acquire images with number of pointers ImagePlus[] images, // last acquire images with number of pointers
// detected>0 // detected>0
...@@ -799,8 +823,8 @@ horizontal axis: ...@@ -799,8 +823,8 @@ horizontal axis:
} }
this.matchSimulatedPatterns[numSensor].debugLevel = debug_level; this.matchSimulatedPatterns[numSensor].debugLevel = debug_level;
ImagePlus imp_eq = this.matchSimulatedPatterns[numSensor].applyFlatField(images[numSensor]); // current image with grid flat-field correction ImagePlus imp_eq = this.matchSimulatedPatterns[numSensor].applyFlatField(images[numSensor]); // current image with grid flat-field correction
//TODO: it shows always 4 pointers (if>0) - the array is sparse //TODO: it shows always 4 pointers (if>0) - the array is sparse
// public int getNumberOfPointers (int sensorNum){ // public int getNumberOfPointers (int sensorNum){
// public int getNumberOfPointers (ImagePlus imp){ // public int getNumberOfPointers (ImagePlus imp){
numPointers[numSensor]=0; numPointers[numSensor]=0;
...@@ -812,7 +836,7 @@ horizontal axis: ...@@ -812,7 +836,7 @@ horizontal axis:
", initial number of pointers was "+numPointers[numSensor]); ", initial number of pointers was "+numPointers[numSensor]);
} }
// matchSimulatedPatterns[numSensor].getChannel(images[numSensor])+" "); // matchSimulatedPatterns[numSensor].getChannel(images[numSensor])+" ");
int numAbsolutePoints = this.matchSimulatedPatterns[numSensor].calculateDistortions( int numAbsolutePoints = this.matchSimulatedPatterns[numSensor].calculateDistortions(
// allow more of grid around pointers? // allow more of grid around pointers?
distortionParameters, // distortionParameters, //
...@@ -825,7 +849,7 @@ horizontal axis: ...@@ -825,7 +849,7 @@ horizontal axis:
true, // don't care -removeOutOfGridPointers true, // don't care -removeOutOfGridPointers
null, // double [][][] hintGrid, // predicted grid array (or null) null, // double [][][] hintGrid, // predicted grid array (or null)
0, // double hintGridTolerance, // allowed mismatch (fraction of period) or 0 - orientation only 0, // double hintGridTolerance, // allowed mismatch (fraction of period) or 0 - orientation only
threadsMax, threadsMax,
updateStatus, updateStatus,
debug_level, debug_level,
...@@ -906,14 +930,14 @@ horizontal axis: ...@@ -906,14 +930,14 @@ horizontal axis:
distortionCalibrationData.setImages(imp_calibrated, // ImagePlus [] images, // imagesin the memory distortionCalibrationData.setImages(imp_calibrated, // ImagePlus [] images, // imagesin the memory
patternParameters); // PatternParameters patternParameters); patternParameters); // PatternParameters patternParameters);
distortionCalibrationData.initImageSet(eyesisCameraParameters); distortionCalibrationData.initImageSet(eyesisCameraParameters);
// Set initial azimuth and elevation // Set initial azimuth and elevation
// Set initial heading and elevation // Set initial heading and elevation
double [] initialHeadEl=distortionCalibrationData.getHeadEl(imgWithMaxPointers); double [] initialHeadEl=distortionCalibrationData.getHeadEl(imgWithMaxPointers);
// set goniometer horizontal axis angle and goniometer axial angles in all images // set goniometer horizontal axis angle and goniometer axial angles in all images
distortionCalibrationData.setGHGA(-initialHeadEl[1], -initialHeadEl[0]); distortionCalibrationData.setGHGA(-initialHeadEl[1], -initialHeadEl[0]);
if (debug_level > 1) System.out.println("Initial Heading and Elevation are set to heading="+IJ.d2s(-initialHeadEl[0],2)+", elvation="+IJ.d2s(-initialHeadEl[1],2)); if (debug_level > 1) System.out.println("Initial Heading and Elevation are set to heading="+IJ.d2s(-initialHeadEl[0],2)+", elvation="+IJ.d2s(-initialHeadEl[1],2));
lensDistortions.copySensorConstants(eyesisCameraParameters); // copy from the first channel lensDistortions.copySensorConstants(eyesisCameraParameters); // copy from the first channel
// lensDistortions.fittingStrategy will be defined later, no need to // lensDistortions.fittingStrategy will be defined later, no need to
// update it with a reference to distortionCalibrationData now // update it with a reference to distortionCalibrationData now
...@@ -932,19 +956,19 @@ horizontal axis: ...@@ -932,19 +956,19 @@ horizontal axis:
IJ.showMessage("Error", "Failed to open fitting strategy file: "+this.goniometerParameters.strategyFile); IJ.showMessage("Error", "Failed to open fitting strategy file: "+this.goniometerParameters.strategyFile);
return null; return null;
} }
if (debug_level > 1) System.out.println("Using fitting strategy template file: "+ lensDistortions.fittingStrategy.pathName); if (debug_level > 1) System.out.println("Using fitting strategy template file: "+ lensDistortions.fittingStrategy.pathName);
// TODO: modify fitting strategy to include all grid images // TODO: modify fitting strategy to include all grid images
lensDistortions.fittingStrategy.adjustNumberOfImages(imp_calibrated.length); lensDistortions.fittingStrategy.adjustNumberOfImages(imp_calibrated.length);
this.goniometerParameters.strategyFile = lensDistortions.fittingStrategy.pathName; this.goniometerParameters.strategyFile = lensDistortions.fittingStrategy.pathName;
// saved fitting strategy maybe for different number of subcameras. // saved fitting strategy maybe for different number of subcameras.
// it will be adjusted here - that works only for simple strategies that use all subcameras at each step. // it will be adjusted here - that works only for simple strategies that use all subcameras at each step.
// TODO: fix repeating subcamera parameters for all subcameras in each strategy // TODO: fix repeating subcamera parameters for all subcameras in each strategy
lensDistortions.fittingStrategy.updateNumberOfSubcameras(); lensDistortions.fittingStrategy.updateNumberOfSubcameras();
// enable azimuth adjust for all but the first camera? not here, later // enable azimuth adjust for all but the first camera? not here, later
// Calculate Sensor Masks // Calculate Sensor Masks
distortionCalibrationData.debugLevel = debug_level; distortionCalibrationData.debugLevel = debug_level;
distortionCalibrationData.updateStatus = updateStatus; distortionCalibrationData.updateStatus = updateStatus;
...@@ -1001,24 +1025,24 @@ horizontal axis: ...@@ -1001,24 +1025,24 @@ horizontal axis:
public double psf_cutoffLevel= 0.2; // disregard pixels below this fraction of the maximal value public double psf_cutoffLevel= 0.2; // disregard pixels below this fraction of the maximal value
public int psf_minArea = 10; // continue increasing the selected area, even if beyound psf_cutoffEnergy and psf_cutoffLevel, public int psf_minArea = 10; // continue increasing the selected area, even if beyound psf_cutoffEnergy and psf_cutoffLevel,
public double psf_blurSigma = 0.0; // optionally blur the calculated mask public double psf_blurSigma = 0.0; // optionally blur the calculated mask
// the following overwrite SimulParameters members // the following overwrite SimulParameters members
//TODO: Make initial pattern search more robust - if it first gets false positive, and number of detected cells is too low - increase threshold and re-try //TODO: Make initial pattern search more robust - if it first gets false positive, and number of detected cells is too low - increase threshold and re-try
public double correlationMinInitialContrast=3.0; // minimal contrast for the pattern of the center (initial point) public double correlationMinInitialContrast=3.0; // minimal contrast for the pattern of the center (initial point)
public int minimalPatternCluster=150; // minimal pattern cluster size (0 - disable retries) public int minimalPatternCluster=150; // minimal pattern cluster size (0 - disable retries)
public double scaleMinimalInitialContrast=2.0; // increase/decrease minimal contrast if initial cluster is >0 but less than minimalPatternCluster public double scaleMinimalInitialContrast=2.0; // increase/decrease minimal contrast if initial cluster is >0 but less than minimalPatternCluster
public double searchOverlap=0.25; // when searching for grid, step this amount of the FFTSize public double searchOverlap=0.25; // when searching for grid, step this amount of the FFTSize
public double smallestSubPix=0.3; // subdivide pixels down to that fraction when simulating public double smallestSubPix=0.3; // subdivide pixels down to that fraction when simulating
public double bitmapNonuniforityThreshold=0.1 ; // subdivide pixels until difference between the corners is below this value public double bitmapNonuniforityThreshold=0.1 ; // subdivide pixels until difference between the corners is below this value
public int subdiv=4; public int subdiv=4;
// overwrites public static class MultiFilePSF.overexposedMaxFraction // overwrites public static class MultiFilePSF.overexposedMaxFraction
public double overexposedMaxFraction=0.1; // allowed fraction of the overexposed pixels in the PSF kernel measurement area public double overexposedMaxFraction=0.1; // allowed fraction of the overexposed pixels in the PSF kernel measurement area
// overwrites public static class PSFParameters.minDefinedArea // overwrites public static class PSFParameters.minDefinedArea
public double minDefinedArea=0.75; // minimal (weighted) fraction of the defined patter pixels in the FFT area public double minDefinedArea=0.75; // minimal (weighted) fraction of the defined patter pixels in the FFT area
public int PSFKernelSize=32; // size of the detected PSF kernel public int PSFKernelSize=32; // size of the detected PSF kernel
public boolean approximateGrid=true; // approximate grid with polynomial public boolean approximateGrid=true; // approximate grid with polynomial
public boolean centerPSF=true; // Center PSF by modifying phase public boolean centerPSF=true; // Center PSF by modifying phase
public double mask1_sigma= 1.0; public double mask1_sigma= 1.0;
public double mask1_threshold=0.25; public double mask1_threshold=0.25;
public double gaps_sigma= 1.0; public double gaps_sigma= 1.0;
...@@ -1031,8 +1055,8 @@ horizontal axis: ...@@ -1031,8 +1055,8 @@ horizontal axis:
public double minUVSpan; // Minimal u/v span in correlation window that triggers increase of the correlation FFT size public double minUVSpan; // Minimal u/v span in correlation window that triggers increase of the correlation FFT size
public boolean flatFieldCorrection=true; public boolean flatFieldCorrection=true;
public double flatFieldExpand=4.0; public double flatFieldExpand=4.0;
public double thresholdFinish=0.001; // Stop iterations if 2 last steps had less improvement (but not worsening ) public double thresholdFinish=0.001; // Stop iterations if 2 last steps had less improvement (but not worsening )
public int numIterations= 100; // maximal number of iterations public int numIterations= 100; // maximal number of iterations
...@@ -1044,7 +1068,7 @@ horizontal axis: ...@@ -1044,7 +1068,7 @@ horizontal axis:
64 - pulses per revolution 64 - pulses per revolution
5682.48889 per degree 5682.48889 per degree
*/ */
// motors rotate positive - look down, positive - CCW // motors rotate positive - look down, positive - CCW
CalibrationHardwareInterface.GoniometerMotors goniometerMotors=null; CalibrationHardwareInterface.GoniometerMotors goniometerMotors=null;
// public double stepsPerDegreeTilt=-5682.48889; // minus that positive steps make negative elevation // public double stepsPerDegreeTilt=-5682.48889; // minus that positive steps make negative elevation
// public double stepsPerDegreeAxial=-36.0; // minus that positive steps make rotate CCW when looking from Eyesis top // public double stepsPerDegreeAxial=-36.0; // minus that positive steps make rotate CCW when looking from Eyesis top
...@@ -1053,26 +1077,26 @@ horizontal axis: ...@@ -1053,26 +1077,26 @@ horizontal axis:
// public double scanLimitTiltStart= 30.0; // scan around horizontal axis from that angle // public double scanLimitTiltStart= 30.0; // scan around horizontal axis from that angle
// public double scanLimitTiltEnd= -80.0; // scan around horizontal axis to that angle // public double scanLimitTiltEnd= -80.0; // scan around horizontal axis to that angle
public double targetDistance= 5817; //mm - foer overlap calculation public double targetDistance= 5817; //mm - foer overlap calculation
public double scanLatitudeLow=-90; // lowest camera latitude to calibrate (nadir=-90) public double scanLatitudeLow=-90; // lowest camera latitude to calibrate (nadir=-90)
public double scanLatitudeHigh=90; // highest camera latitude to calibrate (zenith=90) public double scanLatitudeHigh=90; // highest camera latitude to calibrate (zenith=90)
public double scanOverlapHorizontal= 0.5; public double scanOverlapHorizontal= 0.5;
public double scanOverlapVertical= 0.5; public double scanOverlapVertical= 0.5;
public double scanLimitAxialStart= -200.0; // scan around camera axis from that angle public double scanLimitAxialStart= -200.0; // scan around camera axis from that angle
public double scanLimitAxialEnd= 200.0; // scan around camera axis to that angle public double scanLimitAxialEnd= 200.0; // scan around camera axis to that angle
public boolean scanBidirectional= true; // false - always move axial in the same direction, true - optimize movements public boolean scanBidirectional= true; // false - always move axial in the same direction, true - optimize movements
public boolean motorsSimultaneous= true; // true - move motors simultaneously, false - one at a time public boolean motorsSimultaneous= true; // true - move motors simultaneously, false - one at a time
public GoniometerParameters(CalibrationHardwareInterface.GoniometerMotors goniometerMotors){ public GoniometerParameters(CalibrationHardwareInterface.GoniometerMotors goniometerMotors){
this.goniometerMotors=goniometerMotors; this.goniometerMotors=goniometerMotors;
} }
public GoniometerParameters( public GoniometerParameters(
CalibrationHardwareInterface.GoniometerMotors goniometerMotors, CalibrationHardwareInterface.GoniometerMotors goniometerMotors,
String gridGeometryFile, String gridGeometryFile,
String initialCalibrationFile, // not needed String initialCalibrationFile, // not needed
String strategyFile, String strategyFile,
...@@ -1099,8 +1123,8 @@ horizontal axis: ...@@ -1099,8 +1123,8 @@ horizontal axis:
double searchOverlap, // when searching for grid, step this amount of the FFTSize double searchOverlap, // when searching for grid, step this amount of the FFTSize
double smallestSubPix, // subdivide pixels down to that fraction when simulating double smallestSubPix, // subdivide pixels down to that fraction when simulating
double bitmapNonuniforityThreshold, // subdivide pixels until difference between the corners is below this value double bitmapNonuniforityThreshold, // subdivide pixels until difference between the corners is below this value
int subdiv, int subdiv,
double overexposedMaxFraction, // allowed fraction of the overexposed pixels in the PSF kernel measurement area double overexposedMaxFraction, // allowed fraction of the overexposed pixels in the PSF kernel measurement area
double minDefinedArea, // minimal (weighted) fraction of the defined patter pixels in the FFT area double minDefinedArea, // minimal (weighted) fraction of the defined patter pixels in the FFT area
int PSFKernelSize, int PSFKernelSize,
boolean approximateGrid, // approximate grid with polynomial boolean approximateGrid, // approximate grid with polynomial
...@@ -1115,7 +1139,7 @@ horizontal axis: ...@@ -1115,7 +1139,7 @@ horizontal axis:
double minUVSpan, // Minimal u/v span in correlation window that triggers increase of the correlation FFT size double minUVSpan, // Minimal u/v span in correlation window that triggers increase of the correlation FFT size
boolean flatFieldCorrection, boolean flatFieldCorrection,
double flatFieldExpand, double flatFieldExpand,
double thresholdFinish,// (copied from series) stop iterations if 2 last steps had less improvement (but not worsening ) double thresholdFinish,// (copied from series) stop iterations if 2 last steps had less improvement (but not worsening )
int numIterations, // maximal number of iterations int numIterations, // maximal number of iterations
// double stepsPerDegreeTilt, // minus that positive steps make negative elevation // double stepsPerDegreeTilt, // minus that positive steps make negative elevation
// double stepsPerDegreeAxial, // minus that positive steps make rotate CCW when looking from Eyesis top // double stepsPerDegreeAxial, // minus that positive steps make rotate CCW when looking from Eyesis top
...@@ -1154,12 +1178,12 @@ horizontal axis: ...@@ -1154,12 +1178,12 @@ horizontal axis:
this.searchOverlap=searchOverlap; // when searching for grid, step this amount of the FFTSize this.searchOverlap=searchOverlap; // when searching for grid, step this amount of the FFTSize
this.smallestSubPix=smallestSubPix; this.smallestSubPix=smallestSubPix;
this.bitmapNonuniforityThreshold=bitmapNonuniforityThreshold; this.bitmapNonuniforityThreshold=bitmapNonuniforityThreshold;
this.subdiv=subdiv; this.subdiv=subdiv;
this.overexposedMaxFraction=overexposedMaxFraction; this.overexposedMaxFraction=overexposedMaxFraction;
this.minDefinedArea=minDefinedArea; this.minDefinedArea=minDefinedArea;
this.PSFKernelSize=PSFKernelSize; this.PSFKernelSize=PSFKernelSize;
this.approximateGrid = approximateGrid; // approximate grid with polynomial this.approximateGrid = approximateGrid; // approximate grid with polynomial
this.centerPSF = centerPSF; // approximate grid with polynomial this.centerPSF = centerPSF; // approximate grid with polynomial
this.mask1_sigma = mask1_sigma; this.mask1_sigma = mask1_sigma;
this.mask1_threshold = mask1_threshold; this.mask1_threshold = mask1_threshold;
this.gaps_sigma=gaps_sigma; this.gaps_sigma=gaps_sigma;
...@@ -1170,7 +1194,7 @@ horizontal axis: ...@@ -1170,7 +1194,7 @@ horizontal axis:
this.minUVSpan=minUVSpan; this.minUVSpan=minUVSpan;
this.flatFieldCorrection=flatFieldCorrection; this.flatFieldCorrection=flatFieldCorrection;
this.flatFieldExpand=flatFieldExpand; this.flatFieldExpand=flatFieldExpand;
this.thresholdFinish=thresholdFinish;// (copied from series) stop iterations if 2 last steps had less improvement (but not worsening ) this.thresholdFinish=thresholdFinish;// (copied from series) stop iterations if 2 last steps had less improvement (but not worsening )
this.numIterations=numIterations; // maximal number of iterations this.numIterations=numIterations; // maximal number of iterations
this.goniometerMotors=goniometerMotors; this.goniometerMotors=goniometerMotors;
// this.goniometerMotors.stepsPerDegreeTilt=stepsPerDegreeTilt; // minus that positive steps make negative elevation // this.goniometerMotors.stepsPerDegreeTilt=stepsPerDegreeTilt; // minus that positive steps make negative elevation
...@@ -1185,7 +1209,8 @@ horizontal axis: ...@@ -1185,7 +1209,8 @@ horizontal axis:
this.scanBidirectional=scanBidirectional; this.scanBidirectional=scanBidirectional;
this.motorsSimultaneous=motorsSimultaneous; this.motorsSimultaneous=motorsSimultaneous;
} }
public GoniometerParameters clone(){ @Override
public GoniometerParameters clone(){
return new GoniometerParameters( return new GoniometerParameters(
this.goniometerMotors, this.goniometerMotors,
this.gridGeometryFile, this.gridGeometryFile,
...@@ -1213,8 +1238,8 @@ horizontal axis: ...@@ -1213,8 +1238,8 @@ horizontal axis:
this.searchOverlap, // when searching for grid, step this amount of the FFTSize this.searchOverlap, // when searching for grid, step this amount of the FFTSize
this.smallestSubPix, this.smallestSubPix,
this.bitmapNonuniforityThreshold, this.bitmapNonuniforityThreshold,
this.subdiv, this.subdiv,
this.overexposedMaxFraction, this.overexposedMaxFraction,
this.minDefinedArea, this.minDefinedArea,
this.PSFKernelSize, this.PSFKernelSize,
this.approximateGrid, this.approximateGrid,
...@@ -1229,7 +1254,7 @@ horizontal axis: ...@@ -1229,7 +1254,7 @@ horizontal axis:
this.minUVSpan, this.minUVSpan,
this.flatFieldCorrection, this.flatFieldCorrection,
this.flatFieldExpand, this.flatFieldExpand,
this.thresholdFinish, this.thresholdFinish,
this.numIterations, this.numIterations,
this.targetDistance, this.targetDistance,
this.scanLatitudeLow, this.scanLatitudeLow,
...@@ -1290,20 +1315,20 @@ horizontal axis: ...@@ -1290,20 +1315,20 @@ horizontal axis:
properties.setProperty(prefix+"goniometerMotors_stepsPerSecond", this.goniometerMotors.stepsPerSecond+""); properties.setProperty(prefix+"goniometerMotors_stepsPerSecond", this.goniometerMotors.stepsPerSecond+"");
properties.setProperty(prefix+"goniometerMotors_stepsPerDegreeTilt", this.goniometerMotors.stepsPerDegreeTilt+""); properties.setProperty(prefix+"goniometerMotors_stepsPerDegreeTilt", this.goniometerMotors.stepsPerDegreeTilt+"");
properties.setProperty(prefix+"goniometerMotors_stepsPerDegreeAxial",this.goniometerMotors.stepsPerDegreeAxial+""); properties.setProperty(prefix+"goniometerMotors_stepsPerDegreeAxial",this.goniometerMotors.stepsPerDegreeAxial+"");
properties.setProperty(prefix+"targetDistance",this.targetDistance+""); properties.setProperty(prefix+"targetDistance",this.targetDistance+"");
properties.setProperty(prefix+"scanLatitudeLow",this.scanLatitudeLow+""); properties.setProperty(prefix+"scanLatitudeLow",this.scanLatitudeLow+"");
properties.setProperty(prefix+"scanLatitudeHigh",this.scanLatitudeHigh+""); properties.setProperty(prefix+"scanLatitudeHigh",this.scanLatitudeHigh+"");
properties.setProperty(prefix+"scanOverlapHorizontal",this.scanOverlapHorizontal+""); properties.setProperty(prefix+"scanOverlapHorizontal",this.scanOverlapHorizontal+"");
properties.setProperty(prefix+"scanOverlapVertical",this.scanOverlapVertical+""); properties.setProperty(prefix+"scanOverlapVertical",this.scanOverlapVertical+"");
properties.setProperty(prefix+"scanLimitAxialStart",this.scanLimitAxialStart+""); properties.setProperty(prefix+"scanLimitAxialStart",this.scanLimitAxialStart+"");
properties.setProperty(prefix+"scanLimitAxialEnd",this.scanLimitAxialEnd+""); properties.setProperty(prefix+"scanLimitAxialEnd",this.scanLimitAxialEnd+"");
properties.setProperty(prefix+"scanBidirectional",this.scanBidirectional+""); properties.setProperty(prefix+"scanBidirectional",this.scanBidirectional+"");
properties.setProperty(prefix+"motorsSimultaneous",this.motorsSimultaneous+""); properties.setProperty(prefix+"motorsSimultaneous",this.motorsSimultaneous+"");
} }
public void getProperties(String prefix,Properties properties){ public void getProperties(String prefix,Properties properties){
if (properties.getProperty(prefix+"gridGeometryFile")!=null) if (properties.getProperty(prefix+"gridGeometryFile")!=null)
this.gridGeometryFile=properties.getProperty(prefix+"gridGeometryFile"); this.gridGeometryFile=properties.getProperty(prefix+"gridGeometryFile");
...@@ -1316,7 +1341,7 @@ horizontal axis: ...@@ -1316,7 +1341,7 @@ horizontal axis:
if (properties.getProperty(prefix+"serialNumber")!=null) if (properties.getProperty(prefix+"serialNumber")!=null)
this.serialNumber=properties.getProperty(prefix+"serialNumber"); this.serialNumber=properties.getProperty(prefix+"serialNumber");
// this.serialNumber is only written, but never read from the configuration file (only from device) // this.serialNumber is only written, but never read from the configuration file (only from device)
if (properties.getProperty(prefix+"sensorTemperature")!=null) this.sensorTemperature=Double.parseDouble(properties.getProperty(prefix+"sensorTemperature")); if (properties.getProperty(prefix+"sensorTemperature")!=null) this.sensorTemperature=Double.parseDouble(properties.getProperty(prefix+"sensorTemperature"));
else this.sensorTemperature=Double.NaN; else this.sensorTemperature=Double.NaN;
if (properties.getProperty(prefix+"EEPROM_channel")!=null) if (properties.getProperty(prefix+"EEPROM_channel")!=null)
...@@ -1327,7 +1352,7 @@ horizontal axis: ...@@ -1327,7 +1352,7 @@ horizontal axis:
this.showResults=Boolean.parseBoolean(properties.getProperty(prefix+"showResults")); this.showResults=Boolean.parseBoolean(properties.getProperty(prefix+"showResults"));
if (properties.getProperty(prefix+"comment")!=null) if (properties.getProperty(prefix+"comment")!=null)
this.comment=properties.getProperty(prefix+"comment"); this.comment=properties.getProperty(prefix+"comment");
if ((this.comment.length()>10) && this.comment.substring(0,9).equals("<![CDATA[")) this.comment=this.comment.substring(9,this.comment.length()-3); if ((this.comment.length()>10) && this.comment.substring(0,9).equals("<![CDATA[")) this.comment=this.comment.substring(9,this.comment.length()-3);
if (properties.getProperty(prefix+"maxCorr")!=null) if (properties.getProperty(prefix+"maxCorr")!=null)
this.maxCorr=Double.parseDouble(properties.getProperty(prefix+"maxCorr")); this.maxCorr=Double.parseDouble(properties.getProperty(prefix+"maxCorr"));
if (properties.getProperty(prefix+"showHistoryDetails")!=null) if (properties.getProperty(prefix+"showHistoryDetails")!=null)
...@@ -1402,7 +1427,7 @@ horizontal axis: ...@@ -1402,7 +1427,7 @@ horizontal axis:
this.goniometerMotors.stepsPerDegreeTilt=Double.parseDouble(properties.getProperty(prefix+"goniometerMotors_stepsPerDegreeTilt")); this.goniometerMotors.stepsPerDegreeTilt=Double.parseDouble(properties.getProperty(prefix+"goniometerMotors_stepsPerDegreeTilt"));
if (properties.getProperty(prefix+"goniometerMotors_stepsPerDegreeAxial")!=null) if (properties.getProperty(prefix+"goniometerMotors_stepsPerDegreeAxial")!=null)
this.goniometerMotors.stepsPerDegreeAxial=Double.parseDouble(properties.getProperty(prefix+"goniometerMotors_stepsPerDegreeAxial")); this.goniometerMotors.stepsPerDegreeAxial=Double.parseDouble(properties.getProperty(prefix+"goniometerMotors_stepsPerDegreeAxial"));
if (properties.getProperty(prefix+"targetDistance")!=null) if (properties.getProperty(prefix+"targetDistance")!=null)
this.targetDistance=Double.parseDouble(properties.getProperty(prefix+"targetDistance")); this.targetDistance=Double.parseDouble(properties.getProperty(prefix+"targetDistance"));
if (properties.getProperty(prefix+"scanLatitudeLow")!=null) if (properties.getProperty(prefix+"scanLatitudeLow")!=null)
...@@ -1421,9 +1446,9 @@ horizontal axis: ...@@ -1421,9 +1446,9 @@ horizontal axis:
this.scanBidirectional=Boolean.parseBoolean(properties.getProperty(prefix+"scanBidirectional")); this.scanBidirectional=Boolean.parseBoolean(properties.getProperty(prefix+"scanBidirectional"));
if (properties.getProperty(prefix+"motorsSimultaneous")!=null) if (properties.getProperty(prefix+"motorsSimultaneous")!=null)
this.motorsSimultaneous=Boolean.parseBoolean(properties.getProperty(prefix+"motorsSimultaneous")); this.motorsSimultaneous=Boolean.parseBoolean(properties.getProperty(prefix+"motorsSimultaneous"));
} }
public boolean showDialog(String title) { public boolean showDialog(String title) {
GenericDialog gd = new GenericDialog(title); GenericDialog gd = new GenericDialog(title);
// this.serialNumber, // camera serial number string // this.serialNumber, // camera serial number string
gd.addMessage("Sensor board serial number is "+(((this.serialNumber==null)||(this.serialNumber==""))?"not specified":this.serialNumber)); gd.addMessage("Sensor board serial number is "+(((this.serialNumber==null)||(this.serialNumber==""))?"not specified":this.serialNumber));
...@@ -1453,7 +1478,7 @@ horizontal axis: ...@@ -1453,7 +1478,7 @@ horizontal axis:
gd.addNumericField("Smallest fraction to subdivide pixels at simulation", this.smallestSubPix, 3,5,"sensor pix"); gd.addNumericField("Smallest fraction to subdivide pixels at simulation", this.smallestSubPix, 3,5,"sensor pix");
gd.addNumericField("Maximal difference of the pattern value in the corners that triggers subdivision", this.bitmapNonuniforityThreshold, 3); gd.addNumericField("Maximal difference of the pattern value in the corners that triggers subdivision", this.bitmapNonuniforityThreshold, 3);
gd.addNumericField("Subdivide simulated pattern by:", this.subdiv, 0); gd.addNumericField("Subdivide simulated pattern by:", this.subdiv, 0);
gd.addNumericField("Allowed overexposed pixels (fraction of the area) ",this.overexposedMaxFraction,3); // 0.005; // allowed fraction of the overexposed pixels in the PSF kernel measurement area gd.addNumericField("Allowed overexposed pixels (fraction of the area) ",this.overexposedMaxFraction,3); // 0.005; // allowed fraction of the overexposed pixels in the PSF kernel measurement area
gd.addNumericField("Min fraction of the FFT square (weighted) to have defined pattern", this.minDefinedArea, 3); gd.addNumericField("Min fraction of the FFT square (weighted) to have defined pattern", this.minDefinedArea, 3);
gd.addNumericField ("PSF kernel size", this.PSFKernelSize, 0); gd.addNumericField ("PSF kernel size", this.PSFKernelSize, 0);
gd.addCheckbox ("Approximate pattern grid with a polynomial",this.approximateGrid); // true; // ignore lateral chromatic aberration (center OTF to 0,0) gd.addCheckbox ("Approximate pattern grid with a polynomial",this.approximateGrid); // true; // ignore lateral chromatic aberration (center OTF to 0,0)
...@@ -1470,19 +1495,19 @@ horizontal axis: ...@@ -1470,19 +1495,19 @@ horizontal axis:
gd.addNumericField("Expand during extrapolation (relative to the average grid period)", this.flatFieldExpand, 3); gd.addNumericField("Expand during extrapolation (relative to the average grid period)", this.flatFieldExpand, 3);
gd.addNumericField("Threshold RMS to exit LMA", this.thresholdFinish, 7,9,"pix"); gd.addNumericField("Threshold RMS to exit LMA", this.thresholdFinish, 7,9,"pix");
gd.addNumericField("Maximal number of LMA iterations per series",this.numIterations, 0); gd.addNumericField("Maximal number of LMA iterations per series",this.numIterations, 0);
gd.addMessage("Parameters for scanning/acquisition"); gd.addMessage("Parameters for scanning/acquisition");
gd.addStringField ("Goniometer motors IP address", this.goniometerMotors.ipAddress,40); gd.addStringField ("Goniometer motors IP address", this.goniometerMotors.ipAddress,40);
gd.addNumericField("Motors rotation speed ", this.goniometerMotors.stepsPerSecond,6,12,"steps/second"); gd.addNumericField("Motors rotation speed ", this.goniometerMotors.stepsPerSecond,6,12,"steps/second");
gd.addNumericField("Motor steps per tilt angular degree (currently negative) ",this.goniometerMotors.stepsPerDegreeTilt,6,12,"steps"); gd.addNumericField("Motor steps per tilt angular degree (currently negative) ",this.goniometerMotors.stepsPerDegreeTilt,6,12,"steps");
gd.addNumericField("Motor steps per axial angular degree (currently negative) ",this.goniometerMotors.stepsPerDegreeAxial,6,12,"steps"); gd.addNumericField("Motor steps per axial angular degree (currently negative) ",this.goniometerMotors.stepsPerDegreeAxial,6,12,"steps");
// gd.addNumericField("Tilt scan step (not larger than)", this.scanStepTilt,2,6,"degrees"); // gd.addNumericField("Tilt scan step (not larger than)", this.scanStepTilt,2,6,"degrees");
// gd.addNumericField("Axial scan step (not larger than)", this.scanStepAxial,2,6,"degrees"); // gd.addNumericField("Axial scan step (not larger than)", this.scanStepAxial,2,6,"degrees");
gd.addNumericField("Distance to target (for overlap calculation)", this.targetDistance,2,7,"mm"); gd.addNumericField("Distance to target (for overlap calculation)", this.targetDistance,2,7,"mm");
gd.addNumericField("Horizontal overlap", 100*this.scanOverlapHorizontal,2,5,"%"); gd.addNumericField("Horizontal overlap", 100*this.scanOverlapHorizontal,2,5,"%");
gd.addNumericField("Vertical overlap", 100*this.scanOverlapVertical,2,5,"%"); gd.addNumericField("Vertical overlap", 100*this.scanOverlapVertical,2,5,"%");
gd.addNumericField("Lowest camera view latitude to calibrate (nadir=-90)", this.scanLatitudeLow,2,6,"degrees"); gd.addNumericField("Lowest camera view latitude to calibrate (nadir=-90)", this.scanLatitudeLow,2,6,"degrees");
...@@ -1491,10 +1516,10 @@ horizontal axis: ...@@ -1491,10 +1516,10 @@ horizontal axis:
// gd.addNumericField("Tilt scan end angle", this.scanLimitTiltEnd,2,6,"degrees"); // gd.addNumericField("Tilt scan end angle", this.scanLimitTiltEnd,2,6,"degrees");
gd.addNumericField("Axial scan start angle", this.scanLimitAxialStart,2,6,"degrees"); gd.addNumericField("Axial scan start angle", this.scanLimitAxialStart,2,6,"degrees");
gd.addNumericField("Axial scan end angle", this.scanLimitAxialEnd,2,6,"degrees"); gd.addNumericField("Axial scan end angle", this.scanLimitAxialEnd,2,6,"degrees");
gd.addCheckbox ("Axial scan bidirectional", this.scanBidirectional); gd.addCheckbox ("Axial scan bidirectional", this.scanBidirectional);
gd.addCheckbox ("Allow simultaneous operation of motors", this.motorsSimultaneous); gd.addCheckbox ("Allow simultaneous operation of motors", this.motorsSimultaneous);
if (!Double.isNaN(this.sensorTemperature)) gd.addMessage("Last measured sensor temperature is "+this.sensorTemperature+" C"); if (!Double.isNaN(this.sensorTemperature)) gd.addMessage("Last measured sensor temperature is "+this.sensorTemperature+" C");
WindowTools.addScrollBars(gd); WindowTools.addScrollBars(gd);
gd.showDialog(); gd.showDialog();
...@@ -1524,7 +1549,7 @@ horizontal axis: ...@@ -1524,7 +1549,7 @@ horizontal axis:
this.smallestSubPix= gd.getNextNumber(); this.smallestSubPix= gd.getNextNumber();
this.bitmapNonuniforityThreshold=gd.getNextNumber(); this.bitmapNonuniforityThreshold=gd.getNextNumber();
this.subdiv= (int) gd.getNextNumber(); this.subdiv= (int) gd.getNextNumber();
this.overexposedMaxFraction= gd.getNextNumber(); this.overexposedMaxFraction= gd.getNextNumber();
this.minDefinedArea= gd.getNextNumber(); this.minDefinedArea= gd.getNextNumber();
this.PSFKernelSize= (int) gd.getNextNumber(); this.PSFKernelSize= (int) gd.getNextNumber();
this.approximateGrid= gd.getNextBoolean(); this.approximateGrid= gd.getNextBoolean();
......
...@@ -4873,10 +4873,10 @@ private Panel panel1, ...@@ -4873,10 +4873,10 @@ private Panel panel1,
if (LWIR_READER == null) { if (LWIR_READER == null) {
LWIR_READER = new LwirReader(CLT_PARAMETERS.lwir); LWIR_READER = new LwirReader(CLT_PARAMETERS.lwir);
} }
ImagePlus [] imps = LWIR_READER.acquire(); ImagePlus [] imps = LWIR_READER.acquire("/data_ssd/imagej-elphel/attic/camera_img/test"); // directory to save
if (imps != null) { if (imps != null) {
for (ImagePlus imp: imps) { for (ImagePlus imp: imps) {
imp.show(); // imp.show();
} }
} }
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
*/ */
package com.elphel.imagej.lwir; package com.elphel.imagej.lwir;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.util.Properties; import java.util.Properties;
...@@ -40,9 +41,13 @@ import org.slf4j.LoggerFactory; ...@@ -40,9 +41,13 @@ import org.slf4j.LoggerFactory;
import org.w3c.dom.Document; import org.w3c.dom.Document;
import org.xml.sax.SAXException; import org.xml.sax.SAXException;
import com.elphel.imagej.readers.ImagejJp4Tiff;
import com.elphel.imagej.readers.ImagejJp4TiffMulti; import com.elphel.imagej.readers.ImagejJp4TiffMulti;
import ij.IJ;
import ij.ImagePlus; import ij.ImagePlus;
import ij.Prefs;
import ij.io.FileSaver;
import ij.process.FloatProcessor; import ij.process.FloatProcessor;
import ij.process.ImageProcessor; import ij.process.ImageProcessor;
import loci.formats.FormatException; import loci.formats.FormatException;
...@@ -68,7 +73,7 @@ public class LwirReader { ...@@ -68,7 +73,7 @@ public class LwirReader {
public static final int LWIR_HEIGHT = 120; public static final int LWIR_HEIGHT = 120;
public static final int LWIR_TELEMETRY_LINES = 2; public static final int LWIR_TELEMETRY_LINES = 2;
public static final int FRAMES_SKIP = 3; public static final int FRAMES_SKIP = 4;
public static final int MAX_THREADS = 100; // combine from all classes? public static final int MAX_THREADS = 100; // combine from all classes?
/** Logger for this class. */ /** Logger for this class. */
...@@ -82,6 +87,10 @@ public class LwirReader { ...@@ -82,6 +87,10 @@ public class LwirReader {
private LwirReaderParameters lwirReaderParameters = null; private LwirReaderParameters lwirReaderParameters = null;
private LwirReaderParameters last_programmed = null; private LwirReaderParameters last_programmed = null;
private int [] motorsPosition = null;
public boolean reportTiming=false;
// -- constructors // -- constructors
public LwirReader() { public LwirReader() {
...@@ -99,6 +108,15 @@ public class LwirReader { ...@@ -99,6 +108,15 @@ public class LwirReader {
} }
public void setMotorsPosition (int [] position) {
this.motorsPosition=position;
}
public int [] getMotorsPosition() {
return this.motorsPosition; // may be null
}
// TODO: create // TODO: create
public boolean reSyncNeeded() { public boolean reSyncNeeded() {
return out_of_sync; return out_of_sync;
...@@ -220,6 +238,10 @@ public class LwirReader { ...@@ -220,6 +238,10 @@ public class LwirReader {
imps_avg[chn].setProperty(key, properties0.getProperty(key)); imps_avg[chn].setProperty(key, properties0.getProperty(key));
} }
imps_avg[chn].setProperty("average", ""+num_frames); imps_avg[chn].setProperty("average", ""+num_frames);
if (motorsPosition!=null) for (int m=0;m<motorsPosition.length;m++ ) {
imps_avg[chn].setProperty("MOTOR"+(m+1), ""+motorsPosition[m]);
}
ImagejJp4Tiff.encodeProperiesToInfo(imps_avg[chn]);
// TODO: Overwrite some properties? // TODO: Overwrite some properties?
} }
...@@ -333,10 +355,12 @@ public class LwirReader { ...@@ -333,10 +355,12 @@ public class LwirReader {
for (int c : lrp.lwir_channels) { for (int c : lrp.lwir_channels) {
channels |= 1 << c; channels |= 1 << c;
} }
String hex_chan = String.format("%x", channels); String hex_chan = String.format("0x%x", channels);
String url = "http://"+lrp.lwir_ip+"/parsedit.php?immediate&sensor_port="+chn+ String url = "http://"+lrp.lwir_ip+"/parsedit.php?immediate&sensor_port="+chn+
"&SENSOR_REGS67=0!"+hex_chan; "&SENSOR_REGS67=0!"+hex_chan;
// String url = "http://"+lrp.lwir_ip+"/parsedit.php?immediate&sensor_port="+chn+
// "&SENSOR_REGS67=0&*SENSOR_REGS67="+hex_chan;
Document dom=null; Document dom=null;
LOGGER.warn("calibrate(): Perform calibration (instead of 15 frames), url="+url); LOGGER.warn("calibrate(): Perform calibration (instead of 15 frames), url="+url);
try { try {
...@@ -415,12 +439,12 @@ public class LwirReader { ...@@ -415,12 +439,12 @@ public class LwirReader {
return true; return true;
} }
public ImagePlus [] acquire() { public ImagePlus [] acquire(String dirpath) {
return acquire(lwirReaderParameters); return acquire(lwirReaderParameters, dirpath);
} }
public ImagePlus [] acquire(LwirReaderParameters lrp) { public ImagePlus [] acquire(LwirReaderParameters lrp, String dirpath) {
if (!condProgramLWIRCamera(lrp)) { if (!condProgramLWIRCamera(lrp)) {
LOGGER.error("acquire(): failed to program cameras"); LOGGER.error("acquire(): failed to program cameras");
return null; return null;
...@@ -439,6 +463,20 @@ public class LwirReader { ...@@ -439,6 +463,20 @@ public class LwirReader {
return null; return null;
} }
LOGGER.debug("LWIR_ACQUIRE: got "+imps.length+" image sets"); LOGGER.debug("LWIR_ACQUIRE: got "+imps.length+" image sets");
// Verify fresh FFC for all channels
double [] after_ffc = new double [lrp.lwir_channels.length];
for (int chn = 0; chn < after_ffc.length; chn++) {
double uptime = Double.NaN, ffctime = Double.NaN;
try {
uptime = Double.parseDouble(((String) imps[0][chn].getProperty("TLM_UPTIME")));
ffctime = Double.parseDouble(((String) imps[0][chn].getProperty("TLM_FFC_TIME")));
after_ffc[chn] = uptime-ffctime;
} catch (Exception e) {
LOGGER.warn("acquire(): TLM_UPTIME and/or TLM_FFC_TIME properties are not available for"+imps[0][chn].getTitle());
}
LOGGER.warn(String.format("LWIR channel %d time from FFC: %.3f", chn, after_ffc[chn]));
}
int [] lags = new int [lrp.lwir_channels.length + lrp.vnir_channels.length]; int [] lags = new int [lrp.lwir_channels.length + lrp.vnir_channels.length];
for (int i = 0; i < lags.length; i++) { for (int i = 0; i < lags.length; i++) {
lags[i] = (i >= lrp.lwir_channels.length) ? lrp.vnir_lag : 0; lags[i] = (i >= lrp.lwir_channels.length) ? lrp.vnir_lag : 0;
...@@ -464,6 +502,27 @@ public class LwirReader { ...@@ -464,6 +502,27 @@ public class LwirReader {
} }
} }
ImagePlus [] imps_avg = averageMultiFrames(imps_sync); ImagePlus [] imps_avg = averageMultiFrames(imps_sync);
if (dirpath != null) {
File f_dir = new File(dirpath);
// get series path from the first channel file title
String first_name = imps_sync[0][0].getTitle();
String set_name = first_name.substring(0, first_name.lastIndexOf('_'));
String set_path = dirpath+Prefs.getFileSeparator()+set_name;
File set_dir = new File(set_path);
set_dir.mkdirs(); // including parent
for (ImagePlus imp:imps_avg) {
String fname = imp.getTitle();
fname = fname.substring(0, fname.lastIndexOf('_')) + ".tiff"; // remove _average
FileSaver fs=new FileSaver(imp);
String path=set_path+Prefs.getFileSeparator()+fname;
IJ.showStatus("Saving "+path);
LOGGER.debug("LWIR_ACQUIRE: 'Saving "+path+ " (and other with the same timestamp)" );
fs.saveAsTiff(path);
}
}
return imps_avg; return imps_avg;
} }
......
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