package highspeedacquisitionsample;
import com.oceanoptics.omnidriver.features.boardtemperature.BoardTemperature;
import com.oceanoptics.highrestiming.HighResTimeStamp;
import com.oceanoptics.omnidriver.api.wrapper.Wrapper;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.io.IOException;
import java.text.SimpleDateFormat;

// import java.io.FileWriter;
// import java.io.BufferedWriter;
import java.io.*;
/**
 * This sample demonstrates how to use external trigger modes and the
 * high speed acquisition feature of the OmniDriver "Wrapper" API.
 * 
 * We will wait for a hardware trigger signal (level-triggered) to occur.
 * Then we will configure the spectrometer to acquire 160 spectra in a one second
 * interval.  Then we initiate the high speed acquisition, which will acquire
 * all 160 spectra.  Finally, we extract these spectra out of the internal
 * buffer area so as to be able to manipulate them in our application.
 *The duration of the trigger signal MUST be slightly longer than the time it takes
 * to acquire the initial minimum-integration-time spectrum.  This is because
 * you can only change the trigger mode of a spectrometer during the phase when
 * the spectrometer is actively acquiring a spectrum.  Thus, the trigger signal
 * must be long enough to cause TWO spectra to be acquired.  The first spectrum
 * acquisition causes our initial getSpectrum() method to return control to
 * the application.  Then, while the spectrometer is acquiring a second spectrum,
 * our application calls the setExternalTriggerMode() method to set the mode
 * back to "normal" (aka free-running).
 * <p>As a consequence of this requirement, it means that there will be a small
 * delay (equal to two times the minimum integration time for the spectrometer)
 * following the trigger signal before we begin collecting the desired  spectra.
 */



public class HighSpeedAcquisitionSample_simple {


    
    Wrapper wrapper;
    
  
    public static void main(String[] args) {
        HighSpeedAcquisitionSample_simple    myself;
        //args = [Serialnumber; integration time [us]]
        myself= new HighSpeedAcquisitionSample_simple();
	
        myself.run(args);
    }
    
