Hall A ROOT/C++ Analyzer (podd)
Loading...
Searching...
No Matches
THaDetMap.cxx
Go to the documentation of this file.
1//*-- Author : Ole Hansen 16/05/00
2
4//
5// THaDetMap
6//
7// The standard detector map for a Hall A detector.
8//
10
11#include "THaDetMap.h"
12#include "Decoder.h"
13#include "Helper.h"
14#include <iostream>
15#include <iomanip>
16#include <stdexcept>
17#include <sstream>
18#include <vector>
19#include <algorithm>
20
21using namespace std;
22using namespace Decoder;
23
24// "Database" of known frontend module numbers and types
25// FIXME: load from db_cratemap
26class ModuleDef {
27public:
28 Int_t model; // model identifier
29 ChannelType type; // Module type
30};
31
32static const vector<ModuleDef> module_list {
33 { 1875, ChannelType::kCommonStopTDC },
34 { 1877, ChannelType::kCommonStopTDC },
35 { 1881, ChannelType::kADC },
36 { 1872, ChannelType::kCommonStopTDC },
37 { 3123, ChannelType::kADC },
38 { 1182, ChannelType::kADC },
39 { 792, ChannelType::kADC },
40 { 775, ChannelType::kCommonStopTDC },
41 { 767, ChannelType::kCommonStopTDC },
42 { 3201, ChannelType::kCommonStopTDC },
43 { 6401, ChannelType::kCommonStopTDC },
44 { 1190, ChannelType::kCommonStopTDC },
45 { 250, ChannelType::kMultiFunctionADC },
46};
47
48//_____________________________________________________________________________
50{
51 model = mod;
52 auto it = find_if(ALL(module_list),
53 [mod]( const ModuleDef& m ) { return m.model == mod; });
54 if( it != module_list.end() )
55 type = it->type;
56 else
57 type = ChannelType::kUndefined;
58}
59
60//_____________________________________________________________________________
62{
63 resolution = res;
64}
65
66//_____________________________________________________________________________
68{
69 cmnstart = cstart;
70 if( cstart && type == ChannelType::kCommonStopTDC )
71 type = ChannelType::kCommonStartTDC;
72 else if( !cstart && type == ChannelType::kCommonStartTDC )
73 type = ChannelType::kCommonStopTDC;
74}
75
76//_____________________________________________________________________________
78{
79 if( IsCommonStart() )
80 type = ChannelType::kCommonStartTDC;
81 else
82 type = ChannelType::kCommonStopTDC;
83}
84
85//_____________________________________________________________________________
87{
88 type = ChannelType::kADC;
89}
90
91//_____________________________________________________________________________
93{
94 // Deep-copy the vector of module pointers
95 fMap.reserve(map.capacity());
96 for( const auto& m : map ) {
97 fMap.emplace_back(
98#if __cplusplus >= 201402L
99 std::make_unique<Module>(*m)
100#else
101 new Module(*m)
102#endif
103 );
104 }
105}
106
107//_____________________________________________________________________________
110{
111 // Copy constructor
112
113 CopyMap(rhs.fMap);
114}
115
116//_____________________________________________________________________________
118{
119 // THaDetMap assignment operator
120
121 if( this != &rhs ) {
122 fMap.clear();
123 CopyMap(rhs.fMap);
125 }
126 return *this;
127}
128
129//_____________________________________________________________________________
131 UInt_t chan_lo, UInt_t chan_hi,
132 UInt_t first, Int_t model, Int_t refindex,
133 Int_t refchan, UInt_t plane, UInt_t signal )
134{
135 // Add a module to the map.
136
137 // Logical channels can run either "with" or "against" the physical channel
138 // numbers:
139 // lo<=hi : lo -> first
140 // hi -> first+hi-lo
141 //
142 // lo>hi : hi -> first
143 // lo -> first+lo-hi
144 //
145 // To indicate the second case, The flag "reverse" is set to true in the
146 // module. The fields lo and hi are reversed so that lo<=hi always.
147 //
148 bool reverse = (chan_lo > chan_hi);
149
150#if __cplusplus >= 201402L
151 auto pm = make_unique<Module>();
152#else
153 auto pm = unique_ptr<Module>(new THaDetMap::Module);
154#endif
155 Module& m = *pm;
156 m.crate = crate;
157 m.slot = slot;
158 if( reverse ) {
159 m.lo = chan_hi;
160 m.hi = chan_lo;
161 } else {
162 m.lo = chan_lo;
163 m.hi = chan_hi;
164 }
165 m.first = first;
166 m.model = model;
167 m.refindex = refindex;
168 m.refchan = refchan;
169 m.plane = plane;
170 m.signal = signal;
171 m.SetResolution(0.0);
172 m.reverse = reverse;
173 m.cmnstart = false;
174
175 // Set the module type using our lookup table of known model numbers.
176 // If the model is not predefined, this can be done manually later with
177 // calls to MakeADC()/MakeTDC().
178 if( model != 0 ) {
179 auto it = find_if(ALL(module_list),
180 [model]( const ModuleDef& m ) { return m.model == model; });
181 if( it != module_list.end() )
182 m.type = it->type;
183 else
184 m.type = ChannelType::kUndefined;
185 // return -1; // Unknown module TODO do when module_list is in a database
186 } else
187 m.type = ChannelType::kUndefined;
188
189 fMap.push_back(std::move(pm));
190 return static_cast<Int_t>(GetSize());
191}
192
193//_____________________________________________________________________________
195 UInt_t chan )
196{
197 // Return the module containing crate, slot, and channel chan.
198 // If several matching modules exist (which mean the map is misconfigured),
199 // only the first one is returned. If none match, return nullptr.
200 // Since the map is usually small and not necessarily sorted, a simple
201 // linear search is done.
202
203 auto found = find_if( ALL(fMap), [crate,slot,chan](const unique_ptr<Module>& d)
204 { return ( d->crate == crate && d->slot == slot &&
205 d->lo <= chan && chan <= d->hi );
206 });
207
208 return (found != fMap.end()) ? found->get() : nullptr;
209}
210
211//_____________________________________________________________________________
212Int_t THaDetMap::Fill( const vector<Int_t>& values, UInt_t flags )
213{
214 // Fill the map with 'values'. Depending on 'flags', the values vector
215 // is interpreted as a 4-, 5-, 6- or 7-tuple:
216 //
217 // The first 4 values are interpreted as (crate,slot,start_chan,end_chan)
218 // Each of the following flags causes one more value to be used as part of
219 // the tuple for each module:
220 //
221 // kFillLogicalChannel - Logical channel number for 'start_chan'.
222 // kFillModel - The module's hardware model number (see AddModule())
223 // kFillRefChan - Reference channel (for pipeline TDCs etc.)
224 // kFillRefIndex - Reference index (for pipeline TDCs etc.)
225 // kFillPlane - Which plane in detector (for Hall C)
226 // kFillSignal - Which signal type (for Hall C)
227 //
228 // If more than one flag is present, the numbers will be interpreted
229 // in the order the flags are listed above.
230 // Example:
231 // flags = kFillModel | kFillRefChan
232 // ==>
233 // the vector is interpreted as a series of 6-tuples in the order
234 // (crate,slot,start_chan,end_chan,model,refchan).
235 //
236 // If kFillLogicalChannel is not set then the first logical channel numbers
237 // are automatically calculated for each module, assuming the numbers are
238 // sequential.
239 //
240 // By default, an existing map is overwritten. If the flag kDoNotClear
241 // is present, then the data are appended.
242 //
243 // The return value is the number of modules successfully added,
244 // or negative if an error occurred.
245
246 typedef vector<Int_t>::size_type vsiz_t;
247
248 if( (flags & kFillLogicalChannel) && (flags & kSkipLogicalChannel) )
249 // Bad combination of flags
250 return -128;
251
252 if( (flags & kDoNotClear) == 0 )
253 Clear();
254
255 vsiz_t tuple_size = 4;
256 if( flags & kFillLogicalChannel || flags & kSkipLogicalChannel )
257 tuple_size++;
258 if( flags & kFillModel )
259 tuple_size++;
260 if( flags & kFillRefChan )
261 tuple_size++;
262 if( flags & kFillRefIndex )
263 tuple_size++;
264 if( flags & kFillPlane )
265 tuple_size++;
266 if( flags & kFillSignal )
267 tuple_size++;
268
269 // For historical reasons, logical channel numbers start at 1
270 UInt_t prev_first = 1, prev_nchan = 0;
271 // Defaults for optional values
272 UInt_t first = 0;
273 Int_t plane = 0, signal = 0, model = 0, rchan = -1, ref = -1;
274
275 Int_t ret = 0;
276 for( vsiz_t i = 0; i < values.size(); i += tuple_size ) {
277 // For compatibility with older maps, crate < 0 means end of data
278 if( values[i] < 0 )
279 break;
280 // Now we require a full tuple
281 if( i + tuple_size > values.size() ) {
282 ret = -127;
283 break;
284 }
285
286 vsiz_t k = 4;
287 if( flags & kFillLogicalChannel ) {
288 first = values[i + k++];
289 if( first == 0 )
290 // This map appears to start counting channels at zero
291 // This is actually the exception. For historical reasons (Fortran),
292 // most maps start counting at 1.
293 // This flag is used by the hit iterators only; existing Decode()
294 // methods will not be affected.
295 fStartAtZero = true;
296 } else {
297 if( flags & kSkipLogicalChannel ) {
298 ++k;
299 }
300 first = prev_first + prev_nchan;
301 }
302 if( flags & kFillModel )
303 model = values[i + k++];
304 if( flags & kFillRefChan )
305 rchan = values[i + k++];
306 if( flags & kFillRefIndex )
307 ref = values[i + k++];
308 if( flags & kFillPlane )
309 plane = values[i + k++];
310 if( flags & kFillSignal )
311 signal = values[i + k++];
312
313 auto crate = static_cast<UInt_t>(values[i]);
314 auto slot = static_cast<UInt_t>(values[i+1]);
315 auto ch_lo = static_cast<UInt_t>(values[i+2]);
316 auto ch_hi = static_cast<UInt_t>(values[i+3]);
317 ret = AddModule(crate, slot, ch_lo, ch_hi,
318 first, model, ref, rchan, plane, signal);
319 if( ret <= 0 )
320 break;
321 prev_first = first;
322 prev_nchan = GetNchan(ret - 1);
323 }
324
325 return ret;
326}
327
328//_____________________________________________________________________________
330{
331 // Get sum of the number of channels of all modules in the map. This is
332 // typically the total number of hardware channels used by the detector.
333
334 UInt_t sum = 0;
335 for( const auto & m : fMap )
336 sum += m->GetNchan();
337
338 return sum;
339}
340
341
342//_____________________________________________________________________________
343void THaDetMap::GetMinMaxChan( UInt_t& min, UInt_t& max, ECountMode mode ) const
344{
345 // Put the minimum and maximum logical or reference channel numbers
346 // into min and max. If refidx is true, check refindex, else check logical
347 // channel numbers.
348
349 min = kMaxInt;
350 max = kMinInt;
351 bool do_ref = (mode == kRefIndex);
352 for( const auto& m : fMap ) {
353 UInt_t m_min = do_ref ? m->refindex : m->first;
354 UInt_t m_max = do_ref ? m->refindex : m->first + m->hi - m->lo;
355 if( m_min < min )
356 min = m_min;
357 if( m_max > max )
358 max = m_max;
359 }
360}
361
362
363//_____________________________________________________________________________
365{
366 // Print the contents of the map
367
368 cout << "Size: " << GetSize() << endl;
369 for( const auto& m : fMap ) {
370 cout << " "
371 << setw(5) << m->crate
372 << setw(5) << m->slot
373 << setw(5) << m->lo
374 << setw(5) << m->hi
375 << setw(5) << m->first
376 << setw(5) << m->model;
377 if( m->IsADC() )
378 cout << setw(4) << " ADC";
379 if( m->IsTDC() )
380 cout << setw(4) << " TDC";
381 cout << setw(5) << m->refchan
382 << setw(5) << m->refindex
383 << setw(8) << m->resolution
384 << setw(5) << m->plane
385 << setw(5) << m->signal
386 << endl;
387 }
388}
389
390//_____________________________________________________________________________
392{
393 // Clear() the map and reset the array size to zero, freeing memory.
394
395 Clear();
396 fMap.shrink_to_fit(); // FWIW
397}
398
399//_____________________________________________________________________________
401{
402 // Sort the map by crate/slot/low channel
403
404 sort( ALL(fMap),
405 []( const unique_ptr<Module>& a, const unique_ptr<Module>& b) {
406 if( a->crate < b->crate ) return true;
407 if( a->crate > b->crate ) return false;
408 if( a->slot < b->slot ) return true;
409 if( a->slot > b->slot ) return false;
410 return (a->lo < b->lo);
411 });
412
413}
414
415//=============================================================================
418{
419 return THaDetMap::Iterator(*this, evdata);
420}
421
422//_____________________________________________________________________________
425{
426 return THaDetMap::MultiHitIterator(*this, evdata);
427}
428
429//_____________________________________________________________________________
431 bool do_init )
432 : fDetMap(detmap), fEvData(evdata), fMod(nullptr), fNMod(fDetMap.GetSize()),
433 fNTotChan(fDetMap.GetTotNumChan()), fNChan(0), fIMod(-1), fIChan(-1)
434{
436 // Initialize iterator state to point to the first item
437 if( do_init )
438 ++(*this);
439}
440
441//_____________________________________________________________________________
442string THaDetMap::Iterator::msg( const char* txt ) const
443{
444 // Format message string for exceptions
445 ostringstream ostr;
446 ostr << "Event " << fHitInfo.ev << ", ";
447 ostr << "channel "
448 << fHitInfo.crate << "/" << fHitInfo.slot << "/"
449 << fHitInfo.chan << "/" << fHitInfo.hit << ": ";
450 if( txt and *txt ) ostr << txt; else ostr << "Unspecified error.";
451 return ostr.str();
452}
453
454#define CRATE_SLOT( x ) (x).crate, (x).slot
455static inline bool LOOPDONE( Int_t i, UInt_t n ) { return i < 0 or static_cast<UInt_t>(i) >= n; }
456static inline bool NO_NEXT( Int_t& i, UInt_t n ) { return i >= static_cast<Int_t>(n) or ++i >= static_cast<Int_t>(n); }
457
458//_____________________________________________________________________________
460{
461 // Advance iterator to next active channel
462 nextmod:
463 if( LOOPDONE(fIChan, fNChan) ) {
464 if( NO_NEXT(fIMod, fNMod) ) {
465 fHitInfo.reset();
466 return *this;
467 }
468 fMod = fDetMap.GetModule(fIMod);
469 if( !fMod )
470 throw std::logic_error("NULL detector map module. Program bug. "
471 "Call expert.");
472 fHitInfo.set_crate_slot(fMod);
473 fHitInfo.module = fEvData.GetModule(CRATE_SLOT(fHitInfo));
474 fNChan = fEvData.GetNumChan(CRATE_SLOT(fHitInfo));
475 fIChan = -1;
476 }
477 nextchan:
478 if( NO_NEXT(fIChan, fNChan) )
479 goto nextmod;
480 UInt_t chan = fEvData.GetNextChan(CRATE_SLOT(fHitInfo), fIChan);
481 if( chan < fMod->lo or chan > fMod->hi )
482 goto nextchan; // Not one of my channels
483 UInt_t nhit = fEvData.GetNumHits(CRATE_SLOT(fHitInfo), chan);
484 fHitInfo.chan = chan;
485 fHitInfo.nhit = nhit;
486 if( nhit == 0 ) {
487 ostringstream ostr;
488 ostr << "No hits on active "
489 << (fHitInfo.type == ChannelType::kADC ? "ADC" : "TDC")
490 << " channel. Should never happen. Decoder bug. Call expert.";
491 throw std::logic_error(msg(ostr.str().c_str()));
492 }
493 // If multiple hits on a TDC channel take the one earliest in time.
494 // For a common-stop TDC, this is actually the last hit.
495 fHitInfo.hit = (fHitInfo.type == ChannelType::kCommonStopTDC) ? nhit - 1 : 0;
496 // Determine logical channel. Decode() methods that use this hit iterator
497 // should always assume that logical channel numbers start counting from zero.
498 Int_t lchan = fMod->ConvertToLogicalChannel(chan);
499 if( fDetMap.fStartAtZero )
500 ++lchan; // ConvertToLogicalChannel subtracts 1; undo that here
501 if( lchan < 0 or static_cast<UInt_t>(lchan) >= size() ) {
502 ostringstream ostr;
503 size_t lmin = 1, lmax = size(); // Apparent range in the database file
504 if( fDetMap.fStartAtZero ) { --lmin; --lmax; }
505 ostr << "Illegal logical detector channel " << lchan << "."
506 << "Must be between " << lmin << " and " << lmax << ". Fix database.";
507 throw std::invalid_argument(msg(ostr.str().c_str()));
508 }
509 fHitInfo.lchan = lchan;
510
511 return *this;
512}
513
514//_____________________________________________________________________________
516{
517 // Reset iterator to first element, if any
518
519 fNMod = fDetMap.GetSize();
520 fIMod = fIChan = -1;
521 fHitInfo.reset();
522 ++(*this);
523}
524
525//_____________________________________________________________________________
527 const THaEvData& evdata,
528 bool do_init )
529 : Iterator(detmap, evdata, false), fIHit(-1)
530{
531 if( do_init )
532 ++(*this);
533}
534
535//_____________________________________________________________________________
537{
538 // Advance iterator to next active hit or channel, allowing multiple hits
539 // per channel
540 nexthit:
541 if( LOOPDONE(fIHit, fHitInfo.nhit) ) {
543 if( !Iterator::operator bool() )
544 return *this;
545 fIHit = -1;
546 }
547 if( NO_NEXT(fIHit, fHitInfo.nhit) )
548 goto nexthit;
549 fHitInfo.hit = fIHit; // overwrite value of single-hit case (0 or nhit-1)
550
551 return *this;
552}
553
554//_____________________________________________________________________________
556{
557 fIHit = -1;
559}
560
561//_____________________________________________________________________________
int Int_t
unsigned int UInt_t
uint32_t chan
#define d(i)
size_t size(const MatrixT &matrix)
bool Bool_t
const Int_t kMinInt
const Int_t kMaxInt
double Double_t
const char Option_t
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint const char mode
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
static bool NO_NEXT(Int_t &i, UInt_t n)
#define CRATE_SLOT(x)
static const vector< ModuleDef > module_list
Definition THaDetMap.cxx:32
static bool LOOPDONE(Int_t i, UInt_t n)
#define hi
Int_t model
Definition THaDetMap.cxx:28
ChannelType type
Definition THaDetMap.cxx:29
virtual void reset()
const THaEvData & fEvData
Definition THaDetMap.h:213
std::string msg(const char *txt) const
virtual Iterator & operator++()
void SetResolution(Double_t resolution)
Definition THaDetMap.cxx:61
void SetTDCMode(Bool_t cstart)
Definition THaDetMap.cxx:67
void SetModel(Int_t model)
Definition THaDetMap.cxx:49
Decoder::ChannelType type
Definition THaDetMap.h:52
virtual Iterator & operator++()
virtual Module * Find(UInt_t crate, UInt_t slot, UInt_t chan)
void GetMinMaxChan(UInt_t &min, UInt_t &max, ECountMode mode=kLogicalChan) const
virtual Int_t AddModule(UInt_t crate, UInt_t slot, UInt_t chan_lo, UInt_t chan_hi, UInt_t first=0, Int_t model=0, Int_t refindex=-1, Int_t refchan=-1, UInt_t plane=0, UInt_t signal=0)
ModuleVec_t fMap
Definition THaDetMap.h:142
UInt_t GetSize() const
Definition THaDetMap.h:125
virtual void Print(Option_t *opt="") const
void Clear()
Definition THaDetMap.h:117
virtual void Sort()
void CopyMap(const ModuleVec_t &map)
Definition THaDetMap.cxx:92
THaDetMap::Iterator MakeIterator(const THaEvData &evdata)
UInt_t GetNchan(UInt_t i) const
Definition THaDetMap.h:282
std::vector< std::unique_ptr< Module > > ModuleVec_t
Definition THaDetMap.h:141
@ kFillLogicalChannel
Definition THaDetMap.h:96
@ kFillRefChan
Definition THaDetMap.h:99
@ kDoNotClear
Definition THaDetMap.h:94
@ kFillRefIndex
Definition THaDetMap.h:98
@ kSkipLogicalChannel
Definition THaDetMap.h:95
THaDetMap::MultiHitIterator MakeMultiHitIterator(const THaEvData &evdata)
virtual Int_t Fill(const std::vector< Int_t > &values, UInt_t flags=0)
Bool_t fStartAtZero
Definition THaDetMap.h:148
UInt_t GetTotNumChan() const
virtual void Reset()
THaDetMap & operator=(const THaDetMap &)
UInt_t GetEvNum() const
Definition THaEvData.h:56
const Int_t n
vector< int >::size_type vsiz_t
ChannelType
Definition Decoder.h:61
model
double min(double x, double y)
double max(double x, double y)
STL namespace.
TMarker m
TArc a
ClassImp(TPyArg)