Author: [log in to unmask] Date: Mon Nov 23 07:27:09 2015 New Revision: 3977 Log: puts rf time into event Added: java/trunk/evio/src/main/java/org/hps/evio/RfFitterDriver.java Added: java/trunk/evio/src/main/java/org/hps/evio/RfFitterDriver.java ============================================================================= --- java/trunk/evio/src/main/java/org/hps/evio/RfFitterDriver.java (added) +++ java/trunk/evio/src/main/java/org/hps/evio/RfFitterDriver.java Mon Nov 23 07:27:09 2015 @@ -0,0 +1,164 @@ +package org.hps.evio; + +import java.util.ArrayList; +import java.util.List; +import java.util.logging.Level; +import java.util.logging.Logger; + +import hep.aida.IAnalysisFactory; +import hep.aida.IDataPointSet; +import hep.aida.IFitFactory; +import hep.aida.IFitResult; +import hep.aida.IFitter; +import hep.aida.IFunction; +import hep.aida.IFunctionFactory; + +import org.hps.recon.ecal.FADCGenericHit; +import org.lcsim.event.EventHeader; +import org.lcsim.event.GenericObject; +import org.lcsim.util.Driver; +import org.lcsim.util.aida.AIDA; + +/* + * Extract RF time from waveform and put into lcsim event. + */ +public class RfFitterDriver extends Driver { + + static final double NOISE=2.0; // units = FADC + static final int CRATE=46; + static final int SLOT=13; + static final int CHANNELS[]={0,1}; + static final double NSPERSAMPLE=4; + + + // boilerplate: + AIDA aida = AIDA.defaultInstance(); + IAnalysisFactory analysisFactory = aida.analysisFactory(); + IFunctionFactory functionFactory = analysisFactory.createFunctionFactory(null); + IFitFactory fitFactory = analysisFactory.createFitFactory(); + IFitter fitter=fitFactory.createFitter(); + IDataPointSet fitData=aida.analysisFactory().createDataPointSetFactory(null).create("RF ADC DataPointSet", 2); + + // the function used to fit the RF pulse: + IFunction fitFunction=new RfFitFunction(); + + /* + * Check the event for an RF pulse, and, if found, fit it to get + * RF time and then dump it in the lcsim event. + */ + public void process(EventHeader event) { + if (!event.hasCollection(GenericObject.class,"FADCGenericHits")) return; + + boolean foundRf=false; + double times[]={-9999,-9999}; + + for (GenericObject gob : event.get(GenericObject.class,"FADCGenericHits")) { + FADCGenericHit hit=(FADCGenericHit)gob; + + // ignore hits not from proper RF signals based on crate/slot/channel: + if (hit.getCrate()!=CRATE || hit.getSlot()!=SLOT) continue; + for (int ii=0; ii<CHANNELS.length; ii++) { + if (hit.getChannel()==CHANNELS[ii]) { + + // we found a RF readout, fit it: + foundRf=true; + times[ii] = fitPulse(hit); + + break; + } + } + } + + // if we found an RF readout, dump the fit result in the event: + if (foundRf) { + List <RfHit> rfHits=new ArrayList<RfHit>(); + rfHits.add(new RfHit(times)); + event.put("RFHits", rfHits, RfHit.class, 1); + } + } + + /* + * Perform the fit to the RF pulse: + */ + public double fitPulse(FADCGenericHit hit) { + fitData.clear(); + final int adcSamples[]=hit.getData(); + //stores the number of peaks + int iz=0; + int peakBin[]={-999,-999}; + final int threshold = 300; + double fitThresh[]={-999,-999}; + double pedVal[]={-999,-999}; + + // Look for bins containing the peaks (2-3 peaks) + for (int ii=4; ii<adcSamples.length; ii++) { + // After 2 peaks, stop looking for more + if (iz==2){break;} + if ((adcSamples[ii+1]>0) && (adcSamples[ii-1]>0) && (adcSamples[ii]>threshold) && ii>8){ + if ((adcSamples[ii]>adcSamples[ii+1]) && (adcSamples[ii]>=adcSamples[ii-1]) ){ + + peakBin[iz]=ii; + iz++; + } + } + } + + + int jj=0; + // Choose peak closest to center of window (second peak, ik=1) + final int ik=1; + pedVal[ik] = (adcSamples[peakBin[ik]-6]+adcSamples[peakBin[ik]-7]+adcSamples[peakBin[ik]-8]+adcSamples[peakBin[ik]-9])/4.0; + fitThresh[ik]= (adcSamples[peakBin[ik]]+pedVal[ik])/3.0; + + // Initial values: we find/fit 3 points: + double itime[] = {-999,-999,-999}; + double ifadc[] = {-999,-999,-999}; + + // Find the points of the peak bin to peak bin-5 + for (int ll=0; ll<5; ll++){ + if ((adcSamples[peakBin[ik]-5+ll]) > fitThresh[ik]){ + // One point is below fit threshold and two points are above + if(jj==0 && (adcSamples[peakBin[ik]-6+ll] > pedVal[ik])){ + final int zz=fitData.size(); + fitData.addPoint(); + itime[zz] = peakBin[ik]-6+ll; + ifadc[zz] = adcSamples[peakBin[ik]-6+ll]; + fitData.point(zz).coordinate(0).setValue(peakBin[ik]-6+ll); + fitData.point(zz).coordinate(1).setValue(adcSamples[peakBin[ik]-6+ll]); + fitData.point(zz).coordinate(1).setErrorMinus(NOISE); + fitData.point(zz).coordinate(1).setErrorPlus(NOISE); + jj++; + } + final int zz=fitData.size(); + fitData.addPoint(); + itime[zz] = peakBin[ik]-5+ll; + ifadc[zz] = adcSamples[peakBin[ik]-5+ll]; + fitData.point(zz).coordinate(0).setValue(peakBin[ik]-5+ll); + fitData.point(zz).coordinate(1).setValue(adcSamples[peakBin[ik]-5+ll]); + fitData.point(zz).coordinate(1).setErrorMinus(NOISE); + fitData.point(zz).coordinate(1).setErrorPlus(NOISE); + + jj++; + if (jj==3) {break;} + } + } + + double islope = ((double)(ifadc[2]-ifadc[0]))/(itime[2]-itime[0]); + double icept = ifadc[1] - islope*itime[1]; + // Initialize fit parameters: + fitFunction.setParameter("intercept",icept); + fitFunction.setParameter("slope",islope); + + // this used to be turned on somewhere else on every event, dunno if it still is: + //Logger.getLogger("org.freehep.math.minuit").setLevel(Level.OFF); + + IFitResult fitResults = fitter.fit(fitData,fitFunction); + + // Read the time value at this location on the fit: + double halfVal = (adcSamples[peakBin[1]]+pedVal[1])/2.0; + + return NSPERSAMPLE*(halfVal-fitResults.fittedParameter("intercept"))/fitResults.fittedParameter("slope"); + + } + +}