    public void run(String[] args) {
        
        double  activeSampleIntervalDuration; // units: seconds; this is how long we want to actively acquire spectra
        int integrationTime; // units: microseconds
        int loopCount;
        int loopLimit;
        int minimumIntegrationTime; // units: microseconds
        int numberOfSpectraRequested;
        int numberOfSpectrometers;
        int spectrometerIndex;
        int spectrumNumber;
	String serialNumber; 
	BoardTemperature boardTemperature;
        double           temperatureCelsius;
	int BackgroundIntegTime;
// 	DoubleArray background;
	double[] background;
	double[] wavelength;
	int numberOfPixels; // number of CCD elements/pixels provided by the spectrometer
        wrapper = new Wrapper();
	
	numberOfSpectrometers = wrapper.openAllSpectrometers();

	// choose reguested spectrometer
        spectrometerIndex = -1;
        for (int i = 0;i<numberOfSpectrometers;++i){
	    serialNumber = wrapper.getSerialNumber(i);
	    if (serialNumber.equals(args[0]))	    {
		spectrometerIndex = i;
	    }
	}
	
	
	if (numberOfSpectrometers == -1) {
            System.out.println(wrapper.getLastException());
            System.out.println(wrapper.getLastExceptionStackTrace());
            System.out.println("Error occured while attempting to access spectrometers.  Exiting the application.");
            return;
        } else if (numberOfSpectrometers == 0) {
            System.out.println("No spectrometers found.  Exiting the application.");
            return;
        }
        if (spectrometerIndex == -1) {
	    System.out.println("Spectrometers with serial number "+ args[0]+ " was not found.  Exiting the application.");
            return;	    
	}
	
        serialNumber = wrapper.getSerialNumber(0); 
	System.out.println("spectrometer type: " + wrapper.getName(spectrometerIndex) +
	" s/n: " + wrapper.getSerialNumber(spectrometerIndex) +
	" number of channels: " + wrapper.getWrapperExtensions().getNumberOfEnabledChannels(spectrometerIndex) +
	" firmware: " + wrapper.getFirmwareVersion(spectrometerIndex));
        System.out.flush();
	boardTemperature = wrapper.getFeatureControllerBoardTemperature(spectrometerIndex);
	wavelength = wrapper.getWavelengths(spectrometerIndex);
        activeSampleIntervalDuration = Integer.parseInt(args[1]); //[ms] 
// 	maximum is limited by memory accesible by java virtual maschine to about 3000 spectra
        minimumIntegrationTime = wrapper.getMinimumIntegrationTime(spectrometerIndex);
	
	
	integrationTime = Integer.parseInt(args[2]); //[us]
	if (integrationTime< minimumIntegrationTime){
	    integrationTime = minimumIntegrationTime;
	    System.out.println("To short integration time, set to "+integrationTime/1000+ "ms");	    
	}
	numberOfSpectraRequested = (int)((double)activeSampleIntervalDuration/integrationTime)+1; // this is how may spectra we want to collect during our "active sample interval",
	
	System.out.println("Integration time "+integrationTime/1000.0+ " [ms], number of spectra "+numberOfSpectraRequested+" Sampling time "+activeSampleIntervalDuration);
	BackgroundIntegTime = 1000000; 
        numberOfPixels = wrapper.getNumberOfPixels(spectrometerIndex);
	System.out.println("Number of pixels: " + numberOfPixels);
	SimpleDateFormat date = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
	
	
	
	wrapper.highSpdAcq_AllocateBuffer(spectrometerIndex,1000);
	wrapper.setIntegrationTime(spectrometerIndex,integrationTime);
	wrapper.highSpdAcq_StartAcquisition(spectrometerIndex); 
	double[] readOutPatterns;
	readOutPatterns = wrapper.highSpdAcq_GetSpectrum(0);
	for (spectrumNumber=0; spectrumNumber<wrapper.highSpdAcq_GetNumberOfSpectraAcquired(); ++spectrumNumber) {	    
	    // this will contain the sum of the raw pixel 
	    double[] oneSpectrum; // this will contain the raw pixel values comprising one spectrum
	    oneSpectrum = wrapper.highSpdAcq_GetSpectrum(spectrumNumber);
	    for (int line=0; line<numberOfPixels; ++line) {
		readOutPatterns[line] = readOutPatterns[line]+oneSpectrum[line];
	    }		    
	} 
	
	System.out.println("The readoutnoise patterns acquired");

// 		
		

	
	
	//prepare for high speed acqusition
	

	wrapper.highSpdAcq_AllocateBuffer(spectrometerIndex,numberOfSpectraRequested);


	

	loopCount = 0;
	while (loopCount <1) {
	    ++loopCount;
 
	    System.out.println("Loop " + (loopCount) + " of " + "infinite "+date.format(new Date()));
	    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
            System.out.println("Begin acquisition: " + sdf.format(new Date()));
            



	    try { Thread.sleep(1000); } catch (Exception ee) {}

            // Prepare to acquire auxiliary spectra

	    wrapper.setIntegrationTime(spectrometerIndex,minimumIntegrationTime); // minimize latency when next hardware trigger occurs
            wrapper.setExternalTriggerMode(spectrometerIndex,0); // hardware trigger mode - level triggered
            
           
            System.out.println("Waiting for the hardware trigger ...");
            // Now wait for the hardware trigger signal
            wrapper.getSpectrum(spectrometerIndex);
	
	    
	    
            // Prepare to acquire spectra
            wrapper.setExternalTriggerMode(spectrometerIndex,0); // external hardware trigger mode
	    wrapper.setIntegrationTime(spectrometerIndex,integrationTime);

	    
	    // Now wait for the hardware trigger signal
	    System.out.println("Waiting on trigger 2");

	    // ACQUIRE THE SPECTRA
            wrapper.highSpdAcq_StartAcquisition(spectrometerIndex); 

	    if(wrapper.highSpdAcq_GetNumberOfSpectraAcquired() == 0)
	    {
		continue;
	    }
	    
		
            System.out.println("Spectra acquired");
	    
	    // 	dark noise and background
	    wrapper.setIntegrationTime(spectrometerIndex,BackgroundIntegTime); // minimize latency when next hardware trigger occurs
            wrapper.setExternalTriggerMode(spectrometerIndex,0); // hardware trigger mode - level triggered
	    
	    
	    background = wrapper.getSpectrum(spectrometerIndex);
	    System.out.println("Background acquired");
	    


	    

            // Extract the newly acquired spectra from the internal buffer area
	    try {
		BufferedWriter out = new BufferedWriter(new FileWriter("./data/spectra.txt"));
// 		head of the file
		temperatureCelsius = boardTemperature.getBoardTemperatureCelsius();
		System.out.println("board temperature: " + temperatureCelsius);
		out.write("Data file from Ocean Optics Spectrometer - "+wrapper.getName(spectrometerIndex) +"\n");
		out.write("Spectrometer S/N: "+wrapper.getSerialNumber(spectrometerIndex) +"\n");
		out.write("Date and time:\t"+date.format(new Date()) +"\n");
		out.write("Number of spectra: \t"+wrapper.highSpdAcq_GetNumberOfSpectraAcquired()+"\n");
		out.write("Number pixels in spectra: \t"+numberOfPixels+"\n");
		out.write("Integration time [us]: \t"+integrationTime+"\n");
		out.write("Board temperature [C]: \t"+temperatureCelsius+"\n");
		
		out.write("Exact time stamps:"+"\n");
		for (spectrumNumber=0; spectrumNumber<wrapper.highSpdAcq_GetNumberOfSpectraAcquired(); ++spectrumNumber) {
		    HighResTimeStamp hrts = wrapper.highSpdAcq_GetTimeStamp(spectrumNumber); // this is optional
		    out.write(hrts.toString()+"\n");		    
		}
	    
		// body of the file
		out.write("Wavelengths:"+"\n");
		
		double lambda;
		for (int line=0; line<numberOfPixels; ++line) {
		    lambda = (double)((int)(wavelength[line]*1000))/1000;
		    out.write(lambda+"\n");
		}
		
		
		
		for (spectrumNumber=0; spectrumNumber<wrapper.highSpdAcq_GetNumberOfSpectraAcquired(); ++spectrumNumber) {
		    
		    double[] oneSpectrum; // this will contain the raw pixel values comprising one spectrum
		    oneSpectrum = wrapper.highSpdAcq_GetSpectrum(spectrumNumber);
		    for (int line=0; line<numberOfPixels; ++line) {
			out.write((int)oneSpectrum[line]+"\n");
		    }			    
		} 		
		out.close();
		
		
		// save background
		BufferedWriter background_out = new BufferedWriter(new FileWriter("./data/background.txt"));
		background_out.write("Background file from Ocean Optics Spectrometer - "+wrapper.getName(spectrometerIndex) +"\n");
		background_out.write("Spectrometer S/N: "+wrapper.getSerialNumber(spectrometerIndex) +"\n");
		background_out.write("Date and time:\t"+date.format(new Date()) +"\n");
		background_out.write("Number pixels in spectra: \t"+numberOfPixels+"\n");
		background_out.write("Integration time [us]: \t"+BackgroundIntegTime+"\n");
		for (int line=0; line<numberOfPixels; ++line) {
		    background_out.write((int)background[line]+"\n");
		}		
		background_out.close();	
		
		
	// 	readout noise patterns
    
		wrapper.highSpdAcq_AllocateBuffer(spectrometerIndex,1000);
		wrapper.setIntegrationTime(spectrometerIndex,integrationTime);
		wrapper.highSpdAcq_StartAcquisition(spectrometerIndex); 
		readOutPatterns = wrapper.highSpdAcq_GetSpectrum(0);
		for (spectrumNumber=0; spectrumNumber<wrapper.highSpdAcq_GetNumberOfSpectraAcquired(); ++spectrumNumber) {	    
		    // this will contain the sum of the raw pixel 
		    double[] oneSpectrum; // this will contain the raw pixel values comprising one spectrum
		    oneSpectrum = wrapper.highSpdAcq_GetSpectrum(spectrumNumber);
		    for (int line=0; line<numberOfPixels; ++line) {
			readOutPatterns[line] = readOutPatterns[line]+oneSpectrum[line];
		    }		    
		} 
		
		System.out.println("The readoutnoise patterns acquired");

		
	
		// save readout noise
		BufferedWriter readoutpatternsOut = new BufferedWriter(new FileWriter("./data/readoutpatterns.txt"));
		readoutpatternsOut.write("Readout patterns file from Ocean Optics Spectrometer - "+wrapper.getName(spectrometerIndex) +"\n");
		readoutpatternsOut.write("Spectrometer S/N: "+wrapper.getSerialNumber(spectrometerIndex) +"\n");
		readoutpatternsOut.write("Date and time:\t"+date.format(new Date()) +"\n");
		readoutpatternsOut.write("Number pixels in spectra: \t"+numberOfPixels+"\n");
		readoutpatternsOut.write("Integration time [us]: \t"+integrationTime+"\n");
		readoutpatternsOut.write("Number of averaged spectra: \t"+1000+"\n");

		for (int line=0; line<numberOfPixels; ++line) {
		    readoutpatternsOut.write((readOutPatterns[line]/1001.0)+"\n");
		}
		readoutpatternsOut.close();
	
		
		// save loopnumber
		BufferedWriter ready = new BufferedWriter(new FileWriter("./ready"));
		ready.write(" ");	
		ready.close();
		
		
	    }
	    catch (IOException e) {
		System.out.println( e.getMessage() );
	    try { Thread.sleep(60000); } catch (Exception ee) {}
		    
	    }
        }
    }
}


  