Hall A ROOT/C++ Analyzer (podd)
Loading...
Searching...
No Matches
THaShower.cxx
Go to the documentation of this file.
1
2// //
3// THaShower //
4// //
5// Shower counter class, describing a generic segmented shower detector //
6// (preshower or shower). //
7// Currently, only the "main" cluster, i.e. cluster with the largest energy //
8// deposition is considered. Units of measurements are MeV for energy of //
9// shower and meters for coordinates. //
10// //
12
13#include "THaShower.h"
14#include "THaEvData.h"
15#include "THaDetMap.h"
16#include "VarDef.h"
17#include "VarType.h"
18#include "THaTrack.h"
19#include "TClonesArray.h"
20#include "TDatime.h"
21#include "TMath.h"
22
23#include <iostream>
24#include <iomanip>
25#include <cassert>
26#include <cstdlib>
27#include <iterator>
28
29using namespace std;
30using namespace Podd;
31
32// Macro for better readability
33#if __cplusplus >= 201402L
34# define MKADCDATA(name,title,nelem,chanmap) make_unique<ShowerADCData>((name),(title),(nelem),(chanmap))
35#else
36# define MKADCDATA(name,title,nelem,chanmap) unique_ptr<ShowerADCData>(new ShowerADCData((name),(title),(nelem),(chanmap)))
37#endif
38
39//_____________________________________________________________________________
40THaShower::THaShower( const char* name, const char* description,
41 THaApparatus* apparatus ) :
42 THaPidDetector(name,description,apparatus),
43 fNrows(0), fEmin(0), fAsum_p(kBig), fAsum_c(kBig),
44 fNclust(0), fE(kBig), fX(kBig), fY(kBig), fADCData(nullptr)
45{
46 // Constructor
47}
48
49//_____________________________________________________________________________
52 fNrows(0), fEmin(0), fAsum_p(kBig), fAsum_c(kBig),
53 fNclust(0), fE(kBig), fX(kBig), fY(kBig), fADCData(nullptr)
54{
55 // Default constructor (for ROOT I/O)
56}
57
58//_____________________________________________________________________________
60{
61 // Read parameters from the database.
62 // 'date' contains the date/time of the run being analyzed.
63
64 const char* const here = "ReadDatabase";
65
66 VarType kDataType = std::is_same<Data_t, Float_t>::value ? kFloat : kDouble;
67 VarType kDataTypeV = std::is_same<Data_t, Float_t>::value ? kFloatV : kDoubleV;
68
69 // Read database
71 if( err )
72 return err;
73
74 FILE* file = OpenFile( date );
75 if( !file ) return kFileError;
76
77 // Read fOrigin and fSize (required!)
78 err = ReadGeometry( file, date, true );
79 if( err ) {
80 fclose(file);
81 return err;
82 }
83
84 vector<Int_t> detmap, chanmap;
85 vector<Double_t> xy, dxy;
86 Int_t ncols = 0, nrows = 0;
87
88 // Read mapping/geometry/configuration parameters
89 DBRequest config_request[] = {
90 { "detmap", &detmap, kIntV },
91 { "chanmap", &chanmap, kIntV, 0, true },
92 { "ncols", &ncols, kInt },
93 { "nrows", &nrows, kInt },
94 { "xy", &xy, kDoubleV, 2 }, // center pos of block 1
95 { "dxdy", &dxy, kDoubleV, 2 }, // dx and dy block spacings
96 { "emin", &fEmin, kDataType },
97 { nullptr }
98 };
99 err = LoadDB( file, date, config_request, fPrefix );
100
101 // Sanity checks
102 if( !err && (nrows <= 0 || ncols <= 0) ) {
103 Error( Here(here), "Illegal number of rows or columns: %d %d. Must be > 0. "
104 "Fix database.", nrows, ncols );
105 err = kInitError;
106 }
107
108 Int_t nelem = ncols * nrows;
109 Int_t nclbl = TMath::Min( 3, nrows ) * TMath::Min( 3, ncols );
110
111 // Reinitialization only possible for same basic configuration
112 if( !err ) {
113 if( fIsInit && nelem != fNelem ) {
114 Error( Here(here), "Cannot re-initialize with different number of blocks or "
115 "blocks per cluster (was: %d, now: %d). Detector not re-initialized.",
116 fNelem, nelem );
117 err = kInitError;
118 } else {
119 fNelem = nelem;
120 fNrows = nrows;
121 }
122 }
123 assert( fNelem >= 0 );
124 UInt_t nval = fNelem;
125
126 if( !err ) {
127 // Clear out the old channel map before reading a new one
128 fChanMap.clear();
129 if( FillDetMap(detmap, 0, here) <= 0 ) {
130 err = kInitError; // Error already printed by FillDetMap
131 } else {
132 UInt_t tot_nchan = fDetMap->GetTotNumChan();
133 if( tot_nchan != nval ) {
134 Error(Here(here), "Number of detector map channels (%u) "
135 "inconsistent with number of blocks (%u)",
136 tot_nchan, nval);
137 err = kInitError;
138 }
139 }
140 }
141 if( !err && !chanmap.empty() ) {
142 // If a map is found in the database, ensure it has the correct size
143 size_t cmapsize = chanmap.size();
144 if( cmapsize != nval ) {
145 Error(Here(here), "Channel map size (%lu) and number of detector "
146 "channels (%u) must be equal. Fix database.",
147 cmapsize, nval);
148 err = kInitError;
149 }
150 if( !err ) {
151 // Set up the new channel map. The index into the map is the physical
152 // channel (sequence number in the detector map), the value at that index,
153 // the logical channel. If the map is empty, the mapping is 1-1.
154 fChanMap.assign(chanmap.begin(), chanmap.end());
155 }
156 }
157
158 if( err ) {
159 fclose(file);
160 return err;
161 }
162
163 fBlockPos.clear(); fBlockPos.reserve(nval);
164 fClBlk.clear(); fClBlk.reserve(nclbl);
165 fDetectorData.clear();
166 auto detdata = MKADCDATA(GetPrefixName(), fTitle, nval, fChanMap);
167 fADCData = detdata.get();
168 fDetectorData.emplace_back(std::move(detdata));
169 fIsInit = true;
170 assert( fADCData->GetSize() == nval );
171
172 // Compute block positions
173 for( int c=0; c<ncols; c++ ) {
174 for( int r=0; r<nrows; r++ ) {
175 int k = nrows*c + r;
176 // Units are meters
177 fBlockPos[k].x = xy[0] + r * dxy[0];
178 fBlockPos[k].y = xy[1] + c * dxy[1];
179 }
180 }
181
182 // Read calibration parameters
183
184 // Read ADC pedestals and gains
185 // (in order of **logical** channel number = block number)
186 vector<Data_t> ped, gain;
187 DBRequest calib_request[] = {
188 { "pedestals", &ped, kDataTypeV, nval, true },
189 { "gains", &gain, kDataTypeV, nval, true },
190 { nullptr }
191 };
192 err = LoadDB( file, date, calib_request, fPrefix );
193 fclose(file);
194 if( err )
195 return err;
196
197 for( UInt_t i = 0; i < nval; ++i ) {
198 auto& calib = fADCData->GetCalib(i);
199 calib.ped = ped[i];
200 calib.gain = gain[i];
201 }
202
203#ifdef WITH_DEBUG
204 // Debug printout
205 if ( fDebug > 2 ) {
206 const auto N = static_cast<UInt_t>(fNelem);
207 Double_t pos[3]; fOrigin.GetXYZ(pos);
208 DBRequest list[] = {
209 { "Number of blocks", &fNelem, kInt },
210 { "Detector center", pos, kDouble, 3 },
211 { "Detector size", fSize, kDouble, 3 },
212 { "Channel map", &chanmap, kIntV },
213 { "Position of block 1", &xy, kDoubleV },
214 { "Block x/y spacings", &dxy, kDoubleV },
215 { "Minimum cluster energy", &fEmin, kDataType, 1 },
216 { "ADC pedestals", &ped, kDataTypeV, N },
217 { "ADC gains", &gain, kDataTypeV, N },
218 { nullptr }
219 };
220 DebugPrint( list );
221 }
222#endif
223
224 return kOK;
225}
226
227//_____________________________________________________________________________
229{
230 // Initialize global variables
231
232 // Set up standard variables, including the objects in fDetectorData
234 if( ret )
235 return ret;
236
237 RVarDef vars[] = {
238 { "asum_p", "Sum of ped-subtracted ADCs", "fAsum_p" },
239 { "asum_c", "Sum of calibrated ADCs", "fAsum_c" },
240 { "nclust", "Number of clusters", "fNclust" },
241 { "e", "Energy (MeV) of largest cluster", "fE" },
242 { "x", "x-position of largest cluster", "fX" },
243 { "y", "y-position of largest cluster", "fY" },
244 { "mult", "Multiplicity of largest cluster", "GetMainClusterSize()" },
245 { "nblk", "Numbers of blocks in main cluster", "fClBlk.n" },
246 { "eblk", "Energies of blocks in main cluster", "fClBlk.E" },
247 { nullptr }
248 };
249 return DefineVarsFromList( vars, mode );
250}
251
252//_____________________________________________________________________________
254{
255 // Destructor. Removes global variables.
256
258}
259
260//_____________________________________________________________________________
262{
263 // Clear event data
264
266 fAsum_p = fAsum_c = 0.0;
267 fE = fX = fY = kBig;
268 fClBlk.clear();
269}
270
271//_____________________________________________________________________________
274{
275 // Get the sequence number in the detector map
276 Int_t k = ADCData::GetLogicalChannel(hitinfo);
277
278 // Translate to logical channel number. Recall that logical channel
279 // numbers in the map start at 1, but array indices need to start at 0,
280 // so we subtract 1.
281 if( !fChanMap.empty() )
282#ifdef NDEBUG
283 k = fChanMap[k] - 1;
284#else
285 k = fChanMap.at(k) - 1;
286#endif
287 return k;
288}
289
290//_____________________________________________________________________________
292{
293 // Put decoded frontend data into fDetectorData. Used by Decode().
294 // hitinfo: channel info (crate/slot/channel/hit/type)
295 // data: data registered in this channel
296
298
299 // Add channels with signals to the amplitude sums
300 const auto& ADC = fADCData->GetADC(hitinfo);
301 if( ADC.adc_p > 0 )
302 fAsum_p += ADC.adc_p; // Sum of ADC minus ped
303 if( ADC.adc_c > 0 )
304 fAsum_c += ADC.adc_c; // Sum of ADC corrected
305
306 return 0;
307}
308
309//_____________________________________________________________________________
311{
312 // Reconstruct Clusters in shower detector and copy the data
313 // into the following local data structure:
314 //
315 // fNclust - Number of clusters in shower
316 // fE - Energy (in MeV) of the "main" cluster
317 // fX - X-coordinate (in m) of the cluster
318 // fY - Y-coordinate (in m) of the cluster
319 // fClBlk - Numbers and energies of blocks composing the cluster
320 //
321 // Only one ("main") cluster, i.e. the cluster with the largest energy
322 // deposition is considered. Units are MeV for energies and meters for
323 // coordinates.
324
325 fNclust = 0;
326 fClBlk.clear();
327
328 // Find block with maximum energy deposit
329 int nmax = -1;
330 double emax = fEmin; // Min threshold of energy in center
331 for( int i = 0; i < fNelem; i++ ) { // Find the block with max energy:
332 double ei = fADCData->GetADC(i).adc_c; // Energy in next block
333 if( ei > 0.5*kBig ) continue; // Skip invalid data
334 if( ei > emax ) {
335 nmax = i; // Number of block with max energy
336 emax = ei; // Max energy per a blocks
337 }
338 }
339 if ( nmax >= 0 ) {
340 int nc = nmax/fNrows; // Column of the block with max energy
341 int nr = nmax%fNrows; // Row of the block with max energy
342
343 fClBlk.push_back( {nmax,emax} ); // Add the block to cluster (center)
344 double sxe = emax * fBlockPos[nmax].x; // Sum of xi*ei
345 double sye = emax * fBlockPos[nmax].y; // Sum of yi*ei
346 for( int i = 0; i < fNelem; i++ ) { // Detach surround blocks:
347 double ei = fADCData->GetADC(i).adc_c;// Energy in next block
348 if( ei > 0.5*kBig ) continue; // Skip invalid data
349 if( ei > 0 && i != nmax ) { // Some energy out of cluster center
350 int ic = i / fNrows; // Column of next block
351 int ir = i % fNrows; // Row of next block
352 int dr = nr - ir; // Distance on row up to center
353 int dc = nc - ic; // Distance on column up to center
354 if( -2<dr && dr<2 && -2<dc && dc<2 ) { // Surround block:
355 // Add block to cluster (surround)
356 fClBlk.push_back( {i,ei} ); // Add surround block to cluster
357 sxe += ei * fBlockPos[i].x; // Sum of xi*ei of cluster blocks
358 sye += ei * fBlockPos[i].y; // Sum of yi*ei of cluster blocks
359 emax += ei; // Sum of energies in cluster blocks
360 }
361 }
362 }
363 fNclust = 1; // One ("main") cluster detected
364 fE = emax; // Energy (MeV) in "main" cluster
365 fX = sxe/emax; // X coordinate (m) of the cluster
366 fY = sye/emax; // Y coordinate (m) of the cluster
367 }
368
369 // Calculate track projections onto shower plane
370
372
373 return 0;
374}
375
376//_____________________________________________________________________________
378{
379 // Fine Shower processing.
380
381 // Redo the track-matching, since tracks might have been thrown out
382 // during the FineTracking stage.
383
385
386 return 0;
387}
388
389//_____________________________________________________________________________
390void THaShower::PrintDecodedData( const THaEvData& evdata ) const
391{
392 // Print decoded data (for debugging). Called form Decode()
393
394 cout << "Event " << evdata.GetEvNum() << " Trigger " << evdata.GetEvType()
395 << " Shower Detector " << GetPrefix() << endl;
396 int ncol = 3;
397 for( int i = 0; i < ncol; i++ ) {
398 cout << " Block ADC ADC_p ";
399 }
400 cout << endl;
401
402 for( int i = 0; i < (fNelem + ncol - 1) / ncol; i++ ) {
403 for( int c = 0; c < ncol; c++ ) {
404 int ind = c * fNelem / ncol + i;
405 if( ind < fNelem ) {
406 const auto& ADC = fADCData->GetADC(ind);
407 cout << " " << setw(3) << ind + 1;
408 cout << " ";
409 WriteValue(ADC.adc);
410 cout << " ";
411 WriteValue(ADC.adc_p);
412 cout << " ";
413 } else {
414// cout << endl;
415 break;
416 }
417 }
418 cout << endl;
419 }
420}
421
422//_____________________________________________________________________________
#define kOK
Definition BdataLoc.cxx:40
#define kInitError
Definition BdataLoc.cxx:41
int Int_t
unsigned int UInt_t
const Data_t kBig
Definition DataType.h:15
ROOT::R::TRInterface & r
#define c(i)
double Double_t
const char Option_t
#define N
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void data
Option_t Option_t TPoint xy
Option_t Option_t TPoint TPoint const char mode
char name[80]
#define MKADCDATA(name, title, nelem, chanmap)
Definition THaShower.cxx:36
static const char *const here
Definition THaVar.cxx:64
ADCData_t & GetADC(size_t i)
UInt_t GetSize() const override
ADCCalib_t & GetCalib(size_t i)
static Int_t LoadDB(FILE *file, const TDatime &date, const DBRequest *request, const char *prefix, Int_t search=0, const char *here="THaAnalysisObject::LoadDB")
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
virtual Int_t ReadDatabase(const TDatime &date)
TString GetPrefixName() const
virtual Int_t DefineVariables(EMode mode=kDefine)
virtual FILE * OpenFile(const TDatime &date)
UInt_t GetTotNumChan() const
Int_t FillDetMap(const std::vector< Int_t > &values, UInt_t flags=0, const char *here="FillDetMap")
THaDetMap * fDetMap
virtual Int_t StoreHit(const DigitizerHitInfo_t &hitinfo, UInt_t data)
virtual Int_t ReadGeometry(FILE *file, const TDatime &date, Bool_t required=false)
Double_t fSize[3]
VecDetData_t fDetectorData
UInt_t GetEvType() const
Definition THaEvData.h:53
UInt_t GetEvNum() const
Definition THaEvData.h:56
Int_t CalcTrackProj(TClonesArray &tracks)
Int_t GetLogicalChannel(const DigitizerHitInfo_t &hitinfo) const override
virtual void Clear(Option_t *="")
Int_t fNrows
Definition THaShower.h:52
UInt_t fNclust
Definition THaShower.h:66
virtual ~THaShower()
virtual Int_t StoreHit(const DigitizerHitInfo_t &hitinfo, UInt_t data)
std::vector< ClusterBlock > fClBlk
Definition THaShower.h:76
Data_t fY
Definition THaShower.h:69
Data_t fEmin
Definition THaShower.h:53
Data_t fX
Definition THaShower.h:68
virtual Int_t FineProcess(TClonesArray &tracks)
std::vector< CenterPos > fBlockPos
Definition THaShower.h:61
Data_t fE
Definition THaShower.h:67
std::vector< Int_t > fChanMap
Definition THaShower.h:49
virtual Int_t DefineVariables(EMode mode=kDefine)
virtual Int_t CoarseProcess(TClonesArray &tracks)
ShowerADCData * fADCData
Definition THaShower.h:78
Data_t fAsum_c
Definition THaShower.h:65
Data_t fAsum_p
Definition THaShower.h:64
virtual void PrintDecodedData(const THaEvData &evdata) const
virtual Int_t ReadDatabase(const TDatime &date)
Definition THaShower.cxx:59
TString fTitle
void Clear(Option_t *option="") override
virtual void Error(const char *method, const char *msgfmt,...) const
void GetXYZ(Double_t *carray) const
Double_t Min(Double_t a, Double_t b)
STL namespace.
ClassImp(TPyArg)
void tracks()