package edu.stanford.rsl.conrad.geometry.trajectories; //TODO: Use our own matrices instead of Jama.Matrix import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; import java.util.ArrayList; import edu.stanford.rsl.conrad.geometry.Projection; import edu.stanford.rsl.conrad.io.ConfigFileParser; import edu.stanford.rsl.conrad.numerics.SimpleMatrix; import edu.stanford.rsl.conrad.numerics.SimpleOperators; import edu.stanford.rsl.conrad.utils.Configuration; import edu.stanford.rsl.conrad.utils.ConfigurationUpdater; public class SystemGeometryConfigFileTrajectory extends ConfigFileBasedTrajectory implements ConfigurationUpdater, ConfigFileParser { private static final long serialVersionUID = 2773005628961913345L; private double [] volumeSize = null; private double [] volumeResolution = null; private double [] detectorResolution = null; private double [] detectorPixels = null; private double averageAngularIncrement = -1; private int numProjections = -1; private SimpleMatrix transformToNextProjection; private double SID = -1; private double SAD = -1; private boolean success = false; private Configuration config = null; public SystemGeometryConfigFileTrajectory(String filename, Trajectory model) throws IOException{ super(model); readProjectionMatrices(filename); } public SystemGeometryConfigFileTrajectory(Trajectory model) { super(model); } private double [] readDoubleArrayLine(String line){ String [] values = line.split("\\s+"); ArrayList<String> list = new ArrayList<String>(); for(int i = 0; i < values.length; i++){ if (! values[i].equals("")) list.add(values[i]); } double [] revan = new double[list.size()]; for(int i = 0; i < list.size(); i++){ revan[i] = Double.parseDouble(list.get(i)); } return revan; } private Projection newProjection (double [][] matrix){ return new Projection(new SimpleMatrix(matrix)); } private void readProjectionMatrices(String projectionConfig) throws IOException{ FileReader read = new FileReader(projectionConfig); BufferedReader bufferedReader = new BufferedReader(read); String line = ""; //skip first comment line; line = bufferedReader.readLine(); // readVolumeInformation volumeResolution = readDoubleArrayLine(bufferedReader.readLine()); volumeSize = readDoubleArrayLine(bufferedReader.readLine()); // Comment line line = bufferedReader.readLine(); // Detector info double [] detectorx = readDoubleArrayLine(bufferedReader.readLine()); double [] detectory = readDoubleArrayLine(bufferedReader.readLine()); detectorResolution = new double [2]; detectorResolution[0] = detectorx[0]; pixelDimensionX = detectorx[0]; detectorResolution[1] = detectory[1]; detectorPixels = readDoubleArrayLine(bufferedReader.readLine()); // Comment line line = bufferedReader.readLine(); //read number of matrices numProjectionMatrices = Integer.parseInt(bufferedReader.readLine()); projectionMatrices = new Projection[numProjectionMatrices]; int count = 0; while (count < numProjectionMatrices){ //read one matrix; double [][] projectionMatrix = readMatrix(bufferedReader, 4, 3); projectionMatrices[count++] = newProjection(projectionMatrix); } if (count != numProjectionMatrices){ throw new IOException("Number of Matrices in projection table file does not match the actual number in the file. Please check consistency."); } //read number of projections numProjections = Integer.parseInt(bufferedReader.readLine()); transformToNextProjection = new SimpleMatrix(readMatrix(bufferedReader, 4, 4)); if (numProjectionMatrices < numProjections){ Projection [] newMatrices = new Projection[numProjections]; newMatrices[0] = projectionMatrices[0]; for (int i = 1; i < numProjections; i++){ newMatrices[i] = new Projection(SimpleOperators.multiplyMatrixProd(newMatrices[i-1].computeP(), transformToNextProjection)); } projectionMatrices = newMatrices; numProjectionMatrices = numProjections; } double [] [] scaleProjectionCoordinates = new double [3][3]; scaleProjectionCoordinates[0][0] = 1.0 / detectorResolution[0]; scaleProjectionCoordinates[1][1] = 1.0 / detectorResolution[1]; scaleProjectionCoordinates[2][2] = 1.0; Jama.Matrix scale = new Jama.Matrix(scaleProjectionCoordinates); for (int i = 0; i < projectionMatrices.length; i++){ projectionMatrices[i] = new Projection(SimpleOperators.multiplyMatrixProd(projectionMatrices[i].computeP().transposed(), new SimpleMatrix(scale)).transposed()); } while ((line = bufferedReader.readLine()) != null){ String [] elements = line.split("\\s+"); if (line.contains("SID")){ String target = elements[3]; target = target.substring(0, target.length()-2); SID = Double.parseDouble(target); } if (line.contains("Rotation angle per view")){ String target = elements[6]; target = target.substring(0, target.length()); averageAngularIncrement = Double.parseDouble(target); } if (line.contains("SAD")){ String target = elements[3]; target = target.substring(0, target.length()-2); SAD = Double.parseDouble(target); } } if (averageAngularIncrement != -1){ primaryAngles = new double [projectionMatrices.length]; double current =0; for (int i = 0; i < primaryAngles.length; i++){ primaryAngles[i] = current; current += averageAngularIncrement; } System.out.println(current + " " + averageAngularIncrement); } success = true; bufferedReader.close(); } private double [][] readMatrix(BufferedReader bufferedReader, int width, int height) throws IOException{ double [][] projectionMatrix = new double[height][width]; for (int i =0; i<height;i++){ String line = bufferedReader.readLine(); projectionMatrix[i] = readDoubleArrayLine(line); } return projectionMatrix; } @Override public Configuration getConfiguration() { return config; } @Override public void readConfiguration() { super.setReconDimensions(volumeSize); super.setReconVoxelSizes(volumeResolution); super.setDetectorWidth((int) detectorPixels[0]); super.setDetectorHeight((int) detectorPixels[1]); super.setPixelDimensionX(detectorResolution[0]); super.setPixelDimensionY(detectorResolution[1]); super.setProjectionStackSize(numProjections); super.setSourceToAxisDistance(SAD); super.setSourceToDetectorDistance(SID); super.setPrimaryAngleArray(primaryAngles); super.setAverageAngularIncrement(averageAngularIncrement); config.setVolumeOfInterestFileName(null); //System.out.println("Projections " + super.getProjectionStackSize()); } @Override public void setConfiguration(Configuration config) { this.config = config; } @Override public void readConfigFile(String filename) throws IOException { readProjectionMatrices(filename); } @Override public boolean getSuccess() { return success; } } /* * Copyright (C) 2010-2014 Andreas Maier * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */