
/** 
 * NormalizeTransformThread.java
 * do normalization on data on the data
 * 
 *
 * Created:  Jan 8, 2004
 *
 * @author Nathan Stevens
 * @version 0.3 10/2/05
 */
import java.util.Vector;

public class NormalizeTransformThread extends Thread {
  private TransformDialog transformDialog = null;
  private SpectraData[] sdata = null;
  private Vector sdataVector = new Vector();
  private int normalize = 0;
  private float normalizeFactor = 1.0f;
  private float wl = 0.0f;
  
  public NormalizeTransformThread(TransformDialog transformDialog, SpectraData[] sdata, 
                                                               int normalize, float normalizeFactor, float wl) {
    this.transformDialog = transformDialog;
    this.sdata = sdata;
    this.normalize = normalize;
    this.normalizeFactor = normalizeFactor;
    this.wl = wl;
  }
  
  // the run method
  public void run() {
    if(normalize == 0) {
      normalizeDataToZero();
    }
    else {
      if(wl >= 0.0f) {
        normalizeDataToValue();
      }
      else {
        normalizeAllDataToValue();
      }
    }
  }
  
  // method to normalize  data to zero
  private void normalizeDataToZero() {
    float subnum = 0;
    float rsubnum = 0;
    
    for(int i = 0; i < sdata.length; i++) {
      String[] header = (String[])sdata[i].getHeader().clone();
      String[] dmeta = (String[])sdata[i].getMetaInfo().clone();
      
      float[] limit = getLimit(header);
      float[][] data = sdata[i].getData();
      float[][] rdata = sdata[i].getReferenceData();
      float[][] ndata = new float[data.length][2];
      float[][] nrdata = null;
      if(rdata != null) {
        nrdata = new float[data.length][2];
      }
      
      float precision = (data[1][0] - data[0][0]) * 2;
      
      if(wl >= limit[0] && wl <= limit[1]) {
        int index = getIndexOfWavelength(data, wl, precision);
        subnum = data[index][1];
        
        if(rdata != null) {
          rsubnum = rdata[index][1];
        }
      }
      else {
        int index = getMinimumIntensityIndex(data);
        subnum = data[index][1];
        
        if(rdata != null) {
          rsubnum = rdata[index][1];
        }
      }
      
      for(int j = 0; j < data.length; j++) {
        ndata[j][0] = data[j][0];
        ndata[j][1] = data[j][1] - subnum;
        if(rdata != null) {
          nrdata[j][0] = rdata[j][0];
          nrdata[j][1] = rdata[j][1] - rsubnum;
        }
      }
      
      String name = sdata[i].getName() + "-N0TF";
      SpectraData sd = new SpectraData(name, sdata[i].getType(), header, dmeta,
                                                                  ndata, nrdata);
      sdataVector.addElement(sd);
    }
    
    if(sdataVector.size() > 0) {
      SpectraData[] sda = SpectraDataUtil.getSpectraDataArray(sdataVector);
      transformDialog.setResults(sda);
    }
    
    transformDialog.setStatus(0, "No Message");
  }
  
  // method to normalize  data to one
  private void normalizeDataToValue() {
    float divisionValue = 0;
    float rdivisionValue = 0;
    float maxIntensity = 0.0f;
    float rmaxIntensity = 0.0f;
    
    // find the maximum intensity. assume that the all have more or less the
    // same wavelngth range
    for(int i = 0; i < sdata.length; i++) {
      String[] header = (String[])sdata[i].getHeader().clone();
      
      float[] limit = getLimit(header);
      float[][] data = sdata[i].getData();
      float[][] rdata = sdata[i].getReferenceData();
      
      float precision = (data[1][0] - data[0][0]) * 2;
      
      if(wl >= limit[0] && wl <= limit[1]) {
        int index = getIndexOfWavelength(data, wl, precision);
        maxIntensity = data[index][1];
        
        if(rdata != null) {
          rmaxIntensity = rdata[index][1];
        }
      }
      else {
        int index = getMaximumIntensityIndex(data);
        maxIntensity = data[index][1];
        
        if(rdata != null) {
          rmaxIntensity = rdata[index][1];
        }
      }
      
      if(maxIntensity > divisionValue) {
        divisionValue = maxIntensity;
        rdivisionValue = rmaxIntensity;
      }
    }
    
    // actually normalize the data now
    for(int i = 0; i < sdata.length; i++) {
      String[] header = (String[])sdata[i].getHeader().clone();
      String[] dmeta = (String[])sdata[i].getMetaInfo().clone();
      
      float[][] data = sdata[i].getData();
      float[][] rdata = sdata[i].getReferenceData();
      float[][] ndata = new float[data.length][2];
      float[][] nrdata = null;
      
      if(rdata != null) {
        nrdata = new float[data.length][2];
      }
      
      for(int j = 0; j < data.length; j++) {
        ndata[j][0] = data[j][0];
        ndata[j][1] = (data[j][1]/divisionValue)*normalizeFactor;
        if(rdata != null) {
          nrdata[j][0] = rdata[j][0];
          nrdata[j][1] = rdata[j][1]/rdivisionValue*normalizeFactor;
        }
      }
      
      String name = sdata[i].getName() + "-NTF";
      SpectraData sd = new SpectraData(name, sdata[i].getType(), header, dmeta,
                                                                  ndata, nrdata);
      sdataVector.addElement(sd);
    }
    
    if(sdataVector.size() > 0) {
      SpectraData[] sda = SpectraDataUtil.getSpectraDataArray(sdataVector);
      transformDialog.setResults(sda);
    }
    transformDialog.setStatus(0, "No Message");
  }
  
