content: /*
   * 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;
  	}
  	
  }
  