
/**
 * AbsEmsFileReader.java
 * This class reads in information from tab or comma delimted text files.
 *
 * Created:  June 13, 2006
 *
 * @author Nathan Stevens
 * @version 0.11 4/28/07
 */
import java.io.*;
import java.util.Vector;

public class AbsEmsFileReader extends Thread {
  private String DELIM = "\t";
  private FRETViewPlugin plugin = null;
  private TextInputFile inputFile = null;
  private DonorAcceptorData dyeData = null;
  private File[] files = null;
  
  // Method to read in data
  public AbsEmsFileReader() { }
  
  // The main constructor
  public AbsEmsFileReader(FRETViewPlugin plugin, File[] files) {
    super("Invitrogen File Reader");
    this.plugin = plugin;
    this.files = files;
  }
  
  // The run method to read in the file
  public void run() {
    dyeData = plugin.dyeData;
    DyeSpectra ds;
    
    for(int i = 0; i < files.length; i += 2) {
      ds = importDataFile(files[i], files[i + 1]);
      if(ds != null) {
        dyeData.addDyeSpectra(ds);
      }
      else {
        plugin.print("Error reading data file " + files[i].getName());
        plugin.print("It does not appear to be a tab or coma delimited file...\n");
      }
    }
    
    // update the display now
    plugin.updateDisplay(true);
  }
  
  // Method to read in a file and return an SpectraData object
  private DyeSpectra importDataFile(File file1, File file2) {
    Vector abs_text = new Vector();
    Vector ems_text = new Vector();
    DyeSpectra ds = null;
    String line = null;
    float[][] abs_data = null;
    float[][] ems_data = null;
    String[] sa = null;
    
    // set some variable
    String name = getName(file1);
    String notes = "Abs/Ems data";
    float QY = 1.0f;
    float EC = 100.0f;
    float lifetime = 1.0f;
    
    // read in the absorption file, file1
    inputFile = new TextInputFile(file1);
    
    String regex = "\\d+.*[,\\s]+.*\\d+.*";
    int line_num = 0;
    while(!inputFile.eof()) {
      line = inputFile.readLine();
      if(line.matches(regex)) {
        abs_text.addElement(line);
      }
      else if(line_num == 0) { // read the header information
        name = line;
        notes = inputFile.readLine();
        line = inputFile.readLine();
        sa = line.split(DELIM);
        
        int index = sa[0].indexOf("=") + 1;
        String ecs = sa[0].substring(index);
        
        index = sa[1].indexOf("=") + 1;
        String qys = sa[1].substring(index);
        
        try {
          EC = Float.parseFloat(ecs);
          QY = Float.parseFloat(qys);
        }
        catch(NumberFormatException nfe) {
          System.err.println("Number Format Exception while reading EC & QC " 
          + " EC = " + ecs + "QY = " + qys);
        }
      }
      line_num++;
    }
    inputFile.close();
    
    // read the emission data
    inputFile = new TextInputFile(file2);
    
    while(!inputFile.eof()) {
      line = inputFile.readLine();
      if(line.matches(regex)) {
        ems_text.addElement(line);
      }
    }
    inputFile.close();
    
    // creat the absorbtion spectra data 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] = "FRETView Data";
    dmeta[5] = "mm-dd-yyyy";
    dmeta[6] = "00";
    
    // get the data array now
    abs_data  = getDataArray(abs_text);
    if(abs_data == null) return null;
    
    // now create the absorption and emission SpectraData Objects
    String min = "" + abs_data[0][0];
    String max = "" + abs_data[abs_data.length-1][0];
    String dps = "" + abs_data.length;
    
    String[] header = {min, max, dps, "Unknown", "10", notes};
    SpectraData abs_sd = new SpectraData(name, "transmission", header, dmeta, abs_data, null);
    
    // create the emission spectra object
    dmeta = (String[])dmeta.clone();
    
    ems_data  = getDataArray(ems_text);
    if(ems_data == null) return null;
    
    min = "" + ems_data[0][0];
    max = "" + ems_data[ems_data.length-1][0];
    dps = "" + ems_data.length;
    
    header = new String[]{min, max, dps, "RA", "1.0", "000", "Unknown", notes};
    SpectraData ems_sd = new SpectraData(name, "Em", header, dmeta, ems_data, null);
    
    // create the spectra dyespectra data object and return it
    ds = new DyeSpectra(name, abs_sd, ems_sd, EC, QY);
    ds.setNotes(notes);
    
    return ds;
  }
  
  // Method to read in a descending data array
  private float[][] getDataArray(Vector textlines) {
    Object[] lines = textlines.toArray();
    float[][] xydata = null;
    String[] sa = null;
    String line = null;
    float max = 0.0f;
    
    if(textlines.size() != 0) {
      line = (String)lines[0];
      
      if(line.indexOf(",") != -1) {
        DELIM = ",";
      }
      else {
        DELIM = "\t";
      }
      
      xydata = new float[textlines.size()][2];
      float xvalue = 0.0f;
      float yvalue = 0.0f;
      
      for(int i = 0; i < xydata.length; i++) {
        line = (String)lines[i];
        sa = line.split(DELIM);
        try {
          xvalue = Float.parseFloat(sa[0]);
          yvalue = Float.parseFloat(sa[1]);
        }
        catch (NumberFormatException nfe) {
           xvalue = 0f;
           yvalue = 0f;
        }
        catch (ArrayIndexOutOfBoundsException e) {
          System.err.println("Error Occured on data line " + i + "\n" + line);
          return null;
        }
        
        if(yvalue > max) {
          max = yvalue;
        }
        
        xydata[i][0] = xvalue;
        xydata[i][1] = yvalue;
      }
      
      // see whether to invert the data ao that the smaller number appear first
      if(xydata[0][0] > xydata[1][0]) {
        float[][] nxydata = new float[xydata.length][2];
        int j = xydata.length -1;
        for(int i = 0; i < xydata.length; i++) {
           nxydata[j][0] = xydata[i][0];
           nxydata[j][1] = xydata[i][1];
           j--;
        }
        xydata = nxydata;
      }
      
      // normalize the maximum intensity to 100
      for(int i = 0; i < xydata.length; i++) {
        xydata[i][1] =  (xydata[i][1]/max)*100.0f;
      }
    }
    
    return xydata;
  }
  
  // return the name of the data object
  private String getName(File file) {
    String fn = file.getName();
    int end = fn.indexOf('.');
    String name = fn.substring(0, end);
    
    return name;
  }
} //-- end class AbsEms Data File Reader