  // method to normalize All the data to the same value
  private void normalizeAllDataToValue() {
    float divisionValue = 1;
    float rdivisionValue = 1;
    float maxIntensity = 0.0f;
    float rmaxIntensity = 0.0f;
    
    // reset wavelength now to positive value
    wl *= -1;
    
    // find the maximum intensity. assume that the all have more or less the
    // same wavelngth range
    for(int i = 0; i < sdata.length; i++) {
      String[] header = (String[])sdata[i].getHeader().clone();
      String[] dmeta = (String[])sdata[i].getMetaInfo().clone();
      
      float[] limit = getLimit(header);
      float[][] data = sdata[i].getData();
      float[][] rdata = sdata[i].getReferenceData();
      float[][] ndata = new float[data.length][2];
      float[][] nrdata = null;
      
      if(rdata != null) {
        nrdata = new float[data.length][2];
      }
      
      float precision = (data[1][0] - data[0][0]) * 2;
      
      if(wl >= limit[0] && wl <= limit[1]) {
        int index = getIndexOfWavelength(data, wl, precision);
        maxIntensity = data[index][1];
        
        if(rdata != null) {
          rmaxIntensity = rdata[index][1];
        }
      }
      else {
        int index = getMaximumIntensityIndex(data);
        maxIntensity = data[index][1];
        
        if(rdata != null) {
          rmaxIntensity = rdata[index][1];
        }
      }
      
      divisionValue = maxIntensity;
      rdivisionValue = rmaxIntensity;
      
      // now normalize the data object
      for(int j = 0; j < data.length; j++) {
        ndata[j][0] = data[j][0];
        ndata[j][1] = (data[j][1]/divisionValue)*normalizeFactor;
        if(rdata != null) {
          nrdata[j][0] = rdata[j][0];
          nrdata[j][1] = rdata[j][1]/rdivisionValue*normalizeFactor;
        }
      }
      
      String name = sdata[i].getName() + "-NTF";
      SpectraData sd = new SpectraData(name, sdata[i].getType(), header, dmeta,
      ndata, nrdata);
      sdataVector.addElement(sd);
    }
    
    if(sdataVector.size() > 0) {
      SpectraData[] sda = SpectraDataUtil.getSpectraDataArray(sdataVector);
      transformDialog.setResults(sda);
    }
    transformDialog.setStatus(0, "No Message");
  }
  
  // Method to return the limits
  private float[] getLimit(String[] header) {
    try {
      float min = Float.parseFloat(header[0]);
      float max = Float.parseFloat(header[1]);
      float[] limit = {min, max};
      return limit;
    }
    catch(NumberFormatException nfe) {
      return null;
    }
  }
  
  
  // Method to get the intensity at a certin wavelngth
  private int getIndexOfWavelength(float[][] data, float wl, float precision) {
    int index = 0;
    
    // find wavelengh close to what we need
    for(int i = 0; i < data.length; i++) {
      float value = Math.abs(data[i][0] - wl);
      if(value <= precision) {
        index = i;
        break;
      }
    }
    
    return index;
  }
  
  // Method to find the lowest intensity
  private int getMinimumIntensityIndex(float[][] data) {
    float intensity = 1000000f;
     int index = 0;
     
    // find minumum intensity
    for(int i = 0; i < data.length; i++) {
      if(data[i][1] < intensity) {
        intensity= data[i][1];
        index = i;
      }
    }
    
    return index;
  }
  
  // Method to find the lowest intensity
  private int getMaximumIntensityIndex(float[][] data) {
    float intensity = 0f;
    int index = 0;
    
    // find minumum intensity
    for(int i = 0; i < data.length; i++) {
      if(data[i][1] > intensity) {
        intensity= data[i][1];
        index = i;
      }
    }
    
    return index;
  }
} //--end class NormalizeTransformThread
