
/**
 * OOFileReader.java
 * This class reads in information from a oo spectrometer.
 * The software
 *
 * Created:  Jan 31, 2004
 *
 * @author Nathan Stevens
 * @version 0.2 12/17/04
 */
import java.io.*;
import java.util.*;

public class OOFileReader extends Thread {
  private final int SEQUENCE_FACTOR = 10000; // to get the correct negative delay
  private final String DELIM = "\t";
  private final String TEXT_DELIM = ": ";
  private ExperimentPanel epanel;
  private TextInputFile inputFile;
  private Vector textlines, vdata;
  private File[] files;
  private String type;
  private String delay = "0";
  
  // The main constructor
  public OOFileReader(ExperimentPanel epanel, File[] files, String type) {
    super("OO File Reader");
    this.epanel = epanel;
    this.files = files;
    this.type = type;
  }
  
  // The run method to read in the file
  public void run() {
    vdata = new Vector();
    SpectraData sd;
    
    for(int i = 0; i < files.length; i++) {
      if(type.equals("pump-probe") || type.equals("frgs")) {
        sd = importDataFile(files[i], files[i+1]);
        i++;
      }
      else {
        sd = importDataFile(files[i]);
      }
      
      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 OO data file...\n\n");
      }
    }
    
    SpectraData[] sdata = SpectraDataUtil.getSpectraDataArray(vdata);
    
