// $Id$ // // File: DTranslationTable.cc // Created: Thu Jun 27 16:07:11 EDT 2013 // Creator: davidl (on Darwin harriet.jlab.org 11.4.2 i386) // #include "DTranslationTable.h" #include #include using namespace jana; using namespace std; // Use one translation table for all threads static pthread_mutex_t tt_mutex = PTHREAD_MUTEX_INITIALIZER; static bool tt_initialized = false; static map TT; //................................... // Less than operator for csc_t data types. This is used by // the map to order the entires by key bool operator<(const DTranslationTable::csc_t &a, const DTranslationTable::csc_t &b){ if(a.rocid < b.rocid) return true; if(a.rocid > b.rocid) return false; if(a.slot < b.slot) return true; if(a.slot > b.slot) return false; if(a.channel < b.channel) return true; return false; } //................................... // sort functions bool SortBCALDigiHit(const DBCALDigiHit *a, const DBCALDigiHit *b){ if(a->module == b->module){ if(a->layer == b->layer){ if(a->sector == b->sector){ if(a->end == b->end){ return a->pulse_time < b->pulse_time; }else{ return a->end < b->end; } }else{ return a->sector < b->sector; } }else{ return a->layer< b->layer; } }else { return a->module < b->module; } } //--------------------------------- // DTranslationTable (Constructor) //--------------------------------- DTranslationTable::DTranslationTable(JEventLoop *loop) { // Read in Translation table. This will create DChannelInfo objects // and store them in the "TT" map, indexed by csc_t objects ReadTranslationTable(); // These are used to help the event source report which // types of data it is capable of providing. For practical // purposes, these types are "provided" by the source // because they are generated and placed into their // respective JANA factories during a call to GetObjects(). // The source is responsible for reporting the types it is // directly responsible for (e.g. Df250PulseIntegral) supplied_data_types.insert("DBCALDigiHit"); supplied_data_types.insert("DBCALTDCDigiHit"); supplied_data_types.insert("DCDCDigiHit"); supplied_data_types.insert("DFCALDigiHit"); supplied_data_types.insert("DFDCCathodeDigiHit"); supplied_data_types.insert("DFDCWireDigiHit"); supplied_data_types.insert("DSCDigiHit"); supplied_data_types.insert("DSCTDCDigiHit"); supplied_data_types.insert("DTOFDigiHit"); supplied_data_types.insert("DTOFTDCDigiHit"); } //--------------------------------- // ~DTranslationTable (Destructor) //--------------------------------- DTranslationTable::~DTranslationTable() { } //--------------------------------- // IsSuppliedType //--------------------------------- bool DTranslationTable::IsSuppliedType(string dataClassName) const { return (supplied_data_types.find(dataClassName) != supplied_data_types.end()); } //--------------------------------- // ApplyTranslationTable //--------------------------------- void DTranslationTable::ApplyTranslationTable(JEventLoop *loop) const { /// This will get all of the low level objects and /// generate detector hit objects from them, placing /// them in the appropriate DANA factories. // Containers to hold all of the detector-specific "Digi" // objects. Once filled, these will be copied to the // respective factories at the end of this method. vector vbcal; vector vbcaltdc; vector vcdc; vector vfcal; vector vfdccathode; vector vfdcwire; vector vsc; vector vsctdc; vector vtof; vector vtoftdc; // Df250PulseIntegral (will apply Df250PulseTime via associated objects) vector pulseintegrals250; loop->Get(pulseintegrals250); for(uint32_t i=0; irocid, pi->slot, pi->channel}; map::const_iterator iter = TT.find(csc); if(iter == TT.end()) continue; const DChannelInfo &chaninfo = iter->second; // Check for a pulse time (this should have been added in JEventSource_EVIO.cc) const Df250PulseTime *pt = NULL; try{ pi->GetSingle(pt); }catch(...){} // Create the appropriate hit type based on detector type switch(chaninfo.det_sys){ case BCAL : vbcal.push_back( MakeBCALDigiHit(chaninfo.bcal, pi, pt) ); break; case FCAL : vfcal.push_back( MakeFCALDigiHit(chaninfo.fcal, pi, pt) ); break; case SC : vsc.push_back ( MakeSCDigiHit( chaninfo.sc, pi, pt) ); break; case TOF : vtof.push_back ( MakeTOFDigiHit( chaninfo.tof, pi, pt) ); break; default: break; } } // Df125PulseIntegral (will apply Df125PulseTime via associated objects) vector pulseintegrals125; loop->Get(pulseintegrals125); for(uint32_t i=0; irocid, pi->slot, pi->channel}; map::const_iterator iter = TT.find(csc); if(iter == TT.end()) continue; const DChannelInfo &chaninfo = iter->second; // Check for a pulse time (this should have been added in JEventSource_EVIO.cc const Df125PulseTime *pt = NULL; try{ pi->GetSingle(pt); }catch(...){} // Create the appropriate hit type based on detector type switch(chaninfo.det_sys){ case CDC : vcdc.push_back( MakeCDCDigiHit(chaninfo.cdc, pi, pt) ); break; case FDC_CATHODES: vfdccathode.push_back( MakeFDCCathodeDigiHit(chaninfo.fdc_cathodes, pi, pt) ); break; default: break; } } // DF1TDCHit vector f1tdchits; loop->Get(f1tdchits); for(uint32_t i=0; irocid, hit->slot, hit->channel}; map::const_iterator iter = TT.find(csc); if(iter == TT.end()) continue; const DChannelInfo &chaninfo = iter->second; // Create the appropriate hit type based on detector type switch(chaninfo.det_sys){ case BCAL : vbcaltdc.push_back( MakeBCALTDCDigiHit(chaninfo.bcal, hit) ); break; case FDC_WIRES: vfdcwire.push_back( MakeFDCWireDigiHit(chaninfo.fdc_wires, hit) ); break; case SC : vbcaltdc.push_back( MakeBCALTDCDigiHit(chaninfo.bcal, hit) ); break; case TOF : vbcaltdc.push_back( MakeBCALTDCDigiHit(chaninfo.bcal, hit) ); break; default: break; } } // Sort object order (this makes it easier to browse with hd_dump) sort(vbcal.begin(), vbcal.end(), SortBCALDigiHit); // Find factory for each container and copy the object pointers into it // (n.b. do this even if container is empty since it sets the evnt_called flag) CopyToFactory(loop, vbcal); CopyToFactory(loop, vbcaltdc); CopyToFactory(loop, vcdc); CopyToFactory(loop, vfcal); CopyToFactory(loop, vfdccathode); CopyToFactory(loop, vfdcwire); CopyToFactory(loop, vsc); CopyToFactory(loop, vsctdc); CopyToFactory(loop, vtof); CopyToFactory(loop, vtoftdc); } //--------------------------------- // MakeBCALDigiHit //--------------------------------- DBCALDigiHit* DTranslationTable::MakeBCALDigiHit(const BCALIndex_t &idx, const Df250PulseIntegral *pi, const Df250PulseTime *pt) const { DBCALDigiHit *h = new DBCALDigiHit(); CopyDf250Info(h, pi, pt); h->module = idx.module; h->layer = idx.layer; h->sector = idx.sector; h->end = (DBCALGeometry::End)idx.end; return h; } //--------------------------------- // MakeFCALDigiHit //--------------------------------- DFCALDigiHit* DTranslationTable::MakeFCALDigiHit(const FCALIndex_t &idx, const Df250PulseIntegral *pi, const Df250PulseTime *pt) const { DFCALDigiHit *h = new DFCALDigiHit(); CopyDf250Info(h, pi, pt); h->row = idx.row; h->column = idx.col; return h; } //--------------------------------- // MakeTOFDigiHit //--------------------------------- DTOFDigiHit* DTranslationTable::MakeTOFDigiHit(const TOFIndex_t &idx, const Df250PulseIntegral *pi, const Df250PulseTime *pt) const { DTOFDigiHit *h = new DTOFDigiHit(); CopyDf250Info(h, pi, pt); h->plane = idx.plane; h->bar = idx.bar; h->end = idx.end; return h; } //--------------------------------- // MakeSCDigiHit //--------------------------------- DSCDigiHit* DTranslationTable::MakeSCDigiHit(const SCIndex_t &idx, const Df250PulseIntegral *pi, const Df250PulseTime *pt) const { DSCDigiHit *h = new DSCDigiHit(); CopyDf250Info(h, pi, pt); h->sector = idx.sector; return h; } //--------------------------------- // MakeCDCDigiHit //--------------------------------- DCDCDigiHit* DTranslationTable::MakeCDCDigiHit(const CDCIndex_t &idx, const Df125PulseIntegral *pi, const Df125PulseTime *pt) const { DCDCDigiHit *h = new DCDCDigiHit(); CopyDf125Info(h, pi, pt); h->ring = idx.ring; h->straw = idx.straw; return h; } //--------------------------------- // MakeFDCCathodeDigiHit //--------------------------------- DFDCCathodeDigiHit* DTranslationTable::MakeFDCCathodeDigiHit(const FDC_CathodesIndex_t &idx, const Df125PulseIntegral *pi, const Df125PulseTime *pt) const { DFDCCathodeDigiHit *h = new DFDCCathodeDigiHit(); CopyDf125Info(h, pi, pt); h->package = idx.package; h->chamber = idx.chamber; h->view = idx.view; h->strip = idx.strip; h->strip_type = idx.strip_type; return h; } //--------------------------------- // MakeBCALTDCDigiHit //--------------------------------- DBCALTDCDigiHit* DTranslationTable::MakeBCALTDCDigiHit(const BCALIndex_t &idx, const DF1TDCHit *hit) const { DBCALTDCDigiHit *h = new DBCALTDCDigiHit(); CopyDF1TDCInfo(h, hit); h->module = idx.module; h->layer = idx.layer; h->sector = idx.sector; h->end = (DBCALGeometry::End)idx.end; return h; } //--------------------------------- // MakeFDCWireDigiHit //--------------------------------- DFDCWireDigiHit* DTranslationTable::MakeFDCWireDigiHit(const FDC_WiresIndex_t &idx, const DF1TDCHit *hit) const { DFDCWireDigiHit *h = new DFDCWireDigiHit(); CopyDF1TDCInfo(h, hit); h->package = idx.package; h->chamber = idx.chamber; h->wire = idx.wire; return h; } //--------------------------------- // MakeSCTDCDigiHit //--------------------------------- DSCTDCDigiHit* DTranslationTable::MakeSCTDCDigiHit(const SCIndex_t &idx, const DF1TDCHit *hit) const { DSCTDCDigiHit *h = new DSCTDCDigiHit(); CopyDF1TDCInfo(h, hit); h->sector = idx.sector; return h; } //--------------------------------- // MakeTOFTDCDigiHit //--------------------------------- DTOFTDCDigiHit* DTranslationTable::MakeTOFTDCDigiHit(const TOFIndex_t &idx, const DF1TDCHit *hit) const { DTOFTDCDigiHit *h = new DTOFTDCDigiHit(); CopyDF1TDCInfo(h, hit); h->plane = idx.plane; h->bar = idx.bar; h->end = idx.end; return h; } //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- // The following routines access the translation table //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- static int ModuleStr2ModID(string &type); static DTranslationTable::Detector_t DetectorStr2DetID(string &type); static void StartElement(void *userData, const char *xmlname, const char **atts); static void EndElement(void *userData, const char *xmlname); //--------------------------------- // ReadTranslationTable //--------------------------------- void DTranslationTable::ReadTranslationTable(void) { // It seems expat is not thread safe so we lock a mutex here and // read in the translation table just once pthread_mutex_lock(&tt_mutex); if(tt_initialized){ pthread_mutex_unlock(&tt_mutex); return; } string translationTableName = "tt.xml"; jout << "Reading translation table " << translationTableName << endl; // create parser and specify element handlers XML_Parser xmlParser = XML_ParserCreate(NULL); if(xmlParser==NULL) { jerr << "readTranslationTable...unable to create parser" << endl; exit(EXIT_FAILURE); } XML_SetElementHandler(xmlParser,StartElement,EndElement); XML_SetUserData(xmlParser, &TT); // open and parse the file FILE *f = fopen(translationTableName.c_str(),"r"); if(f!=NULL) { int status,len; bool done; const int bufSize = 50000; char *buf = new char[bufSize]; do { len = fread(buf,1,bufSize,f); done = len!=bufSize; status=XML_Parse(xmlParser,buf,len,done); if((!done)&&(status==0)) { jerr << " ?readTranslationTable...parseXMLFile parse error for " << translationTableName << endl; jerr << XML_ErrorString(XML_GetErrorCode(xmlParser)) << endl; fclose(f); delete [] buf; XML_ParserFree(xmlParser); return; } } while (!done); fclose(f); delete [] buf; jout << TT.size() << " channels defined in translation table" << endl; } else { jerr << " ?readTranslationTable...unable to open " << translationTableName << endl; } XML_ParserFree(xmlParser); pthread_mutex_unlock(&tt_mutex); tt_initialized = true; } //--------------------------------- // ModuleStr2ModID //--------------------------------- int ModuleStr2ModID(string &type) { if(type=="vmecpu") { return(DModuleType::VMECPU); } else if (type=="tid") { return(DModuleType::TID); } else if (type=="fadc250") { return(DModuleType::FADC250); } else if (type=="fadc125") { return(DModuleType::FADC125); } else if (type=="f1tdcv2") { return(DModuleType::F1TDC32); } else if (type=="f1tdcv3") { return(DModuleType::F1TDC48); } else if (type=="jldisc") { return(DModuleType::JLAB_DISC); } else if (type=="vx1290a") { return(DModuleType::CAEN1290); } else { return(DModuleType::UNKNOWN); } } //--------------------------------- // DetectorStr2DetID //--------------------------------- DTranslationTable::Detector_t DetectorStr2DetID(string &type) { if( type=="fdc_cathodes" ) { return DTranslationTable::FDC_CATHODES; } else if( type=="fdc_wires" ) { return DTranslationTable::FDC_WIRES; } else if( type=="bcal" ) { return DTranslationTable::BCAL; } else if( type=="cdc" ) { return DTranslationTable::CDC; } else if( type=="fcal" ) { return DTranslationTable::FCAL; } else if( type=="ps" ) { return DTranslationTable::PS; } else if( type=="psc" ) { return DTranslationTable::PSC; } else if( type=="sc" ) { return DTranslationTable::SC; } else if( type=="tagh" ) { return DTranslationTable::TAGH; } else if( type=="tagm" ) { return DTranslationTable::TAGM; } else if( type=="tof" ) { return DTranslationTable::TOF; } else { return DTranslationTable::UNKNOWN_DETECTOR; } } //--------------------------------- // StartElement //--------------------------------- void StartElement(void *userData, const char *xmlname, const char **atts) { static int crate=0, slot=0; static string type,Type; int mc2codaType= 0; int channel = 0; string Detector; int end; int row,column,module,sector,layer,chan; int ring,straw,plane,bar,gPlane,element; int package,chamber,view,strip,wire; int id, strip_type; // This complicated line just recasts the userData pointer into // a reference to the "TT" member of the DTranslationTable object // that called us. map &TT = *((map*)userData); // store crate summary info, fill both maps if(strcasecmp(xmlname,"halld_online_translation_table")==0) { // do nothing } else if(strcasecmp(xmlname,"crate")==0) { for (int i=0; atts[i]; i+=2) { if(strcasecmp(atts[i],"number")==0) { crate = atoi(atts[i+1]); break; } } } else if(strcasecmp(xmlname,"slot")==0) { for (int i=0; atts[i]; i+=2) { if(strcasecmp(atts[i],"number")==0) { slot = atoi(atts[i+1]); } else if(strcasecmp(atts[i],"type")==0) { Type = string(atts[i+1]); type = string(atts[i+1]); std::transform(type.begin(), type.end(), type.begin(), (int(*)(int)) tolower); } } // The detID value set here shows up in the header of the Data Block Bank // of the output file. It should be set to one if this crate has JLab // made modules that output in the standard format (see document: // "VME Data Format Standards for JLAB Modules"). These would include // f250ADC, f125ADC, F1TDC, .... Slots containing other types of modules // (e.g. CAEN1290) should have their own unique detID. We use detID of // zero for non-digitizing modules like CPUs nd TIDs even though potentially, // one could read data from these. mc2codaType = ModuleStr2ModID(type); } else if(strcasecmp(xmlname,"channel")==0) { for (int i=0; atts[i]; i+=2) { string tag(atts[i+0]); string sval(atts[i+1]); int ival = atoi(atts[i+1]); if( tag == "number" ) channel = ival; else if(tag == "detector" ) Detector = sval; else if(tag == "row" ) row = ival; else if(tag == "column" ) column = ival; else if(tag == "col" ) column = ival; else if(tag == "module" ) module = ival; else if(tag == "sector" ) sector = ival; else if(tag == "layer" ) layer = ival; else if(tag == "chan" ) chan = ival; else if(tag == "ring" ) ring = ival; else if(tag == "straw" ) straw = ival; else if(tag == "gPlane" ) gPlane = ival; else if(tag == "element" ) element = ival; else if(tag == "plane" ) plane = ival; else if(tag == "bar" ) bar = ival; else if(tag == "package" ) package = ival; else if(tag == "chamber" ) chamber = ival; else if(tag == "view" ) view = ival; else if(tag == "strip" ) strip = ival; else if(tag == "wire" ) wire = ival; else if(tag == "id" ) id = ival; else if(tag == "end" ){ if( sval == "U" ) {end = DBCALGeometry::kUpstream; view=1;} else if(sval == "D" ) {end = DBCALGeometry::kDownstream; view=3;} else if(sval == "N" ) end = 0; // TOF north else if(sval == "S" ) end = 1; // TOF south else if(sval == "UP" ) end = 0; // TOF up else if(sval == "DW" ) end = 1; // TOF down } else if(tag == "strip_type"){ if( sval == "full" ) strip_type = 1; else if(sval == "A" ) strip_type = 2; else if(sval == "B" ) strip_type = 3; } } // ignore certain module types if(type == "disc") return; if(type == "ctp") return; if(type == "sd") return; if(type == "a1535sn") return; // // Data integrity check // if(crate<0 || crate>=MAXDCRATE){ // jerr << " Crate value of "<=MAXDSLOT){ // jerr << " Slot value of "<=MAXDCHANNEL){ // jerr << " Crate value of "<