Newer
Older
/** \class THcDetectorMap
\ingroup Base
Class to read and Hall C style detector map
FillMap method builds a map for a specific detector
\author S. A. Wood
*/
#include "THcDetectorMap.h"
#include "TObjArray.h"
#include "TObjString.h"
#include <iostream>
#include <fstream>
#include <cstdlib>
using namespace std;
ClassImp(THcDetectorMap)
inline static bool IsComment( const string& s, string::size_type pos )
{
return ( pos != string::npos && pos < s.length() &&
(s[pos] == '!') );
}
//_____________________________________________________________________________
THcDetectorMap::THcDetectorMap() : fNchans(0), fNIDs(0)
{
}
//_____________________________________________________________________________
THcDetectorMap::~THcDetectorMap()
{
}
bool THcDetectorMap::compare(const ChaninMod *first, const ChaninMod *second) {
// This one not used, but we get a link error if we don't include
// a compare method
return((first->channel < second->channel)? true: false);
}
struct Functor
{
bool operator() (const THcDetectorMap::ChaninMod &first, const THcDetectorMap::ChaninMod &second)
{ return((first.channel < second.channel)? true: false);}
};
//_____________________________________________________________________________
Int_t THcDetectorMap::FillMap(THaDetMap *detmap, const char *detectorname)
{
// Build a DAQ hardware to detector element map for detector detectorname
// Reads through the entire list of mappings, adding one element to
// detmap for each electronics channel that maps to detectorname.
list<ModChanList>::iterator imod;
list<ChaninMod>::iterator ichan;
ChaninMod Achan;
ModChanList Amod;
// Translate detector name into and ID
// For now just long if then else. Could get it from the comments
// at the beginning of the map file.
Int_t did=-1;
for(Int_t i=0; i < fNIDs; i++) {
if(strcasecmp(detectorname,fIDMap[i].name) == 0) {
did = fIDMap[i].id;
break;
}
}
if(did < 0) {
cout << "FillMap Error: No detector ID registered for " << detectorname << endl;
cout << " Using detector id of 0" << endl;
did = 0;
}
mlist.clear();
// cout << "fNchans=" << fNchans << endl;
for(Int_t ich=0;ich<fNchans;ich++) {
if(fTable[ich].did == did) {
Int_t roc=fTable[ich].roc;
Int_t slot=fTable[ich].slot;
Int_t model=fTable[ich].model;
// cout << "ROC=" << fTable[ich].roc << " SLOT=" << fTable[ich].slot
// << " CHANNEL=" << fTable[ich].channel << endl;
Achan.channel = fTable[ich].channel;
Achan.plane = fTable[ich].plane;
Achan.counter = fTable[ich].counter;
Achan.signal = fTable[ich].signal;
Achan.refchan = fTable[ich].refchan;
for(imod=mlist.begin(); imod!= mlist.end(); ++imod) {
if((*imod).roc == roc && (*imod).slot == slot) {
// cout << "Pushing chan " << Achan.channel << " to " << roc
// << " " << slot << endl;
(*imod).clist.push_back(Achan);
break;
}
}
if(imod == mlist.end()) {
Amod.roc = roc;
Amod.slot = slot;
Amod.model = model;
Amod.clist.clear();
Amod.clist.push_back(Achan);
mlist.push_back(Amod);
// cout << "New module " << Achan.channel << " to " << roc
// << " " << slot << endl;
}
}
}
// if(mlist.size() <= 0) {
if(mlist.empty()) {
return(-1);
}
Functor f;
for(imod=mlist.begin(); imod!= mlist.end(); ++imod) {
// cout << "Slot " << (*imod).slot << endl;
list<ChaninMod> *clistp = &((*imod).clist);
clistp->sort(f);//Sort by channel
}
// Copy the information to the Hall A style detector map
// grouping consecutive channels that are all the same plane
// and signal type
for(imod=mlist.begin(); imod!= mlist.end(); ++imod) {
UShort_t roc = (*imod).roc;
UShort_t slot = (*imod).slot;
UInt_t model=(*imod).model;
// cout << "Slot " << slot << endl;
list<ChaninMod> *clistp = &((*imod).clist);
Int_t first_chan = -1;
Int_t last_chan = -1;
Int_t last_plane = -1;
Int_t last_signal = -1;
Int_t first_counter = -1;
Int_t last_counter = -1;
Int_t last_refchan = -1;
for(ichan=clistp->begin(); ichan!=clistp->end(); ++ichan) {
Int_t this_chan = (*ichan).channel;
Int_t this_counter = (*ichan).counter;
Int_t this_signal = (*ichan).signal;
Int_t this_plane = (*ichan).plane;
Int_t this_refchan = (*ichan).refchan;
if(last_chan+1!=this_chan || last_counter+1 != this_counter
|| last_plane != this_plane || last_signal!=this_signal
|| last_refchan != this_refchan) {
if(last_chan >= 0) {
if(ichan != clistp->begin()) {
// cout << "AddModule " << slot << " " << first_chan <<
// " " << last_chan << " " << first_counter << endl;
detmap->AddModule((UShort_t)roc, (UShort_t)slot,
(UShort_t)first_chan, (UShort_t)last_chan,
(UInt_t) first_counter, model, (Int_t) -1,
(Int_t) last_refchan, (UInt_t)last_plane, (UInt_t)last_signal);
}
}
first_chan = this_chan;
first_counter = this_counter;
}
last_chan = this_chan;
last_refchan = this_refchan;
last_counter = this_counter;
last_plane = this_plane;
last_signal = this_signal;
// cout << " Channel " << (*ichan).channel << " " <<
// (*ichan).plane << " " << (*ichan).counter << endl;
}
detmap->AddModule((UShort_t)roc, (UShort_t)slot,
(UShort_t)first_chan, (UShort_t)last_chan,
(UInt_t) first_counter, model, (Int_t) 0,
(Int_t) -1, (UInt_t)last_plane, (UInt_t)last_signal);
}
return(0);
}
//_____________________________________________________________________________
void THcDetectorMap::Load(const char *fname)
{
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
// Load a Hall C ENGINE style detector map file. The map file maps
// a given roc, slot/module, and channel # into a given detector id#, plane
// number, counter number and signal type. The mapping between detector
// names and ids is found in the comments at the begging of the map file.
// This method looks for those comments, of the form:
// XXX_ID = n
// to establish that mapping between detector name and detector ID.
//
// Lines of the form
// DETECTOR = n
// ROC = n
// SLOT = n
// are used to establish the module (roc and slot) and the detector
// for the mapping lines that follow.
// The actual mappings are of the form
// subadd, plane, counter [, signal]
// Each of these lines, combined with the detector, roc, slot values
// establish the roc, slot, subadess -> detector, plane, counter#, sigtype map
// Other lines that may be in the map file are
// NSUBADD = n
// BSUB = n
// MASK = hex value
// These define characteristics of the electronics module (# channels,
// The bit number specifying the location of the subaddress in a data word
// and hex mask that the data word is anded with to retrieve data)
static const char* const whtspc = " \t";
ifstream ifile;
ifile.open(fname);
if(!ifile.is_open()) {
static const char* const here = "THcDetectorMap::Load";
Error(here, "error opening detector map file %s",fname);
return; // Need a success/failure argument?
}
string line;
Int_t roc=0;
Int_t nsubadd=0;
Int_t bsub=0;
Int_t detector=0;
Int_t slot=0;
Int_t model=0;
fNchans = 0;
string::size_type start, pos=0;
char varname[100];
while(getline(ifile,line)) {
// BLank line or comment
if(line.empty()) continue;
if((start = line.find_first_not_of( whtspc )) == string::npos) continue;
if(IsComment(line, start)) { // Check for ID assignments
// Get rid of all white space
while((pos=line.find_first_of(whtspc)) != string::npos) {
line.erase(pos,1);
}
line.erase(0,1); // Erase "!"
if(! ((pos=line.find("_ID=")) == string::npos)) {
string::size_type llen = line.length();
fIDMap[fNIDs].name = new char [pos+1];
strncpy(fIDMap[fNIDs].name,line.c_str(),pos);
fIDMap[fNIDs].name[pos] = '\0';
start = (pos += 4); // Move to after "="
while(pos < llen) {
if(isdigit(line.at(pos))) {
pos++;
} else {
break;
}
}
fIDMap[fNIDs++].id = atoi(line.substr(start,pos-start).c_str());
}
}
// cout << "MAPA: " << line << endl;
// Remove comment from line
while ((pos = line.find_first_of("!", pos+1)) != string::npos) {
if(IsComment(line, pos)) {
line.erase(pos);
break;
}
}
// Get rid of all white space
while((pos=line.find_first_of(whtspc)) != string::npos) {
line.erase(pos,1);
}
// cout << "MAPB: " << line << endl;
// Decide if line is ROC/NSUBADD/MASK/BSUB/DETECTOR/SLOT = something
// or chan, plane, counter[, signal]
if((pos=line.find_first_of("=")) != string::npos) { // Setting parameter
strcpy(varname, (line.substr(0,pos)).c_str());
Int_t valuestartpos = pos+1;
Int_t commapos = line.find_first_of(",");
Int_t value;
Int_t value2 = -1;
if(commapos != string::npos) {
// cout << line.substr(valuestartpos,commapos-valuestartpos) << "|"
// << line.substr(commapos+1) << "|" << endl;
value = atoi(line.substr(valuestartpos,commapos-valuestartpos).c_str());
value2 = atoi(line.substr(commapos+1).c_str());
} else {
value = atoi(line.substr(valuestartpos).c_str());
}
// Some if statements
if(strcasecmp(varname,"detector")==0) {
detector = value;
} else if (strcasecmp(varname,"roc")==0) {
roc = value;
} else if (strcasecmp(varname,"nsubadd")==0) {
nsubadd = value;
} else if (strcasecmp(varname,"mask")==0) { // mask not used here
//mask = value;
} else if (strcasecmp(varname,"bsub")==0) {
bsub = value;
} else if (strcasecmp(varname,"slot")==0) {
slot = value;
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
}
if(nsubadd == 96) {
model = 1877;
} else if (nsubadd == 64) {
if(bsub == 16) {
model = 1872;
} else if(bsub == 17) {
model = 1881;
} else {
model = 0;
}
} else {
model = 0;
}
} else { // Assume channel definition
TString values(line.c_str());
TObjArray *vararr = values.Tokenize(",");
Int_t nvals = vararr->GetLast()+1;
if(nvals<3 || nvals>4) {
if(nvals > 1) { // Silent for help, noecho, nodebug, override
cout << "Map file: Invalid value count: " << line << endl;
}
continue;
}
Int_t channel = ((TObjString*)vararr->At(0))->GetString().Atoi();
Int_t plane = ((TObjString*)vararr->At(1))->GetString().Atoi();
Int_t counter = ((TObjString*)vararr->At(2))->GetString().Atoi();
Int_t signal = 0;
if(nvals==4) {
signal= ((TObjString*)vararr->At(3))->GetString().Atoi();
}
delete vararr; // Discard result of Tokenize
fTable[fNchans].roc=roc;
fTable[fNchans].slot=slot;
fTable[fNchans].refchan=refchan;
fTable[fNchans].channel=channel;
fTable[fNchans].did=detector;
fTable[fNchans].plane=plane;
fTable[fNchans].counter=counter;
fTable[fNchans].signal=signal;
fTable[fNchans].model=model;
fNchans++;
}
}
cout << endl << " Detector ID Map" << endl << endl;
for(Int_t i=0; i < fNIDs; i++) {
cout << fIDMap[i].name << " " << fIDMap[i].id << endl;
}
cout << endl;