content: package edu.stanford.rsl.conrad.utils;
  
  import java.beans.XMLDecoder;
  import java.beans.XMLEncoder;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.FileOutputStream;
  import java.text.NumberFormat;
  import java.util.HashMap;
  import java.util.Locale;
  import java.util.NoSuchElementException;
  import java.util.Set;
  import java.beans.ExceptionListener;
  import javax.swing.JOptionPane;
  
  import edu.stanford.rsl.conrad.filtering.CosineWeightingTool;
  import edu.stanford.rsl.conrad.filtering.ImageFilteringTool;
  import edu.stanford.rsl.conrad.filtering.RampFilteringTool;
  import edu.stanford.rsl.conrad.filtering.redundancy.ParkerWeightingTool;
  import edu.stanford.rsl.conrad.fitting.Function;
  import edu.stanford.rsl.conrad.geometry.Projection.CameraAxisDirection;
  import edu.stanford.rsl.conrad.geometry.trajectories.CircularTrajectory;
  import edu.stanford.rsl.conrad.geometry.trajectories.ConfigFileBasedTrajectory;
  import edu.stanford.rsl.conrad.geometry.trajectories.ExtrapolatedTrajectory;
  import edu.stanford.rsl.conrad.geometry.trajectories.MultiSweepTrajectory;
  import edu.stanford.rsl.conrad.geometry.trajectories.Trajectory;
  import edu.stanford.rsl.conrad.io.ImagePlusDataSink;
  import edu.stanford.rsl.conrad.io.SafeSerializable;
  import edu.stanford.rsl.conrad.numerics.SimpleMatrix;
  import edu.stanford.rsl.conrad.numerics.SimpleVector;
  import edu.stanford.rsl.conrad.physics.detector.SimpleMonochromaticDetector;
  import edu.stanford.rsl.conrad.physics.detector.XRayDetector;
  import edu.stanford.rsl.conrad.pipeline.BufferedProjectionSink;
  import edu.stanford.rsl.conrad.reconstruction.VOIBasedReconstructionFilter;
  import ij.ImageJ;
  
  
  /**
   * Configuration is used to import Conrad configurations more easily and to store them globally.
   * Configuration objects can be used to configure filters and tools faster and more easily as
   * many of them require similar parameters regarding geometry, etc.
   * 
   * @author Andreas Maier
   *
   */
  
  public class Configuration implements SafeSerializable {
  	/**
  	 * 
  	 */
  	private static final long serialVersionUID = 3887275696746174804L;
  
  	private Trajectory geometry = null;
  
  	// Entries for reconstruction:
  	private String volumeOfInterestFileName = null;
  	private String projectionTableFileName = null;
  
  	// Entries for filtering
  	private double cutOffFrequency = 1;
  	private String AutomaticExposureControlConfigFile = null;
  	private String currentRowWeights = null;
  
  	// Entries for C-arm trajectory:
  	private String deviceSerialNumber = null;
  	private double [] realtime = null;
  	private double [] electroCardioGramm = null;
  
  	// Entries for Automatic Exposure Control
  	private double [] voltage = null;
  	private double [] current = null;
  	private double [] time = null;
  
  	private double dCU = 0;
  	private double dose = 0;
  	private int intensifierSize = 0;
  
  	// Entries for Utilities
  	private String currentPath = null;
  	private String recentFileOne = null;
  	private String recentFileTwo = null;
  
  	// Entries for Pipeline
  
  	private ImageFilteringTool [] filterPipeline;
  	private BufferedProjectionSink sink;
  
  	// Entries for GUI
  
  	public static final int MEDLINE_CITATION_FORMAT = 1;
  	public static final int BIBTEX_CITATION_FORMAT = 2;
  
  	private int citationFormat = BIBTEX_CITATION_FORMAT;
  	private boolean importFromDicomAutomatically = false;
  	private boolean useExtrapolatedGeometry = false;
  	private boolean useHounsfieldScaling = false;
  
  	private BilinearInterpolatingDoubleArray beamHardeningLookupTable = null;
  
  	private static Configuration globalConfiguration = null;
  	private Function hounsfieldScaling = null;
  
  	private double [] heartPhases = null;
  	private int numSweeps = 1;
  
  	private HashMap<String,String> registry;
  
  	// Entries for beads location in 2D or 3D, used for weight-bearing scanning	
  	private double [][][] beadPosition2D = null; // [projection #][bead #][u, v, state[0: initial, 1: registered, 2: updated by hough searching]]
  	private double [][] beadMeanPosition3D = null; // [projection #][bead #][u, v]
  	private boolean [] fAccessed = new boolean [500]; // if the projection is accessed
  	
  
  	private double[] respiratoryMotionField = null;
  	private double[] diaphragmPositionField = null;
  	private double[][] diaphragmModelField = null;
  	
  
  	private double maxMotion = 0;
  	private float lowHyst, highHyst;
  	private int seedX, seedY;
  	private int roiWidthHalf, roiHeightTop, roiHeightBottom;
  	
  	private int maxIter;
  	private double projTurningAngle;
  	private double correctionFactor;
  	private double[][] diaphragmCoords = null;
  	
  	public double[][] getDiaphragmModelField() {
  		return diaphragmModelField;
  	}
  
  	public void setDiaphragmModelField(double[][] diaphragmModelField) {
  		this.diaphragmModelField = diaphragmModelField;
  	}
  	
  	public void setDiaphragmModelEntry(int i, double[] entry) {
  		this.diaphragmModelField[i] = entry;
  	}
  	
  	public double[] getDiaphragmModelEntry(int i ) {
  		return this.diaphragmModelField[i];
  	}
  	
  	public void setProjTurningAngle(double p){
  		this.projTurningAngle = p;
  	}
  	public double getProjTurningAngle(){
  		return projTurningAngle;
  	}
  	public double getCorrectionFactor() {
  		return correctionFactor;
  	}
  	public void setCorrectionFactor(double correctionFactor) {
  		this.correctionFactor = correctionFactor;
  	}
  	public int getMaxIter() {
  		return maxIter;
  	}
  	public void setMaxIter(int maxIter) {
  		this.maxIter = maxIter;
  	}
  	public float getLowHyst() {
  		return lowHyst;
  	}
  	public void setLowHyst(float lowHyst) {
  		this.lowHyst = lowHyst;
  	}
  	public float getHighHyst() {
  		return highHyst;
  	}
  	public void setHighHyst(float highHyst) {
  		this.highHyst = highHyst;
  	}
  	public int getSeedX() {
  		return seedX;
  	}
  	public void setSeedX(int seedX) {
  		this.seedX = seedX;
  	}
  	public int getSeedY() {
  		return seedY;
  	}
  	public void setSeedY(int seedY) {
  		this.seedY = seedY;
  	}
  	public int getRoiWidthHalf() {
  		return roiWidthHalf;
  	}
  	public void setRoiWidthHalf(int roiWidthHalf) {
  		this.roiWidthHalf = roiWidthHalf;
  	}
  	public int getRoiHeightTop() {
  		return roiHeightTop;
  	}
  	public void setRoiHeightTop(int roiHeightTop) {
  		this.roiHeightTop = roiHeightTop;
  	}
  	public int getRoiHeightBottom() {
  		return roiHeightBottom;
  	}
  	public void setRoiHeightBottom(int roiHeightBottom) {
  		this.roiHeightBottom = roiHeightBottom;
  	}
  	public void setRespiratoryMotionField(double[] field) {
  		respiratoryMotionField = field;
  	}
  	public void setRespiratoryMotionFieldEntry(int entry, double value) {
  		respiratoryMotionField[entry] = value;
  	}
  	public double getRespiratoryMotionFieldEntry(int entry) {
  		return respiratoryMotionField[entry];
  	}
  	public double[] getRespiratoryMotionField() {
  		return respiratoryMotionField;
  	}
  	
  	public void setDiaphragmPositionField(double[] field) {
  		diaphragmPositionField = field;
  	}
  	public double[] getDiaphragmPositionField() {
  		return diaphragmPositionField;
  	}
  	public double getDiaphragmPositionFieldEntry(int i) {
  		return diaphragmPositionField[i];
  	}
  	
  	public void setDiaphragmCoords(double[][] field) {
  		this.diaphragmCoords = field;
  	}
  	public double[][] getDiaphragmCoords() {
  		return this.diaphragmCoords;
  	}
  	public double[] getDiaphragmCoordsEntry(int entry) {
  		return this.diaphragmCoords[entry];
  	}
  	public void setDiaphragmCoordsEntry(int entry, double[] values) {
  		this.diaphragmCoords[entry] = values;
  	}
  	public void setMaxMotion(double m){
  		this.maxMotion=m;
  	}
  	public double getMaxMotion(){
  		return maxMotion;
  	}
  	
  	/**
  	 * @return the registry
  	 */
  	public HashMap<String, String> getRegistry() {
  		return registry;
  	}
  
  	/**
  	 * @param registry the registry to set
  	 */
  	public void setRegistry(HashMap<String, String> registry) {
  		this.registry = registry;
  	}
  
  	public static void saveConfiguration(){
  		String filename = System.getProperty("user.home") + "/Conrad.xml";
  		saveConfiguration(getGlobalConfiguration(), filename);
  		setGlobalConfiguration(null);
  		loadConfiguration();
  	}
  
  	public static void saveConfiguration(Configuration config, String filename){
  		try {
  			Thread.currentThread().setContextClassLoader(Configuration.class.getClassLoader());
  			XMLEncoder oos = new XMLEncoder (new FileOutputStream(filename));
  			config.prepareForSerialization();
  			oos.writeObject(config);
  			oos.close();
  		} catch (FileNotFoundException e) {
  			e.printStackTrace();
  		} 
  	}
  
  	public static void loadConfiguration(){
  		if (getGlobalConfiguration() == null){
  			String filename = System.getProperty("user.home") + "/Conrad.xml";
  			Configuration config = loadConfiguration(filename);
  			if (config !=null) {
  				setGlobalConfiguration(config);
  			}
  		}
  	}
  
  	public static Configuration loadConfiguration(String filename){
  		try {
  			Thread.currentThread().setContextClassLoader(Configuration.class.getClassLoader());
  			ExceptionListener el = new ExceptionListener() {
  				public void exceptionThrown(Exception e) {
  					e.printStackTrace();
  				};
  			};
  			XMLDecoder ois = new XMLDecoder (new FileInputStream(filename), null, el);		
  			Configuration config = (Configuration) ois.readObject();
  			ois.close();
  			return config;
  		} catch (FileNotFoundException e) {
  			e.printStackTrace();
  			System.out.println("No Conrad.xml found. Creating default config.");
  			int revan = JOptionPane.showConfirmDialog(null, "No config file found. Create default config?");
  			if (revan == JOptionPane.YES_OPTION) initConfig();
  		} catch (ClassCastException e) {
  			e.printStackTrace();
  			System.out.println("Previous Conrad.xml invalid rewrite forced. Creating default config.");
  			int revan = JOptionPane.showConfirmDialog(null, "Could not read config file. Overwrite with default config?");
  			if (revan == JOptionPane.YES_OPTION) initConfig();
  		} catch (NoSuchElementException e) {
  			e.printStackTrace();
  			System.out.println("Previous Conrad.xml invalid rewrite forced. Creating default config.");
  			int revan = JOptionPane.showConfirmDialog(null, "Could not read config file. Overwrite with default config?");
  			if (revan == JOptionPane.YES_OPTION) initConfig();
  		}
  		return null;
  	}
  
  	public static Configuration getGlobalConfiguration(){
  		return globalConfiguration;
  	}
  
  	public static void setGlobalConfiguration(Configuration config){
  		globalConfiguration = config;
  	}
  
  	public String getVolumeOfInterestFileName() {
  		return volumeOfInterestFileName;
  	}
  	public void setVolumeOfInterestFileName(String volumeOfInterestFileName) {
  		this.volumeOfInterestFileName = volumeOfInterestFileName;
  	}
  	public String getProjectionTableFileName() {
  		return projectionTableFileName;
  	}
  	public void setProjectionTableFileName(String projectionTableFileName) {
  		this.projectionTableFileName = projectionTableFileName;
  	}
  
  	public void setCutOffFrequency(double cutOffFrequency) {
  		this.cutOffFrequency = cutOffFrequency;
  	}
  	public double getCutOffFrequency() {
  		return cutOffFrequency;
  	}
  
  	public void setAutomaticExposureControlConfigFile(
  			String automaticExposureControlConfigFile) {
  		AutomaticExposureControlConfigFile = automaticExposureControlConfigFile;
  	}
  
  	public String getAutomaticExposureControlConfigFile() {
  		return AutomaticExposureControlConfigFile;
  	}
  
  	public void setCurrentRowWeights(String currentRowWeights) {
  		this.currentRowWeights = currentRowWeights;
  	}
  
  	public String getCurrentRowWeights() {
  		return currentRowWeights;
  	}
  
  	public void setDeviceSerialNumber(String deviceSerialNumber) {
  		this.deviceSerialNumber = deviceSerialNumber;
  	}
  
  	public String getDeviceSerialNumber() {
  		return deviceSerialNumber;
  	}
  
  	/**
  	 * returns the voltage in [kV]
  	 * @return the voltage
  	 */
  	public double[] getVoltage() {
  		return voltage;
  	}
  
  	public void setVoltage(double[] voltage) {
  		this.voltage = voltage;
  	}
  
  	/**
  	 * Returns the current in [mA]
  	 * @return the current
  	 */
  	public double[] getCurrent() {
  		return current;
  	}
  
  	public void setCurrent(double[] current) {
  		this.current = current;
  	}
  
  	/**
  	 * Returns exposure time in [s]
  	 * @return the exposure time
  	 */
  	public double[] getTime() {
  		return time;
  	}
  
  	/**
  	 * Sets the exposure time in [s]
  	 * @param time
  	 */
  	public void setTime(double[] time) {
  		this.time = time;
  	}
  
  	public void setRealtime(double [] realtime) {
  		this.realtime = realtime;
  	}
  
  	public double [] getRealtime() {
  		return realtime;
  	}
  
  	public void setElectroCardioGramm(double [] electroCardioGramm) {
  		this.electroCardioGramm = electroCardioGramm;
  	}
  
  	public double [] getElectroCardioGramm() {
  		return electroCardioGramm;
  	}
  
  	public double getdCU() {
  		return dCU;
  	}
  
  	public void setdCU(double dCU) {
  		this.dCU = dCU;
  	}
  
  	public double getDose() {
  		return dose;
  	}
  
  	public void setDose(double dose) {
  		this.dose = dose;
  	}
  
  	public void setIntensifierSize(int intensifierSize) {
  		this.intensifierSize = intensifierSize;
  	}
  
  	public int getIntensifierSize() {
  		return intensifierSize;
  	}
  
  	public void setCurrentPath(String currentPath) {
  		this.currentPath = currentPath;
  	}
  
  	public String getCurrentPath() {
  		return currentPath;
  	}
  
  	public void setRecentFileOne(String recentFileOne) {
  		this.recentFileOne = recentFileOne;
  	}
  
  	public String getRecentFileOne() {
  		return recentFileOne;
  	}
  
  	public void setRecentFileTwo(String recentFileTwo) {
  		this.recentFileTwo = recentFileTwo;
  	}
  
  	public String getRecentFileTwo() {
  		return recentFileTwo;
  	}
  
  	public void setFilterPipeline(ImageFilteringTool [] pipline) {
  		this.filterPipeline = pipline;
  	}
  
  	public ImageFilteringTool [] getFilterPipeline() {
  		return filterPipeline;
  	}
  
  	public void setSink(BufferedProjectionSink sink) {
  		this.sink = sink;
  	}
  
  	public BufferedProjectionSink getSink() {
  		return sink;
  	}
  	
  	public void setBeadPosition2D(double [][][] beadPosition2D) {
  		this.beadPosition2D = beadPosition2D;
  	}
  	
  	public void setBeadPosition2D(int i, int j, int k, double value) {
  		this.beadPosition2D[i][j][k] = value;
  	}
  	
  	public double [][][] getBeadPosition2D() {
  		return beadPosition2D;
  	}
  	
  	public void setBeadMeanPosition3D(double [][] beadMeanPosition3D) {
  		this.beadMeanPosition3D = beadMeanPosition3D;
  	}
  	
  	public double [][] getBeadMeanPosition3D() {
  		return beadMeanPosition3D;
  	}
  	
  	public boolean [] getfAccessed() {
  		return fAccessed;
  	}
  	
  	public static void initConfig(){
  		new ImageJ();
  		Configuration config = new Configuration();
  		config.geometry = new Trajectory();
  		config.detector = new SimpleMonochromaticDetector();
  		config.geometry.setDetectorUDirection(CameraAxisDirection.DETECTORMOTION_PLUS);
  		config.geometry.setDetectorVDirection(CameraAxisDirection.ROTATIONAXIS_PLUS);
  		config.geometry.setDetectorHeight(480);
  		config.geometry.setDetectorWidth(620);
  		config.geometry.setSourceToAxisDistance(600.0);
  		config.geometry.setSourceToDetectorDistance(1200.0);
  		config.geometry.setReconDimensions(256, 256, 256);
  		config.geometry.setPixelDimensionX(1);
  		config.geometry.setPixelDimensionY(1);
  		config.geometry.setVoxelSpacingX(1.0);
  		config.geometry.setVoxelSpacingY(1.0);
  		config.geometry.setVoxelSpacingZ(1.0);
  		config.geometry.setAverageAngularIncrement(1.0);
  		config.geometry.setProjectionStackSize(200);
  		config.registry = new HashMap<String, String>();
  		config.registry.put(RegKeys.PATH_TO_CALIBRATION, "C:\\calibration");
  		config.registry.put(RegKeys.PATH_TO_CONTROL, "C:\\control");
  		config.registry.put(RegKeys.MAX_THREADS, "8");
  		config.registry.put(RegKeys.XCAT_PATH, "E:\\phantom data\\numeric phantoms\\xcat\\NCAT2.0_PC");
  		ImageFilteringTool[] standardPipeline = new ImageFilteringTool[] {
  				new CosineWeightingTool(),
  				new ParkerWeightingTool(),
  				new RampFilteringTool(),
  				new VOIBasedReconstructionFilter()
  		};
  		config.setFilterPipeline(standardPipeline);
  //		config.setFilterPipeline(ImageFilteringTool.getFilterTools());
  		config.setCitationFormat(MEDLINE_CITATION_FORMAT);
  		config.setSink(new ImagePlusDataSink());
  		
  		int numProjectionMatrices = config.getGeometry().getProjectionStackSize();
  		double sourceToAxisDistance = config.getGeometry().getSourceToAxisDistance();
  		double averageAngularIncrement = config.getGeometry().getAverageAngularIncrement();
  		double detectorOffsetU = config.getGeometry().getDetectorOffsetU();
  		double detectorOffsetV = config.getGeometry().getDetectorOffsetV();
  		CameraAxisDirection uDirection = config.getGeometry().getDetectorUDirection();
  		CameraAxisDirection vDirection = config.getGeometry().getDetectorVDirection();
  		SimpleVector rotationAxis = new SimpleVector(0, 0, 1);
  		Trajectory geom = new CircularTrajectory(config.getGeometry());
  		geom.setSecondaryAngleArray(null);
  		((CircularTrajectory)geom).setTrajectory(numProjectionMatrices, sourceToAxisDistance, averageAngularIncrement, detectorOffsetU, detectorOffsetV, uDirection, vDirection, rotationAxis);
  		if (geom != null){
  			config.setGeometry(geom);
  		}
  		setGlobalConfiguration(config);
  		saveConfiguration();
  	}
  
  	public static Trajectory loadGeometrySource(Configuration config) throws Exception{
  		Trajectory loaded = null;
  		if (config.getProjectionTableFileName() != null){
  			loaded = ConfigFileBasedTrajectory.openAsGeometrySource(config.getProjectionTableFileName(), config.getGeometry());
  		} else {
  			if (config.getGeometry().getAverageAngularIncrement() != -1){
  				// Binning is determined by the detector size in pixels
  				String binning = "4x4";
  				if (config.getGeometry().getDetectorWidth() == 1240) {
  					binning = "2x2";
  				}
  				if (config.getGeometry().getDetectorWidth() == 960) {
  					binning = "2x2";
  				}
  				
  				String filename = "";
  				if (config.getDeviceSerialNumber().equals("55242"))	// IR1
  					filename = config.registry.get(RegKeys.PATH_TO_CALIBRATION) + "/" + config.getDeviceSerialNumber() + "/active/g_Left_"+ config.getIntensifierSize() + "_" + getStandardNumberFormat().format(config.geometry.getAverageAngularIncrement()) + "0_" + binning +"/projtable.txt";
  				else 				
  					filename = config.registry.get(RegKeys.PATH_TO_CALIBRATION) + "/" + config.getDeviceSerialNumber() + "/active/-903" + "/g/" + config.getIntensifierSize() + "/" + getStandardNumberFormat().format(config.geometry.getAverageAngularIncrement()) + "/projtable.txt";
  				loaded = ConfigFileBasedTrajectory.openAsGeometrySource(filename, config.getGeometry());
  			} 
  		}
  		if ((config.geometry != null)&&(config.getUseExtrapolatedGeometry())) {
  			ExtrapolatedTrajectory extra = new ExtrapolatedTrajectory(loaded);
  			extra.extrapolateProjectionGeometry();
  			loaded = (Trajectory) extra;
  		}
  		if ((config.geometry != null)&&(config.getNumSweeps() > 1)) {
  			MultiSweepTrajectory extra = new MultiSweepTrajectory(loaded);
  			extra.extrapolateProjectionGeometry();
  			loaded = (Trajectory) extra;
  		}
  		if (loaded != null){
  			System.out.println("Found projection geometry with " + loaded.getNumProjectionMatrices() + " projections.");
  		} else {
  			System.out.println("No geometry loaded.");
  		}
  		return loaded;
  	}
  
  	public static NumberFormat getStandardNumberFormat(){
  		NumberFormat nf = NumberFormat.getInstance(Locale.US);
  		nf.setMaximumFractionDigits(1);
  		nf.setMinimumFractionDigits(1);
  		nf.setMaximumIntegerDigits(1);
  		nf.setMinimumIntegerDigits(1);
  		return nf;
  	}
  
  	public void setCitationFormat(int citationFormat) {
  		this.citationFormat = citationFormat;
  	}
  
  	public int getCitationFormat() {
  		return citationFormat;
  	}
  
  	public void setImportFromDicomAutomatically(boolean importFromDicomAutomatically) {
  		this.importFromDicomAutomatically = importFromDicomAutomatically;
  	}
  
  	public boolean getImportFromDicomAutomatically() {
  		return importFromDicomAutomatically;
  	}
  
  
  	public void setUseExtrapolatedGeometry(boolean useExtrapolatedGeometry) {
  		this.useExtrapolatedGeometry = useExtrapolatedGeometry;
  	}
  
  
  	public boolean getUseExtrapolatedGeometry() {
  		return useExtrapolatedGeometry;
  	}
  
  
  	public void setUseHounsfieldScaling(boolean useHounsfieldScaling) {
  		this.useHounsfieldScaling = useHounsfieldScaling;
  	}
  
  
  	public boolean getUseHounsfieldScaling() {
  		return useHounsfieldScaling;
  	}
  
  
  	public void setHounsfieldScaling(Function hounsfieldScaling) {
  		this.hounsfieldScaling = hounsfieldScaling;
  	}
  
  	public Function getHounsfieldScaling(){
  		return hounsfieldScaling;
  	}
  
  	public void setHeartPhases(double [] heartPhases) {
  		this.heartPhases = heartPhases;
  	}
  
  	public double [] getHeartPhases() {
  		return heartPhases;
  	}
  
  	public void setNumSweeps(int numSweeps) {
  		this.numSweeps = numSweeps;
  	}
  
  	public int getNumSweeps() {
  		return numSweeps;
  	}
  
  	public Trajectory getGeometry() {
  		if (geometry == null){
  			geometry = new Trajectory();
  		}
  		return geometry;
  	}
  
  	public void setGeometry(Trajectory geometry) {
  		this.geometry = geometry;
  	}
  
  	/**
  	 * @param beamHardeningLookupTable the beamHardeningLookupTable to set
  	 */
  	public void setBeamHardeningLookupTable(BilinearInterpolatingDoubleArray beamHardeningLookupTable) {
  		this.beamHardeningLookupTable = beamHardeningLookupTable;
  	}
  
  	/**
  	 * @return the beamHardeningLookupTable
  	 */
  	public BilinearInterpolatingDoubleArray getBeamHardeningLookupTable() {
  		return beamHardeningLookupTable;
  	}
  
  	public void setRegistryEntry(String key, String value){
  		registry.put(key, value);
  	}
  
  	/**
  	 * Reads a key from the registry. If the key is not set, the default value will be returned.
  	 * @param key
  	 * @return the value in the registry
  	 */
  	public String getRegistryEntry(String key){
  		String valueString = registry.get(key);
  		if (valueString==null){
  			valueString = RegKeys.defaultValues.get(key);
  		}
  		return valueString;
  	}
  
  	public Set<String> getRegistryKeys(){
  		if (registry == null){
  			resetRegistry();
  		}
  		return registry.keySet();
  	}
  	
  	public void resetRegistry(){
  		registry = new HashMap<String, String>();
  	}
  
  	public void prepareForSerialization() {
  		if (getSink() != null) getSink().prepareForSerialization();
  		if (getGeometry() != null) getGeometry().prepareForSerialization();
  		ImageFilteringTool [] pipeline = getFilterPipeline();
  		for (ImageFilteringTool tool : pipeline){
  			tool.prepareForSerialization();
  		}
  	}
  
  	/**
  	 * Convenience method to access the registry:<BR>
  	 * Reads a key form the registry and converts it to int.
  	 * A RuntimeException will be thrown, if the number cannot be parsed.
  	 * @param key
  	 * @return the int value. 
  	 */
  	public int queryIntFromRegistry(String key) {
  		String value = getRegistryEntry(key);
  		return Integer.parseInt(value);
  	}
  	
  		//Geometry of crosscalibration phantom
  	private double[] originKinect;
  	private double[] originKinect2;
  	private SimpleMatrix rotationKinectToZeego; //rotation matrix, [0]-[2]=first column, etc.
  	private SimpleMatrix rotationKinectToZeego2; //rotation matrix, [0]-[2]=first column, etc.
  	private double[] translationKinectToZeego;
  	private SimpleVector[][] clickedCentersXYZ = new SimpleVector[3][6];
  	private SimpleVector[][] clickedCentersXYZ2 = new SimpleVector[3][6];
  	private String pathDepthImageCalibration;
  	private String pathDepthImageCalibration2;
  	private String pathDepthImagePhantom;
  	private String pathDepthImagePhantom2;
  	private XRayDetector detector;
  	
  	public double[] getOriginKinect() {
  		return originKinect;
  	}
  	
  	public void setOriginKinect(double[] originKinect) {
  		this.originKinect = originKinect;
  	}
  	
  	public SimpleMatrix getRotationKinectToZeego() {
  		return rotationKinectToZeego;
  	}
  	
  	public void setRotationKinectToZeego(SimpleMatrix rotationKinectToZeego) {
  		this.rotationKinectToZeego = rotationKinectToZeego;
  	}
  	
  	public double[] getTranslationKinectToZeego() {
  		return translationKinectToZeego;
  	}
  	
  	public void setTranslationKinectToZeego(double[] translationKinectToZeego) {
  		this.translationKinectToZeego = translationKinectToZeego;
  	}
  	
  	public String getPathDepthImageCalibration() {
  		return pathDepthImageCalibration;
  	}
  	
  	public void setPathDepthImageCalibration(String pathDepthImage) {
  		this.pathDepthImageCalibration = pathDepthImage;
  	}
  	public String getPathDepthImagePhantom() {
  		return pathDepthImagePhantom;
  	}
  	public void setPathDepthImagePhantom(String pathDepthImagePhantom) {
  		this.pathDepthImagePhantom = pathDepthImagePhantom;
  	}
  	public SimpleVector[][] getClickedCentersXYZ() {
  		return clickedCentersXYZ;
  	}
  	public void setClickedCentersXYZ(SimpleVector[][] clickedCentersXYZ) {
  		this.clickedCentersXYZ = clickedCentersXYZ;
  	}
  	public SimpleMatrix getRotationKinectToZeego2() {
  		return rotationKinectToZeego2;
  	}
  	public void setRotationKinectToZeego2(SimpleMatrix rotationKinectToZeego2) {
  		this.rotationKinectToZeego2 = rotationKinectToZeego2;
  	}
  	public SimpleVector[][] getClickedCentersXYZ2() {
  		return clickedCentersXYZ2;
  	}
  	public void setClickedCentersXYZ2(SimpleVector[][] clickedCentersXYZ2) {
  		this.clickedCentersXYZ2 = clickedCentersXYZ2;
  	}
  	public String getPathDepthImageCalibration2() {
  		return pathDepthImageCalibration2;
  	}
  	public void setPathDepthImageCalibration2(String pathDepthImageCalibration2) {
  		this.pathDepthImageCalibration2 = pathDepthImageCalibration2;
  	}
  	public String getPathDepthImagePhantom2() {
  		return pathDepthImagePhantom2;
  	}
  	public void setPathDepthImagePhantom2(String pathDepthImagePhantom2) {
  		this.pathDepthImagePhantom2 = pathDepthImagePhantom2;
  	}
  	public double[] getOriginKinect2() {
  		return originKinect2;
  	}
  	public void setOriginKinect2(double[] originKinect2) {
  		this.originKinect2 = originKinect2;
  	}
  
  	public XRayDetector getDetector() {
  		return detector;
  	}
  	
  	public void setDetector(XRayDetector detector){
  		this.detector = detector;	
  	}
  
  }
  /*
   * Copyright (C) 2010-2014  Andreas Maier
   * CONRAD is developed as an Open Source project under the GNU General Public License (GPL).
  */