Commit d7dab33b authored by Andrey Filippov's avatar Andrey Filippov
Browse files

Added alignment statistics

parent 48ba44a4
Loading
Loading
Loading
Loading
+25 −1
Original line number Diff line number Diff line
@@ -84,7 +84,6 @@ import loci.formats.FormatException;

//import javax.swing.SwingUtilities;
//import javax.swing.UIManager;

public class Eyesis_Correction extends PlugInFrame implements ActionListener {
   /**
	 *
@@ -587,6 +586,7 @@ private Panel panel1,
			addButton("Rig offset",                 panelClt4, color_configure);
			addButton("Save offset",                panelClt4, color_process);
			addButton("SHOW extrinsics",            panelClt4, color_configure);
			addButton("LIST extrinsics",            panelClt4, color_configure);
			addButton("RIG DSI",                    panelClt4, color_conf_process);
			addButton("MAIN extrinsics",            panelClt4, color_process);
			addButton("AUX extrinsics",             panelClt4, color_process);
@@ -4579,6 +4579,11 @@ private Panel panel1,
        QuadCLT dbg_QUAD_CLT_AUX = QUAD_CLT_AUX;

        return;
/* ======================================================================== */
    } else if (label.equals("LIST extrinsics")) {
    	listExtrinsics();
    	return;

/* ======================================================================== */
    } else if (label.equals("Reset GT")) {
        DEBUG_LEVEL=MASTER_DEBUG_LEVEL;
@@ -5580,6 +5585,25 @@ private Panel panel1,
		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() {
		if (TWO_QUAD_CLT == null) {
			System.out.println("TWO_QUAD_CLT is not initialized");
+42 −1
Original line number Diff line number Diff line
@@ -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");
		}

		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 {
		this.rigOffset.showRigOffsets();
	}

	public double getRigOffsetParameter(int indx, boolean inPix) {
		return this.rigOffset.getRigOffsetParameter(indx,inPix);
	}

	public boolean setRigOffsetFromProperies(String parent_prefix,Properties properties) {
		RigOffset rigOffset = new RigOffset();
		boolean gotit = rigOffset.getProperties(parent_prefix, properties);
@@ -1248,6 +1268,27 @@ public class GeometryCorrection {
		{
			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
		public String toString()
+416 −0
Original line number Diff line number Diff line
@@ -21,20 +21,32 @@
 **
 */
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.FileVisitResult;
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.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Properties;

import ij.IJ;
import ij.ImagePlus;
import ij.ImageStack;
import ij.Prefs;
import ij.gui.GenericDialog;
import ij.io.FileSaver;
import ij.text.TextWindow;

public class TwoQuadCLT {
	public static  int DSI_DISPARITY_MAIN = 0;
@@ -6335,5 +6347,409 @@ if (debugLevel > -100) return true; // temporarily !
			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);
	}

}