Commit d7dab33b authored by Andrey Filippov's avatar Andrey Filippov

Added alignment statistics

parent 48ba44a4
...@@ -84,7 +84,6 @@ import loci.formats.FormatException; ...@@ -84,7 +84,6 @@ import loci.formats.FormatException;
//import javax.swing.SwingUtilities; //import javax.swing.SwingUtilities;
//import javax.swing.UIManager; //import javax.swing.UIManager;
public class Eyesis_Correction extends PlugInFrame implements ActionListener { public class Eyesis_Correction extends PlugInFrame implements ActionListener {
/** /**
* *
...@@ -587,6 +586,7 @@ private Panel panel1, ...@@ -587,6 +586,7 @@ private Panel panel1,
addButton("Rig offset", panelClt4, color_configure); addButton("Rig offset", panelClt4, color_configure);
addButton("Save offset", panelClt4, color_process); addButton("Save offset", panelClt4, color_process);
addButton("SHOW extrinsics", panelClt4, color_configure); addButton("SHOW extrinsics", panelClt4, color_configure);
addButton("LIST extrinsics", panelClt4, color_configure);
addButton("RIG DSI", panelClt4, color_conf_process); addButton("RIG DSI", panelClt4, color_conf_process);
addButton("MAIN extrinsics", panelClt4, color_process); addButton("MAIN extrinsics", panelClt4, color_process);
addButton("AUX extrinsics", panelClt4, color_process); addButton("AUX extrinsics", panelClt4, color_process);
...@@ -4579,6 +4579,11 @@ private Panel panel1, ...@@ -4579,6 +4579,11 @@ private Panel panel1,
QuadCLT dbg_QUAD_CLT_AUX = QUAD_CLT_AUX; QuadCLT dbg_QUAD_CLT_AUX = QUAD_CLT_AUX;
return; return;
/* ======================================================================== */
} else if (label.equals("LIST extrinsics")) {
listExtrinsics();
return;
/* ======================================================================== */ /* ======================================================================== */
} else if (label.equals("Reset GT")) { } else if (label.equals("Reset GT")) {
DEBUG_LEVEL=MASTER_DEBUG_LEVEL; DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
...@@ -5580,6 +5585,25 @@ private Panel panel1, ...@@ -5580,6 +5585,25 @@ private Panel panel1,
return true; return true;
} }
// listExtrinsics();
public boolean listExtrinsics() {
String dir= CalibrationFileManagement.selectDirectory(
false, // true, // smart,
false, // newAllowed, // save
"Model directories to scan", // title
"Select", // button
null, // filter
CORRECTION_PARAMETERS.x3dDirectory); //this.sourceDirectory);
if (dir!=null) {
System.out.println("top directory = "+dir);
}
//listExtrinsics(String dir, String mask)
// if (TWO_QUAD_CLT == null) {
// return false;
// }
return TwoQuadCLT.listExtrinsics(dir); // , mask);
}
public boolean showDSI() { public boolean showDSI() {
if (TWO_QUAD_CLT == null) { if (TWO_QUAD_CLT == null) {
System.out.println("TWO_QUAD_CLT is not initialized"); System.out.println("TWO_QUAD_CLT is not initialized");
......
...@@ -953,6 +953,22 @@ public class GeometryCorrection { ...@@ -953,6 +953,22 @@ public class GeometryCorrection {
System.out.println(" Relative zoom - difference from 1.0 in parts parts per 1/1000 "+ (par_scales[AUX_ZOOM_INDEX] * this.aux_zoom) +"pix"); System.out.println(" Relative zoom - difference from 1.0 in parts parts per 1/1000 "+ (par_scales[AUX_ZOOM_INDEX] * this.aux_zoom) +"pix");
} }
public double getRigOffsetParameter(int indx, boolean inPix)
{
if ((indx <0.0) || (indx >=par_scales.length)){
return Double.NaN;
}
double k = inPix? par_scales[indx] : 1.0;
switch (indx) {
case AUX_AZIMUTH_INDEX: return k * this.aux_azimuth;
case AUX_TILT_INDEX: return k * this.aux_tilt;
case AUX_ROLL_INDEX: return k * this.aux_roll;
case AUX_ZOOM_INDEX: return k * this.aux_zoom;
case AUX_ANGLE_INDEX: return k * this.aux_angle;
case AUX_BASELINE_INDEX: return k * this.baseline; // if inPix - show rig baseline/main baseline
}
return Double.NaN;
}
} }
...@@ -967,6 +983,10 @@ public class GeometryCorrection { ...@@ -967,6 +983,10 @@ public class GeometryCorrection {
this.rigOffset.showRigOffsets(); this.rigOffset.showRigOffsets();
} }
public double getRigOffsetParameter(int indx, boolean inPix) {
return this.rigOffset.getRigOffsetParameter(indx,inPix);
}
public boolean setRigOffsetFromProperies(String parent_prefix,Properties properties) { public boolean setRigOffsetFromProperies(String parent_prefix,Properties properties) {
RigOffset rigOffset = new RigOffset(); RigOffset rigOffset = new RigOffset();
boolean gotit = rigOffset.getProperties(parent_prefix, properties); boolean gotit = rigOffset.getProperties(parent_prefix, properties);
...@@ -1248,6 +1268,27 @@ public class GeometryCorrection { ...@@ -1248,6 +1268,27 @@ public class GeometryCorrection {
{ {
return vector[6 + indx] + roll[indx] * Math.PI/180.0; return vector[6 + indx] + roll[indx] * Math.PI/180.0;
} }
/**
* Return parameter value for reports
* @param indx parameter index (use CorrVector.XXX static integers)
* @param inPix show result in pixels , false - in radians (even for zooms)
* @return parameter value
*/
public double getExtrinsicParameterValue(int indx, boolean inPix) {
if (indx <0) return Double.NaN;
if (indx < ROLL_INDEX) return vector[indx]* (inPix? (1000.0*focalLength /pixelSize): 1.0); // tilt and azimuth
if (indx < LENGTH_ANGLES) return vector[indx]* (inPix? (1000.0*distortionRadius/pixelSize): 1.0); // rolls
if (indx < LENGTH) return vector[indx]* (inPix? (1000.0*distortionRadius/pixelSize): 1.0); // zooms
return Double.NaN;
}
public double getExtrinsicSymParameterValue(int indx, boolean inPix) {
double [] sym_vect = toSymArray(null);
if (indx <0) return Double.NaN;
if (indx < ROLL_INDEX) return sym_vect[indx]* (inPix? (1000.0*focalLength /pixelSize): 1.0); // tilt and azimuth
if (indx < LENGTH_ANGLES) return sym_vect[indx]* (inPix? (1000.0*distortionRadius/pixelSize): 1.0); // rolls
if (indx < LENGTH) return sym_vect[indx]* (inPix? (1000.0*distortionRadius/pixelSize): 1.0); // zooms
return Double.NaN;
}
@Override @Override
public String toString() public String toString()
......
...@@ -21,20 +21,32 @@ ...@@ -21,20 +21,32 @@
** **
*/ */
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.nio.file.FileVisitResult;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import ij.IJ; import ij.IJ;
import ij.ImagePlus; import ij.ImagePlus;
import ij.ImageStack; import ij.ImageStack;
import ij.Prefs; import ij.Prefs;
import ij.gui.GenericDialog;
import ij.io.FileSaver; import ij.io.FileSaver;
import ij.text.TextWindow;
public class TwoQuadCLT { public class TwoQuadCLT {
public static int DSI_DISPARITY_MAIN = 0; public static int DSI_DISPARITY_MAIN = 0;
...@@ -6335,5 +6347,409 @@ if (debugLevel > -100) return true; // temporarily ! ...@@ -6335,5 +6347,409 @@ if (debugLevel > -100) return true; // temporarily !
System.out.println("Configuration parameters are saved to "+path); System.out.println("Configuration parameters are saved to "+path);
} }
} }
public static boolean listExtrinsics(String dir) // , String mask)
{
Path path= Paths.get(dir);
boolean inPixels = true;
boolean inMrad = false;
boolean showATR = true;
boolean showZooms = true;
boolean showSym = true;
boolean showRigATR = true;
boolean showRigZoom = true;
boolean showRigAngle = true;
boolean showRigBaseline = false;
GenericDialog gd = new GenericDialog("Select file mask");
gd.addStringField ("Extrinsics (or general configuration) file mask: ", ".*EXTRINSICS\\.corr-xml", 40);
gd.addCheckbox("Show results in pixels (false in angular units)",inPixels);
gd.addCheckbox("Show results in mrad (false in arcseconds)", inMrad);
gd.addCheckbox("Show azimuths, tilts, rolls", showATR);
gd.addCheckbox("Show zooms", showZooms);
gd.addCheckbox("Show symmetric angles", showSym);
gd.addCheckbox("Show rig azimuth, tilt, roll", showRigATR);
gd.addCheckbox("Show rig zoom", showRigZoom);
gd.addCheckbox("Show rig angle", showRigAngle);
gd.addCheckbox("Show rig baseline", showRigBaseline);
gd.showDialog ();
if (gd.wasCanceled()) return false;
String mask = gd.getNextString();
inPixels = gd.getNextBoolean();
inMrad = gd.getNextBoolean();
showATR = gd.getNextBoolean();
showZooms = gd.getNextBoolean();
showSym = gd.getNextBoolean();
showRigATR = gd.getNextBoolean();
showRigZoom = gd.getNextBoolean();
showRigAngle = gd.getNextBoolean();
showRigBaseline = gd.getNextBoolean();
String units = inPixels ? "pix":(inMrad?"mil":"\"");
String zunits = inPixels ? "pix":(inMrad?"mil":"\"");
double scale = inPixels ? 1.0 : (inMrad?1000.0:(180.0/Math.PI*60*60)); //leave pixels as is, convert radians to arc-sec
String fmt = "\t"+(inPixels ? "%8.4f":(inMrad?"%8.4f":"%8.2f"));
String fmt_angle = "\t%8.3f";
String fmt_len = "\t%8.3f";
class ModVerString{
String model;
String version;
String txt;
ModVerString (String model, String version, String txt){
this.model = model;
this.version = version;
this.txt = txt;
}
@Override
public String toString() {
return model+"\t"+version+txt;
}
}
ArrayList<ModVerString> line_list = new ArrayList<ModVerString>();
String title = "Extrinsic parameters variations";
String header="#\tModel\tVersion";
int num_col = 0;
if (showATR) {
header+=String.format("\taz m0 (%s)\taz m1 (%s) \taz m2 (%s)\taz m3 (%s)"+
"\ttl m0 (%s)\ttl m1 (%s) \ttl m2 (%s)\ttl m3 (%s)"+
"\trl m0 (%s)\trl m1 (%s) \trl m2 (%s)\trl m3 (%s)",
units,units,units,units,units,units,units,units,units,units,units,units);
num_col+=12;
}
if (showZooms) {
header+=String.format("\tzm m0 (%s)\tzm m1 (%s)\tzm m2 (%s)\tzm m3 (%s)", zunits, zunits, zunits, zunits);
num_col+=4;
}
if (showSym) {
for (int i = 0; i < GeometryCorrection.CorrVector.LENGTH; i++) {
header+=String.format("\tsym%02d-m", i);
}
num_col+=GeometryCorrection.CorrVector.LENGTH;
}
if (showATR) {
header+=String.format("\taz a0 (%s)\taz a1 (%s) \taz a2 (%s)\taz a3 (%s)"+
"\ttl a0 (%s)\ttl m1 (%s) \ttl m2 (%s)\ttl m3 (%s)"+
"\trl a0 (%s)\trl a1 (%s) \trl a2 (%s)\trl a3 (%s)",
units,units,units,units,units,units,units,units,units,units,units,units);
num_col+=12;
}
if (showZooms) {
header+=String.format("\tzm a0 (%s)\tzm a1 (%s)\tzm a2 (%s)\tzm a3 (%s)", zunits, zunits, zunits, zunits);
num_col+=4;
}
if (showSym) {
for (int i = 0; i < GeometryCorrection.CorrVector.LENGTH; i++) {
header+=String.format("\tsym%02d-a", i);
}
num_col+=GeometryCorrection.CorrVector.LENGTH;
}
if (showRigATR) {
header+=String.format("\trig azmth (%s)\trig tilt(%s)\trig roll (%s)", units, units, units);
num_col+=3;
}
if (showRigZoom) {
header+=String.format("\trig zoom (%s)", zunits);
num_col+=1;
}
//
if (showRigAngle) {
header+="\trig angle (°)";
num_col+=1;
}
if (showRigBaseline) {
header+="\trig baseline (mm)";
num_col+=1;
}
System.out.println("File mask = "+mask);
final List<Path> files=new ArrayList<>();
final String fMask = mask;
try {
Files.walkFileTree(path, new SimpleFileVisitor<Path>(){
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
if(!attrs.isDirectory()){
if (file.toString().matches(fMask)) {
files.add(file);
}
}
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
e.printStackTrace();
}
int indx=1;
double [][] stats = new double [num_col][2];
String [] fmts = new String[num_col];
for (Path p:files) {
int count = p.getNameCount();
if (count >=3) {
String model = p.getName(count-3).toString();
String version = p.getName(count-2).toString();
String name = p.getName(count-1).toString();
System.out.println(indx+": model:"+model+", version:"+version+", name: "+name);
Properties properties = loadProperties(
p.toString(), // String path,
null); // Properties properties)
QuadCLT qcm = new QuadCLT(
QuadCLT.PREFIX, // String prefix,
properties, // Properties properties,
null, // EyesisCorrections eyesisCorrections,
null // EyesisCorrectionParameters.CorrectionParameters correctionsParameters
);
QuadCLT qca = new QuadCLT(
QuadCLT.PREFIX_AUX, // String prefix,
properties, // Properties properties,
null, // EyesisCorrections eyesisCorrections,
null // EyesisCorrectionParameters.CorrectionParameters correctionsParameters
);
System.out.println(indx+": model:"+model+", version:"+version+", name: "+name);
GeometryCorrection.CorrVector cvm = qcm.geometryCorrection.getCorrVector();
GeometryCorrection.CorrVector cva = qca.geometryCorrection.getCorrVector();
// double [] vect_main = qcm.geometryCorrection.getCorrVector().toArray();
StringBuffer sb = new StringBuffer();
int ncol = 0;
// sb.append(indx+"\t"+model+"\t"+version);
if (showATR) { // main camera
double [] v = new double[4];
for (int i = 0; i <4; i++) {
if (i < 3) {
v[i] = scale * cvm.getExtrinsicParameterValue(i+GeometryCorrection.CorrVector.AZIMUTH_INDEX, inPixels);
v[3] -= v[i];
}
sb.append(String.format(fmt,v[i])); // azimuths
fmts [ncol] = fmt;
stats[ncol ][0]+=v[i];
stats[ncol++][1]+=v[i]*v[i];
}
v = new double[4];
for (int i = 0; i <4; i++) {
if (i < 3) {
v[i] = scale * cvm.getExtrinsicParameterValue(i+GeometryCorrection.CorrVector.TILT_INDEX, inPixels);
v[3] -= v[i];
}
sb.append(String.format(fmt,v[i])); // tilts
fmts [ncol] = fmt;
stats[ncol ][0]+=v[i];
stats[ncol++][1]+=v[i]*v[i];
}
v = new double[4];
for (int i = 0; i <4; i++) {
if (i < 3) {
v[i] = scale * cvm.getExtrinsicParameterValue(i+GeometryCorrection.CorrVector.ROLL_INDEX, inPixels);
v[3] -= v[i];
}
sb.append(String.format(fmt,v[i])); // rolls
fmts [ncol] = fmt;
stats[ncol ][0]+=v[i];
stats[ncol++][1]+=v[i]*v[i];
}
}
if (showZooms) { // main camera
double [] v = new double[4];
for (int i = 0; i <4; i++) {
if (i < 3) {
v[i] = scale * cvm.getExtrinsicParameterValue(i+GeometryCorrection.CorrVector.ZOOM_INDEX, inPixels);
v[3] -= v[i];
}
sb.append(String.format(fmt,v[i])); // zooms
fmts [ncol] = fmt;
stats[ncol ][0]+=v[i];
stats[ncol++][1]+=v[i]*v[i];
}
}
if (showSym) {
for (int i = 0; i < GeometryCorrection.CorrVector.LENGTH; i++) {
double v = scale * cvm.getExtrinsicSymParameterValue(i, inPixels);
sb.append(String.format(fmt,v)); // sym parameters
fmts [ncol] = fmt;
stats[ncol ][0]+=v;
stats[ncol++][1]+=v*v;
}
}
if (showATR) { // aux camera
double [] v = new double[4];
for (int i = 0; i <4; i++) {
if (i < 3) {
v[i] = scale * cva.getExtrinsicParameterValue(i+GeometryCorrection.CorrVector.AZIMUTH_INDEX, inPixels);
v[3] -= v[i];
}
sb.append(String.format(fmt,v[i])); // azimuths
fmts [ncol] = fmt;
stats[ncol ][0]+=v[i];
stats[ncol++][1]+=v[i]*v[i];
}
v = new double[4];
for (int i = 0; i <4; i++) {
if (i < 3) {
v[i] = scale * cva.getExtrinsicParameterValue(i+GeometryCorrection.CorrVector.TILT_INDEX, inPixels);
v[3] -= v[i];
}
sb.append(String.format(fmt,v[i])); // tilts
fmts [ncol] = fmt;
stats[ncol ][0]+=v[i];
stats[ncol++][1]+=v[i]*v[i];
}
v = new double[4];
for (int i = 0; i <4; i++) {
if (i < 3) {
v[i] = scale * cva.getExtrinsicParameterValue(i+GeometryCorrection.CorrVector.ROLL_INDEX, inPixels);
v[3] -= v[i];
}
sb.append(String.format(fmt,v[i])); // rolls
fmts [ncol] = fmt;
stats[ncol ][0]+=v[i];
stats[ncol++][1]+=v[i]*v[i];
}
}
if (showZooms) { // aux camera
double [] v = new double[4];
for (int i = 0; i <4; i++) {
if (i < 3) {
v[i] = scale * cva.getExtrinsicParameterValue(i+GeometryCorrection.CorrVector.ZOOM_INDEX, inPixels);
v[3] -= v[i];
}
sb.append(String.format(fmt,v[i])); // zooms
fmts [ncol] = fmt;
stats[ncol ][0]+=v[i];
stats[ncol++][1]+=v[i]*v[i];
}
}
if (showSym) {
for (int i = 0; i < GeometryCorrection.CorrVector.LENGTH; i++) {
double v = scale * cva.getExtrinsicSymParameterValue(i, inPixels);
sb.append(String.format(fmt,v)); // sym parameters
fmts [ncol] = fmt;
stats[ncol ][0]+=v;
stats[ncol++][1]+=v*v;
}
}
if (showRigATR) {
int [] indices = {
GeometryCorrection.RigOffset.AUX_AZIMUTH_INDEX,
GeometryCorrection.RigOffset.AUX_TILT_INDEX,
GeometryCorrection.RigOffset.AUX_ROLL_INDEX};
for (int i = 0; i < indices.length; i++) {
double v = scale * qca.geometryCorrection.getRigOffsetParameter(indices[i], inPixels);
sb.append(String.format(fmt,v)); // tig atz parameters
fmts [ncol] = fmt;
stats[ncol ][0]+=v;
stats[ncol++][1]+=v*v;
}
}
if (showRigZoom) {
double v = scale * qca.geometryCorrection.getRigOffsetParameter(GeometryCorrection.RigOffset.AUX_ZOOM_INDEX, inPixels);
sb.append(String.format(fmt,v)); // tig atz parameters
fmts [ncol] = fmt;
stats[ncol ][0]+=v;
stats[ncol++][1]+=v*v;
}
if (showRigAngle) {
// sb.append(String.format(fmt_angle, 180/Math.PI * qca.geometryCorrection.getRigOffsetParameter(GeometryCorrection.RigOffset.AUX_ANGLE_INDEX, false)));
double v = 180/Math.PI * qca.geometryCorrection.getRigOffsetParameter(GeometryCorrection.RigOffset.AUX_ANGLE_INDEX, inPixels);
sb.append(String.format(fmt_angle,v)); // tig atz parameters
fmts [ncol] = fmt_angle;
stats[ncol ][0]+=v;
stats[ncol++][1]+=v*v;
}
if (showRigBaseline) {
// sb.append(String.format(fmt_len, qca.geometryCorrection.getRigOffsetParameter(GeometryCorrection.RigOffset.AUX_BASELINE_INDEX, false)));
double v = qca.geometryCorrection.getRigOffsetParameter(GeometryCorrection.RigOffset.AUX_ANGLE_INDEX, inPixels);
sb.append(String.format(fmt_len,v)); // tig atz parameters
fmts [ncol] = fmt_len;
stats[ncol ][0]+=v;
stats[ncol++][1]+=v*v;
}
sb.append("\n");
line_list.add( new ModVerString(model,version,sb.toString()));
indx++;
}
}
Collections.sort(line_list, new Comparator<ModVerString>() {
@Override
public int compare(ModVerString lhs, ModVerString rhs) {
// -1 - less than, 1 - greater than, 0 - equal, not inverted for ascending disparity
int rslt = lhs.model.compareTo(rhs.model);
if (rslt == 0) rslt = lhs.version.compareTo(rhs.version);
return rslt;
}
});
StringBuffer sb_avg = new StringBuffer();
StringBuffer sb_rms = new StringBuffer();
sb_avg.append("--\tAverage\t");
sb_rms.append("--\tStandard deviation\t");
int nrows = indx -1;
if (indx > 0) {
for (int ncol = 0; ncol < num_col; ncol++) {
stats[ncol][0] /= nrows;
stats[ncol][1] /= nrows;
stats[ncol][1] = Math.sqrt(stats[ncol][1] - stats[ncol][0]*stats[ncol][0]);
if (Double.isNaN(stats[ncol][1])) { // small negative by rounding error?
stats[ncol][1] = 0.0;
}
sb_avg.append(String.format(fmts[ncol],stats[ncol][0]));
sb_rms.append(String.format(fmts[ncol],stats[ncol][1]));
}
}
// ~1280
// int a = GeometryCorrection.RigOffset.VECTOR_LENGTH;
StringBuffer sb = new StringBuffer();
indx = 1;
for (ModVerString mvs:line_list) {
sb.append((indx++)+"\t"+mvs.toString());
}
sb.append(sb_avg.toString()+"\n");
sb.append(sb_rms.toString()+"\n");
new TextWindow (title, header, sb.toString(), 1200,800);
return true;
}
public static Properties loadProperties(
String path,
Properties properties){
if (properties == null) {
properties = new Properties();
}
InputStream is;
try {
is = new FileInputStream(path);
} catch (FileNotFoundException e) {
IJ.showMessage("Error","Failed to open configuration file: "+path);
return null;
}
try {
properties.loadFromXML(is);
} catch (IOException e) {
IJ.showMessage("Error","Failed to read XML configuration file: "+path);
return null;
}
try {
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return properties;
// getAllProperties(properties);
// if (DEBUG_LEVEL>0) System.out.println("Configuration parameters are restored from "+path);
}
} }
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