Skip to content

Commit 0b6a87f

Browse files
committed
restore thread safety
1 parent ad9d08b commit 0b6a87f

File tree

1 file changed

+95
-98
lines changed
  • common-tools/clas-detector/src/main/java/org/jlab/detector/pulse

1 file changed

+95
-98
lines changed

common-tools/clas-detector/src/main/java/org/jlab/detector/pulse/ModeAHDC.java

Lines changed: 95 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)