Translation table 13-jul-2011
Contents
Background
We need a prototype translation table in order for the DAQ group to create a simulated raw data file from HDDM input. We will pay the DAQ group will do this work.
Proposed Translation Table Format
<translation_table version="0.1"> <crate number="1" type="VXS"> <slot number="1" type="FADC250"> <channel number="1" detector="FCAL" row="3" column="4" /> <channel number="2" detector="BCAL" module="10" sector="2" layer="3" end="0" /> <channel number="3" detector="SC" sector="21" /> <channel number="4" detector="Tagger" row="24" column="2" /> <channel number="5" detector="TOF" plane="1" bar="6" end="1" /> </slot> <slot number="2" type="FADC125" > <channel number="1" detector="FDCCathode" gplane="5" element="33" /> <channel number="2" detector="CDC" ring="3" straw="45" /> </slot> <slot number="3" type="F1TDC32" > <channel number="1" detector="TOF" plane="2" bar="1" end="0" /> <channel number="2" detector="Tagger" row="42" column="10" /> <channel number="3" detector="BCAL" module="6" sector="1" layer="3" end="1" /> <channel number="4" detector="SC" sector="38" /> </slot> <slot number="3" type="F1TDC64" > <channel number="1" detector="FDCAnode" gplane="2" element="99" /> </slot> <slot number="17" type="TI" /> <slot number="18" type="CPU" /> <switchSlot number="1" type="CTP" /> <switchSlot number="2" type="SD" /> </crate> </translation_table>
Fake Table Generation
I used a Python script to generate a full translation table. It includes both ADC and TDC data for the same detector when appropriate:
detectorOn = { 'CDC': 1, 'FDC': 1, 'BCAL': 1, 'FCAL': 1, 'SC': 1, 'TOF': 1, 'TAGGER': 1 } # SC: FADC250, 16 channels/slot if (detectorOn['SC']==1): type = 'FADC250' slot = slot+1 channel = 1 if (slot>max_slot): file.write(' </crate>\n\n\n') crate = crate+1 file.write(' <crate number="%i" type="VXS">\n\n' % crate) slot=1 file.write((' <slot number="%i"' % slot) + ' type="' + type + '">\n') for sector in range(1,41): if (channel>channelCount[type]): file.write(' </slot>\n\n') slot = slot+1 channel = 1 if (slot>max_slot): file.write(' </crate>\n\n\n') crate = crate+1 file.write(' <crate number="%i" type="VXS">\n\n' % crate) slot = 1 file.write((' <slot number="%i"' % slot) + ' type="' + type + '">\n') file.write(' <channel number="%i" detector="SC" sector="%i" />\n' % (channel,sector) ) channel = channel+1 file.write(' </slot>\n\n')
Fragment of Table
The full table contains 33k lines, 2.3 MB raw, 134k gzipped. Note that it currently includes more entries then actually exist:
<translation_table version="0.1"> <crate number="1" type="VXS"> <slot number="1" type="FADC125"> <channel number="1" detector="CDC" ring="1" straw="1" /> <channel number="2" detector="CDC" ring="1" straw="2" /> <channel number="3" detector="CDC" ring="1" straw="3" /> <channel number="4" detector="CDC" ring="1" straw="4" /> <channel number="5" detector="CDC" ring="1" straw="5" /> <channel number="6" detector="CDC" ring="1" straw="6" /> <channel number="7" detector="CDC" ring="1" straw="7" /> <channel number="8" detector="CDC" ring="1" straw="8" />
Programmatic Usage
The rawevent plugin uses the translation as follows:
// DTOFRawHit - FADC250 and F1TDC32 (60 ps) vector<const DTOFRawHit*> dtofrawhits; eventLoop->Get(dtofrawhits); for(i=0; i<dtofrawhits.size(); i++) { float dE = dtofrawhits[i]->dE; float t = dtofrawhits[i]->t; // translate to crate/slot/channel cscRef cscADC = DTOFRawHitTranslationADC(dtofrawhits[i]); cscRef cscTDC = DTOFRawHitTranslationTDC(dtofrawhits[i]); // do something with ADC info int crate = cscADC.get<0>(); // may change to different crate/slot/channel storage mechanism for efficiency int slot = cscADC.get<1>(); int channel = cscADC.get<2>(); }
Under the Hood
The XML translation table is read in, parsed and the data is stored in cscMap using a custom string as the map key:
// in the XML parser startElement handler: string s="unknown::"; if(detector=="fcal") { if(type=="fadc250") { s = "fcaladc::"; } else { s = "unknownFCAL::"; jerr << endl << endl << "?startElement...illegal type for FCAL: " << Type << endl << endl; } s += row + ":" + column; cscMap[s] = csc;
The map is used internally as follows
cscRef JEventProcessor_rawevent::DFCALHitTranslationADC(const DFCALHit* hit) const { string s = "fcaladc::" + lexical_cast<string>(hit->row) + ":" + lexical_cast<string>(hit->column); return(cscMap[s]); }
Inverse
I programmed and tested the inverse operation:
#define MAX_CRATE 58+1 #define MAX_SLOT 16+1 #define MAX_CHANNEL 72+1 static string detectorMap[MAX_CRATE][MAX_SLOT][MAX_CHANNEL]; // in XML parser string customString = ...; detectorMap[crate][slot][channel] = customString; ... // usage string customString = detectorMap[crate][slot][channel]; // parsing is detector-dependent
Online Usage
A reasonable scenario is for using the translation table in the Experiment Controls system is as follows:
- Latest table is stored in database (IRMIS?). Technicians need ability to add to/modify table when they install or move cables.
- At begin run the table is compared to most recent table stored in CCDB (ascii? gzipped?).
- If no change, do nothing, otherwise store new table in CCDB.
- If techs discover mistakes in the table then:
- table must be updated
- new version must be stored in CCDB for affected run range
Still to Do
The rawevent plugin should work for the DAQ task as it stands. Future improvements:
- optimize storage structures since methods are used in the innermost loops
- eliminate non-existant channels from fake translation table
- generate real translation table according to Fernando's detector mapping/labeling strategy