    // add generate spectra data absorption panel now
    if(sdata != null) {
      epanel.addSpectraData(sdata);
    }
  }
  
  // Method to read in a file and return an SpectraData object
  private SpectraData importDataFile(File file) {
    String[] lines = getTextLines(file);
    if(lines == null) {
      return null;
    }
    
    String[] hd = getHeader(lines);
    float[][] xydata = getDataArray(lines);
    SpectraData sd;
    
    // 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.pump-probe");
    dmeta[5] = "mm-dd-yyyy";
    dmeta[6] = "00";
    
    // now create a SpectraDataObject
    String name = getName(file);
    String min = "" + xydata[0][0];
    String max = "" + xydata[xydata.length-1][0];
    String dps = "" + xydata.length;
    
    String[] header = {min, max, dps, "N/A", hd[0], hd[1], "N/A", "Unknown", "None"};
    sd = new SpectraData(name, type, header, dmeta, xydata, null);
    
    // return the data object
    return sd;
  }
  
  // get a spectra data with a reference data
  private SpectraData importDataFile(File file, File rfile) {
    String[] lines = getTextLines(file);
    String[] rlines = getTextLines(rfile);
    
    if(lines == null || rlines == null) {
      return null;
    }
    
    String[] hd = getHeader(lines);
    float[][] xydata  = getDataArray(lines);
    float[][] tmpxy = getDataArray(rlines);
    float[][] rxydata  = getNormalizedDataArray(xydata, tmpxy);
    SpectraData sd;
    
    // 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.pump-probe");
    dmeta[5] = "mm-dd-yyyy";
    dmeta[6] = "00";
    
    // now create a SpectraDataObject
    String name = getName(file);
    String min = "" + xydata[0][0];
    String max = "" + xydata[xydata.length-1][0];
    String dps = "" + xydata.length;
    
    String[] header = {min, max, dps, delay, hd[0], hd[1], "000.0", "Unknown", "None"};
    sd = new SpectraData(name, type, header, dmeta, xydata, rxydata);
    sd.setDelay(delay);
    
    // return the data object
    return sd;
  }
  
  // Method to get the header information
  private String[] getHeader(String[] lines) {
    String[] hd = new String[2];
    hd[0] = lines[5].split(TEXT_DELIM)[1];
    hd[1] = lines[6].split(TEXT_DELIM)[1];
    
    return hd;
  }
  
  // Method to return a float array containing the data
  private float[][] getDataArray(String[] lines) {
    String[] dlines = getDataLines(lines);
    float[][] xydata;
    String[] sa;
    String line;
    
    xydata = new float[dlines.length][2];
    float xvalue = 0f;
    float yvalue = 0f;
    
    for(int i = 0; i < xydata.length; i++) {
      line = dlines[i];
      sa = line.split(DELIM);
      try {
        xvalue = Float.parseFloat(sa[0]);
        yvalue = Float.parseFloat(sa[1]);
      }
      catch (NumberFormatException nfe) {
        xvalue = 0f;
        yvalue = 4.0f;
      }
      
      //shouldn't hava any zero so just set any thing zero or less to 4
      if(yvalue <= 0.0f) {
        yvalue = 4.0f;
      }
      
      xydata[i][0] = xvalue;
      xydata[i][1] = yvalue;
    }
    
    return xydata;
  }
  
  // Method to get the Normalized reference data. Basically the reference spectra is called
  // as to have the same value at ~850nm (array index 1956)
  private float[][] getNormalizedDataArray(float[][] xydata, float[][] tmpxy) {
    float[][] rxydata = new float[xydata.length][2];
    float nvalue = xydata[1956][1] - tmpxy[1956][1];
    
    for(int i = 0; i < rxydata.length; i++) {
      rxydata[i][0] = tmpxy[i][0];
      rxydata[i][1] = tmpxy[i][1] + nvalue;
    }
    
    return rxydata;
  }
  
  // Method to get Data lines from the text file
  private String[] getTextLines(File file) {
    String[] lines;
    textlines = new Vector();
    inputFile = new TextInputFile(file);
    
    // check to see if this is the correct format
    String line = inputFile.readLine();
    if(!line.startsWith("OOIBase32")) {
      return null;
    }
    
    // now reading the data
    while(!inputFile.eof()) {
      line = inputFile.readLine();
      textlines.addElement(line);
    }
    inputFile.close();
    
    // was this an emty file? is so return null
    if(textlines.size() < 10) {
      return null;
    }
    
    lines = new String[textlines.size()];
    
    // add the lines to the line array
    Enumeration theLines = textlines.elements();
    int i = 0;
    while(theLines.hasMoreElements()) {
      line = (String)theLines.nextElement();
      lines[i] = line;
      i++;
    }
    
    return lines;
  }
  
  // Method to get Data lines from the text file
  private String[] getDataLines(String[] lines) {
    String[] dlines;
    textlines = new Vector();
    String line;
    
    // now reading the data
    for(int i = 0; i < lines.length; i++) {
      line = lines[i];
      if(line.indexOf("\t") != -1) {
        textlines.addElement(line);
      }
    }
    
    dlines = new String[textlines.size()];
    
    // add the lines to the line array
    Enumeration theLines = textlines.elements();
    int i = 0;
    while(theLines.hasMoreElements()) {
      line = (String)theLines.nextElement();
      dlines[i] = line;
      i++;
    }
    
    return dlines;
  }
  
  // return the name of the data object
  private String getName(File file) {
    String name;
    String fn = file.getName();
    int end = fn.indexOf('.');
    name = fn.substring(0, end);
    
    if(type.equals("pump-probe")) {
      // see if this is file corresponds to a negative delay
      if(name.indexOf("--") != -1) {
        String[] sa = name.split("--", 2);
        int dn = SEQUENCE_FACTOR - getDelayNumber(sa[1]);
        
        name = sa[0];
        delay = "-"+ dn;
      }
      else {
        String[] sa = name.split("-", 2);
        int dn = getDelayNumber(sa[1]);
        
        name = sa[0];
        delay = ""+ dn;
      }
    }
    
    return name;
  }
  
  // Method to return and int value or zero
  private int getDelayNumber(String ds) {
    int dn = 0;
    try {
      dn = Integer.parseInt(ds);
    }
    catch(NumberFormatException nfe) { }
    
    return dn;
  }
} //--OOFileReader
