
/** 
 * StreakCleanThread.java
 * this thread is used to remove the electronic noise from streak data 
 * 
 *
 * Created:  Mar 14, 2004
 *
 * @author Nathan Stevens
 * @version 0.2 1/26/05
 */
import java.util.Vector;

public class StreakCleanThread extends Thread {
  private TransformDialog transformDialog;
  private SpectraData[] sdata;
  private Vector sdataVector = new Vector();
  private float mindiff;
  private float percent;
  
  public StreakCleanThread(TransformDialog transformDialog, SpectraData[] sdata, 
                                                float mindiff, float percent) {
    this.transformDialog = transformDialog;
    this.sdata = sdata;
    this.mindiff = mindiff;
    this.percent = percent;
    
    //System.out.println("Percent and Num. to Avg. " + percent + " : " + navg);
  }
  
  // The run method
  public void run() {
    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[][] ndata = getCleanData(data);
      
      String name = sdata[i].getName() + "-SCTF";
      SpectraData sd = new SpectraData(name, sdata[i].getType(), header, dmeta,
                                                                  ndata, null);
      sd.set3D(true);
      sdataVector.addElement(sd);
    }
    
    if(sdataVector.size() > 0) {
      SpectraData[] sda = SpectraDataUtil.getSpectraDataArray(sdataVector);
      transformDialog.setResults(sda);
    }
    transformDialog.setStatus(0, "No Message");
  }
  
  // Method to get the clean data
  private float[][] getCleanData(float[][] data) {
    float[][] ndata = new float[data.length][data[0].length];
    
    // add in the wavelengths now
    int i = 0;
    for(i = 0; i < data[0].length; i++) {
      ndata[0][i] = data[0][i];
    }
    
    // add in the time values now
    for(i = 0; i < data.length; i++) {
      ndata[i][0] = data[i][0];
    }
    
    for(int j = 1; j < ndata.length; j++) {
      for(int k = 1; k < ndata[0].length; k++) {
        //skip the first 5 and last data points and do checking
        float diff1 = 0.0f;
        float diff2 = 0.0f;
        if(k > 4 && k < (ndata[0].length - 4)) {
          diff1 = Math.abs(data[j][k-1] - data[j][k]);
          diff2 = Math.abs(data[j][k] - data[j][k+1]);
          if(diff1 >= mindiff && diff2 >= mindiff) {  // we found noise in the data, so fix
            ndata[j][k] = getRandomValue(ndata[j][k-1]);
            
            /* debug code
            System.out.println("The K -1 value is : " + data[j][k-1]);
            System.out.println("Noise Data Found... Diff 1 : " + diff1 + " diff 2 " + diff2);*/
          }
          else {
            ndata[j][k] = data[j][k];
          }
        }
        else {
          ndata[j][k] = data[j][k];
        }
      }
    }
    return ndata;
  }
  
  // return a radom number bigger or smaller that the value given
  private float getRandomValue(float value) {
    float nvalue = 0.0f;
    float rn1 = (float)Math.random();
    float rn2 = (float)Math.random();
    
    float pvalue = rn1*percent;
    int v1 = Math.round((pvalue/100.0f)*value);
    
    if(rn2 >= 0.5f) {
      nvalue = value + v1;
    }
    else {
      nvalue = value - v1;
    }
    
    return nvalue;
  }
  
  /**Old Streak clean code.  Don't want to delete so commenting out
  // the run method
  public void run() {
    for(int i = 0; i < sdata.length; i++) {
      String[] header = sdata[i].getHeader();
      String[] dmeta = sdata[i].getMetaInfo();
      
      float[][] data = sdata[i].getData();
      float[][] ndata = new float[data.length][data[0].length];
      
      // add in the wavelengths now
      int j;
      for(j = 0; j < data[0].length; j++) {
        ndata[0][j] = data[0][j];
      }
      
      // add in the time value now
      for(j = 0; j < data.length; j++) {
        ndata[j][0] = data[j][0];
      }
      
      ndata = getCleanData(data);
      
      String name = sdata[i].getName() + "-SCTF";
      SpectraData sd = new SpectraData(name, sdata[i].getType(), header, dmeta,
                                                                  ndata, null);
      sd.set3D(true);
      sdataVector.addElement(sd);
    }
    
    if(sdataVector.size() > 0) {
      SpectraData[] sda = SpectraDataUtil.getSpectraDataArray(sdataVector);
      transformDialog.setResults(sda);
    }
    transformDialog.setStatus(0, "No Message");
  }
  
  
  // Method to get the clean data
  private float[][] getCleanData(float[][] data) {
    float[][] ndata = new float[data.length][data[0].length];
    
    // add in the wavelengths now
    int i = 0;
    for(i = 0; i < data[0].length; i++) {
      ndata[0][i] = data[0][i];
    }
    
    // add in the time values now
    for(i = 0; i < data.length; i++) {
      ndata[i][0] = data[i][0];
    }
    
    for(int j = 1; j < ndata.length; j++) {
      for(int k = 1; k < ndata[0].length; k++) {
        //skip the first 3 data points
        if(k > 3) {
          
          // correct the bad value
          float prev = ndata[j][k - 1];
          ndata[j][k] = getNoiseValue(prev);
          
          k++;
          if(k < ndata[0].length) {
            prev = ndata[j][k -1];
            ndata[j][k] = getNoiseValue(prev);
          }
          
          k++;
          if(k < ndata[0].length) {
            prev = ndata[j][k -1];
            ndata[j][k] = getNoiseValue(prev);
          }
          
          // now add the good values now
          k++;
          if(k < ndata[0].length) {
            ndata[j][k] = data[j][k];
          }
          
          k++;
          if(k < ndata[0].length) {
            ndata[j][k] = data[j][k];
          }
          
          k++;
          if(k < ndata[0].length) {
            ndata[j][k] = data[j][k];
          }
          
          k++;
          if(k < ndata[0].length) {
            ndata[j][k] = data[j][k];
          }
          
          k++;
          if(k < ndata[0].length) {
            ndata[j][k] = data[j][k];
          }
        }
        else {
          ndata[j][k] += data[j][k];
        }
      }
    }
    
    return ndata;
  }
  
  // return a radom number bigger or smaller that the value given
  private float getNoiseValue(float value) {
    float noise = 0.0f;
    float rn1 = (float)Math.random();
    float rn2 = (float)Math.random();
    
    float pvalue = rn1*percent;
    int v1 = Math.round((pvalue/100.0f)*value);
    
    if(rn2 >= 0.5f) {
      noise = value + v1;
    }
    else {
      noise = value - v1;
    }
    
    return noise;
  }**/
}//--end class StreakCleanThread
