package edu.stanford.rsl.conrad.geometry.motion; import java.io.BufferedWriter; import java.io.File; import java.io.BufferedReader; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.Serializable; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Date; import java.util.StringTokenizer; import edu.stanford.rsl.conrad.numerics.SimpleMatrix; import edu.stanford.rsl.conrad.utils.CONRAD; import edu.stanford.rsl.conrad.utils.Configuration; import edu.stanford.rsl.conrad.utils.RegKeys; /** * File handling of beads marker txt file (INITIAL_BEADS_LOCATION_FILE in RegKeys). * This is used for the weight-bearing project * * @author Jang-Hwan Choi */ public class WeightBearingBeadPositionBuilder implements Serializable { /** * */ private static final long serialVersionUID = -4691626378724299348L; private static String beadInitialPositionFile; private static File fileMarkers; // column number for each item // private static int colNoProjectionNo, colNoBeadNo, colNoU, colNoV; Configuration config = Configuration.getGlobalConfiguration(); int noProjection = config.getGeometry().getProjectionStackSize(); public static int beadNo = 22; // total bead number attached on both knee public static int currentBeadNo = 7; //private static ArrayList<ArrayList<Double>> beads; private double [][][] beadsIn2D = new double [noProjection][beadNo][3]; // [projection #][bead #][u, v, state[0: initial, 1: registered, 2: detected by hough seraching]] private double [][] beadsMeanIn3D = new double [beadNo][3]; ; // [bead #][x, y, z] public WeightBearingBeadPositionBuilder(){ //beadsIn2D = readInitialBeadPositionFromFile(); } public static void main(String [] args) { CONRAD.setup(); WeightBearingBeadPositionBuilder beadBuilder = new WeightBearingBeadPositionBuilder(); beadBuilder.readInitialBeadPositionFromFile(); beadBuilder.estimateBeadMeanPositionIn3D(); //beadBuilder.writeBeadPositionToFile(); System.out.println("DONE"); } public void readInitialBeadPositionFromFile() { ArrayList<Double> myCurrentRow; try { beadInitialPositionFile = config.getRegistryEntry(RegKeys.INITIAL_BEADS_LOCATION_FILE); fileMarkers = new File(beadInitialPositionFile); // create BufferedReader to read txt file BufferedReader br = new BufferedReader(new FileReader(fileMarkers)); String strLine = ""; StringTokenizer st = null; int lineNumber = 0, tokenNumber = 0; String tokenName; //read tab separated file line by line while( (strLine = br.readLine()) != null) { //break tab separated line using " " st = new StringTokenizer(strLine, "\t"); myCurrentRow = new ArrayList<Double>(); while(st.hasMoreTokens()){ tokenName = st.nextToken().trim(); if (lineNumber > 1){ myCurrentRow.add(Double.valueOf(tokenName).doubleValue()); } //display txt values //System.out.println("Line # " + lineNumber + ", Token # " + tokenNumber + ", Token : " + tokenName); tokenNumber++; } // save except the first 2 title rows if(lineNumber > 1) { beadsIn2D[myCurrentRow.get(0).intValue()][myCurrentRow.get(1).intValue()][0] = myCurrentRow.get(2); beadsIn2D[myCurrentRow.get(0).intValue()][myCurrentRow.get(1).intValue()][1] = myCurrentRow.get(3); if (myCurrentRow.size() < 5) beadsIn2D[myCurrentRow.get(0).intValue()][myCurrentRow.get(1).intValue()][2] = 1; // state 1: registered by txt file else beadsIn2D[myCurrentRow.get(0).intValue()][myCurrentRow.get(1).intValue()][2] = myCurrentRow.get(4); // state 1: registered by txt file } lineNumber++; //reset token number tokenNumber = 0; } } catch(Exception e) { System.out.println("Exception while reading txt file: " + e); } } public void writeBeadPositionToFile() { try { fileCopy(); beadInitialPositionFile = config.getRegistryEntry(RegKeys.INITIAL_BEADS_LOCATION_FILE); BufferedWriter out = new BufferedWriter(new FileWriter(beadInitialPositionFile)); String strLine = DateFormat.getDateTimeInstance(DateFormat.LONG, DateFormat.LONG).format(new Date()) + "\n"; strLine += "P_NO\tBEAD_NO\tU\tV\tSTATE[0: initial, 1: registered, 2: detected by hough seraching]\n"; // [projection #][bead #][u, v, state[0: initial, 1: registered, 2: updated by hough seraching]] double [][][] beadPosition2D = config.getBeadPosition2D(); int projNo = config.getGeometry().getProjectionStackSize(); //for (int i=0; i< beadNo; i++){ for (int i=currentBeadNo; i>= 0; i--){ for (int j=0; j< projNo; j++) { //if (beadPosition2D[j][i][2]>0) { strLine += j + "\t" + i + "\t" + beadPosition2D[j][i][0] + "\t" + beadPosition2D[j][i][1] + "\t" + (int)beadPosition2D[j][i][2] + "\n"; //} } } out.write(strLine); out.close(); } catch(Exception e) { System.out.println("Exception while writing txt file: " + e); } } public void estimateBeadMeanPositionIn3D() { /* * Muv(u,v) = M * Mxyz */ Jama.Matrix Muv; // = new Jama.Matrix (3, 3); Jama.Matrix M; // = new Jama.Matrix (3, 1); Jama.Matrix Mxyz = new Jama.Matrix (3, 1); int beadNoRegistered; double u, v, state; SimpleMatrix mat; for (int i=0; i< beadNo; i++){ beadNoRegistered = 0; for (int j=0; j< noProjection; j++) { if (beadsIn2D[j][i][0]>0 && beadsIn2D[j][i][1]>0) { beadNoRegistered++; } } Muv = new Jama.Matrix (2*beadNoRegistered, 1); M = new Jama.Matrix (2*beadNoRegistered, 3); beadNoRegistered = 0; for (int j=0; j< noProjection; j++) { mat = config.getGeometry().getProjectionMatrix(j).computeP(); u = beadsIn2D[j][i][0]; v = beadsIn2D[j][i][1]; state = beadsIn2D[j][i][2]; // if initial bead position in 2d is registered, (exclude beads detected by hough) if (state == 1) { beadNoRegistered++; M.set((beadNoRegistered-1)*2, 0, u*mat.getElement(2, 0)-mat.getElement(0, 0)); M.set((beadNoRegistered-1)*2, 1, u*mat.getElement(2, 1)-mat.getElement(0, 1)); M.set((beadNoRegistered-1)*2, 2, u*mat.getElement(2, 2)-mat.getElement(0, 2)); M.set((beadNoRegistered-1)*2+1, 0, v*mat.getElement(2, 0)-mat.getElement(1, 0)); M.set((beadNoRegistered-1)*2+1, 1, v*mat.getElement(2, 1)-mat.getElement(1, 1)); M.set((beadNoRegistered-1)*2+1, 2, v*mat.getElement(2, 2)-mat.getElement(1, 2)); Muv.set((beadNoRegistered-1)*2, 0, -u*mat.getElement(2, 3)+mat.getElement(0, 3)); Muv.set((beadNoRegistered-1)*2+1, 0, -v*mat.getElement(2, 3)+mat.getElement(1, 3)); } } if (beadNoRegistered > 3) { //Mxyz = M.inverse().times(Muv); Mxyz = M.solve(Muv); beadsMeanIn3D[i][0] = Mxyz.get(0, 0); beadsMeanIn3D[i][1] = Mxyz.get(1, 0); beadsMeanIn3D[i][2] = Mxyz.get(2, 0); //System.out.println("x,y,z="+Mxyz.get(0, 0)+","+Mxyz.get(1, 0)+","+Mxyz.get(2, 0)); } } config.setBeadMeanPosition3D(beadsMeanIn3D); config.setBeadPosition2D(beadsIn2D); } public double [][][] getBeadPositionIn2D() { return beadsIn2D; } public void fileCopy() throws IOException { SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd_HH-mm-ss"); // file backup File inputFile = new File(config.getRegistryEntry(RegKeys.INITIAL_BEADS_LOCATION_FILE)); File outputFile = new File(config.getRegistryEntry(RegKeys.INITIAL_BEADS_LOCATION_FILE) + "_" + format.format(new Date()) + ".txt"); FileReader in = new FileReader(inputFile); FileWriter out = new FileWriter(outputFile); int c; while ((c = in.read()) != -1) out.write(c); in.close(); out.close(); } } /* * Copyright (C) 2010-2014 Jang-Hwan Choi * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */