
/**
 * F900FileReader.java
 * This class reads in information from a F900 formated files.
 *
 * Created:  March 6, 2006
 *
 * @author Nathan Stevens
 * @version 0.1 5/2/06
 */
import java.io.*;
import java.util.Vector;

public class F900FileReader extends Thread {
  private final String DELIM = "\t"; // data dilimeter
  private ExperimentPanel epanel = null; // experiment panel
  private TextInputFile inputFile = null; // used to red in the input files
  private Vector vdata = null; // holds any SDL objects created from reading the data files
  private File[] files = null; // the files to read in
  private String time_scale = "ns";
  
  // the main constructor
  public F900FileReader(ExperimentPanel epanel, File[] files) {
    super("F900 File Reader");
    this.epanel = epanel;
    this.files = files;
    
    vdata = new Vector();
  }
  
  // The run method to read in the file
  public void run() {
    importData();
    
    SpectraData[] sda = SpectraDataUtil.getSpectraDataArray(vdata);
    
    // add generated spectra data  streak camera panel now
    if(sda != null) {
      epanel.addSpectraData(sda);
    }
  }
  
  // Method to import decay profile data
  private void importData() {
    for(int i = 0; i < files.length; i++) {
      readDataFile(files[i]);
    }
  }
  
  // Method to read in data
  private void readDataFile(File file) {
    inputFile = new TextInputFile(file);
    String line= null;
    String[] sa = null;
    String[] data_names = null;
    int sd_count = 0;
    boolean fit_data = false;
    
    // check to see if this file is the correct file type
    line = inputFile.readLine();
    sa = line.split(DELIM);
     
    if(line.indexOf("Labels") == -1) {
      epanel.print("Error Reading Data File " + file.getName() + ".\n");
      epanel.print("It Does not appear to be a F900 Decay Profile file...\n\n");
      return;
    }
    
    // now check to see if the file contains emission map data
    if(line.indexOf("nm") != -1 && sa.length > 5) {
      inputFile.close(); // close the file and call the read emission map file method
      readEmissionMapFile(file);
      return;
    }
    
    // see if to import a wavelength profile instead
    if(line.indexOf("Time") != -1) {
      inputFile.close();
      readWavelengthProfileFile(file);
      return;
    }
    
    // now figure out the number of data objects we have
    if(line.indexOf("F1") != -1 ||  line.indexOf("F2") != -1 || line.indexOf("F3") != -1 ||
    line.indexOf("F4") != -1) { // checks to see if there is fit data
      sd_count = sa.length - 2;
      fit_data = true;
    }
    else {
      sd_count = sa.length - 1;
    }
    
    // store the data names
    data_names = new String[sd_count];
    int max = sa.length;
    
    if(fit_data) {
      max -= 1;
    }
    
    for(int i = 1; i < max; i++) {
      data_names[i-1] = sa[i];
    }
    
    // now create the vectors that hold the text data
    Vector[] xyv = new Vector[sd_count];
    for(int i = 0; i < xyv.length; i++) {
      xyv[i] = new Vector();
    }
    
    // read in the xy data now
    while(!inputFile.eof()) {
      line = inputFile.readLine();
      
      if(line.length() > 5) { // make sure the line has data
        sa = line.split(DELIM);
        
        for(int i = 1; i < sa.length; i++) {
          if(fit_data && i == sa.length - 2) {
            if(sa[i].length() > 3) {// make sure there is data there
              String xys = new String(sa[0] + "\t" + sa[i] + "\t" + sa[i+1]);
              xyv[i-1].addElement(xys);
            }
            i++;
          }
          else {
            String xys = new String(sa[0] + "\t" + sa[i]);
            xyv[i-1].addElement(xys);
          }
        }
      }
    }
    inputFile.close();
    
    // create the spectra objects now
    SpectraData sd = null;
    float[][] xydata = null;
    float[][] rxydata = null;
    
    for(int i = 0; i < xyv.length; i++) {
      Object[] obja = xyv[i].toArray();
      
      try {
        if(fit_data && i == xyv.length -1) {
          xydata = new float[obja.length][2];
          rxydata = new float[obja.length][2];
          
          for(int j = 0; j < obja.length; j++) {
            String xys = (String)obja[j];
            sa = xys.split(DELIM);
            
            xydata[j][0] = Float.parseFloat(sa[0]);
            xydata[j][1] = Float.parseFloat(sa[1]);
            rxydata[j][0] = Float.parseFloat(sa[0]);
            rxydata[j][1] = Float.parseFloat(sa[2]);
          }
        }
        else {
          xydata = new float[obja.length][2];
          
          for(int j = 0; j < obja.length; j++) {
            String xys = (String)obja[j];
            sa = xys.split(DELIM);
            
            xydata[j][0] = Float.parseFloat(sa[0]);
            xydata[j][1] = Float.parseFloat(sa[1]);
          }
        }
        
        // see whether to scale the time scale up to us seconds
        float time = xydata[xydata.length -1][0]; 
        
        if(time >= 100000.0f) { // rescale to microsecond time scale
          divideTimeScale(xydata, 1000.0f);
          time_scale = "us";
        }
        else {
          time_scale = "ns";
        }
      }
      catch(NumberFormatException nfe) {
        System.err.println("Can't convert X or Y value in class F900FileReader...");
        return;
      }
      
      // get the name and the wavelength if it there
      String[] name_wl = getNameAndWavelength(file, data_names[i]);
      
      // 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] = "F900";
      dmeta[5] = "mm-dd-yyyy";
      dmeta[6] = "00";
      
      // now create a SpectraDataObject
      String name = name_wl[0];
      String minwl = name_wl[1];
      String maxwl = name_wl[1];
      String mint = "" + xydata[0][0];
      String maxt = "" + xydata[xydata.length-1][0];
      String slaser = "000";
      String dps = "" + xydata.length;
      String sexp = "N/A";
      String snexp = "N/A";
      
      String[] header = {minwl, maxwl, mint, maxt, dps, slaser, sexp, snexp, 
      "Unknown", "None", time_scale};
      
      sd = new SpectraData(name, "streak", header, dmeta, xydata, rxydata);
      sd.setProfileDirection(1);
      
      vdata.addElement(sd);
    }
  }
  
  // function to extract out wavelength data for a file name
  private String[] getNameAndWavelength(File file, String data_name) {
    String[] name_wl = new String[2];
    String name = getName(file);
    
    if(data_name.indexOf("=") != -1 && data_name.indexOf("nm") != -1) {
      int start = data_name.indexOf("=") + 1;
      int end = data_name.indexOf("nm");
      
      String wl = data_name.substring(start, end).trim();
      
      name_wl[0] = name + "_" + wl;
      name_wl[1] = wl;
    }
    else {
      name_wl[0] = data_name;
      name_wl[1] = "000";
    }
    
    return name_wl;
  }
  
  // Method to read in data
  private void readWavelengthProfileFile(File file) {
    inputFile = new TextInputFile(file);
    String line= null;
    String[] sa = null;
    
    // check to see if this file is the correct file type
    line = inputFile.readLine();
    
    // now figure out the number of data objects we have
    sa = line.split(DELIM);
    
    // create the array holding the time units. index zero will hold the spacing
    float[] delay = new float[sa.length];
    
    for(int i = 1; i < sa.length; i++) {
      int start = sa[i].indexOf("=") + 1;
      int end = sa[i].indexOf("ns");
      
      String ts = sa[i].substring(start, end).trim();
      
      try {
        delay[i] = Float.parseFloat(ts);
      }
      catch(NumberFormatException nfe) {
        System.err.println("Invalid time value in F900FileReader wavelengh profile.");
        return;
      }
    }
    
    delay[0] = delay[2] + delay[1]; // calculate the spacing between time values
    
    // now read in the lines of data and place into vector, then object array
    Vector textlines = new Vector();
    
    while(!inputFile.eof()) {
      line = inputFile.readLine();
      if(line.length() > 5) { // skip any empty lines
        textlines.addElement(line);
      }
    }
    inputFile.close();
    
    Object[] lines = textlines.toArray();
    
    // interate through the lines and create the spectra data objects
    String base_name = getName(file);
    for(int i = 1; i < delay.length; i++) {
      float[][] xydata = new float[lines.length][2];
      
      for(int j = 0; j < lines.length; j++) {
        line = (String)lines[j];
        sa = line.split(DELIM);
        
        try {
          xydata[j][0] = Float.parseFloat(sa[0]);
          xydata[j][1] = Float.parseFloat(sa[i]);
        }
        catch(NumberFormatException nfe) {
          System.err.println("Invalid intensity value in F900FileReader wavelengh profile.");
          return;
        }
      }
      
      // 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] = "F900";
      dmeta[5] = "mm-dd-yyyy";
      dmeta[6] = "00";
      
      // now create a SpectraDataObject
      String name = base_name + "_" + i;
      String minwl = "" + xydata[0][0];
      String maxwl = "" + xydata[xydata.length-1][0];
      String mint = "" + delay[i];
      String maxt = ""  + (delay[i] + delay[0]);
      String slaser = "000";
      String dps = "" + xydata.length;
      String sexp = "N/A";
      String snexp = "N/A";
      
      String[] header = {minwl, maxwl, mint, maxt, dps, slaser, sexp, snexp, 
      "Unknown", "None"};
      
      SpectraData sd = new SpectraData(name, "streak", header, dmeta, xydata, null);
      sd.setProfileDirection(0);
      
      vdata.addElement(sd);
    }
  }
  
