diff --git a/src/THcDetMap.cxx b/src/THcDetMap.cxx new file mode 100644 index 0000000000000000000000000000000000000000..feb8424ca7818147e153eeecfa0c53a887984a58 --- /dev/null +++ b/src/THcDetMap.cxx @@ -0,0 +1,370 @@ +//*-- Author : Ole Hansen 16/05/00 + +////////////////////////////////////////////////////////////////////////// +// +// THaDetMap +// +// The standard detector map for a Hall A detector. +// +////////////////////////////////////////////////////////////////////////// + +#include "THaDetMap.h" +#include <iostream> +#include <iomanip> +#include <cstring> +#include <cstdlib> + +using namespace std; + +const int THaDetMap::kDetMapSize; + +// FIXME: load from db_cratemap +struct ModuleType { + UInt_t model; // model identifier + Bool_t adc; // true if ADC + Bool_t tdc; // true if TDC +}; + +static const ModuleType module_list[] = { + { 1875, 0, 1 }, + { 1877, 0, 1 }, + { 1881, 1, 0 }, + { 1872, 0, 1 }, + { 3123, 1, 0 }, + { 1182, 1, 0 }, + { 792, 1, 0 }, + { 775, 0, 1 }, + { 767, 0, 1 }, + { 3201, 0, 1 }, + { 6401, 0, 1 }, + { 1190, 0, 1 }, + { 0 } +}; + +//_____________________________________________________________________________ +void THaDetMap::Module::SetModel( UInt_t m ) +{ + model = m & kModelMask; + const ModuleType* md = module_list; + while ( md->model && model != md->model ) md++; + if( md->adc ) MakeADC(); + if( md->tdc ) MakeTDC(); +} + +//_____________________________________________________________________________ +void THaDetMap::Module::SetResolution( Double_t res ) +{ + resolution = res; +} + +//_____________________________________________________________________________ +THaDetMap::THaDetMap() : fNmodules(0), fMap(0), fMaplength(0) +{ + // Default constructor. Creates an empty detector map. +} + +//_____________________________________________________________________________ +THaDetMap::THaDetMap( const THaDetMap& rhs ) +{ + // Copy constructor + + fMaplength = rhs.fMaplength; + fNmodules = rhs.fNmodules; + if( fMaplength > 0 ) { + fMap = new Module[fMaplength]; + memcpy(fMap,rhs.fMap,fNmodules*sizeof(Module)); + } +} + +//_____________________________________________________________________________ +THaDetMap& THaDetMap::operator=( const THaDetMap& rhs ) +{ + // THaDetMap assignment operator + + if ( this != &rhs ) { + if ( fMaplength != rhs.fMaplength ) { + delete [] fMap; + fMaplength = rhs.fMaplength; + if( fMaplength > 0 ) + fMap = new Module[fMaplength]; + } + fNmodules = rhs.fNmodules; + memcpy(fMap,rhs.fMap,fNmodules*sizeof(Module)); + } + return *this; +} + +//_____________________________________________________________________________ +THaDetMap::~THaDetMap() +{ + // Destructor + + delete [] fMap; +} + +//_____________________________________________________________________________ +Int_t THaDetMap::AddModule( UShort_t crate, UShort_t slot, + UShort_t chan_lo, UShort_t chan_hi, + UInt_t first, UInt_t model, Int_t refindex, + Int_t refchan ) +{ + // Add a module to the map. + + if( fNmodules >= kDetMapSize ) return -1; //Map is full + // Logical channels can run either "with" or "against" the physical channel + // numbers: + // lo<=hi : lo -> first + // hi -> first+hi-lo + // + // lo>hi : hi -> first + // lo -> first+lo-hi + // + // To indicate the second case, The flag "reverse" is set to true in the + // module. The fields lo and hi are reversed so that lo<=hi always. + // + bool reverse = ( chan_lo > chan_hi ); + + if ( fNmodules >= fMaplength ) { // need to expand the Map + Int_t oldlen = fMaplength; + fMaplength += 10; + Module* tmpmap = new Module[fMaplength]; // expand in groups of 10 + if( oldlen > 0 ) { + memcpy(tmpmap,fMap,oldlen*sizeof(Module)); + delete [] fMap; + } + fMap = tmpmap; + } + + Module& m = fMap[fNmodules]; + m.crate = crate; + m.slot = slot; + if( reverse ) { + m.lo = chan_hi; + m.hi = chan_lo; + } else { + m.lo = chan_lo; + m.hi = chan_hi; + } + m.first = first; + m.SetModel( model ); + m.refindex = refindex; + m.refchan = refchan; + m.SetResolution( 0.0 ); + m.reverse = reverse; + + return ++fNmodules; +} + +//_____________________________________________________________________________ +THaDetMap::Module* THaDetMap::Find( UShort_t crate, UShort_t slot, + UShort_t chan ) +{ + // Return the module containing crate, slot, and channel chan. + // If several matching modules exist (which mean the map is misconfigured), + // only the first one is returned. If none match, return NULL. + // Since the map is usually small and not necessarily sorted, a simple + // linear search is done. + + Module* found = NULL; + for( UShort_t i = 0; i < fNmodules; ++i ) { + Module* d = uGetModule(i); + if( d->crate == crate && d->slot == slot && + d->lo <= chan && chan <= d->hi ) { + found = d; + break; + } + } + return found; +} + +//_____________________________________________________________________________ +Int_t THaDetMap::Fill( const vector<Int_t>& values, UInt_t flags ) +{ + // Fill the map with 'values'. Depending on 'flags', the values vector + // is interpreted as a 4-, 5-, 6- or 7-tuple: + // + // The first 4 values are interpreted as (crate,slot,start_chan,end_chan) + // Each of the following flags causes one more value to be used as part of + // the tuple for each module: + // + // kFillLogicalChannel - Logical channel number for 'start_chan'. + // kFillModel - The module's hardware model number (see AddModule()) + // kFillRefChan - Reference channel (for pipeline TDCs etc.) + // kFillRefIndex - Reference index (for pipeline TDCs etc.) + // + // If more than one flag is present, the numbers will be interpreted + // in the order the flags are listed above. + // Example: + // flags = kFillModel | kFillRefChan + // ==> + // the vector is interpreted as a series of 6-tuples in the order + // (crate,slot,start_chan,end_chan,model,refchan). + // + // If kFillLogicalChannel is not set then the first logical channel numbers + // are automatically calculated for each module, assuming the numbers are + // sequential. + // + // By default, an existing map is overwritten. If the flag kDoNotClear + // is present, then the data are appended. + // + // The return value is the number of modules successfully added, + // or negative if an error occurred. + + typedef vector<Int_t>::size_type vsiz_t; + + if( (flags & kDoNotClear) == 0 ) + Clear(); + + vsiz_t tuple_size = 4; + if( flags & kFillLogicalChannel ) + tuple_size++; + if( flags & kFillModel ) + tuple_size++; + if( flags & kFillRefChan ) + tuple_size++; + if( flags & kFillRefIndex ) + tuple_size++; + + UInt_t prev_first = 0, prev_nchan = 0; + // Defaults for optional values + UInt_t first = 0, model = 0; + Int_t rchan = -1, ref = -1; + + Int_t ret = 0; + for( vsiz_t i = 0; i < values.size(); i += tuple_size ) { + // For compatibility with older maps, crate < 0 means end of data + if( values[i] < 0 ) + break; + // Now we require a full tuple + if( i+tuple_size > values.size() ) { + ret = -127; + break; + } + + vsiz_t k = 4; + if( flags & kFillLogicalChannel ) + first = values[i+k++]; + else { + first = prev_first + prev_nchan; + } + if( flags & kFillModel ) + model = values[i+k++]; + if( flags & kFillRefChan ) + rchan = values[i+k++]; + if( flags & kFillRefIndex ) + ref = values[i+k++]; + + ret = AddModule( values[i], values[i+1], values[i+2], values[i+3], + first, model, ref, rchan ); + if( ret<=0 ) + break; + prev_first = first; + prev_nchan = GetNchan( ret-1 ); + } + + return ret; +} + +//_____________________________________________________________________________ +Int_t THaDetMap::GetTotNumChan() const +{ + // Get sum of the number of channels of all modules in the map. This is + // typically the total number of hardware channels used by the detector. + + Int_t sum = 0; + for( UShort_t i = 0; i < fNmodules; i++ ) + sum += GetNchan(i); + + return sum; +} + + +//_____________________________________________________________________________ +void THaDetMap::GetMinMaxChan( Int_t& min, Int_t& max, ECountMode mode ) const +{ + // Put the minimum and maximum logical or reference channel numbers + // into min and max. If refidx is true, check refindex, else check logical + // channel numbers. + + min = kMaxInt; + max = kMinInt; + bool do_ref = ( mode == kRefIndex ); + for( UShort_t i = 0; i < fNmodules; i++ ) { + Module* m = GetModule(i); + Int_t m_min = do_ref ? m->refindex : m->first; + Int_t m_max = do_ref ? m->refindex : m->first + m->hi - m->lo; + if( m_min < min ) + min = m_min; + if( m_max > max ) + max = m_max; + } +} + + +//_____________________________________________________________________________ +void THaDetMap::Print( Option_t* ) const +{ + // Print the contents of the map + + cout << "Size: " << fNmodules << endl; + for( UShort_t i=0; i<fNmodules; i++ ) { + Module* m = GetModule(i); + cout << " " + << setw(5) << m->crate + << setw(5) << m->slot + << setw(5) << m->lo + << setw(5) << m->hi + << setw(5) << m->first + << setw(5) << GetModel(m); + if( IsADC(m) ) + cout << setw(4) << " ADC"; + if( IsTDC(m) ) + cout << setw(4) << " TDC"; + cout << setw(5) << m->refchan + << setw(5) << m->refindex + << setw(8) << m->resolution + << endl; + } +} + +//_____________________________________________________________________________ +void THaDetMap::Reset() +{ + // Clear() the map and reset the array size to zero, freeing memory. + + Clear(); + delete [] fMap; + fMap = NULL; + fMaplength = 0; +} + +//_____________________________________________________________________________ +static int compare_modules( const void* p1, const void* p2 ) +{ + // Helper function for sort + + const THaDetMap::Module* lhs = static_cast<const THaDetMap::Module*>(p1); + const THaDetMap::Module* rhs = static_cast<const THaDetMap::Module*>(p2); + + if( lhs->crate < rhs->crate ) return -1; + if( lhs->crate > rhs->crate ) return 1; + if( lhs->slot < rhs->slot ) return -1; + if( lhs->slot > rhs->slot ) return 1; + if( lhs->lo < rhs->lo ) return -1; + if( lhs->lo > rhs->lo ) return 1; + return 0; +} + +//_____________________________________________________________________________ +void THaDetMap::Sort() +{ + // Sort the map by crate/slot/low channel + + if( fMap && fNmodules ) + qsort( fMap, fNmodules, sizeof(Module), compare_modules ); + +} + +//_____________________________________________________________________________ +ClassImp(THaDetMap) + diff --git a/src/THcDetMap.h b/src/THcDetMap.h new file mode 100644 index 0000000000000000000000000000000000000000..317bc0072e3d7aa9faf52252783fde658aaf133a --- /dev/null +++ b/src/THcDetMap.h @@ -0,0 +1,161 @@ + +#ifndef ROOT_THaDetMap +#define ROOT_THaDetMap + +////////////////////////////////////////////////////////////////////////// +// +// THaDetMap +// +// Standard detector map. +// The detector map defines the hardware channels that correspond to a +// single detector. Typically, "channels" are Fastbus or VMW addresses +// characterized by +// +// Crate, Slot, range of channels +// +////////////////////////////////////////////////////////////////////////// + +//FIXME: Several things here are duplicates of information that already is +// (or should be) available from the cratemap: specifically "model" and +// "resolution", as well as the "model map" in AddModule. We should get it from +// there - to ensure consistency and have one less maintenance headache. + +#include "Rtypes.h" +#include <vector> + +class THaDetMap { + +protected: + static const UInt_t kADCBit = BIT(31); + static const UInt_t kTDCBit = BIT(30); + // Upper byte of model reserved for property bits + static const UInt_t kModelMask = 0x00ffffff; + +public: + struct Module { + UShort_t crate; + UShort_t slot; + UShort_t lo; + UShort_t hi; + UInt_t first; // logical number of first channel + UInt_t model; // model number of module (for ADC/TDC identification). + Int_t refchan; // for pipeline TDCs: reference channel number + Int_t refindex; // for pipeline TDCs: index into reference channel map + Double_t resolution; // Resolution (s/chan) for TDCs + Bool_t reverse; // Indicates that "first" corresponds to hi, not lo + + bool operator==( const Module& rhs ) const + { return crate == rhs.crate && slot == rhs.slot; } + bool operator!=( const Module& rhs ) const + { return !(*this==rhs); } + Int_t GetNchan() const { return hi-lo+1; } + UInt_t GetModel() const { return model & kModelMask; } + Bool_t IsTDC() const { return model & kTDCBit; } + Bool_t IsADC() const { return model & kADCBit; } + void SetModel( UInt_t model ); + void SetResolution( Double_t resolution ); + void MakeTDC() { model |= kTDCBit; } + void MakeADC() { model |= kADCBit; } + }; + + // Flags for GetMinMaxChan() + enum ECountMode { + kLogicalChan = 0, + kRefIndex = 1 + }; + // Flags for Fill() + enum EFillFlags { + kDoNotClear = BIT(0), // Don't clear the map first + kFillLogicalChannel = BIT(10), // Parse the logical channel number + kFillModel = BIT(11), // Parse the model number + kFillRefIndex = BIT(12), // Parse the reference index + kFillRefChan = BIT(13) // Parse the reference channel + }; + + THaDetMap(); + THaDetMap( const THaDetMap& ); + THaDetMap& operator=( const THaDetMap& ); + virtual ~THaDetMap(); + + virtual Int_t AddModule( UShort_t crate, UShort_t slot, + UShort_t chan_lo, UShort_t chan_hi, + UInt_t first=0, UInt_t model=0, + Int_t refindex=-1, Int_t refchan = -1 ); + void Clear() { fNmodules = 0; } + virtual Module* Find( UShort_t crate, UShort_t slot, UShort_t chan ); + virtual Int_t Fill( const std::vector<Int_t>& values, UInt_t flags = 0 ); + void GetMinMaxChan( Int_t& min, Int_t& max, + ECountMode mode = kLogicalChan ) const; + Module* GetModule( UShort_t i ) const ; + Int_t GetNchan( UShort_t i ) const; + Int_t GetTotNumChan() const; + Int_t GetSize() const { return static_cast<Int_t>(fNmodules); } + + UInt_t GetModel( UShort_t i ) const; + Bool_t IsADC( UShort_t i ) const; + Bool_t IsTDC( UShort_t i ) const; + static UInt_t GetModel( Module* d ); + static Bool_t IsADC( Module* d ); + static Bool_t IsTDC( Module* d ); + + virtual void Print( Option_t* opt="" ) const; + virtual void Reset(); + virtual void Sort(); + + static const int kDetMapSize = (1<<16)-1; //Sanity limit on map size + +protected: + UShort_t fNmodules; // Number of modules (=crate,slot) in the map + + Module* fMap; // Array of modules, each module is a 7-tuple + // (create,slot,chan_lo,chan_hi,first_logical, + // model,refindex) + + Int_t fMaplength; // current size of the fMap array + + Module* uGetModule( UShort_t i ) const { return fMap+i; } + + ClassDef(THaDetMap,0) //The standard detector map +}; + +inline THaDetMap::Module* THaDetMap::GetModule( UShort_t i ) const { + return i<fNmodules ? uGetModule(i) : NULL; +} + +inline Bool_t THaDetMap::IsADC(Module* d) { + if( !d ) return kFALSE; + return d->IsADC(); +} + +inline Bool_t THaDetMap::IsTDC(Module* d) { + if( !d ) return kFALSE; + return d->IsTDC(); +} + +inline UInt_t THaDetMap::GetModel(Module* d) { + if( !d ) return 0; + return d->GetModel(); +} + +inline Bool_t THaDetMap::IsADC( UShort_t i ) const { + if( i >= fNmodules ) return kFALSE; + return uGetModule(i)->IsADC(); +} + +inline Bool_t THaDetMap::IsTDC( UShort_t i ) const { + if( i >= fNmodules ) return kFALSE; + return uGetModule(i)->IsTDC(); +} + +inline UInt_t THaDetMap::GetModel( UShort_t i ) const { + if( i >= fNmodules ) return 0; + return uGetModule(i)->GetModel(); +} + +inline Int_t THaDetMap::GetNchan( UShort_t i ) const { + // Return the number of channels of the i-th module + if( i >= fNmodules ) return 0; + return uGetModule(i)->GetNchan(); +} + +#endif