@@ -45,17 +45,6 @@ public class ModeAHDC extends HipoExtractor {
4545 // dream clock for fine timestamp correction
4646 private final float dream_clock = 8.0f ;
4747
48- //Waveform and corresponding pulse
49- //This is the CURRENT pulse, it is initialized
50- //at every extraction. This is not the cleanest
51- //but it avoids feeding the same arguments to all methods
52- private short [] samples ;
53- private Pulse pulse ;
54- private long time_ZS ;
55- private int binMax ;
56- private int numberOfBins ;
57- private int effectiveNumberOfBins ;
58-
5948 //Waveform types:
6049 //wfType 6 ⇒ too small (nsamples <= 10)
6150 //wfType 5 ⇒ decreasing baseline (or leadingEdgeTime fails)
@@ -65,47 +54,55 @@ public class ModeAHDC extends HipoExtractor {
6554 //wfType 1 ⇒ saturing
6655 //wfType 0 ⇒ OK
6756
57+ public static class AHDCPulse extends Pulse {
58+ public long time_ZS ;
59+ public int binMax ;
60+ public int numberOfBins ;
61+ public int effectiveNumberOfBins ;
62+ private short [] samples ;
63+ }
64+
6865 /**
6966 *
7067 */
71- public void preProcess () {
72- assignValidType (0 );
73- this .numberOfBins = samples .length ;
68+ public void preProcess (AHDCPulse p ) {
69+ assignValidType (0 , p );
70+ p .numberOfBins = p . samples .length ;
7471 // check if the signal is too short
7572 int countNotZeros = 0 ;
7673 boolean FirstNonZeroFromTheTailReached = false ;
77- for (int i = samples .length -1 ; i >= 0 ; i --) {
78- if (samples [i ] > 0 ) {
74+ for (int i = p . samples .length -1 ; i >= 0 ; i --) {
75+ if (p . samples [i ] > 0 ) {
7976 countNotZeros ++;
8077 if (!FirstNonZeroFromTheTailReached ) {
8178 FirstNonZeroFromTheTailReached = true ;
82- this .effectiveNumberOfBins = i +1 ; // this value can be identified as the effective number of bins
79+ p .effectiveNumberOfBins = i +1 ; // this value can be identified as the effective number of bins
8380 }
8481 }
8582 }
86- if (countNotZeros <= 10 ) assignInvalidType ();
83+ if (countNotZeros <= 10 ) assignInvalidType (p );
8784 }
8885
8986 /**
9087 * This method computes the waveform baseline
9188 * from the average of the first few samples
9289 */
93- public void baselineComputation ()
90+ public void baselineComputation (AHDCPulse p )
9491 {
9592 //Default baseline
9693 float adcOffset = -99 ;
9794
9895 //Check if the wf has sufficient length, if not it is invalid
99- if (numberOfBins >= this .nBaselineSamples +1 ){
96+ if (p . numberOfBins >= this .nBaselineSamples +1 ){
10097
10198 //The baseline is the average of the first few samples
10299 for (int i =0 ; i <this .nBaselineSamples ;i ++){
103- adcOffset += this .samples [i ];
100+ adcOffset += p .samples [i ];
104101 }
105102 adcOffset = adcOffset /this .nBaselineSamples ;
106103 }
107- else {this .assignInvalidType ();}//invalid, too short wf
108- this . pulse .pedestal = adcOffset ;
104+ else {this .assignInvalidType (p );}//invalid, too short wf
105+ p .pedestal = adcOffset ;
109106 }
110107
111108 /**
@@ -115,16 +112,16 @@ public void baselineComputation()
115112 *
116113 * @param type an int that is the new wf type to be applied
117114 */
118- public void assignValidType (int type ){
115+ public void assignValidType (int type , AHDCPulse p ){
119116 //We only assign a new type if a more restrictive type was not defined before
120- if (type >this . pulse . wftype ) this . pulse .wftype = (short ) type ;
117+ if (type >p . wftype ) p .wftype = (short ) type ;
121118 }
122119
123120 /**
124121 * This method assigns an invalid type (-1) to the waveform
125122 */
126- public void assignInvalidType (){
127- this . pulse .wftype = 6 ;
123+ public void assignInvalidType (AHDCPulse p ){
124+ p .wftype = 6 ;
128125 }
129126
130127 /**
@@ -135,13 +132,13 @@ public void assignInvalidType(){
135132 * @return an int for status
136133 *
137134 */
138- public int waveformADCProcessing ()
135+ public int waveformADCProcessing (AHDCPulse p )
139136 {
140137 //int numberOfBins = this.samples.length;
141138
142139 //Initialize to dummy values
143- this . pulse .adcMax = -99 ;
144- this .binMax = -99 ;
140+ p .adcMax = -99 ;
141+ p .binMax = -99 ;
145142
146143 //For invalid wf, dummy values kept
147144 //if(this.pulse.wftype == 6) return 0;
@@ -154,20 +151,20 @@ public int waveformADCProcessing()
154151 int endPlateau = -99 ;
155152
156153 //Looping through samples
157- for (int bin = 0 ; bin < numberOfBins ; bin ++){
154+ for (int bin = 0 ; bin < p . numberOfBins ; bin ++){
158155 //Baseline subtraction
159- this .samples [bin ] = (short ) Math .max (this .samples [bin ] - this . pulse .pedestal , 0 );
156+ p .samples [bin ] = (short ) Math .max (p .samples [bin ] - p .pedestal , 0 );
160157 //Look for maximum
161- if ((this . pulse . adcMax < this .samples [bin ]) && (bin >= nBaselineSamples )) { // the max should not be in the baseline
162- this . pulse . adcMax = this .samples [bin ];
163- this .binMax = bin ;
158+ if ((p . adcMax < p .samples [bin ]) && (bin >= nBaselineSamples )) { // the max should not be in the baseline
159+ p . adcMax = p .samples [bin ];
160+ p .binMax = bin ;
164161 }
165162 //Integration
166- this . pulse . integral += this .samples [bin ];
163+ p . integral += p .samples [bin ];
167164
168165 //Check for saturation: if the sample exceeds the ths
169166 //and if it belongs to a group of saturating samples
170- if (this .samples [bin ]>(this .ADC_LIMIT -this . pulse .pedestal )){
167+ if (p .samples [bin ]>(this .ADC_LIMIT -p .pedestal )){
171168 //if this is the first sample saturating, start a new plateau
172169 if (nsaturating ==0 ) startPlateau = bin ;
173170 //else continue the plateau
@@ -182,23 +179,23 @@ public int waveformADCProcessing()
182179 //Saturating samples: if the number of consecutive saturating samples
183180 //is greater than the limit, we consider the wf saturated
184181 if (maxNsaturating >=this .consecutiveSaturatingSamples ){
185- this .assignValidType (1 );
182+ this .assignValidType (1 , p );
186183 //The time is taken as the middle of the plateau
187- this .binMax = (startPlateau + endPlateau )/2 ;
184+ p .binMax = (startPlateau + endPlateau )/2 ;
188185 }
189186
190187 //Define the pulse time as the peak time
191- this . pulse . time = (this .binMax + this .time_ZS )*this .samplingTime ;
188+ p . time = (p .binMax + p .time_ZS )*this .samplingTime ;
192189 //If there are 2*npts+1 points around the peak
193190 //(if the peak is not at an edge of the window)
194191 //Then the peak ADC value is revisited to be the average of these
195192 //TO DO: just use the adcmax???
196193 int npts = 1 ;
197- if (this . pulse . adcMax == 0 ) { assignValidType (5 );} // classification before the fit
198- if ((this .binMax - npts >= 0 ) && (this .binMax + npts <= numberOfBins - 1 )){
199- this . pulse .adcMax = 0 ;
200- for (int bin = this .binMax - npts ; bin <= this .binMax + npts ; bin ++) this . pulse . adcMax += this .samples [bin ];
201- this . pulse . adcMax = this . pulse .adcMax /(2 *npts +1 );
194+ if (p . adcMax == 0 ) { assignValidType (5 , p );} // classification before the fit
195+ if ((p .binMax - npts >= 0 ) && (p .binMax + npts <= p . numberOfBins - 1 )){
196+ p .adcMax = 0 ;
197+ for (int bin = p .binMax - npts ; bin <= p .binMax + npts ; bin ++) p . adcMax += p .samples [bin ];
198+ p . adcMax = p .adcMax /(2 *npts +1 );
202199 }
203200
204201 return 0 ;
@@ -212,47 +209,47 @@ public int waveformADCProcessing()
212209 * @return an int for status
213210 *
214211 */
215- public int waveformCFAprocessing (){
212+ public int waveformCFAprocessing (AHDCPulse p ){
216213
217214 //Initialization
218- this . pulse .leadingEdgeTime = -9999 ;
219- this . pulse .trailingEdgeTime = -9999 ;
220- this . pulse .timeOverThreshold = -9999 ;
215+ p .leadingEdgeTime = -9999 ;
216+ p .trailingEdgeTime = -9999 ;
217+ p .timeOverThreshold = -9999 ;
221218
222219 //Set the CFA threshold
223- float threshold = this .amplitudeFractionCFA *this . pulse .adcMax ;
220+ float threshold = this .amplitudeFractionCFA *p .adcMax ;
224221
225222 //Crossing the threshold before the peak
226223 int binRise = -99 ;
227- for (int bin = 0 ; bin < binMax - 1 ; bin ++){
228- if (this .samples [bin ] < threshold && this .samples [bin +1 ] >= threshold )
224+ for (int bin = 0 ; bin < p . binMax - 1 ; bin ++){
225+ if (p .samples [bin ] < threshold && p .samples [bin +1 ] >= threshold )
229226 binRise = bin ; //Here we keep only the last time the signal crosses the threshold
230227 }
231228 //If the waveform does not cross the ths before the peak
232229 //it was early or remant from a previous event and we cannot define a leading time
233230 //we set the time at zero
234231 if (binRise ==-99 ) {
235- this .assignValidType (5 );
236- this . pulse . leadingEdgeTime = (0 + this .time_ZS )*this .samplingTime ;
232+ this .assignValidType (5 , p );
233+ p . leadingEdgeTime = (0 + p .time_ZS )*this .samplingTime ;
237234 }
238235 else
239236 {
240237 float slopeRise = 0 ;
241238 //linear interpolation
242239 //threshold = leadingtime*(ADC1-ADC0)+ADC0
243- if (binRise + 1 <= numberOfBins -1 )
244- slopeRise = this .samples [binRise +1 ] - this .samples [binRise ];
245- float fittedBinRise = (slopeRise == 0 ) ? binRise : binRise + (threshold - this .samples [binRise ])/slopeRise ;
246- this . pulse . leadingEdgeTime = (fittedBinRise + this .time_ZS )*this .samplingTime ;
240+ if (binRise + 1 <= p . numberOfBins -1 )
241+ slopeRise = p .samples [binRise +1 ] - p .samples [binRise ];
242+ float fittedBinRise = (slopeRise == 0 ) ? binRise : binRise + (threshold - p .samples [binRise ])/slopeRise ;
243+ p . leadingEdgeTime = (fittedBinRise + p .time_ZS )*this .samplingTime ;
247244 }
248245
249246 //Crossing the threshold back down after the peak
250247 int binFall = -99 ;
251- for (int bin = binMax ; bin < numberOfBins -1 ; bin ++){
252- if (this .samples [bin ] > threshold
253- && this .samples [bin +1 ] <= threshold
254- && this .samples [bin ]>0
255- && this .samples [bin +1 ]>0 ){
248+ for (int bin = p . binMax ; bin < p . numberOfBins -1 ; bin ++){
249+ if (p .samples [bin ] > threshold
250+ && p .samples [bin +1 ] <= threshold
251+ && p .samples [bin ]>0
252+ && p .samples [bin +1 ]>0 ){
256253 binFall = bin +1 ;
257254 break ; //We keep only the first time the signal crosses back the threshold
258255 }
@@ -261,21 +258,21 @@ public int waveformCFAprocessing(){
261258 //it was late and falling edge cannot be defined
262259 //the time correspond to the end of the signal
263260 if (binFall ==-99 ) {
264- this .assignValidType (2 );
265- this . pulse . trailingEdgeTime = (this .effectiveNumberOfBins -1 + this .time_ZS )*this .samplingTime ;
261+ this .assignValidType (2 , p );
262+ p . trailingEdgeTime = (p .effectiveNumberOfBins -1 + p .time_ZS )*this .samplingTime ;
266263 }
267264 else
268265 {
269266 float slopeFall = 0 ;
270267 if (binFall - 1 >= 0 )
271- slopeFall = this .samples [binFall ] - this .samples [binFall -1 ];
272- float fittedBinFall = (slopeFall == 0 ) ? binFall : binFall -1 + (threshold - this .samples [binFall -1 ])/slopeFall ;
273- this . pulse . trailingEdgeTime = (fittedBinFall + this .time_ZS )*this .samplingTime ;
268+ slopeFall = p .samples [binFall ] - p .samples [binFall -1 ];
269+ float fittedBinFall = (slopeFall == 0 ) ? binFall : binFall -1 + (threshold - p .samples [binFall -1 ])/slopeFall ;
270+ p . trailingEdgeTime = (fittedBinFall + p .time_ZS )*this .samplingTime ;
274271 }
275272
276- this . pulse . timeOverThreshold = this . pulse . trailingEdgeTime - this . pulse .leadingEdgeTime ;
273+ p . timeOverThreshold = p . trailingEdgeTime - p .leadingEdgeTime ;
277274 //if ((this.pulse.timeOverThreshold < 300) || (this.pulse.timeOverThreshold > 750)) this.assignValidType(4); // bad tot
278- if (this . pulse . timeOverThreshold < 300 ) this .assignValidType (4 ); // tot too small
275+ if (p . timeOverThreshold < 300 ) this .assignValidType (4 , p ); // tot too small
279276
280277 return 0 ;
281278 }
@@ -287,24 +284,24 @@ public int waveformCFAprocessing(){
287284 * @return an int for status
288285 *
289286 */
290- public int computeTimeUsingConstantFractionDiscriminator (){
287+ public int computeTimeUsingConstantFractionDiscriminator (AHDCPulse p ){
291288 //Dummy values for hits for which the leading edge is not defined
292- this . pulse .constantFractionTime = -99 ;
293- if (this . pulse .wftype >=4 ) return 0 ;
289+ p .constantFractionTime = -99 ;
290+ if (p .wftype >=4 ) return 0 ;
294291
295292 //int numberOfBins = this.samples.length;
296- float [] signal = new float [numberOfBins ];
293+ float [] signal = new float [p . numberOfBins ];
297294
298295 // signal generation
299- for (int bin = 0 ; bin < numberOfBins ; bin ++){
300- signal [bin ] = (1 - this .fractionCFD )*this .samples [bin ]; // we fill it with a fraction of the original signal
301- if (bin < numberOfBins - this .binDelayCFD )
302- signal [bin ] += -1 *this .fractionCFD *this .samples [bin + this .binDelayCFD ]; // we advance and invert a complementary fraction of the original signal and superimpose it to the previous signal
296+ for (int bin = 0 ; bin < p . numberOfBins ; bin ++){
297+ signal [bin ] = (1 - this .fractionCFD )*p .samples [bin ]; // we fill it with a fraction of the original signal
298+ if (bin < p . numberOfBins - this .binDelayCFD )
299+ signal [bin ] += -1 *this .fractionCFD *p .samples [bin + this .binDelayCFD ]; // we advance and invert a complementary fraction of the original signal and superimpose it to the previous signal
303300 }
304301 // determine the two humps
305302 int binHumpSup = 0 ;
306303 int binHumpInf = 0 ;
307- for (int bin = 0 ; bin < numberOfBins ; bin ++){
304+ for (int bin = 0 ; bin < p . numberOfBins ; bin ++){
308305 if (signal [bin ] > signal [binHumpSup ])
309306 binHumpSup = bin ;
310307 }
@@ -319,10 +316,10 @@ public int computeTimeUsingConstantFractionDiscriminator(){
319316 binZero = bin ; // last pass below zero
320317 } // at this stage : binZero < constantFractionTime/samplingTime <= binZero + 1 // constantFractionTime is determined by assuming a linear fit between binZero and binZero + 1
321318 float slopeCFD = 0 ;
322- if (binZero + 1 <= numberOfBins )
319+ if (binZero + 1 <= p . numberOfBins )
323320 slopeCFD = signal [binZero +1 ] - signal [binZero ];
324321 float fittedBinZero = (slopeCFD == 0 ) ? binZero : binZero + (0 - signal [binZero ])/slopeCFD ;
325- this . pulse . constantFractionTime = (fittedBinZero + this .time_ZS )*this .samplingTime ;
322+ p . constantFractionTime = (fittedBinZero + p .time_ZS )*this .samplingTime ;
326323
327324 return 0 ;
328325 }
@@ -336,9 +333,9 @@ public int computeTimeUsingConstantFractionDiscriminator(){
336333 * @param fineTimeStampResolution correspond to the dream clock (usually equals to 8; but to be checked!)
337334 */
338335
339- private void fineTimeStampCorrection (long timestamp , float fineTimeStampResolution ) {
336+ private void fineTimeStampCorrection (long timestamp , float fineTimeStampResolution , AHDCPulse p ) {
340337 long fineTimeStamp = timestamp & 0x00000007 ; // keep and convert last 3 bits of binary timestamp
341- this . pulse .leadingEdgeTime += (double ) ((fineTimeStamp +0.5 ) * fineTimeStampResolution ); //fineTimeStampCorrection, only on the leadingEdgeTime for the moment (we don't use timeMax or constantFractionTime in the reconstruction yet)
338+ p .leadingEdgeTime += (double ) ((fineTimeStamp +0.5 ) * fineTimeStampResolution ); //fineTimeStampCorrection, only on the leadingEdgeTime for the moment (we don't use timeMax or constantFractionTime in the reconstruction yet)
342339 }
343340
344341 /**
@@ -357,33 +354,33 @@ public List<Pulse> extract(NamedEntry pars, int id, long timestamp, long time_ZS
357354 //Initialize everything each time a new wf is read
358355 //and new adc information is extracted.
359356 //This is messy but avoids feeding the same arguments to all methods
360- this .pulse = new Pulse ();
361- this .pulse .id = id ;
362- this .pulse .timestamp = timestamp ;
363- this .time_ZS = time_ZS ;
364- this .samples = samples ;
365- this .binMax = -99 ;
366-
367- List <Pulse > output = new ArrayList <>();
357+ AHDCPulse pulse = new AHDCPulse ();
358+ pulse .id = id ;
359+ pulse .timestamp = timestamp ;
360+ pulse .time_ZS = time_ZS ;
361+ pulse .samples = samples ;
362+ pulse .binMax = -99 ;
368363
369364 // Pre Process
370- this .preProcess ();
365+ this .preProcess (pulse );
366+
371367 //Baseline computation
372- this .baselineComputation ();
368+ this .baselineComputation (pulse );
373369
374370 //Get the ADC information from the pulse (peak ADC and time, integral)
375- this .waveformADCProcessing ();
371+ this .waveformADCProcessing (pulse );
376372
377373 //Get the time overr threshold
378- this .waveformCFAprocessing ();
374+ this .waveformCFAprocessing (pulse );
379375
380376 //Get the CFD time
381- this .computeTimeUsingConstantFractionDiscriminator ();
377+ this .computeTimeUsingConstantFractionDiscriminator (pulse );
382378
383379 // Fine timestamp correction on leadingEdgeTime
384- this .fineTimeStampCorrection (timestamp , dream_clock );
380+ this .fineTimeStampCorrection (timestamp , dream_clock , pulse );
385381
386- output .add (this .pulse );
382+ List <Pulse > output = new ArrayList <>();
383+ output .add (pulse );
387384 return output ;
388385 }
389386
0 commit comments