Author: [log in to unmask] Date: Wed May 27 14:10:48 2015 New Revision: 3040 Log: ~final pulse fitting Added: java/trunk/steering-files/src/main/resources/org/hps/steering/users/baltzell/EcalReconPulseFit.lcsim Modified: java/trunk/users/src/main/java/org/hps/users/baltzell/Ecal3PoleFunction.java java/trunk/users/src/main/java/org/hps/users/baltzell/EcalPulseFitter.java java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverter.java java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverterDriver.java Added: java/trunk/steering-files/src/main/resources/org/hps/steering/users/baltzell/EcalReconPulseFit.lcsim ============================================================================= --- java/trunk/steering-files/src/main/resources/org/hps/steering/users/baltzell/EcalReconPulseFit.lcsim (added) +++ java/trunk/steering-files/src/main/resources/org/hps/steering/users/baltzell/EcalReconPulseFit.lcsim Wed May 27 14:10:48 2015 @@ -0,0 +1,52 @@ +<lcsim xmlns:xs="http://www.w3.org/2001/XMLSchema-instance" + xs:noNamespaceSchemaLocation="http://www.lcsim.org/schemas/lcsim/1.0/lcsim.xsd"> + <execute> + <driver name="EcalRunningPedestal"/> + <driver name="EcalRawConverter" /> + <driver name="ReconClusterer" /> + <driver name="LCIOWriter" /> + <!--<driver name="AidaSaveDriver" />--> + <driver name="CleanupDriver" /> + </execute> + <drivers> + <driver name="EcalRunningPedestal" type="org.hps.recon.ecal.EcalRunningPedestalDriver"> + <minLookbackEvents>10</minLookbackEvents> + <maxLookbackEvents>50</maxLookbackEvents> + </driver> + <driver name="EcalRawConverter" type="org.hps.users.baltzell.EcalRawConverterDriver"> + <ecalCollectionName>EcalCalHits</ecalCollectionName> + <use2014Gain>false</use2014Gain> + <useTimestamps>false</useTimestamps> + <useTruthTime>false</useTruthTime> + <useRunningPedestal>true</useRunningPedestal> + <useTimeWalkCorrection>false</useTimeWalkCorrection> + <emulateFirmware>true</emulateFirmware> + <emulateMode7>true</emulateMode7> + <leadingEdgeThreshold>12</leadingEdgeThreshold> + <nsa>20</nsa> + <nsb>100</nsb> + <useFit>true</useFit> + <fixShapeParameter>true</fixShapeParameter> + <debug>0</debug> + <!--<fitFileName>ecalPulseFits.txt</fitFileName>--> + </driver> + <driver name="ReconClusterer" type="org.hps.recon.ecal.cluster.ReconClusterDriver"> + <logLevel>WARNING</logLevel> + <outputClusterCollectionName>EcalClusters</outputClusterCollectionName> + <hitEnergyThreshold>0.01</hitEnergyThreshold> + <seedEnergyThreshold>0.050</seedEnergyThreshold> + <clusterEnergyThreshold>0.100</clusterEnergyThreshold> + <minTime>0.0</minTime> + <timeWindow>25.0</timeWindow> + <useTimeCut>true</useTimeCut> + <writeRejectedHitCollection>false</writeRejectedHitCollection> + </driver> + <driver name="LCIOWriter" type="org.lcsim.util.loop.LCIODriver"> + <outputFilePath>${outputFile}.slcio</outputFilePath> + </driver> + <driver name="AidaSaveDriver" type="org.lcsim.job.AidaSaveDriver"> + <outputFileName>ecalPulseFits.root</outputFileName> + </driver> + <driver name="CleanupDriver" type="org.lcsim.recon.tracking.digitization.sisim.config.ReadoutCleanupDriver" /> + </drivers> +</lcsim> Modified: java/trunk/users/src/main/java/org/hps/users/baltzell/Ecal3PoleFunction.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/baltzell/Ecal3PoleFunction.java (original) +++ java/trunk/users/src/main/java/org/hps/users/baltzell/Ecal3PoleFunction.java Wed May 27 14:10:48 2015 @@ -2,9 +2,17 @@ import hep.aida.ref.function.AbstractIFunction; +/* + * + * "3-Pole Function:" x**2 * exp(-x/tau) + * + * Here x is time, and we have pedestal and time offsets, and it's normalized: + * PEDESTAL + INTEGRAL / WIDTH^3 / 2 * (TIME-TIME0)**2 * exp(-(TIME-TIME0)/WIDTH) + * + */ public class Ecal3PoleFunction extends AbstractIFunction { - + protected double pedestal=0; protected double time0=0; protected double integral=0; @@ -21,8 +29,9 @@ init(title); } - void setDebug(boolean debug) { this.debug=debug; } - + public void setDebug(boolean debug) { this.debug=debug; } + public double maximum() { return value(new double[]{time0+2*width}); } + @Override public double value(double[] v) { final double time = v[0]; @@ -36,20 +45,20 @@ @Override public void setParameters(double[] pars) throws IllegalArgumentException { super.setParameters(pars); - pedestal=pars[0]; - time0=pars[1]; - integral=pars[2]; - width=pars[3]; + pedestal = pars[0]; + time0 = pars[1]; + integral = pars[2]; + width = pars[3]; if (debug) System.err.println(String.format("%8.2f %8.2f %8.2f %8.2f",pars[0],pars[1],pars[2],pars[3])); } @Override public void setParameter(String key,double value) throws IllegalArgumentException{ super.setParameter(key,value); - if (key.equals("pedestal")) pedestal=value; - else if (key.equals("time0")) time0=value; - else if (key.equals("integral")) integral=value; - else if (key.equals("width")) width=value; + if (key.equals("pedestal")) pedestal = value; + else if (key.equals("time0")) time0 = value; + else if (key.equals("integral")) integral = value; + else if (key.equals("width")) width = value; } } Modified: java/trunk/users/src/main/java/org/hps/users/baltzell/EcalPulseFitter.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/baltzell/EcalPulseFitter.java (original) +++ java/trunk/users/src/main/java/org/hps/users/baltzell/EcalPulseFitter.java Wed May 27 14:10:48 2015 @@ -13,34 +13,110 @@ import java.util.logging.Level; import java.util.logging.Logger; +import org.hps.conditions.database.DatabaseConditionsManager; +import org.hps.conditions.ecal.EcalChannelConstants; +import org.hps.conditions.ecal.EcalConditions; +import org.lcsim.event.RawTrackerHit; +import org.lcsim.geometry.Detector; import org.lcsim.util.aida.AIDA; public class EcalPulseFitter { + + public int debug = 0; + public String fitFileName = null; + public boolean fixShapeParameter = true; + + private final static int nsPerSample=4; + private final boolean doTimeFit = false; + private FileWriter fitFileWriter = null; + private EcalConditions ecalConditions = null; + + // don't bother fitting pulses with threshold crossing outside this sample range: + private final static int threshRange[]={7,18}; // (28 ns <--> 72 ns) + + // fit sample range relative to threshold crossing: + private final static int fitRange[]={-10,15}; + + // sample range relative to threshold crossing used to initialize pedestal fit parameter: + private final static int pedRange[]={-10,-5}; + + private final static double threePoleWidths[]={ + 2.44057,2.40057,2.53389,2.32095,2.44267,2.43631,2.40292,2.46911,2.36032,2.42132,2.41473,2.43864,2.37710,2.43278,2.49126,2.41739,2.40560, + 2.42042,2.51278,2.46731,2.42647,2.35636,2.55308,2.47517,2.38748,2.48324,2.53726,2.54780,2.50771,2.45188,2.35011,2.35110,2.37575,2.37649, + 2.41037,2.38817,2.52422,2.47389,2.40672,2.59415,2.35626,2.44359,2.54118,2.42893,2.43100,2.32748,2.34831,2.30641,2.40003,2.38997,2.41643, + 2.45717,2.44830,2.48149,2.44339,2.33572,2.42276,2.43731,2.44205,2.37290,2.54975,2.44517,2.39132,2.48821,2.45687,2.39768,2.61674,2.52142, + 2.46620,2.46802,2.54764,2.45238,2.48421,2.44521,2.47204,2.50415,2.47346,2.51053,2.44811,2.54895,2.44839,2.51419,2.45706,2.38596,2.46743, + 2.49971,2.37904,2.46478,2.43015,2.52088,2.55846,2.50522,2.30973,2.41450,2.40907,2.31343,2.48668,2.46800,2.43559,2.42113,2.47494,2.36971, + 2.44022,2.44193,2.42661,2.41918,2.41102,2.51565,2.34875,2.36750,2.37355,2.48763,2.36659,2.42424,2.44321,2.46651,2.52053,2.46172,2.41316, + 2.41670,2.41661,2.53472,2.49345,2.46496,2.40006,2.41084,2.44442,2.49113,2.42821,2.56839,2.45630,2.46344,2.42585,2.43730,2.44339,2.44315, + 2.48069,2.39892,2.36987,2.40482,2.40103,2.36307,2.46118,2.47136,2.39327,2.46267,2.30668,2.45917,2.46903,2.51727,2.27056,2.46365,2.35228, + 2.52188,2.44052,2.41457,2.25591,2.51210,2.43585,2.57410,2.46877,2.37902,2.46975,2.45628,2.44264,2.36588,2.48233,2.46351,2.37512,2.44228, + 2.52664,2.51927,2.37348,2.52284,2.52505,2.55755,2.51522,2.44848,2.51430,2.41387,2.42311,2.42880,2.46546,2.40000,2.45992,2.46841,2.43101, + 2.22369,2.43262,2.41324,2.45465,2.40752,2.50491,2.45191,2.40109,2.49099,2.37011,2.70111,2.46843,2.44336,2.44675,2.42308,2.51800,2.45660, + 2.43406,2.43297,2.37133,2.50718,2.43035,2.42818,2.47709,2.40578,2.39228,2.47350,2.51876,2.39584,2.44114,2.49120,2.48185,2.59246,2.41612, + 2.42914,2.51496,2.38785,2.53339,2.30056,2.25807,2.40500,2.53300,2.37439,2.48418,2.33764,2.47934,2.33080,2.48834,2.48318,2.42860,2.28253, + 2.44013,2.38272,2.23632,2.37630,2.34564,2.34538,2.44281,2.33952,2.33574,2.40939,2.44992,2.43986,2.45022,2.39336,2.43253,2.38136,2.41941, + 2.56685,2.54684,2.43060,2.33258,2.43024,2.48895,2.51698,2.38837,2.45276,2.38518,2.35826,2.38321,2.31616,2.46480,2.53753,2.28027,2.50727, + 2.35369,2.29179,2.06776,2.49429,2.35639,2.42628,2.55657,2.51859,2.49579,2.45617,2.41293,2.47083,2.51653,2.47478,2.46354,2.48828,2.34846, + 2.34419,2.43172,2.46589,2.45462,2.52146,2.35946,2.38810,2.46027,2.53848,2.48102,2.42701,2.51750,2.57911,2.45136,2.48329,2.39329,2.48209, + 2.35948,2.49431,2.36117,2.26121,2.40899,2.51383,2.41642,2.52102,2.39702,2.43949,2.40867,2.38560,2.46874,2.22937,2.40741,2.36007,2.38784, + 2.41052,2.42673,2.39476,2.40239,2.46902,2.55278,2.44661,2.54734,2.41863,2.42451,2.40056,2.44307,2.35066,2.46254,2.43270,2.50439,2.49733, + 2.55563,2.48589,2.45219,2.44774,2.41116,2.49081,2.43893,2.43731,2.55774,2.42404,2.37911,2.45140,2.47196,2.50533,2.38292,2.47868,2.48262, + 2.39845,2.42290,2.54415,2.43109,2.54306,2.49385,2.35113,2.43233,2.50552,2.49532,2.42667,2.53772,2.41398,2.41968,2.59536,2.52077,2.42026, + 2.51269,2.42584,2.54930,2.63547,2.42869,2.43348,2.42402,2.38768,2.41903,2.50153,2.45315,2.45472,2.41113,2.44795,2.50849,2.41817,2.44166, + 2.61143,2.38567,2.40737,2.39843,2.43711,2.35324,2.48315,2.38388,2.45665,2.30220,2.41293,2.36640,2.38185,2.40913,2.49233,2.46818,2.51527, + 2.54177,2.37051,2.37318,2.38405,2.53258,2.58176,2.53786,2.52385,2.40308,2.45279,2.39370,2.50056,2.41076,2.40789,2.47444,2.52857,2.40741, + 2.38524,2.39403,2.42442,2.56829,2.56063,2.58340,2.42897,2.58796,2.56262,2.53480,2.43707,2.38258,2.46584,2.40596,2.42590,2.48281,2.47800 + }; AIDA aida = AIDA.defaultInstance(); IAnalysisFactory analysisFactory = aida.analysisFactory(); IFunctionFactory functionFactory = analysisFactory.createFunctionFactory(null); IFitFactory fitFactory = analysisFactory.createFitFactory(); IFitter fitter=fitFactory.createFitter(); - IFunction fitFunction=new Ecal3PoleFunction(); + IFunction fitFcn3Pole=new Ecal3PoleFunction(); + IFunction fitFcnLinear=functionFactory.createFunctionFromScript("fitFcnLinear",1,"p0+x[0]*p1","p0,p1","",null); IDataPointSet fitData=aida.analysisFactory().createDataPointSetFactory(null).create("ADC DataPointSet", 2); - private final int nsPerSample=4; - public int debug = 0; - public String fitFileName = null; - public FileWriter fitFileWriter = null; - public boolean fixShapeParameter = false; - final private double threePoleWidth=2.478; - - - public IFitResult fitPulse(short samples[],int threshCross,double maxADC,double noise) { + public IFitResult fitLeadingEdge(RawTrackerHit hit,int threshCross) { + + final short samples[] = hit.getADCValues(); + final double noise = findChannel(hit.getCellID()).getCalibration().getNoise(); + + int imaxADC=0; + for (int ii=threshCross; ii<samples.length-1; ii++) + { + if (ii<0) continue; + if (ii>=samples.length) break; + if (samples[ii+1] < samples[ii]) { + imaxADC=ii; + break; + } + } + fitData.clear(); + int nFitPoints=0; + for (int ii=threshCross-1; ii<imaxADC-1; ii++) { + fitData.addPoint(); + fitData.point(nFitPoints).coordinate(0).setValue(ii); + fitData.point(nFitPoints).coordinate(1).setValue(samples[ii]); + fitData.point(nFitPoints).coordinate(1).setErrorMinus(noise); + fitData.point(nFitPoints).coordinate(1).setErrorPlus(noise); + nFitPoints++; + } + + if (nFitPoints<2) return null; + + return fitter.fit(fitData,fitFcnLinear); + } + + public IFitResult[] fitPulse(RawTrackerHit hit,int threshCross,double maxADC) { if (debug>0) System.err.println("FITTING....................................................."); - final int threshRange[]={6,25}; - final int fitRange[]={-10,15}; - final int pedRange[]={-10,-5}; - + final short samples[] = hit.getADCValues(); + final double noise = findChannel(hit.getCellID()).getCalibration().getNoise(); + final int cid = ecalConditions.getChannelCollection().findGeometric(hit.getCellID()).getChannelId(); + // don't bother with pulses far from trigger: if (threshCross < threshRange[0] || threshCross > threshRange[1]) return null; @@ -62,6 +138,7 @@ // choose points to fit and get starting value for pulse integral: fitData.clear(); int nFitPoints=0; + int iPeakADC=-1; int sumADC=0; // int maxADC=0; for (int ii=threshCross+fitRange[0]; ii<threshCross+fitRange[1]; ii++) @@ -70,6 +147,9 @@ if (ii>=samples.length) break; if (debug>0) System.err.print(ii+":"+samples[ii]+" "); // if (samples[ii] > maxADC) maxADC=samples[ii]; + if (iPeakADC<0 && ii<samples.length-1 && samples[ii+1] < samples[ii]) { + iPeakADC=ii; + } sumADC += samples[ii]; fitData.addPoint(); fitData.point(nFitPoints).coordinate(0).setValue(ii); @@ -89,28 +169,29 @@ final double pulseIntegral = sumADC-ped*nFitPoints; // initialize parameters: - fitFunction.setParameter("pedestal",ped); - fitFunction.setParameter("time0",(double)threshCross-2); - fitFunction.setParameter("integral",pulseIntegral>0 ? pulseIntegral : 2); - fitFunction.setParameter("width",threePoleWidth); + fitFcn3Pole.setParameter("pedestal",ped); + fitFcn3Pole.setParameter("time0",(double)threshCross-2); + fitFcn3Pole.setParameter("integral",pulseIntegral>0 ? pulseIntegral : 2); + fitFcn3Pole.setParameter("width",threePoleWidths[cid-1]); // constrain parameters: fitter.fitParameterSettings("integral").setBounds(0,999999); fitter.fitParameterSettings("time0").setBounds(1,30); +// fitter.fitParameterSettings("time0").setBounds(threshRange[0]-5,threshRange[1]+20); fitter.fitParameterSettings("width").setBounds(0.1,5); if (fixShapeParameter) fitter.fitParameterSettings("width").setFixed(true); - ((Ecal3PoleFunction)fitFunction).setDebug(debug>1); + ((Ecal3PoleFunction)fitFcn3Pole).setDebug(debug>1); if (debug>0) { - System.err.println(String.format("A= %8.2f",fitFunction.parameter("integral"))); - System.err.println(String.format("T= %8.2f",fitFunction.parameter("time0")*4)); - System.err.println(String.format("P= %8.2f",fitFunction.parameter("pedestal"))); - System.err.println(String.format("S= %8.2f",fitFunction.parameter("width"))); + System.err.println(String.format("A= %8.2f",fitFcn3Pole.parameter("integral"))); + System.err.println(String.format("T= %8.2f",fitFcn3Pole.parameter("time0")*4)); + System.err.println(String.format("P= %8.2f",fitFcn3Pole.parameter("pedestal"))); + System.err.println(String.format("S= %8.2f",fitFcn3Pole.parameter("width"))); } else Logger.getLogger("org.freehep.math.minuit").setLevel(Level.OFF); - IFitResult fitResult = fitter.fit(fitData,fitFunction); - writeFit(samples,fitResult); + IFitResult fitResult = fitter.fit(fitData,fitFcn3Pole); + writeFit(samples,fitResult,cid); if (debug>0) { final double P = fitResult.fittedParameter("pedestal"); @@ -119,22 +200,31 @@ final double S = fitResult.fittedParameter("width"); final double Q = fitResult.quality(); final double E[] = fitResult.errors(); - - if (debug>0) { - System.err.println(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"); - System.err.println(String.format("I = %8.2f %8.2f",I,sumADC-P*30)); - System.err.println(String.format("T = %8.2f %8.2f",T,threshCross)); - System.err.println(String.format("P = %8.2f %8.2f",P,ped)); - System.err.println(String.format("S = %8.2f %8.2f",S,threePoleWidth)); - System.err.println(String.format("M = %8.2f",maxADC-P)); + System.err.println(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"); + System.err.println(String.format("I = %8.2f %8.2f",I,sumADC-P*30)); + System.err.println(String.format("T = %8.2f %8.2f",T,threshCross)); + System.err.println(String.format("P = %8.2f %8.2f",P,ped)); + System.err.println(String.format("S = %8.2f %8.2f",S,threePoleWidths[cid-1])); + System.err.println(String.format("M = %8.2f",maxADC-P)); + System.err.println(String.format("Q = %8.2f",Q)); + } + + // now fit just leading edge: + IFitResult timeResult = null; + if (doTimeFit) { + for (int ii=fitData.size()-1; ii>=0; ii--) { + if (fitData.point(ii).coordinate(0).value() > iPeakADC+1) fitData.removePoint(ii); + else break; } - } - - return fitResult; - } - - - public void writeFit(short samples[],IFitResult fit) { + fitter.fit(fitData,fitFcn3Pole); + } + + IFitResult fitResults[] = {fitResult,timeResult}; + return fitResults; + } + + + public void writeFit(short samples[],IFitResult fit,final int cid) { if (fitFileName == null) return; if (fitFileWriter == null) { try { fitFileWriter=new FileWriter(fitFileName); } @@ -147,10 +237,31 @@ fitFileWriter.write(String.format("%8.3f",fit.fittedParameter("pedestal"))); fitFileWriter.write(String.format("%8.3f",fit.fittedParameter("width"))); fitFileWriter.write(String.format("%8.3f",fit.quality())); + fitFileWriter.write(String.format("%4d",cid)); fitFileWriter.write("\n"); } catch (IOException ee) { throw new RuntimeException("Error writing file "+fitFileName,ee); } } - -} + + public double getSmartPedestal(short samples[]) { + double ped = 99999; + final int nSamples = 6; + for (int ii=0; ii<samples.length-nSamples; ii++) { + double aped = 0; + for (int jj=ii; jj<ii+nSamples; jj++) aped += samples[jj]; + aped /= nSamples; + if (aped < ped) ped = aped; + } + return ped; + } + public void setDetector(Detector detector) { + // ECAL combined conditions object. + ecalConditions = DatabaseConditionsManager.getInstance().getEcalConditions(); + } + public EcalChannelConstants findChannel(long cellID) { + return ecalConditions.getChannelConstants(ecalConditions.getChannelCollection().findGeometric(cellID)); + } + + +} Modified: java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverter.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverter.java (original) +++ java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverter.java Wed May 27 14:10:48 2015 @@ -1,20 +1,12 @@ package org.hps.users.baltzell; -import org.hps.users.baltzell.Ecal3PoleFunction; - -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 hep.aida.IHistogram1D; +//import hep.aida.IHistogram1D; +//import hep.aida.IHistogram2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.io.FileWriter; -import java.io.IOException; import java.util.ArrayList; import java.util.Map; import java.util.logging.Level; @@ -49,7 +41,9 @@ * @author Nathan Baltzell <[log in to unmask]> * @author Holly Szumila <[log in to unmask]> * - * baltzell: New in 2015: (default behavior is still unchanged) + * baltzell: New in May, 2015: Pulse Fitting. + * + * baltzell: New in Early-2015: (default behavior is still unchanged) * * Implemented conversion of Mode-1 to Mode-3. * @@ -67,18 +61,22 @@ */ public class EcalRawConverter { - - // wtf. + EcalPulseFitter pulseFitter = new EcalPulseFitter(); + + /* AIDA aida = AIDA.defaultInstance(); - IAnalysisFactory analysisFactory = aida.analysisFactory(); - IFunctionFactory functionFactory = analysisFactory.createFunctionFactory(null); - IFitFactory fitFactory = analysisFactory.createFitFactory(); - IFitter fitter=fitFactory.createFitter(); - IFunction fitFunction=new Ecal3PoleFunction(); - IDataPointSet data=aida.analysisFactory().createDataPointSetFactory(null).create("ADC DataPointSet", 2); - - IHistogram1D hWidth = aida.histogram1D("hShape",500,0,5); - IHistogram1D hQuality = aida.histogram1D("hChiSquare",500,0,5); + IHistogram1D hWidth = aida.histogram1D("hWidth",500,0,5); + IHistogram2D hWidthE = aida.histogram2D("hWidthE",500,0,5,100,0,5000.0); + IHistogram1D hChiSquare = aida.histogram1D("hChiSquare",500,0,5); + IHistogram2D hWidthChan = aida.histogram2D("hWidthChan",500,0,5,442,0.5,442.5); + IHistogram2D hSamplesChanW = aida.histogram2D("hSamplesChanW",442,0.5,442.5,50,-0.5,49.5); + IHistogram2D hSamplesChan = aida.histogram2D("hSamplesChan",442,0.5,442.5,50,-0.5,49.5); + IHistogram2D hSamplesChanLoW = aida.histogram2D("hSamplesChanLoW",442,0.5,442.5,50,-0.5,49.5); + IHistogram2D hSamplesChanLo = aida.histogram2D("hSamplesChanLo",442,0.5,442.5,50,-0.5,49.5); + IHistogram2D hSamplesChanHiW = aida.histogram2D("hSamplesChanHiW",442,0.5,442.5,50,-0.5,49.5); + IHistogram2D hSamplesChanHi = aida.histogram2D("hSamplesChanHi",442,0.5,442.5,50,-0.5,49.5); + IHistogram2D hWidthEnergy153 = aida.histogram2D("hWidthEnergy153",500,0,5,500,0,5000); + */ private boolean useTimeWalkCorrection = false; private boolean useRunningPedestal = false; @@ -93,6 +91,11 @@ public String fitFileName = null; public FileWriter fitFileWriter = null; public boolean fixShapeParameter = false; + //final private double threePoleWidth=2.478; + + public void setUseFit(boolean useFit) { this.useFit=useFit; } + public void setFitFileName(String name) { pulseFitter.fitFileName=name; } + public void setFixShapeParameter(boolean fix) { pulseFitter.fixShapeParameter=fix; } /* * The time for one FADC sample (units = ns). @@ -322,89 +325,6 @@ return (lastSample-firstSample+1)*getSingleSamplePedestal(event,cellID); } - public IFitResult fitPulse(short samples[],int thresholdCrossing,double maxADC,double noise) { - - if (thresholdCrossing < 9 || thresholdCrossing > 15) return null; - - if (debug>0) System.err.println("FITTING....................................................."); - - data.clear(); - int nped=0; - double ped=0; - for (int ii=thresholdCrossing-9; ii<thresholdCrossing-5; ii++) { - if (ii<0 || ii>=samples.length) break; - ped += samples[ii]; - nped++; - } - ped /= nped; - if (nped==0) return null; - int npts=0; - int sumADC=0; - for (int ii=thresholdCrossing-10; ii<thresholdCrossing+15; ii++) { - if (ii<0) continue; - if (ii>=samples.length) break; - if (debug>0) System.err.print(ii+":"+samples[ii]+" "); - data.addPoint(); - data.point(npts).coordinate(0).setValue(ii); - data.point(npts).coordinate(1).setValue(samples[ii]); - data.point(npts).coordinate(1).setErrorMinus(noise); - data.point(npts).coordinate(1).setErrorPlus(noise); - sumADC += samples[ii]; - npts++; - } - if (debug>0) System.err.print("\n"); - if (npts>=10) { - if (debug>0) System.err.println("------- "+ped+" "+thresholdCrossing+" "+maxADC); - if (maxADC-ped < 0) return null; - final double pulseIntegral = sumADC-ped*npts; - fitFunction.setParameter("pedestal",ped); - fitFunction.setParameter("time0",(double)thresholdCrossing-2); - fitFunction.setParameter("integral",pulseIntegral>0?pulseIntegral:10); - fitFunction.setParameter("width",2.478); - ((Ecal3PoleFunction)fitFunction).setDebug(debug>1); - - if (debug>0) { - System.err.println(String.format("A= %8.2f",fitFunction.parameter("integral"))); - System.err.println(String.format("T= %8.2f",fitFunction.parameter("time0")*4)); - System.err.println(String.format("P= %8.2f",fitFunction.parameter("pedestal"))); - System.err.println(String.format("S= %8.2f",fitFunction.parameter("width"))); - } - - fitter.fitParameterSettings("integral").setBounds(0,999999); - fitter.fitParameterSettings("time0").setBounds(5,40); - fitter.fitParameterSettings("width").setBounds(0.1,5); - if (fixShapeParameter) fitter.fitParameterSettings("width").setFixed(true); - - if (debug<1) Logger.getLogger("org.freehep.math.minuit").setLevel(Level.OFF); - IFitResult fitResult = fitter.fit(data,fitFunction); - writeFit(samples,fitResult); - return fitResult; - } - return null; - } - - public void writeFit(short samples[],IFitResult fit) { - if (fitFileName == null) return; - if (fitFileWriter == null) { - try { fitFileWriter=new FileWriter(fitFileName); } - catch (IOException ee) { throw new RuntimeException("Error opening file "+fitFileName,ee); } - } - - try { - for (final short ss : samples) fitFileWriter.write(String.format("%6d ",ss)); - fitFileWriter.write(String.format("%8.3f",fit.fittedParameter("integral"))); - fitFileWriter.write(String.format("%8.3f",fit.fittedParameter("time0"))); - fitFileWriter.write(String.format("%8.3f",fit.fittedParameter("pedestal"))); - fitFileWriter.write(String.format("%8.3f",fit.fittedParameter("width"))); - fitFileWriter.write(String.format("%8.3f",fit.quality())); - fitFileWriter.write("\n"); - } catch (IOException ee) { - throw new RuntimeException("Error writing file "+fitFileName,ee); - } - } - - - /* * Emulate the FADC250 firmware in conversion of Mode-1 waveform to a Mode-3/7 pulse, * given a time for threshold crossing. @@ -490,9 +410,13 @@ final int a0 = samples[t0]; final int a1 = samples[t1]; final double slope = (a1 - a0); // units = ADC/sample - final double yint = a1 - slope * t1; // units = ADC + final double yint = a1 - slope * t1; // units = ADC + + // mode-7 time, time at half max: pulseTime = ((halfMax - a0)/(a1-a0) + t0)* nsPerSample; - + + // mode-8 time, time at pedestal intersection: + //pulseTime = (minADC-yint)/slope * nsPerSample; } } @@ -500,40 +424,50 @@ if (useFit) { - final double noise=findChannel(hit.getCellID()).getCalibration().getNoise(); - IFitResult fitResult=fitPulse(samples,thresholdCrossing,maxADC,noise); - - if (fitResult != null) { - - final double P=fitResult.fittedParameter("pedestal"); - final double A=fitResult.fittedParameter("integral"); - final double T=fitResult.fittedParameter("time0"); - final double S=fitResult.fittedParameter("width"); - final double Q=fitResult.quality(); - - // finite integral from T to T+NSAMP: - //final int NSAMP=30; - //final double I = (A/2/S) * S*S*S* ( 2 - Math.exp(-NSAMP/S) * (Math.pow((S+NSAMP)/S,2) + 1)); - - // infinite integral: - //final double I = A*S*S; + IFitResult fitResults[] = pulseFitter.fitPulse(hit,thresholdCrossing,maxADC); + if (fitResults!=null && fitResults[0]!=null) { - // after normalizing the function: - final double I = A; + IFitResult fitResult=fitResults[0]; + IFitResult timeResult=fitResults[1]==null?fitResults[0]:fitResults[1]; + + pulseTime = timeResult.fittedParameter("time0")*nsPerSample; + sumADC = fitResult.fittedParameter("integral"); + minADC = fitResult.fittedParameter("pedestal"); + maxADC = ((Ecal3PoleFunction)fitResult.fittedFunction()).maximum(); - if (debug>0) { - System.err.println(";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"); - System.err.println(String.format("A= %8.2f %8.2f",I,sumADC-P*30)); - System.err.println(String.format("T= %8.2f %8.2f",T*4,pulseTime)); - System.err.println(String.format("P= %8.2f %8.2f",P,minADC)); - System.err.println(String.format("S= %8.2f",S)); - System.err.println(String.format("M= %8.2f %8.2f",A,(maxADC-P))); - } - - hWidth.fill(S); - hQuality.fill(Q); - pulseTime = T*4; - sumADC = I; + /* + final double width = fitResult.fittedParameter("width"); + //final double E[] = fitResult.errors(); + final int cid = getChannelId(hit.getCellID()); + hWidth.fill(width); + hWidthE.fill(width,fitResult.fittedParameter("integral")); + if (cid==153) hWidthEnergy153.fill(width,fitResult.fittedParameter("integral")); + hChiSquare.fill(fitResult.quality()); + hWidthChan.fill(width,cid); + for (int ii=0; ii<samples.length; ii++) { + hSamplesChan.fill(cid,ii); + hSamplesChanW.fill(cid,ii,samples[ii]); + if (fitResult.fittedParameter("integral") > 2000) + { + hSamplesChanHi.fill(cid,ii); + hSamplesChanHiW.fill(cid,ii,samples[ii]); + } + else if (fitResult.fittedParameter("integral") < 1000) + { + hSamplesChanLo.fill(cid,ii); + hSamplesChanLoW.fill(cid,ii,samples[ii]); + } + } + */ + + /* + timeResult = pulseFitter.fitLeadingEdge(hit,thresholdCrossing); + if (timeResult != null) { + final double p0 = timeResult.fittedParameter("p0"); + final double p1 = timeResult.fittedParameter("p1"); + pulseTime = (minADC-p0)/p1 * nsPerSample; + } + */ } } return new double []{pulseTime,sumADC,minADC,maxADC}; @@ -711,6 +645,8 @@ public void setDetector(Detector detector) { // ECAL combined conditions object. ecalConditions = DatabaseConditionsManager.getInstance().getEcalConditions(); + + pulseFitter.setDetector(detector); } /** @@ -723,4 +659,8 @@ return ecalConditions.getChannelConstants(ecalConditions.getChannelCollection().findGeometric(cellID)); } + public int getChannelId(long cellID) { + return ecalConditions.getChannelCollection().findGeometric(cellID).getChannelId(); + } + } Modified: java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverterDriver.java ============================================================================= --- java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverterDriver.java (original) +++ java/trunk/users/src/main/java/org/hps/users/baltzell/EcalRawConverterDriver.java Wed May 27 14:10:48 2015 @@ -57,9 +57,9 @@ converter = new EcalRawConverter(); } - public void setUseFit(boolean useFit) { converter.useFit=useFit; } - public void setFitFileName(String name) { converter.fitFileName=name; } - public void setFixShapeParameter(boolean fix) { converter.fixShapeParameter=fix; } + public void setUseFit(boolean useFit) { converter.setUseFit(useFit); } + public void setFitFileName(String name) { converter.setFitFileName(name); } + public void setFixShapeParameter(boolean fix) { converter.setFixShapeParameter(fix); } /**