Neutral Particle Spectrometer analysis code
Loading...
Searching...
No Matches
THcNPSArray.cxx
Go to the documentation of this file.
1
8#include "THcNPSArray.h"
9#include "THcHodoscope.h"
10#include "TClonesArray.h"
11#include "THcSignalHit.h"
12#include "THcGlobals.h"
13#include "THcParmList.h"
14#include "THcHitList.h"
15#include "THcNPSCalorimeter.h"
17#include "THcRawShowerHit.h"
18#include "TClass.h"
19//#include "TSpectrum.h" // DJH 09/04/22 -- commented out for now
20#include "math.h"
21#include "THaTrack.h"
22#include "THaTrackProj.h"
23#include "THcCherenkov.h" //for efficiency calculations
25#include "Helper.h"
26
27#include <cstring>
28#include <cstdio>
29#include <cstdlib>
30#include <iostream>
31#include <cassert>
32#include <fstream>
33
34using namespace std;
35
37
38//______________________________________________________________________________
39THcNPSArray::THcNPSArray( const char* name,
40 const char* description,
41 const Int_t layernum,
42 THaDetectorBase* parent )
43 : THaSubDetector(name,description,parent)
44{
45 fADCHits = new TClonesArray("THcSignalHit",100);
46 fLayerNum = layernum;
47
48 //C.Y. Mar 15, 2021: Is '16' the maximum total number of hits for all blocks / event ?
49 //This limit seems low, as there may be more total hits (see shms_all_10300.dat) (specially for higher block density of NPS)
50 //Need to remember and increase this upper limit when the time comes.
51 frAdcPedRaw = new TClonesArray("THcSignalHit", 16);
52 frAdcErrorFlag = new TClonesArray("THcSignalHit", 16);
53 frAdcPulseIntRaw = new TClonesArray("THcSignalHit", 16);
54 frAdcPulseAmpRaw = new TClonesArray("THcSignalHit", 16);
55 frAdcPulseTimeRaw = new TClonesArray("THcSignalHit", 16);
56 frAdcPed = new TClonesArray("THcSignalHit", 16);
57 frAdcPulseInt = new TClonesArray("THcSignalHit", 16);
58 frAdcPulseAmp = new TClonesArray("THcSignalHit", 16);
59 frAdcPulseTime = new TClonesArray("THcSignalHit", 16);
60
61 // DJH 14 Sep 22
62 frAdcSampPedRaw = new TClonesArray("THcSignalHit", 16);
63 frAdcSampPulseIntRaw = new TClonesArray("THcSignalHit", 16);
64 frAdcSampPulseAmpRaw = new TClonesArray("THcSignalHit", 16);
65 frAdcSampPulseTimeRaw = new TClonesArray("THcSignalHit", 16);
66 frAdcSampPed = new TClonesArray("THcSignalHit", 16);
67 frAdcSampPulseInt = new TClonesArray("THcSignalHit", 16);
68 frAdcSampPulseAmp = new TClonesArray("THcSignalHit", 16);
69 frAdcSampPulseTime = new TClonesArray("THcSignalHit", 16);
70
71 fClusterList = new THcNPSShowerClusterList; // List of hit clusters
72
73
74
75}
76
77//______________________________________________________________________________
79{
80 // Destructor
81
82 Clear(); // deletes allocations in fClusterList
83 for (UInt_t i=0; i<fNRows; i++) {
84 delete [] fXPos[i];
85 delete [] fYPos[i];
86 delete [] fZPos[i];
87 }
88 delete [] fXPos; fXPos = 0;
89 delete [] fYPos; fYPos = 0;
90 delete [] fZPos; fZPos = 0;
91
92 delete [] fPedLimit;
93 delete [] fGain;
94 delete [] fPedSum;
95 delete [] fPedSum2;
96 delete [] fPedCount;
97 delete [] fSig;
98 delete [] fPed;
99 delete [] fThresh;
100
101 delete fADCHits; fADCHits = NULL;
102
103 delete frAdcPedRaw; frAdcPedRaw = NULL;
104 delete frAdcErrorFlag; frAdcErrorFlag = NULL;
105 delete frAdcPulseIntRaw; frAdcPulseIntRaw = NULL;
106 delete frAdcPulseAmpRaw; frAdcPulseAmpRaw = NULL;
108 delete frAdcPed; frAdcPed = NULL;
109 delete frAdcPulseInt; frAdcPulseInt = NULL;
110 delete frAdcPulseAmp; frAdcPulseAmp = NULL;
111 delete frAdcPulseTime; frAdcPulseTime = NULL;
112
113 // DJH 14 Sep 22
114 delete frAdcSampPedRaw; frAdcSampPedRaw = NULL;
118 delete frAdcSampPed; frAdcSampPed = NULL;
122
123 //delete [] fA;
124 //delete [] fP;
125 //delete [] fA_p;
126
127 //delete [] fE;
128 delete [] fBlock_ClusterID;
129
130 delete fClusterList; fClusterList = 0;
131
134
135 delete [] fAdcPulseTimeMin; fAdcPulseTimeMin = 0;
136 delete [] fAdcPulseTimeMax; fAdcPulseTimeMax = 0;
137 delete [] fPedDefault; fPedDefault = 0;
138
139}
140
141//_____________________________________________________________________________
143{
144
145 THcHallCSpectrometer *app = dynamic_cast<THcHallCSpectrometer*>
146 ( FindModule( "H", "THcHallCSpectrometer"));
148 if( !app ||
149 !(fglHod = dynamic_cast<THcHodoscope*>(app->GetDetector("hod"))) ) {
151 static const char* const here = "ReadDatabase()";
152 Warning(Here(here),"Hodoscope \"%s\" not found. ","hod");
153 }
154
155 string kwPrefix = GetApparatus()->GetPrefix();
156 std::transform(kwPrefix.begin(), kwPrefix.end(), kwPrefix.begin(), ::tolower);
157
158 //C.Y. Jan 21, 2021 : For some odd reason, the kwPrefix returns the spectrometer apparatus prefix as "nps."
159 //so I had to manually erase this last "." character for the prefix to be fixed and properly read the NPS
160 //parameters
161 fKwPrefix = kwPrefix.erase(kwPrefix.size()-1);
162
163 // Extra initialization for shower layer: set up DataDest map
164 if( IsZombie())
165 return fStatus = kInitError;
166
167 EStatus status;
168 if( (status=THaSubDetector::Init( date )) )
169 return fStatus = status;
170
171 return fStatus = kOK;
172
173}
174
175//_____________________________________________________________________________
177{
178
179 // cout << "Parent name: " << GetParent()->GetPrefix() << endl;
183 fUsingFADC=0;
184 fPedSampLow=0;
185 fPedSampHigh=9;
186 fDataSampLow=23;
187 fDataSampHigh=49;
188 fStatCerMin=1.;
189 fStatSlop=3.;
190 fStatMaxChi2=10.;
191 DBRequest list[]={
192 {"_cal_arr_nrows", &fNRows, kInt},
193 {"_cal_arr_ncolumns", &fNColumns, kInt},
194 {"_cal_arr_front_x", &fXFront, kDouble},
195 {"_cal_arr_front_y", &fYFront, kDouble},
196 {"_cal_arr_front_z", &fZFront, kDouble},
197 {"_cal_arr_xstep", &fXStep, kDouble},
198 {"_cal_arr_ystep", &fYStep, kDouble},
199 {"_cal_arr_zsize", &fZSize, kDouble},
200 {"_cal_using_fadc", &fUsingFADC, kInt, 0, 1},
201 {"_cal_clustering", &fClustMethod, kInt, 0, 1},
202 // {"_cal_arr_ADCMode", &fADCMode, kInt, 0, 1},
203 {"_cal_arr_AdcThreshold", &fAdcThreshold, kDouble, 0, 1},
204 {"_cal_arr_adc_samp_threshold", &fAdcSampThreshold, kDouble, 0, 1},
205 {"_cal_arr_adc_peak_samp_width", &fDataSampWidth, kDouble, 0, 1},
206 {"_cal_ped_sample_low", &fPedSampLow, kInt, 0, 1},
207 {"_cal_ped_sample_high", &fPedSampHigh, kInt, 0, 1},
208 {"_cal_data_sample_low", &fDataSampLow, kInt, 0, 1},
209 {"_cal_data_sample_high", &fDataSampHigh, kInt, 0, 1},
210 {"_cal_debug_adc", &fDebugAdc, kInt, 0, 1},
211 {"_stat_cermin", &fStatCerMin, kDouble, 0, 1},
212 {"_stat_slop_array", &fStatSlop, kDouble, 0, 1},
213 {"_stat_maxchisq", &fStatMaxChi2, kDouble, 0, 1},
214 {0}
215 };
216
217 fClustMethod = 0; //Set default clusterin method to HMS/SHMS original
218 fDebugAdc = 0; // Set ADC debug parameter to false unless set in parameter file
219 // fADCMode=kADCDynamicPedestal;
220 fAdcThreshold=0.;
221 fAdcSampThreshold=30; // Peak found if this amount above pedestal
222 fDataSampWidth=15; // Integrate this # of samples to get peak area
223
224 gHcParms->LoadParmValues((DBRequest*)&list, fKwPrefix.c_str());
225
227
228 fXPos = new Double_t* [fNRows];
229 fYPos = new Double_t* [fNRows];
230 fZPos = new Double_t* [fNRows];
231 for (UInt_t i=0; i<fNRows; i++) {
232 fXPos[i] = new Double_t [fNColumns];
233 fYPos[i] = new Double_t [fNColumns];
234 fZPos[i] = new Double_t [fNColumns];
235 }
236
237 //Looking to the front, the numbering goes from left to right, and from bottom
238 //to top.
239
240 for (UInt_t j=0; j<fNColumns; j++)
241 for (UInt_t i=0; i<fNRows; i++) {
242 fXPos[i][j] = fXFront - (fNColumns-1)*fXStep/2 + fXStep*j;
243 fYPos[i][j] = fYFront - (fNRows-1)*fYStep/2 + fYStep*i;
244 fZPos[i][j] = fZFront ;
245 }
246
248
249 // Debug output.
250
251 fParent = GetParent();
252
253 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_init_cal) {
254 cout << "---------------------------------------------------------------\n";
255 cout << "Debug output from THcNPSArray::ReadDatabase for "
256 << GetParent()->GetPrefix() << ":" << endl;
257
258 cout << " Layer #" << fLayerNum << ", number of elements " << dec << fNelem
259 << endl;
260 cout << " Columns " << fNColumns << ", Rows " << fNRows << endl;
261
262 cout << "Front X, Y Z: " << fXFront << ", " << fYFront << ", " << fZFront
263 << " cm" << endl;
264
265 cout << " Block to block X and Y distances: " << fXStep << ", " << fYStep
266 << " cm" << endl;
267
268 cout << " Block size along Z: " << fZSize << " cm" << endl;
269
270 cout << "Block X coordinates:" << endl;
271 for (UInt_t i=0; i<fNRows; i++) {
272 for (UInt_t j=0; j<fNColumns; j++) {
273 cout << fXPos[i][j] << " ";
274 }
275 cout << endl;
276 }
277 cout << endl;
278
279 cout << "Block Y coordinates:" << endl;
280 for (UInt_t i=0; i<fNRows; i++) {
281 for (UInt_t j=0; j<fNColumns; j++) {
282 cout << fYPos[i][j] << " ";
283 }
284 cout << endl;
285 }
286 cout << endl;
287
288 cout << "Block Z coordinates:" << endl;
289 for (UInt_t i=0; i<fNRows; i++) {
290 for (UInt_t j=0; j<fNColumns; j++) {
291 cout << fZPos[i][j] << " ";
292 }
293 cout << endl;
294 }
295 cout << endl;
296
297 cout << " Origin of Array:" << endl;
298 cout << " Xorig = " << GetOrigin().X() << endl;
299 cout << " Yorig = " << GetOrigin().Y() << endl;
300 cout << " Zorig = " << GetOrigin().Z() << endl;
301 cout << endl;
302
303 cout << " Using FADC " << fUsingFADC << endl;
304 if (fUsingFADC) {
305 cout << " FADC pedestal sample low = " << fPedSampLow << ", high = "
306 << fPedSampHigh << endl;
307 cout << " FADC data sample low = " << fDataSampLow << ", high = "
308 << fDataSampHigh << endl;
309 }
310
311 }
312
313 // Here read the 2-D arrays of pedestals, gains, etc.
314
315 // Pedestal limits per channel.
316 fPedLimit = new Int_t [fNelem];
317
318 Double_t cal_arr_cal_const[fNelem];
319 Double_t cal_arr_gain_cor[fNelem];
320
322
325
328 fPedDefault = new Int_t [fNelem];
329 Double_t fAdcTdcOffset_All=0.0;
330 DBRequest list1[]={
331 {"_cal_arr_ped_limit", fPedLimit, kInt, static_cast<UInt_t>(fNelem),1},
332 {"_cal_arr_cal_const", cal_arr_cal_const, kDouble, static_cast<UInt_t>(fNelem)},
333 {"_cal_arr_gain_cor", cal_arr_gain_cor, kDouble, static_cast<UInt_t>(fNelem)},
334 {"_cal_arr_adc_tdc_offset_all", &fAdcTdcOffset_All, kDouble, 0,1},
335 {"_cal_arr_adc_tdc_offset", fAdcTdcOffset, kDouble, static_cast<UInt_t>(fNelem),1},
336 {"_cal_arr_AdcTimeWindowMin", fAdcTimeWindowMin, kDouble, static_cast<UInt_t>(fNelem),1},
337 {"_cal_arr_AdcTimeWindowMax", fAdcTimeWindowMax, kDouble, static_cast<UInt_t>(fNelem),1},
338 {"_cal_arr_AdcPulseTimeMin", fAdcPulseTimeMin, kDouble, static_cast<UInt_t>(fNelem),1},
339 {"_cal_arr_AdcPulseTimeMax", fAdcPulseTimeMax, kDouble, static_cast<UInt_t>(fNelem),1},
340 // DJH 14 Sep 22
341 {"_cal_arr_PedDefault", fPedDefault, kInt, static_cast<UInt_t>(fNelem),1},
342 {"_cal_arr_SampThreshold", &fSampThreshold, kDouble,0,1},
343 {"_cal_arr_SampNSA", &fSampNSA, kInt,0,1},
344 {"_cal_arr_SampNSAT", &fSampNSAT, kInt,0,1},
345 {"_cal_arr_SampNSB", &fSampNSB, kInt,0,1},
346 {"_cal_arr_OutputSampWaveform", &fOutputSampWaveform, kInt,0,1},
347 {"_cal_arr_OutputSampRawWaveform", &fOutputSampRawWaveform, kInt,0,1},
348 {"_cal_arr_UseSampWaveform", &fUseSampWaveform, kInt,0,1},
349 {0}
350 };
351
352 for(Int_t ip=0;ip<fNelem;ip++) {
353 fAdcTdcOffset[ip] = 0.;
354 fAdcTimeWindowMin[ip] = -1000.;
355 fAdcTimeWindowMax[ip] = 1000.;
356 fAdcPulseTimeMin[ip] = -1000.;
357 fAdcPulseTimeMax[ip] = 1000.;
358 fPedDefault[ip] = 0;
359 }
360
361 // DJH 14 Sep 22
362 fSampThreshold = 5.;
363 fSampNSA = 0; // use value stored in event 125 info
364 fSampNSB = 0; // use value stored in event 125 info
365 fSampNSAT = 2; // default value in THcRawHit::SetF250Params
366 cout << " fSampThreshold 1 = " << fSampThreshold << endl;
367 fOutputSampWaveform = 1; // 0= no output , 1 = output Sample Waveform
368 fOutputSampRawWaveform = 0; // 0= output pedestal subtracted (mV) , 1 = output Sample Raw Waveform (ADC chan)
369 fUseSampWaveform = 1; // 0= do not use , 1 = use Sample Waveform
370
371 gHcParms->LoadParmValues((DBRequest*)&list1, fKwPrefix.c_str());
372 for(Int_t ip=0;ip<fNelem;ip++) {
373 fAdcTdcOffset[ip] += fAdcTdcOffset_All;
374 }
375 // Debug output.
376 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_init_cal) {
377 cout << " fPedLimit:" << endl;
378 Int_t el=0;
379 for (UInt_t j=0; j<fNColumns; j++) {
380 cout << " ";
381 for (UInt_t i=0; i<fNRows; i++) {
382 cout << fPedLimit[el++] << " ";
383 };
384 cout << endl;
385 };
386
387 cout << " cal_arr_adc_tdc_offset:" << endl;
388 el=0;
389 for (UInt_t j=0; j<fNColumns; j++) {
390 cout << " ";
391 for (UInt_t i=0; i<fNRows; i++) {
392 cout << fAdcTdcOffset[el++] << " ";
393 };
394 cout << endl;
395 };
396
397 cout << " cal_arr_cal_const:" << endl;
398 el=0;
399 for (UInt_t j=0; j<fNColumns; j++) {
400 cout << " ";
401 for (UInt_t i=0; i<fNRows; i++) {
402 cout << cal_arr_cal_const[el++] << " ";
403 };
404 cout << endl;
405 };
406
407 cout << " cal_arr_gain_cor:" << endl;
408 el=0;
409 for (UInt_t j=0; j<fNColumns; j++) {
410 cout << " ";
411 for (UInt_t i=0; i<fNRows; i++) {
412 cout << cal_arr_gain_cor[el++] << " ";
413 };
414 cout << endl;
415 };
416
417 } // end of debug output
418
419 // Calibration constants (GeV / ADC channel).
420 fGain = new Double_t [fNelem];
421 for (Int_t i=0; i<fNelem; i++) {
422 fGain[i] = cal_arr_cal_const[i] * cal_arr_gain_cor[i];
423 }
424
425 // Debug output.
426 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_init_cal) {
427
428 cout << " fGain:" << endl;
429 Int_t el=0;
430 for (UInt_t j=0; j<fNColumns; j++) {
431 cout << " ";
432 for (UInt_t i=0; i<fNRows; i++) {
433 cout << fGain[el++] << " ";
434 };
435 cout << endl;
436 };
437
438 }
439
440 fMinPeds = static_cast<THcNPSCalorimeter*>(fParent)->GetMinPeds();
441
443
444 // Event by event amplitude and pedestal
445 //fA = new Double_t[fNelem];
446 //fP = new Double_t[fNelem];
447 //fA_p = new Double_t[fNelem];
448
449 fE = vector<Double_t> (fNelem, 0.0);
450 fNumGoodAdcHits = vector<Int_t> (fNelem, 0.0);
451 fGoodAdcPulseIntRaw = vector<Double_t> (fNelem, 0.0);
452 fGoodAdcPed = vector<Double_t> (fNelem, 0.0);
453 fGoodAdcMult = vector<Double_t> (fNelem, 0.0);
454 fGoodAdcPulseInt = vector<Double_t> (fNelem, 0.0);
455 fGoodAdcPulseAmp = vector<Double_t> (fNelem, 0.0);
456 fGoodAdcPulseTime = vector<Double_t> (fNelem, 0.0);
457 fGoodAdcTdcDiffTime = vector<Double_t> (fNelem, 0.0);
458
459 /*
460 //C.Y. Mar 16, 2021: Add "Good Variables" but in 2D vectors (to keep track of
461 //the total number of hits for each block element (this is to be used by actual NPS cluster
462 //algorithm, in which all possible good hits will be used).
463 //set vector of vectors size to be the total number of blocks, fNelem
464 fE_2D.resize(fNelem);
465 fNumGoodAdcHits_2D.resize(fNelem);
466 fGoodAdcPulseIntRaw_2D.resize(fNelem);
467 fGoodAdcPed_2D.resize(fNelem);
468 fGoodAdcMult_2D.resize(fNelem);
469 fGoodAdcPulseInt_2D.resize(fNelem);
470 fGoodAdcPulseAmp_2D.resize(fNelem);
471 fGoodAdcPulseTime_2D.resize(fNelem);
472 fGoodAdcTdcDiffTime_2D.resize(fNelem);
473
474 //--------------------------------------
475 */
476
478
479 // Energy depositions per block.
480
481 //fE = new Double_t[fNelem];
482
483 // Numbers of tracks and hits , for efficiency calculations.
484
485 fStatNumTrk = vector<Int_t> (fNelem, 0);
486 fStatNumHit = vector<Int_t> (fNelem, 0);
487 fTotStatNumTrk = 0;
488 fTotStatNumHit = 0;
489
490#ifdef HITPIC
491 hitpic = new char*[fNRows];
492 for(Int_t row=0;row<fNRows;row++) {
493 hitpic[row] = new char[NPERLINE*(fNColumns+1)+2];
494 }
495 piccolumn=0;
496#endif
497
498 // Debug output.
499
500 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_init_cal) {
501
502 cout << " fMinPeds = " << fMinPeds << endl;
503
504 cout << "---------------------------------------------------------------\n";
505 }
506
507 fADCMode=static_cast<THcNPSCalorimeter*>(fParent)->GetADCMode();
508
509 return kOK;
510}
511
512//_____________________________________________________________________________
514{
515 // Initialize global variables
516
517 if( mode == kDefine && fIsSetup ) return kOK;
518 fIsSetup = ( mode == kDefine );
519
520 // Register counters for efficiency calculations in gHcParms so that the
521 // variables can be used in end of run reports.
522
523 gHcParms->Define(Form("%sstat_trksum_array", fParent->GetPrefix()),
524 "Number of tracks in calo. array", fTotStatNumTrk);
525 gHcParms->Define(Form("%sstat_hitsum_array", fParent->GetPrefix()),
526 "Number of hits in calo. array", fTotStatNumHit);
527
528 // Register variables in global list
529 if (fDebugAdc) {
530 RVarDef vars[] = {
531 {"adcPedRaw", "List of raw ADC pedestals", "frAdcPedRaw.THcSignalHit.GetData()"},
532 {"adcPulseIntRaw", "List of raw ADC pulse integrals.", "frAdcPulseIntRaw.THcSignalHit.GetData()"},
533 {"adcPulseAmpRaw", "List of raw ADC pulse amplitudes.", "frAdcPulseAmpRaw.THcSignalHit.GetData()"},
534 {"adcPulseTimeRaw", "List of raw ADC pulse times.", "frAdcPulseTimeRaw.THcSignalHit.GetData()"},
535
536 {"adcPed", "List of ADC pedestals", "frAdcPed.THcSignalHit.GetData()"},
537 {"adcPulseInt", "List of ADC pulse integrals.", "frAdcPulseInt.THcSignalHit.GetData()"},
538 {"adcPulseAmp", "List of ADC pulse amplitudes.", "frAdcPulseAmp.THcSignalHit.GetData()"},
539 {"adcPulseTime", "List of ADC pulse times.", "frAdcPulseTime.THcSignalHit.GetData()"},
540
541 // DJH 14 Sep 22
542 {"adcSampPedRaw", "Raw ADCSAMP pedestals", "frAdcSampPedRaw.THcSignalHit.GetData()"},
543 {"adcSampPulseIntRaw", "Raw ADCSAMP pulse integrals", "frAdcSampPulseIntRaw.THcSignalHit.GetData()"},
544 {"adcSampPulseAmpRaw", "Raw ADCSAMP pulse amplitudes", "frAdcSampPulseAmpRaw.THcSignalHit.GetData()"},
545 {"adcSampPulseTimeRaw", "Raw ADCSAMP pulse times", "frAdcSampPulseTimeRaw.THcSignalHit.GetData()"},
546 {"adcSampPed", "ADCSAMP pedestals", "frAdcSampPed.THcSignalHit.GetData()"},
547 {"adcSampPulseInt", "ADCSAMP pulse integrals", "frAdcSampPulseInt.THcSignalHit.GetData()"},
548 {"adcSampPulseAmp", "ADCSAMP pulse amplitudes", "frAdcSampPulseAmp.THcSignalHit.GetData()"},
549 {"adcSampPulseTime", "ADCSAMP pulse times", "frAdcSampPulseTime.THcSignalHit.GetData()"},
550
551 { 0 }
552 };
553 DefineVarsFromList( vars, mode);
554 } //end debug statement
555
556 // DJH 14 Sep 22
557 if (fOutputSampWaveform>=1) {
558 RVarDef vars[] = {
559 {"adcSampWaveform", "FADC Sample Waveform", "fSampWaveform"},
560 { 0 }
561 };
562 DefineVarsFromList( vars, mode);
563 }
564
565 RVarDef vars[] = {
566 //{"adchits", "List of ADC hits", "fADCHits.THcSignalHit.GetPaddleNumber()"}, // appears an empty histogram in the root file
567
568 {"adcErrorFlag", "Error Flag When FPGA Fails", "frAdcErrorFlag.THcSignalHit.GetData()"},
569
570 {"adcCounter", "List of ADC counter numbers.", "frAdcPulseIntRaw.THcSignalHit.GetPaddleNumber()"}, //raw occupancy
571 {"numGoodAdcHits", "Number of Good ADC Hits per PMT", "fNumGoodAdcHits" }, //good occupancy
572
573 {"totNumAdcHits", "Total Number of ADC Hits", "fTotNumAdcHits" }, // raw multiplicity
574 {"totNumGoodAdcHits", "Total Number of Good ADC Hits", "fTotNumGoodAdcHits" }, // good multiplicity
575
576
577 {"goodAdcPulseIntRaw", "Good Raw ADC Pulse Integrals", "fGoodAdcPulseIntRaw"}, //this is defined as pulseIntRaw, NOT ADC Amplitude in FillADC_DynamicPedestal() method
578 {"goodAdcPed", "Good ADC Pedestals", "fGoodAdcPed"},
579 {"goodAdcMult", "Good ADC Multiplicity", "fGoodAdcMult"},
580 {"goodAdcPulseInt", "Good ADC Pulse Integrals", "fGoodAdcPulseInt"}, //this is defined as pulseInt, which is the pedestal subtracted pulse integrals, and is defined if threshold is passed
581 {"goodAdcPulseAmp", "Good ADC Pulse Amplitudes", "fGoodAdcPulseAmp"},
582 {"goodAdcPulseTime", "Good ADC Pulse Times", "fGoodAdcPulseTime"}, //this is defined as pulseInt, which is the pedestal subtracted pulse integrals, and is defined if threshold is passed
583 {"goodAdcTdcDiffTime", "Good Hodo Starttime - ADC Pulse Times", "fGoodAdcTdcDiffTime"},
584
585
586 {"e", "Energy Depositions per block", "fE"}, //defined as fE = fA_p*fGain = pulseInt * Gain
587 {"earray", "Energy Deposition in Shower Array", "fEarray"}, //defined as a Double_t and represents a sum of the total deposited energy in the shower counter
588
589 {"nclust", "Number of clusters", "fNclust" }, //what is the difference between nclust defined here and that in THcShower.cxx ?
590 {"block_clusterID", "Cluster ID number", "fBlock_ClusterID"}, // im NOT very clear about this. it is histogrammed at wither -1 or 0.
591 {"ntracks", "Number of shower tracks", "fNtracks" }, //number of cluster-to-track associations
592
593
594 { 0 }
595 };
596
597 return DefineVarsFromList(vars, mode );
598}
599
600//_____________________________________________________________________________
602{
603 // Clears the hit lists
604 fADCHits->Clear();
605
606 fTotNumAdcHits = 0;
608 fNclust = 0;
609 fClustSize = 0;
610 fNtracks = 0;
611 fMatchClX = -1000.;
612 fMatchClY = -1000.;
613 fMatchClMaxEnergyBlock = -1000.;
614
615
616 for (THcNPSShowerClusterListIt i=fClusterList->begin(); i!=fClusterList->end();
617 ++i) {
618 Podd::DeleteContainer(**i);
619 delete *i;
620 }
621 fClusterList->clear();
622
628
629 frAdcPed->Clear();
633
634 // DJH 14 Sep 22
643
644 for (UInt_t ielem = 0; ielem < fGoodAdcPed.size(); ielem++) {
645 fGoodAdcPulseIntRaw.at(ielem) = 0.0;
646 fGoodAdcPed.at(ielem) = 0.0;
647 fGoodAdcMult.at(ielem) = 0.0;
648 fGoodAdcPulseInt.at(ielem) = 0.0;
649 fGoodAdcPulseAmp.at(ielem) = 0.0;
650 fGoodAdcPulseTime.at(ielem) = kBig; //original (use only if considering single hit per event per block)
651 fGoodAdcTdcDiffTime.at(ielem) = kBig;
652 fNumGoodAdcHits.at(ielem) = 0.0;
653 fE.at(ielem) = 0.0;
654 }
655 /*
656 for (UInt_t ielem = 0; ielem < fE_2D.size(); ielem++) {
657 fGoodAdcPulseIntRaw_2D[ielem].clear();
658 fGoodAdcPed_2D[ielem].clear();
659 fGoodAdcMult_2D[ielem].clear();
660 fGoodAdcPulseInt_2D[ielem].clear();
661 fGoodAdcPulseAmp_2D[ielem].clear();
662 fGoodAdcPulseTime_2D[ielem].clear();
663 fGoodAdcTdcDiffTime_2D[ielem].clear();
664 fNumGoodAdcHits_2D[ielem].clear();
665 fE_2D[ielem].clear();
666 }
667 */
668}
669
670//_____________________________________________________________________________
672{
673 // Doesn't actually get called. Use Fill method instead
674
675 return 0;
676}
677
678//_____________________________________________________________________________
680{
681
682 //C.Y. Feb 07 2021: The tracks input on this method is irrelevant as NPS does NOT use tracks (should eventually be taken out)
683
684 // Fill set of unclustered shower array hits.
685 // Reuse hit class pertained to the HMS/SOS type calorimeters.
686 // Save energy deposition in the module as hit mean energy, do not use
687 // positive and negative side energies.
688
689 THcNPSShowerHitSet HitSet; //set of hits
690
691 // Check that block id k computed correct for NPS
692 UInt_t k=0;
693 for (UInt_t i=0; i<fNRows; i++) {
694 for(UInt_t j=0; j < fNColumns; j++) {
695
696 if (fGoodAdcPulseInt.at(k) > 0) { //hit
697
698 THcNPSShowerHit* hit =
699 new THcNPSShowerHit(k, i, j, fXPos[i][j], fYPos[i][j], fZPos[i][j], fE[k], fGoodAdcPulseTime.at(k), fGoodAdcPulseInt.at(k));
700
701 HitSet.insert(hit);
702 }
703
704 k++; // k = i*fNColumns + j
705 }
706 }
707
708
709
710 //Debug output, print out hits before clustering.
711
712 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_clusters_cal) {
713 cout << "---------------------------------------------------------------\n";
714 cout << "Debug output from THcNPSArray::CoarseProcess for " << GetName()
715 << endl;
716
717 cout << " List of unclustered hits. Total hits: " << fTotNumAdcHits << endl;
718 THcNPSShowerHitIt it = HitSet.begin(); //<set> version
719 /*for (Int_t i=0; i!=fTotNumGoodAdcHits; i++) {
720 cout << " hit " << i << ": ";
721 (*(it++))->show();
722 }*/
723 cout << "---Calling clustering process---" << endl;
724 }
725
727
728 // if ((int)HitSet.size() != fTotNumGoodAdcHits) {
729 // cout << "***" << endl;
730 // cout << "*** THcNPSArray::CoarseProcess: HitSet.size = " << HitSet.size()
731 // << " != fTotNumGoodAdcHits = " << fTotNumGoodAdcHits << endl;
732 // cout << "***" << endl;
733 // }
734
735 // Cluster hits and fill list of clusters.
736
737 if(fClustMethod==0){ //Original HCANA calorimeter clustering method
738 static_cast<THcNPSCalorimeter*>(fParent)->ClusterHits(HitSet, fClusterList);
739 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_clusters_cal) cout << "---Calling ClusterHits (original HCANA method)---" << endl;
740 }
741
742 if(fClustMethod==1){ //C.Y. Feb 09, 2021: NPS Clustering using 'Cellular Automata' approach
743 static_cast<THcNPSCalorimeter*>(fParent)->ClusterNPS_Hits(HitSet, fClusterList);
744 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_clusters_cal) cout << "---Calling ClusterNPS_Hits (cellular automata method)---" << endl;
745 }
746
747 assert( HitSet.empty() ); // else bug in ClusterHits()
748 fNclust = (*fClusterList).size(); //number of clusters
749
750
751 // Set cluster ID for each block
752 Int_t ncl=0;
753 Int_t block;
754 for (THcNPSShowerClusterListIt ppcl = (*fClusterList).begin();
755 ppcl != (*fClusterList).end(); ++ppcl) {
756 for (THcNPSShowerClusterIt pph=(**ppcl).begin(); pph!=(**ppcl).end();
757 ++pph) {
758 //C.Y. Feb 09, 2021: I believe a +1 is not necessary if block numbering starts at zero (simply, "block = column * fNRows + Row" will do)
759 // block = ((**pph).hitColumn())*fNRows + (**pph).hitRow(); //+1;
760 block = ((**pph).hitRow())*fNColumns + (**pph).hitColumn(); //+1;
761 if (block >=0 && block < fNelem) fBlock_ClusterID[block] = ncl;
762 }
763 ncl++;
764 }
765
766 //Debug output, print out clustered hits.
767
768 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_clusters_cal) {
769
770 cout << " Clustered hits. Number of clusters: " << fNclust << endl;
771
772 UInt_t i = 0;
773 for (THcNPSShowerClusterListIt ppcl = (*fClusterList).begin();
774 ppcl != (*fClusterList).end(); ++ppcl) {
775
776 cout << " Cluster #" << i++
777 <<": E=" << clE(*ppcl)
778 << " Epr=" << clEpr(*ppcl)
779 << " X=" << clX(*ppcl)
780 << " Y=" << clY(*ppcl)
781 << " Z=" << clZ(*ppcl)
782 << " T=" << clT(*ppcl)
783 << " size=" << (**ppcl).size()
784 << endl;
785
786 Int_t j=0;
787 for (THcNPSShowerClusterIt pph=(**ppcl).begin(); pph!=(**ppcl).end();
788 ++pph) {
789 cout << " hit " << j++ << ": ";
790 (**pph).show();
791 }
792
793 }
794
795 cout << "---------------------------------------------------------------\n";
796 }
797
798 return 0;
799}
800
801//_____________________________________________________________________________
803{
804 return 0;
805}
806
807//_____________________________________________________________________________
809{
810 /* This decision really belongs in decode */
811 /* if(fADCMode == kADCDynamicPedestal) {
812 FillADC_DynamicPedestal();
813 } else if (fADCMode == kADCSampleIntegral) {
814 FillADC_SampleIntegral();
815 } else if (fADCMode == kADCSampIntDynPed) {
816 FillADC_SampIntDynPed();
817 } else {
818 FillADC_Standard();
819 }*/
821 //
822 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_decoded_cal) {
823
824 cout << "---------------------------------------------------------------\n";
825 cout << "Debug output from THcNPSArray::ProcessHits for "
826 << static_cast<THcNPSCalorimeter*>(fParent)->GetPrefix() << ":" << endl;
827
828 cout << " Sparsified hits for shower array, plane #" << fLayerNum
829 << ", " << GetName() << ":" << endl;
830
831 Int_t nspar = 0;
832 Int_t k=0;
833 for (UInt_t i=0; i<fNRows; i++) {
834 for(UInt_t j=0; j < fNColumns; j++) {
835
836 if(fGoodAdcPulseIntRaw.at(k) > fThresh[k]) {
837 cout << " counter = " << k
838 << " E = " << fE[k]
839 << endl;
840 nspar++;
841 }
842 k++;
843 }
844 }
845
846 if (nspar == 0) cout << " No hits\n";
847
848 cout << " Earray = " << fEarray << endl;
849 cout << "---------------------------------------------------------------\n";
850 }
851 //
852 return 1;
853}
854//_____________________________________________________________________________
856{
857 /* For each hit noted by the ADC, get the sample data, analyze it, use the
858 information from that analysis instead of the pulse data.
859 How can we tell decoder to send us all the sample data?
860 */
861}
862
863//_____________________________________________________________________________
865{
867 // adc_neg_pedsub = hit->GetRawAdcHitNeg().GetSampleIntRaw() - fNegPed[hit->fCounter -1];
868 // adc_pos = hit->GetRawAdcHitPos().GetSampleIntRaw();
869 // adc_neg = hit->GetRawAdcHitNeg().GetSampleIntRaw();
870 // need to create
871}
872//_____________________________________________________________________________
876//_____________________________________________________________________________
878{
879 Double_t StartTime = 50.0; // Centriod of the HMS startime during NPS
880
881 if(fHodoscope_found) StartTime = fglHod->GetStartTime();
882
883 //Loop over all entries (all hits over all elements (i.e., all hits of all blocks))
884 for (Int_t ielem=0;ielem<frAdcPulseInt->GetEntries();ielem++) {
885 //npad is block # of the corresponding ielem (hit)
886 Int_t npad = ((THcSignalHit*) frAdcPulseInt->ConstructedAt(ielem))->GetPaddleNumber();
887 if (npad > fNelem-1) continue;
888 Double_t pulseIntRaw = ((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(ielem))->GetData();
889 Double_t pulsePed = ((THcSignalHit*) frAdcPed->ConstructedAt(ielem))->GetData();
890 Double_t pulseInt = ((THcSignalHit*) frAdcPulseInt->ConstructedAt(ielem))->GetData();
891 Double_t pulseAmp = ((THcSignalHit*) frAdcPulseAmp->ConstructedAt(ielem))->GetData();
892 Double_t pulseTime = ((THcSignalHit*) frAdcPulseTime->ConstructedAt(ielem))->GetData();
893 Double_t adctdcdiffTime = pulseTime-(StartTime-50);
894 Bool_t errorflag = ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(ielem))->GetData();
895 Bool_t pulseTimeCut = (adctdcdiffTime > fAdcTimeWindowMin[npad]) && (adctdcdiffTime < fAdcTimeWindowMax[npad]);
896
897 ((THcSignalHit*) frAdcPulseTime->ConstructedAt(ielem))->Set(npad,adctdcdiffTime);
898 ((THcSignalHit*) frAdcSampPulseTime->ConstructedAt(ielem))->Set(npad,adctdcdiffTime);
899 if (!errorflag)
900 {
901 fGoodAdcMult.at(npad) += 1;
902 }
903
904 if (!errorflag && pulseTimeCut) {
905
906 fGoodAdcPulseIntRaw.at(npad) = pulseIntRaw;
907
908 //store multiple raw pulse integral per paddle (in the case of >1 hits)
909 //fGoodAdcPulseIntRaw_2D[npad].push_back(pulseIntRaw);
910
911
912 //cout << "FADP " << npad << " " << fGoodAdcPulseIntRaw.at(npad) << " " << fThresh[npad] << " " << pulseInt << endl;
913 /* Is this basically always true? pulseInt is large (includes pedestals), fThresh is small
914 Why is fThresh small? In pulse mode, (1), fThresh is OK, but Good hists not getting
915 filled. */
916
917 //if(fClustMethod == 0){
918 /*C.Y. Mar 15, 2021 : This block of code (below) requires fGoodAdcPulseInt to NOT have been
919 previously filled (==0), so the quantities filled here only take the 1st hit within the
920 adctdcdiffTime window. This is what is originally done in THcShower.cxx for HMS/SHMS */
921
922
923 if(fGoodAdcPulseInt.at(npad)==0) {
925 fGoodAdcPulseInt.at(npad) = pulseInt;
926 fGoodAdcPed.at(npad) = pulsePed;
927 fGoodAdcPulseAmp.at(npad) = pulseAmp;
928 fGoodAdcPulseTime.at(npad) = pulseTime-(StartTime-50);
929 fGoodAdcTdcDiffTime.at(npad) = adctdcdiffTime;
930
931 // Gain pararmeter is obtained for amp -> ene conversion
932 fE.at(npad) = fGoodAdcPulseAmp.at(npad)*fGain[npad];
933 fEarray += fE.at(npad);
934
935 fNumGoodAdcHits.at(npad) = npad;// Looks wrong, but is correct.
936 // See https://github.com/JeffersonLab/hcana/issues/463
937 // Not npad+1 here because we number first block as 0
938 }
939
940 //}
941
942 /*
943 if(fClustMethod == 1){
944
945 //C.Y. Mar 15, 2021 : This block of code (below) only requires raw integral to be above threshold,
946 // but all possible hits that are within the adctdcdiffTime are NOT discarded, but are actually
947 // considered as "good hits. Will most likely consider all possible good hits for NPS".
948 // To store multiple hits separately to analyze later, we actually need a 2D vector to fill all hits per block.
949
950
951
952 //multiple hits per npad are considered (and stored in _2D) here
953 if(fGoodAdcPulseIntRaw.at(npad) > fThresh[npad]) {
954
955 fTotNumGoodAdcHits++;
956
957 //-------Store possible multiple "good" hits in 2D Vector-----
958 //(Which of these is needed for NPS clustering?)
959 //store multiple hits separate for each [npad]
960 fGoodAdcPulseInt_2D[npad].push_back(pulseInt);
961 fE_2D[npad].push_back(pulseInt*fGain[npad]);
962 fGoodAdcPed_2D[npad].push_back(pulsePed);
963 fGoodAdcPulseAmp_2D[npad].push_back(pulseAmp);
964 fGoodAdcPulseTime_2D[npad].push_back(pulseTime);
965 fGoodAdcTdcDiffTime_2D[npad].push_back(adctdcdiffTime);
966 fNumGoodAdcHits_2D[npad].push_back(npad);
967
968 }
969 }
970 */
971
972
973 }
974
975 }
976
977 /*
978 if(fClustMethod == 1){
979
980 //=====TESTING: SELECT HIT WITH HIGHEST PULESE INTEGRAL AS "GOOD HIT"====
981
982 //Loop over all blocks
983 for(Int_t i=0; i<fNelem; i++){
984
985 //check if there is at least a good hit
986 if(fGoodAdcPulseInt_2D[i].size()>0){
987
988 //Get the index of the hit with the maximum pulse integral (and select as good hit)
989 int maxIdx = std::max_element(fGoodAdcPulseInt_2D[i].begin(), fGoodAdcPulseInt_2D[i].end()) - fGoodAdcPulseInt_2D[i].begin();
990 float maxElement = *std::max_element(fGoodAdcPulseInt_2D[i].begin(), fGoodAdcPulseInt_2D[i].end());
991
992
993 //Assign the 1D vectors the corresponding value to the hit with the max pulse Int within the adctdcdiffTime window
994 fGoodAdcPulseIntRaw.at(i) = fGoodAdcPulseIntRaw_2D[i].at(maxIdx);
995 fGoodAdcPulseInt.at(i) = fGoodAdcPulseInt_2D[i].at(maxIdx);
996 fE.at(i) = fE_2D[i].at(maxIdx);
997 fEarray += fE.at(i);
998
999 fGoodAdcPed.at(i) = fGoodAdcPed_2D[i].at(maxIdx);
1000 fGoodAdcPulseAmp.at(i) = fGoodAdcPulseAmp_2D[i].at(maxIdx);
1001 fGoodAdcPulseTime.at(i) = fGoodAdcPulseTime_2D[i].at(maxIdx);
1002 fGoodAdcTdcDiffTime.at(i) = fGoodAdcTdcDiffTime_2D[i].at(maxIdx);
1003
1004 fNumGoodAdcHits.at(i) = fNumGoodAdcHits_2D[i].at(maxIdx);
1005
1006 }
1007
1008 }
1009
1010 }
1011 */
1012
1013}
1014//_____________________________________________________________________________
1016{
1017 // Extract the data for this layer from hit list.
1018
1019 //THcNPSCalorimeter fParent;
1020 //fParent = (THcNPSCalorimeter) GetParent();
1021
1022 // Initialize variables.
1023
1024 fADCHits->Clear();
1025
1026 frAdcPedRaw->Clear();
1031
1032 frAdcPed->Clear();
1036
1037 for(Int_t i=0;i<fNelem;i++) {
1038 //fA[i] = 0;
1039 //fA_p[i] = 0;
1040 //fE[i] = 0;
1041
1042 fBlock_ClusterID[i] = -1;
1043 }
1044
1045 fEarray = 0;
1046 return(0);
1047}
1048//_____________________________________________________________________________
1050{
1051 // cout << "Calling THcNPSArray::AccumulateHits() . . ." << endl;
1052 // Extract the data for this layer from hit list without clearing.
1053 // accumulating for several events (to simulate high rate)
1054 // If transform is 1-3 or 5-7, transform the block numbers to other quadrants
1055 // 1-3 is a translation transformation, 5-7 is a reflection transformation
1056
1057 Int_t nrawhits = rawhits->GetLast()+1;
1058
1059 Int_t ihit = nexthit;
1060
1061 UInt_t nrAdcHits = 0;
1062 UInt_t nrSampAdcHits = 0;
1063 fSampWaveform.clear();
1064
1065 //cout << "THcNPSArray::AccumulateHits | # of blocks hit: " << nrawhits << endl;
1066 //Loop over each block hit (nrawhits is total number of blocks hit)
1067
1068 while(ihit < nrawhits) {
1069 THcRawShowerHit* hit = (THcRawShowerHit *) rawhits->At(ihit);
1070
1071 if(hit->fPlane != fLayerNum) {
1072 break;
1073 }
1074
1075 Int_t padnum = hit->fCounter;
1076
1077
1078 // Int_t padnum = shms2nps_transform(hit->fCounter, transform);
1079
1080 //Create rawAdcHit object (passed by ref.) to access raw ADC quantities, and Fill the frAdc* TClonesArray
1081 THcRawAdcHit& rawAdcHit = hit->GetRawAdcHitPos();
1082
1083 if ( fUseSampWaveform == 0 ) {
1084 for (UInt_t thit=0; thit<rawAdcHit.GetNPulses(); ++thit) {
1085
1086 ((THcSignalHit*) frAdcPedRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPedRaw());
1087 if (padnum < fNelem) fThresh[padnum]=rawAdcHit.GetPedRaw()*rawAdcHit.GetF250_PeakPedestalRatio()+fAdcThreshold;
1088 ((THcSignalHit*) frAdcPed->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPed());
1089
1090 ((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseIntRaw(thit));
1091 ((THcSignalHit*) frAdcPulseInt->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseInt(thit));
1092
1093 ((THcSignalHit*) frAdcPulseAmpRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseAmpRaw(thit));
1094 ((THcSignalHit*) frAdcPulseAmp->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseAmp(thit));
1095
1096 ((THcSignalHit*) frAdcPulseTimeRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseTimeRaw(thit));
1097 ((THcSignalHit*) frAdcPulseTime->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseTime(thit)+fAdcTdcOffset[padnum]);
1098
1099 if (rawAdcHit.GetPulseAmpRaw(thit) > 0) ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(padnum, 0);
1100 if (rawAdcHit.GetPulseAmpRaw(thit) <= 0) ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(padnum, 1);
1101 if (rawAdcHit.GetPulseAmpRaw(thit) <= 0 && rawAdcHit.GetNSamples() >0) ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(padnum, 2);
1102
1103 if (rawAdcHit.GetPulseAmpRaw(thit) <= 0) {
1104 Double_t PeakPedRatio= rawAdcHit.GetF250_PeakPedestalRatio();
1105 Int_t NPedSamples= rawAdcHit.GetF250_NPedestalSamples();
1106 Double_t AdcToC = rawAdcHit.GetAdcTopC();
1107 Double_t AdcToV = rawAdcHit.GetAdcTomV();
1108 if (fPedDefault[padnum-1] !=0) {
1109 Double_t tPulseInt = AdcToC*(rawAdcHit.GetPulseIntRaw(thit) - fPedDefault[padnum-1]*PeakPedRatio);
1110 ((THcSignalHit*) frAdcPulseInt->ConstructedAt(nrAdcHits))->Set(padnum, tPulseInt);
1111 ((THcSignalHit*) frAdcPedRaw->ConstructedAt(nrAdcHits))->Set(padnum, fPedDefault[padnum-1]);
1112 ((THcSignalHit*) frAdcPed->ConstructedAt(nrAdcHits))->Set(padnum, float(fPedDefault[padnum-1])/float(NPedSamples)*AdcToV);
1113
1114 }
1115 ((THcSignalHit*) frAdcPulseAmp->ConstructedAt(nrAdcHits))->Set(padnum, 0.);
1116 }
1117
1118 ++nrAdcHits;
1120 }
1121 }
1122
1123 if (rawAdcHit.GetNSamples() >0 ) {
1124
1126 if (fSampNSA == 0) fSampNSA=rawAdcHit.GetF250_NSA();
1127 if (fSampNSB == 0) fSampNSB=rawAdcHit.GetF250_NSB();
1128 rawAdcHit.SetF250Params(fSampNSA,fSampNSB,4); // Set NPED =4
1129 if (fSampNSAT != 2) rawAdcHit.SetSampNSAT(fSampNSAT);
1130 rawAdcHit.SetSampIntTimePedestalPeak();
1131 if (fOutputSampWaveform == 1 || (fOutputSampWaveform == 2 && rawAdcHit.GetNSampPulses()>0)) {
1132 fSampWaveform.push_back(float(padnum));
1133 fSampWaveform.push_back(float(rawAdcHit.GetNSamples()));
1134
1135 for (UInt_t thit = 0; thit < rawAdcHit.GetNSamples(); thit++) {
1136 if (fOutputSampRawWaveform == 1) {
1137 fSampWaveform.push_back(rawAdcHit.GetSampleRaw(thit)); // raw sample (Adc chan)
1138 } else {
1139 fSampWaveform.push_back(rawAdcHit.GetSample(thit)); // ped subtracted sample (mV)
1140 }
1141 }
1142 }
1143 for (UInt_t thit = 0; thit < rawAdcHit.GetNSampPulses(); thit++) {
1144 ((THcSignalHit*) frAdcSampPedRaw->ConstructedAt(nrSampAdcHits))->Set(padnum, rawAdcHit.GetSampPedRaw());
1145 ((THcSignalHit*) frAdcSampPed->ConstructedAt(nrSampAdcHits))->Set(padnum, rawAdcHit.GetSampPed());
1146
1147 ((THcSignalHit*) frAdcSampPulseIntRaw->ConstructedAt(nrSampAdcHits))->Set(padnum, rawAdcHit.GetSampPulseIntRaw(thit));
1148 ((THcSignalHit*) frAdcSampPulseInt->ConstructedAt(nrSampAdcHits))->Set(padnum, rawAdcHit.GetSampPulseInt(thit));
1149
1150 ((THcSignalHit*) frAdcSampPulseAmpRaw->ConstructedAt(nrSampAdcHits))->Set(padnum, rawAdcHit.GetSampPulseAmpRaw(thit));
1151 ((THcSignalHit*) frAdcSampPulseAmp->ConstructedAt(nrSampAdcHits))->Set(padnum, rawAdcHit.GetSampPulseAmp(thit));
1152 ((THcSignalHit*) frAdcSampPulseTimeRaw->ConstructedAt(nrSampAdcHits))->Set(padnum, rawAdcHit.GetSampPulseTimeRaw(thit));
1153 if (padnum<fNelem) ((THcSignalHit*) frAdcSampPulseTime->ConstructedAt(nrSampAdcHits))->Set(padnum, rawAdcHit.GetSampPulseTime(thit)+fAdcTdcOffset[padnum]);
1154 //
1155 if ( rawAdcHit.GetNPulses() == 0 || fUseSampWaveform ==1 ) {
1156 ((THcSignalHit*) frAdcPedRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetSampPedRaw());
1157 ((THcSignalHit*) frAdcPed->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetSampPed());
1158
1159 ((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(nrAdcHits))->Set(padnum,rawAdcHit.GetSampPulseIntRaw(thit));
1160 ((THcSignalHit*) frAdcPulseInt->ConstructedAt(nrAdcHits))->Set(padnum,rawAdcHit.GetSampPulseInt(thit));
1161
1162 ((THcSignalHit*) frAdcPulseAmpRaw->ConstructedAt(nrAdcHits))->Set(padnum,rawAdcHit.GetSampPulseAmpRaw(thit));
1163 ((THcSignalHit*) frAdcPulseAmp->ConstructedAt(nrAdcHits))->Set(padnum,rawAdcHit.GetSampPulseAmp(thit) );
1164
1165 ((THcSignalHit*) frAdcPulseTimeRaw->ConstructedAt(nrAdcHits))->Set(padnum,rawAdcHit.GetSampPulseTimeRaw(thit) );
1166 if (padnum<fNelem) ((THcSignalHit*) frAdcPulseTime->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetSampPulseTime(thit)+fAdcTdcOffset[padnum]);
1167
1168 ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(padnum, 3);
1169 if (fUseSampWaveform ==1) ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(padnum, 0);
1170 ++nrAdcHits;
1172 }
1173 ++nrSampAdcHits;
1174 }
1175 }
1176 ihit++;
1177 }
1178
1179 // DJH 09/04/22 -- commented out for now
1180
1181// // cout << "fADCMode=" << fADCMode << endl;
1182// if(fADCMode == kADCSampIntDynPed) {
1183// /* Assume channels from fPedSampLow to fPedSampHigh are pedestal */
1184// Int_t nsamples = rawAdcHit.GetNSamples();
1185// if( nsamples <= 0 ) {
1186// cout << "No sample data when expected. Falling back to pulse mode." << endl;
1187// fADCMode = kADCDynamicPedestal;
1188// } else {
1189// Int_t pedsum=0;
1190// Double_t pedestal=0.0;
1191// for(Int_t i=fPedSampLow;i<=fPedSampHigh;i++) {
1192// pedsum += rawAdcHit.GetSampleRaw(i);
1193// }
1194// pedestal = ((Double_t) pedsum)/(fPedSampHigh+1-fPedSampLow);
1195// // cout << "PAD " << padnum << " Pedestal: " << pedestal << " Threshold: " << fAdcSampThreshold << endl;
1196// // for(Int_t i=0;i<nsamples;i++) {
1197// // cout << rawAdcHit.GetSampleRaw(i) << " ";
1198// // }
1199// // cout << endl;
1200// Int_t i = fPedSampHigh+1;
1201// while(i<nsamples) {
1202// Int_t sampfirst = rawAdcHit.GetSampleRaw(i);
1203// if(sampfirst >= pedestal+fAdcSampThreshold) {
1204// Int_t lastchan = TMath::Min(i+fDataSampWidth-1,nsamples-1);
1205// Int_t integralraw=sampfirst;
1206// Double_t integral=sampfirst-pedestal;
1207// Int_t sampmax=sampfirst;
1208// Int_t chanmax=i;
1209// Double_t rawtime = i*4/0.0625;
1210// for(Int_t j=i+1;j<=lastchan;j++) {
1211// Int_t sample = rawAdcHit.GetSampleRaw(j);
1212// if(sample > sampmax) {
1213// sampmax = sample;
1214// chanmax = j;
1215// }
1216// integralraw += sample;
1217// integral += sample-pedestal;
1218// }
1219// if(chanmax>i) { // Update time calculation
1220// // Interpolate between first sample and max sample to find where
1221// // amplitude reaches half the maximum.
1222// // This is what I presume calculation in FADC250 to be
1223// // cout << "Rawtime: " << rawtime/64.0 << " ";
1224// rawtime += 0.5*(chanmax-i)*(1-(sampfirst-pedestal)/(sampmax-sampfirst))*4/0.0625;
1225// // cout << rawtime/64.0 << endl;
1226// }
1227// // Do something
1228// ((THcSignalHit*) frAdcPedRaw->ConstructedAt(nrAdcHits))->Set(padnum, pedsum);
1229// ((THcSignalHit*) frAdcPed->ConstructedAt(nrAdcHits))->Set(padnum, pedestal*rawAdcHit.GetAdcTomV());
1230// ((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(nrAdcHits))->Set(padnum, integralraw);
1231// ((THcSignalHit*) frAdcPulseInt->ConstructedAt(nrAdcHits))->Set(padnum, integral*rawAdcHit.GetAdcTopC());
1232// // fThresh[padnum] = xxx
1233// // Need to check how it gets peak. Is pedestal subtracted? No.
1234// ((THcSignalHit*) frAdcPulseAmpRaw->ConstructedAt(nrAdcHits))->Set(padnum, sampmax);
1235// ((THcSignalHit*) frAdcPulseAmp->ConstructedAt(nrAdcHits))->Set(padnum, (sampmax-pedestal)*rawAdcHit.GetAdcTomV());
1236// ((THcSignalHit*) frAdcPulseTimeRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawtime);
1237// Double_t time = (rawtime - rawAdcHit.GetRefTime())*rawAdcHit.GetAdcTons()+fAdcTdcOffset[padnum];
1238// // ((THcSignalHit*) frAdcPulseTime->ConstructedAt(nrAdcHits))->
1239// // Set(padnum, (rawtime - rawAdcHit.GetRefTime())*rawAdcHit.GetAdcTons()+fAdcTdcOffset[padnum]);
1240// ((THcSignalHit*) frAdcPulseTime->ConstructedAt(nrAdcHits))->
1241// Set(padnum, time);
1242// if (sampmax-pedestal>0&&integralraw>0) {
1243// ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(padnum,0);
1244// } else {
1245// ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(padnum,1);
1246// }
1247// ++nrAdcHits;
1248// Int_t j = lastchan+1;
1249// while(j<nsamples) { // Skip ahead until we are below threshold
1250// Int_t sample = rawAdcHit.GetSampleRaw(j);
1251// j++;
1252// if(sample < pedestal+fAdcSampThreshold) {
1253// break;
1254// }
1255// }
1256// i = j;
1257// // cout << "Resuming peak search at " << i << endl;
1258// } else {
1259// i++;
1260// }
1261// }
1262// }
1263// }
1264// //#define DEBUG112 1
1265// #ifdef DEBUG112
1266// if(padnum == 112) {
1267// for (UInt_t thit=0; thit<rawAdcHit.GetNPulses(); ++thit) {
1268// Double_t rawtime = rawAdcHit.GetPulseTimeRaw(thit);
1269// Double_t time = rawAdcHit.GetPulseTime(thit)+fAdcTdcOffset[padnum];
1270// cout << "Pulse: " << thit << " " << time << " " << rawtime << " " << fAdcTdcOffset[padnum] <<
1271// " R" << rawAdcHit.GetRefTime() << endl;
1272// }
1273// }
1274// #endif
1275// if(fADCMode != kADCSampIntDynPed) {
1276// //cout << "Total # of NPulses ------>" << rawAdcHit.GetNPulses() << endl;
1277
1278
1279// //Loop over total number of pulses per block hit
1280// for (UInt_t thit=0; thit<rawAdcHit.GetNPulses(); ++thit) {
1281
1282// ((THcSignalHit*) frAdcPedRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPedRaw());
1283// // cout << "pedRaw " << rawAdcHit.GetPedRaw() << endl;
1284// fThresh[padnum]=rawAdcHit.GetPedRaw()*rawAdcHit.GetF250_PeakPedestalRatio()+fAdcThreshold;
1285// // cout << padnum << " " << rawAdcHit.GetPedRaw() << " " << rawAdcHit.GetF250_PeakPedestalRatio()
1286// // << " " << fAdcThreshold << " " << fThresh[padnum] << endl;
1287// ((THcSignalHit*) frAdcPed->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPed());
1288// // cout << "pedNotRaw " << rawAdcHit.GetPed() << endl;
1289// ((THcSignalHit*) frAdcPulseIntRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseIntRaw(thit));
1290// ((THcSignalHit*) frAdcPulseInt->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseInt(thit));
1291
1292// ((THcSignalHit*) frAdcPulseAmpRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseAmpRaw(thit));
1293// ((THcSignalHit*) frAdcPulseAmp->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseAmp(thit));
1294
1295// ((THcSignalHit*) frAdcPulseTimeRaw->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseTimeRaw(thit));
1296// ((THcSignalHit*) frAdcPulseTime->ConstructedAt(nrAdcHits))->Set(padnum, rawAdcHit.GetPulseTime(thit)+fAdcTdcOffset[padnum]);
1297
1298// if (rawAdcHit.GetPulseAmp(thit)>0&&rawAdcHit.GetPulseIntRaw(thit)>0) {
1299// ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(padnum,0);
1300// } else {
1301// ((THcSignalHit*) frAdcErrorFlag->ConstructedAt(nrAdcHits))->Set(padnum,1);
1302// }
1303
1304
1305// //increment number of adc hits per block
1306// ++nrAdcHits;
1307
1308
1309
1310// }//end loop over ADC Pulses per block
1311
1312
1313// } //end (fADCMode != kADCSampIntDynPed) requirement
1314
1315// #define SAMPLEHACKING 0
1316// #ifdef SAMPLEHACKING
1317// if(rawAdcHit.GetNPulses() > 0) {
1318// Int_t NSamples = rawAdcHit.GetNSamples();
1319// // cout << "NSamples = " << NSamples << endl;
1320// Double_t *spectrum = new Double_t[NSamples];
1321// Double_t *dest = new Double_t[NSamples];
1322// Double_t maxamp=0.0;
1323// for(Int_t i=0;i<NSamples;i++) {
1324// spectrum[i] = rawAdcHit.GetSampleRaw(i);
1325// if(spectrum[i] > maxamp) maxamp = spectrum[i];
1326// }
1327
1328 // TSpectrum s;
1329 // // Last sample is zero
1330 // Int_t npeaks = 1; //s.SearchHighRes(spectrum,dest,NSamples,3.0,30.0,kTRUE,5,kTRUE,3);
1331 // if(npeaks > 10) {
1332 // Double_t *pos = s.GetPositionX();
1333 // cout << "Nsamples " << NSamples << endl;
1334 // cout << "ADC";
1335 // for(UInt_t i=0;i<rawAdcHit.GetNPulses();i++) {
1336 // cout << " " << 0.0625*rawAdcHit.GetPulseTimeRaw(i)/4.;
1337 // }
1338 // cout << endl;
1339 // cout << "FIT";
1340 // for(Int_t i=0;i<npeaks;i++) {
1341 // cout << " " << pos[i];
1342 // }
1343 // if(npeaks==1 && rawAdcHit.GetNPulses() == 1) {
1344 // cout << " " << pos[0]-0.0625*rawAdcHit.GetPulseTimeRaw(0)/4.;
1345 // }
1346 // cout << endl;
1347 // }
1348 // if(npeaks > 4) {
1349 // for(Int_t i=0;i<NSamples;i++) {
1350 // cout << i << " " << rawAdcHit.GetSampleRaw(i) << " " << spectrum[i] << endl;
1351 // }
1352 // }
1353
1354
1355 // if(padnum==112) {
1356 // cout << "PAD # " << padnum << " MAX " << maxamp << endl;
1357 // for(Int_t i=0;i<NSamples;i++) {
1358 // cout << rawAdcHit.GetSampleRaw(i);
1359 // if((i+1)%25==0) {
1360 // cout << ":";
1361 // }
1362 // cout << " ";
1363 // }
1364 // cout << endl;
1365 // }
1366
1367// }
1368
1369// #endif
1370// ihit++;
1371// }
1372
1373#if 0
1374 if(fTotNumGoodAdcHits > 0) {
1375 cout << "+";
1376 for(Int_t column=0;column<fNColumns;column++) {
1377 cout << "-";
1378 }
1379 cout << "+" << endl;
1380 for(Int_t row=0;row<fNRows;row++) {
1381 cout << "|";
1382 for(Int_t column=0;column<fNColumns;column++) {
1383 Int_t counter = row*fNColumns + column;
1384 if(fGoodAdcPulseIntRaw.at(counter) > threshold) {
1385 cout << "X";
1386 } else {
1387 cout << " ";
1388 }
1389 }
1390 cout << "|" << endl;
1391 }
1392 }
1393#endif
1394#ifdef HITPIC
1395 if(fTotNumGoodAdcHits > 0) {
1396 for(Int_t row=0;row<fNRows;row++) {
1397 if(piccolumn==0) {
1398 hitpic[row][0] = '|';
1399 }
1400 for(Int_t column=0;column<fNColumns;column++) {
1401 Int_t counter = row*fNColumns + column;
1402 if(fGoodAdcPulseIntRaw.at(counter) > threshold) {
1403 hitpic[row][piccolumn*(fNColumns+1)+column+1] = 'X';
1404 } else {
1405 hitpic[row][piccolumn*(fNColumns+1)+column+1] = ' ';
1406 }
1407 hitpic[row][(piccolumn+1)*(fNColumns+1)] = '|';
1408 }
1409 }
1410 piccolumn++;
1411 if(piccolumn==NPERLINE) {
1412 cout << "+";
1413 for(Int_t pc=0;pc<NPERLINE;pc++) {
1414 for(Int_t column=0;column<fNColumns;column++) {
1415 cout << "-";
1416 }
1417 cout << "+";
1418 }
1419 cout << endl;
1420 for(Int_t row=0;row<fNRows;row++) {
1421 hitpic[row][(piccolumn+1)*(fNColumns+1)+1] = '\0';
1422 cout << hitpic[row] << endl;
1423 }
1424 piccolumn = 0;
1425 }
1426 }
1427#endif
1428
1429 //Debug output.
1430
1431
1432 return(ihit);
1433}
1434//_____________________________________________________________________________
1436{
1437 // Extract data for this plane from hit list and accumulate in
1438 // arrays for subsequent pedestal calculations.
1439
1440 Int_t nrawhits = rawhits->GetLast()+1;
1441
1442 Int_t ihit = nexthit;
1443
1444 while(ihit < nrawhits) {
1445
1446 THcRawShowerHit* hit = (THcRawShowerHit *) rawhits->At(ihit);
1447
1448 if(hit->fPlane != fLayerNum) {
1449 break;
1450 }
1451
1452 Int_t element = hit->fCounter - 1; // Should check if in range
1453 // Should check that counter # is in range
1454 Int_t adc = 0;
1455 if (fUsingFADC) {
1456 adc = hit->GetRawAdcHitPos().GetData(
1458 );
1459 }
1460 else {
1461 adc = hit->GetData(0);
1462 }
1463
1464 if(adc <= fPedLimit[element]) {
1465 fPedSum[element] += adc;
1466 fPedSum2[element] += adc*adc;
1467 fPedCount[element]++;
1468 if(fPedCount[element] == fMinPeds/5) {
1469 fPedLimit[element] = 100 + fPedSum[element]/fPedCount[element];
1470 }
1471 }
1472 ihit++;
1473 }
1475
1476 // Debug output.
1477
1478 if ( static_cast<THcNPSCalorimeter*>(fParent)->fdbg_raw_cal ) {
1479
1480 cout << "---------------------------------------------------------------\n";
1481 cout << "Debug output from THcNPSArray::AcculatePedestals for "
1482 << fParent->GetPrefix() << ":" << endl;
1483
1484 cout << "Processed hit list for plane " << GetName() << ":\n";
1485
1486 for (Int_t ih=nexthit; ih<nrawhits; ih++) {
1487
1488 THcRawShowerHit* hit = (THcRawShowerHit *) rawhits->At(ih);
1489
1490 if(hit->fPlane != fLayerNum) {
1491 break;
1492 }
1493
1494 Int_t adc = 0;
1495 if (fUsingFADC) {
1496 adc = hit->GetRawAdcHitPos().GetData(
1498 );
1499 }
1500 else {
1501 adc = hit->GetData(0);
1502 }
1503
1504 cout << " hit " << ih << ":"
1505 << " plane = " << hit->fPlane
1506 << " counter = " << hit->fCounter
1507 << " ADC = " << adc
1508 << endl;
1509 }
1510
1511 cout << "---------------------------------------------------------------\n";
1512
1513 }
1514
1515 return(ihit);
1516}
1517
1518//_____________________________________________________________________________
1520{
1521 // Use the accumulated pedestal data to calculate pedestals.
1522
1523 for(Int_t i=0; i<fNelem;i++) {
1524
1525 fPed[i] = ((Float_t) fPedSum[i]) / TMath::Max(1, fPedCount[i]);
1526 fSig[i] = sqrt(((Float_t)fPedSum2[i])/TMath::Max(1, fPedCount[i])
1527 - fPed[i]*fPed[i]);
1528 fThresh[i] = fPed[i] + TMath::Min(50., TMath::Max(10., 3.*fSig[i]));
1529
1530 }
1531
1532 // Debug output.
1533
1534 if ( static_cast<THcNPSCalorimeter*>(fParent)->fdbg_raw_cal ) {
1535
1536 cout << "---------------------------------------------------------------\n";
1537 cout << "Debug output from THcNPSArray::CalculatePedestals for "
1538 << fParent->GetPrefix() << ":" << endl;
1539
1540 cout << " ADC pedestals and thresholds for calorimeter plane "
1541 << GetName() << endl;
1542 for(Int_t i=0; i<fNelem;i++) {
1543 cout << " element " << i << ": "
1544 << " Pedestal = " << fPed[i]
1545 << " threshold = " << fThresh[i]
1546 << endl;
1547 }
1548 cout << "---------------------------------------------------------------\n";
1549
1550 }
1551
1552}
1553//_____________________________________________________________________________
1555{
1556 fNPedestalEvents = 0;
1557
1558 fPedSum = new Int_t [fNelem];
1559 fPedSum2 = new Int_t [fNelem];
1560 fPedCount = new Int_t [fNelem];
1561
1562 fSig = new Float_t [fNelem];
1563 fPed = new Float_t [fNelem];
1564 fThresh = new Float_t [fNelem];
1565
1566 for(Int_t i=0;i<fNelem;i++) {
1567 fPedSum[i] = 0;
1568 fPedSum2[i] = 0;
1569 fPedCount[i] = 0;
1570 }
1571}
1572
1573//------------------------------------------------------------------------------
1574
1575
1576//------------------------------------------------------------------------------
1578{
1579 /*
1580 C.Y. Feb 09, 2021
1581 Brief: Method to transform shms to nps block numbering used when moving data from
1582 shms calorimeter to "fake" nps quadrants to mimic NPS. This transformation of block
1583 numbering is done explicitly in ::AccumulateHits() method.
1584 This method takes as input:
1585 padnum -> the shms calorimeter block number id (0-223)
1586 transform -> a integer to describe to which quadrant the block will be moved to.
1587 if transform(0, 4), data will be translated to one of the four quadrants
1588 --------------
1589 transform 0 -> bottom right quadrant
1590 transform 1 -> bottom left quadrant
1591 transform 2 -> top right quadrant
1592 transform 3 -> bottom left quadrant
1593 --------------
1594 else if transform(4,8) data will be reflected to one of the four quadrants
1595 */
1596
1597 // cout << "Calling THcNPSArray::shms2nps_transform() . . ." << endl;
1598
1599 if(transform < 0) {
1600 return padnum;
1601 }
1602 Int_t column = padnum/(fNRows/2);
1603 Int_t row = padnum%(fNRows/2);
1604 if(transform>0 && transform < 4) {
1605 if(transform%2 == 1) {
1606 column += fNColumns/2;
1607 }
1608 if(transform/2 == 1) {
1609 row += fNRows/2;
1610 }
1611 } else if (transform>4 && transform < 8) {
1612 if(transform%2 == 1) {
1613 column = fNColumns/2 - column - 1 ;
1614 }
1615 if((transform-4)/2 == 1) {
1616 row = fNRows/2 - row - 1;
1617 }
1618 }
1619
1620
1621 //C.Y. Feb 15 : Column offsets necessary to get the "translation" mapping of SHMS to NPS blocks correct
1622 //For checking the transformation is correct, compare SHMS block (MAPS/DETEC/pcal_nps_standard.map) with NPS block ( MAPS/DETEC/pcal_nps_translation.map)
1623 //transform = 0 (bottom right) and 2 (top right) have offset of 13
1624 if(transform==0 || transform==2){
1625 column = 13-column;
1626 }
1627 //transform = 1 (bottom left) and 3 (top left) have offset of 41
1628 if(transform==1 || transform==3){
1629 column = 41-column;
1630 }
1631
1632 padnum = column*fNRows + row;
1633
1634 //return padnum (if no transformation is done, i.e., transform = 0, 4, 8),
1635 //then padnum is the same as input padnum (nothing changes)
1636 return padnum;
1637}
1638
1639//C.Y. Feb 11, 2021 : Introduce various method (or function) necessary for
1640//the NPS Clustering algorithm
1641
1642//------------------------------------------------------------------------
1643std::pair<int, int> THcNPSArray::GetBlockij(Int_t id)
1644{
1645
1646 //Brief: This method returns the pair (irow, jcol) block indices based on the block id number
1647
1648 //temporary placeholders (ith row, jth colum and block id)
1649 int itmp, jtmp, id_tmp;
1650 itmp = jtmp = id_tmp = -1; //defaults to -1 if no match is found
1651
1652 for (UInt_t irow=0; irow<fNRows; irow++){
1653 for (UInt_t jcol=0; jcol<fNColumns; jcol++){
1654
1655 id_tmp = irow * fNColumns + jcol;
1656
1657 //check if block id matches input id
1658 if(id_tmp == id){
1659 itmp = irow;
1660 jtmp = jcol;
1661 break;
1662 }
1663 }
1664 }
1665
1666 return std::make_pair(itmp, jtmp);
1667
1668}
1669
1670//------------------------------------------------------------------------
1672{
1673 /*Brief: This method returns the block number id
1674 given the block (ith row, jth col).
1675 NOTE: Unlike in SHMS, the block ID and block number
1676 are the same for NPS, since both start at block 0
1677 */
1678
1679 Int_t block_id;
1680 // Int_t fNBlocks = fNRows * fNColumns; //total number of blocks (0 to fNBlocks-1)
1681
1682 //Calculate the block id based on the (i,j) indices
1683 // block_id = jcol * fNRows + irow;
1684 block_id = irow * fNColumns + jcol;
1685
1686 //Check if input (irow, jcol) is out-of-bounds
1687 if( irow<0 || irow>=fNRows || jcol<0 || jcol>=fNColumns ){
1688 block_id = -1;
1689 return block_id;
1690 }
1691 else{
1692 return block_id;
1693 }
1694
1695}
1696
1698{
1699 /*Brief: This method returns the neighbor block number (id_k)
1700 of central block id given the index k of the neighboring block
1701 id: central block id number
1702 k : neighboring block index (0,1,2,....7) -> 8 nearest blocks
1703 If at an edge or corner, then neighboring blocks will be < 8
1704
1705 NPS Block Numberbing Scheme (showing central block and its nearest neighbors)
1706 NPS Front View (beam going into screen)
1707
1708 k -> (0) (1) (2)
1709 ____________________________________ fNRows
1710 | (i+1,j+1) | (i+1,j) | (i+1,j-1) | ^
1711 |____________|__________|____________| |
1712(7) | (i,j+1) | (i,j) | (i,j-1) | (3) | i rows (0, fNRows)
1713 |____________|__________|____________| |
1714 | (i-1,j+1) | (i-1,j) | (i-1,j-1) |
1715 -------------------------------------- 0
1716 (6) (5) (4)
1717
1718 fNColumns <--- 0
1719 j columns (0, fNColumns )
1720 */
1721
1722
1723 //1) Determine the (i,j) corresponding to central block id
1724 Int_t i, j;
1725 std::tie(i,j) = GetBlockij(id); //unpack (i,j) pair
1726
1727 //cout << "1) Central Block: (id, irow, jcol) = " << id << ", " << i << ", " << j << endl;
1728
1729 //2) Depending on the neighbor block index k (0-7),
1730 //and using the knowledge of the central block (i,j).
1731 //obtain the neighboring block (i +/- offset, j +/- offset)
1732 Int_t ik, jk;
1733 Int_t ik_offset, jk_offset;
1734 ik_offset = jk_offset = 1;
1735
1736 Bool_t shms_cal_map = kFALSE;
1737 if(shms_cal_map){
1738 ik_offset = 1, jk_offset = -1; //reverse the column orientation if SHMS cal map is used for testing
1739 }
1740
1741 if (k==0) { ik = i + ik_offset, jk = j + jk_offset; }
1742 else if(k==1) { ik = i + ik_offset, jk = j; }
1743 else if(k==2) { ik = i + ik_offset, jk = j - jk_offset; }
1744 else if(k==3) { ik = i, jk = j - jk_offset; }
1745 else if(k==4) { ik = i - ik_offset, jk = j - jk_offset; }
1746 else if(k==5) { ik = i - ik_offset, jk = j; }
1747 else if(k==6) { ik = i - ik_offset, jk = j + jk_offset; }
1748 else if(k==7) { ik = i, jk = j + jk_offset; }
1749
1750 //Check if the central block index is valid, otherwise, invalidate kth neighboring block indices
1751 if(i<0 || j <0){ik=-1, jk=-1;}
1752
1753 //cout << "2) Neighbor Block: (k, ik, jk) = " << k << ", " << ik << ", " << jk << endl;
1754
1755 //3) Call method to find the neighboring block number
1756 //corresponding to (i +/- offset, j +/- offset)
1757 UInt_t id_k;
1758 id_k = GetBlockID(ik, jk);
1759 //cout << "3) (id_k, ik, jk) = " << id_k << ", " << ik << ", " << jk << endl;
1760 return id_k;
1761
1762
1763}
1764
1765void THcNPSArray::GetMax(Float_t pInei[8], Int_t nei[8], Int_t &virus_blk, Float_t &max)
1766{
1767
1768 /*
1769 Brief: This method returns (by reference) the highest
1770 pulse integral neighbor block hit index (virus_blk) and corresponding pulse
1771 integral (max) out of at most 8 neighboring blocks.
1772 */
1773
1774 max = -1;
1775 virus_blk = -1;
1776
1777 //loop over each of the (at most) 8 neighbors
1778 for(Int_t k=0; k<8; k++){
1779
1780 if(pInei[k]>=max) {
1781
1782 max = pInei[k];
1783 virus_blk = nei[k];
1784
1785 }
1786
1787 }
1788
1789}
1790
1791
1792// Fiducial volume limits.
1793
1795 return fXPos[0][0] - fXStep/2 + static_cast<THcNPSCalorimeter*>(fParent)->fvDelta;
1796}
1797
1799 return fYPos[0][0] + fYStep/2 - static_cast<THcNPSCalorimeter*>(fParent)->fvDelta;
1800}
1801
1803 return fXPos[fNRows-1][fNColumns-1] + fXStep/2 - static_cast<THcNPSCalorimeter*>(fParent)->fvDelta;
1804}
1805
1807 return fYPos[fNRows-1][fNColumns-1] - fYStep/2 + static_cast<THcNPSCalorimeter*>(fParent)->fvDelta;
1808}
1810 Double_t max_energy=-1.;
1811 Double_t max_block=-1.;
1812 for (THcNPSShowerClusterIt it=(*cluster).begin(); it!=(*cluster).end(); ++it) {
1813 if ( (**it).hitE() > max_energy ) {
1814 max_energy = (**it).hitE();
1815 max_block = ((**it).hitColumn())*fNRows + (**it).hitRow()+1;
1816 }
1817 }
1818 return max_block;
1819}
1820
1821
1822
1823
1824#if 0
1825//_____________________________________________________________________________
1827{
1828 // Accumumate statistics for efficiency calculations.
1829 //
1830 // Choose electron events in gas Cherenkov with good Chisq of the best track.
1831 // Project best track to Array,
1832 // calculate module number for the track,
1833 // accrue number of tracks for the module,
1834 // accrue number of hits for the module, if it is hit.
1835 // Accrue total numbers of tracks and hits for Array.
1836
1837 THaTrack* BestTrack = static_cast<THaTrack*>( tracks[0]);
1838 if (BestTrack->GetChi2()/BestTrack->GetNDoF() > fStatMaxChi2) return 0;
1839
1840 Double_t XTrk = kBig;
1841 Double_t YTrk = kBig;
1842 Double_t pathl = kBig;
1843
1844 // Track interception with Array. The coordinates are in the calorimeter's
1845 // local system.
1846
1847 fOrigin = GetOrigin();
1848 static_cast<THcNPSCalorimeter*>(fParent)->CalcTrackIntercept(BestTrack, pathl, XTrk, YTrk);
1849
1850 // Transform coordiantes to the spectrometer's coordinate system.
1851 XTrk += GetOrigin().X();
1852 YTrk += GetOrigin().Y();
1853
1854 for (Int_t i=0; i<fNelem; i++) {
1855
1856 Int_t row = i%fNRows;
1857 Int_t col =i/fNRows;
1858
1859 if (TMath::Abs(XTrk - fXPos[row][col]) < fStatSlop &&
1860 TMath::Abs(YTrk - fYPos[row][col]) < fStatSlop) {
1861
1862 fStatNumTrk.at(i)++;
1864
1865 if (fGoodAdcPulseInt.at(i) > 0.) {
1866 fStatNumHit.at(i)++;
1868 }
1869
1870 }
1871
1872 }
1873
1874 if (static_cast<THcNPSCalorimeter*>(fParent)->fdbg_tracks_cal ) {
1875 cout << "---------------------------------------------------------------\n";
1876 cout << "THcNPSArray::AccumulateStat:" << endl;
1877 cout << " Chi2/NDF = " <<BestTrack->GetChi2()/BestTrack->GetNDoF() <<endl;
1878 // cout << " HGCER Npe = " << hgcer->GetCerNPE() << endl;
1879 cout << " XTrk, YTrk = " << XTrk << " " << YTrk << endl;
1880 for (Int_t i=0; i<fNelem; i++) {
1881
1882 Int_t row = i%fNRows;
1883 Int_t col =i/fNRows;
1884
1885 if (TMath::Abs(XTrk - fXPos[row][col]) < fStatSlop &&
1886 TMath::Abs(YTrk - fYPos[row][col]) < fStatSlop) {
1887
1888 cout << " Module " << i << ", X=" << fXPos[i/fNRows][i%fNRows]
1889 << ", Y=" << fYPos[i/fNRows][i%fNRows] << " matches track" << endl;
1890
1891 if (fGoodAdcPulseInt.at(i) > 0.)
1892 cout << " PulseIntegral = " << fGoodAdcPulseInt.at(i) << endl;
1893 }
1894 }
1895
1896 cout << "---------------------------------------------------------------\n";
1897 // getchar();
1898 }
1899
1900 return 1;
1901}
1902#endif
1903
1904
int Int_t
unsigned int UInt_t
const Data_t kBig
bool Bool_t
const Bool_t kFALSE
float Float_t
double Double_t
const Bool_t kTRUE
const char Option_t
Option_t Option_t TPoint TPoint const char mode
ClassImp(VDC::AnalyticTTDConv) using namespace std
R__EXTERN class THcParmList * gHcParms
Double_t clT(THcNPSShowerCluster *cluster)
THcNPSShowerCluster::iterator THcNPSShowerClusterIt
THcNPSShowerClusterList::iterator THcNPSShowerClusterListIt
vector< THcNPSShowerCluster * > THcNPSShowerClusterList
THcNPSShowerHitSet THcNPSShowerCluster
THcNPSShowerHitSet::iterator THcNPSShowerHitIt
set< THcNPSShowerHit * > THcNPSShowerHitSet
Double_t clE(THcShowerCluster *cluster)
Double_t clX(THcShowerCluster *cluster)
Double_t clEpr(THcShowerCluster *cluster)
Double_t clZ(THcShowerCluster *cluster)
Double_t clY(THcShowerCluster *cluster)
char * Form(const char *fmt,...)
UInt_t threshold[NUMSLOTS][NADCCHAN]
void Clear(Option_t *option="") override
TObject * ConstructedAt(Int_t idx)
static Int_t DefineVarsFromList(const void *list, EType type, EMode mode, const char *def_prefix, const TObject *obj, const char *prefix, const char *here, const char *comment_subst="")
virtual const char * Here(const char *) const
const char * GetPrefix() const
THaAnalysisObject * FindModule(const char *name, const char *classname, bool do_error=true)
TVector3 fOrigin
const TVector3 & GetOrigin() const
THaDetectorBase * GetParent() const
THaApparatus * GetApparatus() const
Double_t GetChi2() const
Int_t GetNDoF() const
THaVar * Define(const char *name, const Byte_t &var, const Int_t *count=nullptr)
Double_t GetStartTime() const
Fly's eye array of shower blocks.
Definition THcNPSArray.h:33
Int_t * fBlock_ClusterID
TClonesArray * fADCHits
Double_t * fGain
Double_t * fAdcPulseTimeMin
Bool_t fHodoscope_found
THcNPSArray(const char *name, const char *description, Int_t planenum, THaDetectorBase *parent=NULL)
Double_t fXStep
Double_t * fAdcTdcOffset
std::string fKwPrefix
Double_t * fAdcPulseTimeMax
Int_t GetBlockID(UInt_t irow, UInt_t jcol)
Float_t * fSig
TClonesArray * frAdcPulseTimeRaw
Double_t fStatSlop
vector< Int_t > fNumGoodAdcHits
TClonesArray * frAdcPulseIntRaw
Double_t fStatMaxChi2
Double_t fMatchClY
vector< Double_t > fGoodAdcPulseTime
Int_t * fPedLimit
TClonesArray * frAdcSampPulseIntRaw
Int_t fTotStatNumHit
std::pair< int, int > GetBlockij(Int_t id)
vector< Double_t > fGoodAdcMult
virtual void FillADC_DynamicPedestal()
Double_t fXFront
vector< Double_t > fGoodAdcPulseAmp
virtual Int_t AccumulatePedestals(TClonesArray *rawhits, Int_t nexthit)
vector< Double_t > fGoodAdcPulseInt
Int_t fDataSampHigh
Int_t fPedSampLow
virtual void FillADC_SampIntDynPed()
Int_t fTotStatNumTrk
TClonesArray * frAdcSampPulseTime
virtual Int_t CoarseProcessHits()
THaDetectorBase * fParent
Double_t fClustSize
TClonesArray * frAdcPulseAmp
Int_t fSampNSAT
Double_t fvYmax()
Int_t * fPedCount
Int_t fTotNumAdcHits
vector< Double_t > fE
Int_t fOutputSampWaveform
Double_t ** fXPos
virtual void FillADC_SampleIntegral()
Double_t fMatchClX
Double_t fAdcSampThreshold
vector< Double_t > fGoodAdcPulseIntRaw
Double_t fvXmin()
virtual void CalculatePedestals()
vector< Double_t > fGoodAdcTdcDiffTime
vector< Double_t > fSampWaveform
Int_t fUsingFADC
THcNPSShowerClusterList * fClusterList
TClonesArray * frAdcPedRaw
Double_t fSampThreshold
virtual void Clear(Option_t *opt="")
virtual Int_t ClearProcessedHits()
TClonesArray * frAdcPulseAmpRaw
TClonesArray * frAdcSampPed
Double_t * fAdcTimeWindowMax
vector< Int_t > fStatNumTrk
Double_t fvYmin()
Int_t fTotNumGoodAdcHits
Double_t fMatchClMaxEnergyBlock
virtual Int_t AccumulateHits(TClonesArray *rawhits, Int_t nexthit, Int_t quadrant)
Int_t fNPedestalEvents
Int_t fDataSampWidth
Double_t ** fZPos
Double_t fEarray
TClonesArray * frAdcErrorFlag
Double_t fYFront
TClonesArray * frAdcSampPulseAmp
Int_t fLayerNum
Int_t fOutputSampRawWaveform
Int_t fDebugAdc
Double_t fStatCerMin
TClonesArray * frAdcPulseTime
Double_t * fAdcTimeWindowMin
virtual Int_t CoarseProcess(TClonesArray &tracks)
virtual ~THcNPSArray()
Int_t fUseSampWaveform
Int_t fDataSampLow
vector< Int_t > fStatNumHit
Double_t fZFront
Int_t fPedSampHigh
Double_t ** fYPos
Float_t * fThresh
UInt_t fNColumns
TClonesArray * frAdcSampPulseAmpRaw
Float_t * fPed
Int_t AccumulateStat(TClonesArray &tracks)
virtual Int_t FineProcess(TClonesArray &tracks)
Double_t clMaxEnergyBlock(THcNPSShowerCluster *cluster)
vector< Double_t > fGoodAdcPed
TClonesArray * frAdcSampPulseTimeRaw
TClonesArray * frAdcPulseInt
Int_t * fPedSum
Double_t fvXmax()
TClonesArray * frAdcSampPulseInt
virtual void FillADC_Standard()
Int_t GetNeighbor(UInt_t id, UInt_t k)
Double_t fAdcThreshold
Double_t fZSize
Int_t fClustMethod
TClonesArray * frAdcSampPedRaw
virtual Int_t ReadDatabase(const TDatime &date)
void GetMax(Float_t pInei[8], Int_t nei[8], Int_t &virus_blk, Float_t &max)
virtual void InitializePedestals()
Int_t * fPedDefault
Int_t shms2nps_transform(Int_t padnum, Int_t transform)
TClonesArray * frAdcPed
virtual Int_t DefineVariables(EMode mode=kDefine)
UInt_t fNRows
Int_t * fPedSum2
Double_t fYStep
virtual Int_t Decode(const THaEvData &)
THcHodoscope * fglHod
Generic segmented shower detector.
Int_t LoadParmValues(const DBRequest *list, const char *prefix="")
Int_t GetSampPulseIntRaw(UInt_t iPulse=0) const
Double_t GetF250_PeakPedestalRatio()
UInt_t GetNSampPulses() const
Double_t GetAdcTopC() const
Double_t GetSampPulseInt(UInt_t iPulse=0) const
Int_t GetPedRaw() const
Int_t GetSampPulseAmpRaw(UInt_t iPulse=0) const
Double_t GetSampPulseTime(UInt_t iPulse=0) const
UInt_t GetNPulses() const
UInt_t GetNSamples() const
Double_t GetAdcTomV() const
Int_t GetSampPedRaw() const
Int_t GetF250_NSB()
void SetSampNSAT(Int_t nsat)
void SetSampThreshold(Double_t thres)
Double_t GetPulseAmp(UInt_t iPulse=0) const
Double_t GetSample(UInt_t iSample=0) const
Int_t GetF250_NSA()
void SetSampIntTimePedestalPeak()
Int_t GetPulseAmpRaw(UInt_t iPulse=0) const
Double_t GetPed() const
Int_t GetPulseTimeRaw(UInt_t iPulse=0) const
Double_t GetSampPulseAmp(UInt_t iPulse=0) const
Double_t GetPulseTime(UInt_t iPulse=0) const
Int_t GetSampleRaw(UInt_t iSample=0) const
Int_t GetPulseIntRaw(UInt_t iPulse=0) const
Int_t GetSampPulseTimeRaw(UInt_t iPulse=0) const
Double_t GetSampPed() const
Int_t GetF250_NPedestalSamples()
void SetF250Params(Int_t NSA, Int_t NSB, Int_t NPED)
Double_t GetData(UInt_t iPedLow, UInt_t iPedHigh, UInt_t iIntLow, UInt_t iIntHigh) const
Double_t GetPulseInt(UInt_t iPulse=0) const
Int_t fPlane
Int_t fCounter
virtual Int_t GetData(Int_t signal)
THcRawAdcHit & GetRawAdcHitPos()
const char * GetName() const override
Int_t GetEntries() const override
TObject * At(Int_t idx) const override
Int_t GetLast() const override
virtual void Warning(const char *method, const char *msgfmt,...) const
R__ALWAYS_INLINE Bool_t IsZombie() const
Double_t Z() const
void SetXYZ(Double_t x, Double_t y, Double_t z)
Double_t Y() const
Double_t X() const
Expr< UnaryOp< Sqrt< T >, Expr< A, T, D, D2, R >, T >, T, D, D2, R > sqrt(const Expr< A, T, D, D2, R > &rhs)
double max(double x, double y)
Double_t Min(Double_t a, Double_t b)
Double_t Abs(Double_t d)
Double_t Max(Double_t a, Double_t b)
STL namespace.
void tracks()