
/**
 * StreakCameraFileReader.java
 * This class reads in information from a streak camera format file.
 * The software
 *
 * Created:  Jan 22, 2004
 *
 * @author Nathan Stevens
 * @version 0.3 4/26/05
 */
import java.io.*;
import java.util.Vector;

public class StreakCameraFileReader extends Thread {
  private final String DELIM = "\t";
  private ExperimentPanel epanel = null;
  private TextInputFile inputFile = null;
  private Vector textlines = null;
  private Vector vdata = null;
  private File[] files = null;
  private int xsize = 0;
  private int ysize = 0;
  private String time_scale = "ps";
  
  // the main constructor
  public StreakCameraFileReader(ExperimentPanel epanel, File[] files) {
    super("Streak Camera File Reader");
    this.epanel = epanel;
    this.files = files;
  }
  
  // The run method to read in the file
  public void run() {
    vdata = new Vector();
    SpectraData sd;
    
    for(int i = 0; i < files.length; i += 2) {
      sd = importDataFile(files[i], files[i+1]);
      if(sd != null) {
        vdata.addElement(sd);
      }
      else {
        epanel.print("Error Reading Data File " + files[i].getName() + ".\n");
        epanel.print("It Does not appear to be a Streak Camera file...\n\n");
      }
    }
    
    SpectraData[] sdata = SpectraDataUtil.getSpectraDataArray(vdata);
    
    // add generated spectra data streak camera panel now
    if(sdata != null) {
      epanel.addSpectraData(sdata);
    }
  }
  
  // Method to read in a file and return an SpectraData object
  private SpectraData importDataFile(File file, File dfile) { 
    textlines = new Vector();
    inputFile = new TextInputFile(file);
    SpectraData sd;
    String[] sa;
    String line;
    xsize = 0;
    ysize = 0;
    int size = 0;
    int exp = 0;
    int nexp = 0;
    float laser = 0.0f;
    float[][] xydata;
    
    // check to see if this is the right format
    line = inputFile.readLine();
    if(line.indexOf("STREAK") == -1) {
      return null;
    }
    
    // read in the header info
    try {
      sa = inputFile.readLine().split(DELIM);
      xsize = Integer.parseInt(sa[0]);
      ysize =  Integer.parseInt(sa[1]);
      
      laser = Float.parseFloat(inputFile.readLine());
      
      sa = inputFile.readLine().split(DELIM);
      exp = Integer.parseInt(sa[0]);
      nexp =  Integer.parseInt(sa[1]);
    }
    catch(NumberFormatException nfe) {
      return null;
    }
    
    // now reading the data
    while(!inputFile.eof()) {
      line = inputFile.readLine();
      if(line.length() > 5) {
        textlines.addElement(line);
      }
    }
    inputFile.close();
    
    // set the size of the xydata array
    xydata = new float[ysize + 1][xsize + 1];
    xydata[0][0] = -1.0f;
    
    // add the xy labels
    if(textlines.size() != 0) {
      addXYLabels(xydata, textlines);
    }
    else {
      return null;
    }
    
    // reset the textlines and add the data to the array
    inputFile = new TextInputFile(dfile);
    textlines = new Vector();
    
    // now reading the data
    while(!inputFile.eof()) {
      line = inputFile.readLine();
      textlines.addElement(line);
    }
    inputFile.close();
    
    if(textlines.size() != 0) {
      // add the data array now
      addXYData(xydata, textlines);
    }
    else {
      return null;
    }
    
    // Initialize the meta information now
    String dmeta[] = new String[8];
    dmeta[0] = InstruView.getProperty("organization");
    dmeta[1] = InstruView.getProperty("laboratory");
    dmeta[2] = InstruView.getProperty("owner");
    dmeta[3] = InstruView.getProperty("email");
    dmeta[4] = InstruView.getProperty("instrument.streak");
    dmeta[5] = "mm-dd-yyyy";
    dmeta[6] = "00";
    
    // now create a SpectraDataObject
    String name = getName(file);
    String minwl = "" + xydata[0][1];
    String maxwl = "" + xydata[0][xydata[0].length-1];
    String mint = "" + xydata[1][0];
    String maxt = "" + xydata[xydata.length-1][0];
    String slaser = "" + laser;
    String dps = "" + (xsize*ysize);
    String sexp = "" + exp;
    String snexp = "" + nexp;
    
    String[] header = {minwl, maxwl, mint, maxt, dps, slaser, sexp, snexp, 
                                    "Unknown", "None", time_scale};
    sd = new SpectraData(name, "streak", header, dmeta, xydata, null);
    sd.set3D(true);
    
    // return the data object
    return sd;
  }
  
  // Method to add the x and y labels to the data array
  private void addXYLabels(float[][] xydata, Vector textlines) {
    Object[] lines = textlines.toArray();
    String[] sa;
    String line;
    float wl = 0f;
    float time = 0f;
    
    // add the wavelengths value
    for(int i = 0; i < (xydata[0].length-1); i++) {
      line = (String)lines[i];
      sa = line.split(DELIM);
      try {
        wl = Float.parseFloat(sa[0]);
        time = Float.parseFloat(sa[1]);
      }
      catch (NumberFormatException nfe) { }
      
      xydata[0][i+1] = wl;
      
      if(i < ysize) { // stop reading time values if we are greater than the ysize
        xydata[i+1][0] = time;
      }
    }
    
    
    // see whether to devide the time values to shift the scale to nanoseconds
    time = xydata[xydata.length -1][0]; // set the biggest time now
    
    if(time >= 10000000.0f) { //rescale to microsecond time scale
      divideTimeScale(xydata, 100000.0f);
      time_scale = "us";
    }
    else if(time >= 100000.0f) { // rescale to nanosecond time scale
      divideTimeScale(xydata, 1000.0f);
      time_scale = "ns";
    }
  }
  
  // method to devide the time values by a certain number
  private void divideTimeScale(float[][] xydata, float div_factor) {
    for(int i = 1; i < xydata.length; i++) {
      xydata[i][0] /= div_factor;
    }
  }
  
  // Method to add the data to the xydata file
  private void addXYData(float[][] xydata, Vector textlines) {
    Object[] lines = textlines.toArray();
    String[] sa;
    String line;
    float value = 0f;
    
    for(int i = 0; i < (xydata.length-1); i++) {
      line = (String)lines[i];
      sa = line.split(DELIM);
      for(int j = 0; j < sa.length; j++) {
        try {
          value = Float.parseFloat(sa[j]);
        }
        catch (NumberFormatException nfe) { }
        
        xydata[i+1][j+1] = value;
      }
    }
  }
  
  // return the name of the data object
  private String getName(File file) {
    String fn = file.getName();
    int end = fn.lastIndexOf('_');
    String name = fn.substring(0, end);
    
    return name;
  }
}  //--end class StreakCameraFileReader
