/* * Copyright (C) 2010-2014 Andreas Maier * CONRAD is developed as an Open Source project under the GNU General Public License (GPL). */ package edu.stanford.rsl.conrad.io; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import edu.stanford.rsl.conrad.utils.Configuration; /** * Class to read and write VTK vector fields. Geometry information is taken from global Configuration. * @author akmaier */ public abstract class VTKVectorField { /** * Writes a 3D/3D vector field that is stored as a float[] into the file denoted by filename * @param filename the filename * @param motionfield the vector field * @throws IOException happens if file cannot be read. */ public static void writeToFile3D(String filename, float [] motionfield) throws IOException{ Configuration config = Configuration.getGlobalConfiguration(); FileOutputStream fos = new FileOutputStream(filename); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos)); //write header bw.write("# vtk DataFile Version 3.0\n"); bw.write("VTK File Generated by Insight Segmentation and Registration Toolkit (ITK)\n"); bw.write("BINARY\n"); bw.write("DATASET STRUCTURED_POINTS\n"); bw.write("DIMENSIONS " + config.getGeometry().getReconDimensionX() + " " + config.getGeometry().getReconDimensionY() + " " + config.getGeometry().getReconDimensionZ()+"\n"); bw.write("SPACING "+ config.getGeometry().getVoxelSpacingX() + " " +config.getGeometry().getVoxelSpacingY() + " "+ config.getGeometry().getVoxelSpacingZ() +"\n"); bw.write("ORIGIN "+ config.getGeometry().getOriginX() + " " + config.getGeometry().getOriginY() + " "+ config.getGeometry().getOriginZ() + "\n"); bw.write("POINT_DATA " + config.getGeometry().getReconDimensionX() * config.getGeometry().getReconDimensionY() * config.getGeometry().getReconDimensionZ() +"\n"); bw.write("VECTORS vectors float\n"); bw.flush(); // write vector field DataOutputStream doStream = new DataOutputStream(fos); for (int i = 0; i<motionfield.length; i++){ doStream.writeFloat(motionfield[i]); } doStream.flush(); doStream.close(); fos.close(); } /** * Reads a file and interprets it as a VTK vector field. Note that this reader has only limited capabilities in terms of formats and needs to be extended in the future. * At present only structured float vector data is available. The geometry information is not read, but mapped the the current geometry defined in the global Configuration. * @param filename the filename * @return the vector field as float [] * @throws IOException may occur during reading */ public static float [] readFromFile3D(String filename) throws IOException{ Configuration config = Configuration.getGlobalConfiguration(); FileInputStream fos = new FileInputStream(filename); BufferedReader bw = new BufferedReader(new InputStreamReader(fos)); // VTK header has variable size. Thus we need to compute the size of the reader while reading it. int read = 0; //read header read += bw.readLine().length()+1; //content: ("# vtk DataFile Version 3.0\n"); read += bw.readLine().length()+1; //content: ("VTK File Generated by Insight Segmentation and Registration Toolkit (ITK)\n"); String format = bw.readLine(); read += format.length()+1; //content: ("BINARY\n"); if (!format.toUpperCase().contains("BINARY")){ throw new RuntimeException("VTKVectorField.readFromFile3D can only read binary data!"); } format = bw.readLine(); read += format.length()+1; //content: ("DATASET STRUCTURED_POINTS\n"); if (!format.toUpperCase().contains("DATASET STRUCTURED_POINTS")){ throw new RuntimeException("VTKVectorField.readFromFile3D can only read structured point data!"); } format = bw.readLine(); read += format.length()+1; // content: ("DIMENSIONS " + config.getGeometry().getReconDimensionX() + " " + config.getGeometry().getReconDimensionY() + " " + config.getGeometry().getReconDimensionZ()+"\n"); if (!format.toUpperCase().contains("DIMENSIONS")){ throw new RuntimeException("VTKVectorField.readFromFile3D expects dimensions now!"); } format = bw.readLine(); read += format.length()+1; // content: ("SPACING "+ config.getGeometry().getVoxelSpacingX() + " " +config.getGeometry().getVoxelSpacingY() + " "+ config.getGeometry().getVoxelSpacingZ() +"\n"); if (!format.toUpperCase().contains("SPACING")){ throw new RuntimeException("VTKVectorField.readFromFile3D expects spacing now!"); } format = bw.readLine(); read += format.length()+1; // content: ("ORIGIN "+ config.getGeometry().getOriginX() + " " + config.getGeometry().getOriginY() + " "+ config.getGeometry().getOriginZ() + "\n"); if (!format.toUpperCase().contains("ORIGIN")){ throw new RuntimeException("VTKVectorField.readFromFile3D expects origin now!"); } format = bw.readLine(); read += format.length()+1; // content: ("POINT_DATA " + config.getGeometry().getReconDimensionX() * config.getGeometry().getReconDimensionY() * config.getGeometry().getReconDimensionZ() +"\n"); format = bw.readLine(); read += format.length()+1; // content: ("VECTORS vectors float\n") bw.close(); fos = new FileInputStream(filename); float [] vectorfield = new float[config.getGeometry().getReconDimensionX()*config.getGeometry().getReconDimensionY()*config.getGeometry().getReconDimensionZ()*3]; DataInputStream doStream = new DataInputStream(fos); // Skip header bytes... doStream.skipBytes(read); // Read vector field. for (int i = 0; i<vectorfield.length; i++){ vectorfield[i] = doStream.readFloat(); //System.out.println("data: " + i + " " + vectorfield[i]); } fos.close(); return vectorfield; } }