  // Method to import emission map data
  private void readEmissionMapFile(File file) {
    inputFile = new TextInputFile(file);
    String line= null;
    String[] sa = null;
    
    // check to see if this file is the correct file type
    line = inputFile.readLine();
    
    // now figure out the number of data objects we have
    sa = line.split(DELIM);
    
    // create the array holding the wavelength units
    float[] wls = new float[sa.length];
    
    for(int i = 1; i < sa.length; i++) {
      int start = sa[i].indexOf("=") + 1;
      int end = sa[i].indexOf("nm");
      
      String ws = sa[i].substring(start, end).trim();
      
      try {
        wls[i] = Float.parseFloat(ws);
      }
      catch(NumberFormatException nfe) {
        System.err.println("Invalid time value in F900FileReader readEmissionMap.");
        return;
      }
    }
    
    // now read in the lines of data and place into vector, then object array
    Vector textlines = new Vector();
    
    while(!inputFile.eof()) {
      line = inputFile.readLine();
      if(line.length() > 5) { // skip any empty lines
        textlines.addElement(line);
      }
    }
    inputFile.close();
    
    Object[] lines = textlines.toArray();
    
    // create the data array and populate it
    float xydata[][] = new float[lines.length + 1][sa.length];
    
    for(int i = 0; i < xydata[0].length; i++) {
      xydata[0][i] = wls[i];
    }
    
    for(int i =1; i < xydata.length; i++) {
      line = (String)lines[i-1];
      sa = line.split(DELIM);
      for(int j = 0; j < sa.length; j++) {
        xydata[i][j] = Float.parseFloat(sa[j]);
      }
    }
    
    // see whether to scale the time scale up to us seconds
    float time = xydata[xydata.length -1][0]; 
    
    if(time >= 100000.0f) { // rescale to microsecond time scale
      divideTimeScale(xydata, 1000.0f);
      time_scale = "us";
    }
    else {
      time_scale = "ns";
    }
    
    // now // 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] = "F900";
    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 = "000";
    String dps = "" + (xydata.length*xydata[0].length);
    String sexp = "N/A";
    String snexp = "N/A";
    
    String[] header = {minwl, maxwl, mint, maxt, dps, slaser, sexp, snexp, 
    "Unknown", "None", time_scale};
    
    SpectraData sd = new SpectraData(name, "streak", header, dmeta, xydata, null);
    sd.set3D(true);
    
    vdata.addElement(sd);
  }
  
  // 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;
    }
  }
  
  // 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 F900FileReader
