2 ROOT Macro to generate ascii files for AliCaloAltroMapping; offline decoder
3 - based on the map file produced by EMCALNumbering.C
5 Update: 20 Aug 2008 - update to write separate files for A and C sides +
6 added TRU and LED channels also..
8 LED channels look like regular FEE data; just from rcu=0, branch=0, FEC=0
9 TRU data has one block of data from the whole TRU; all other FEC=0 slots
10 (rcu, branch) = (0,1), (1,0), (1,1)
12 Some further documentation is available at:
13 http://cern.ch/dsilverm/mapping/emcal_mapping.html
15 Author: David Silvermyr, ORNL; silvermy@mail.phy.ornl.gov
18 // First we define some constants - the main method WriteRCUs comes later
19 const int kNTRU = 3; // per SM
20 const int kNTRUChanBlocks = 128; // max. per TRU
21 const int kNLED = 24; // one per StripModule
23 const int kNGAIN = 2; // low (0) and high (1)
24 const int kNFEEChannelsPerRCU = 1152;
25 int NChannelsPerRCU[2];
26 // RCU 0: FEE + NTRUChanBlocks + NLED*NGAIN
27 NChannelsPerRCU[0] = kNFEEChannelsPerRCU + kNTRUChanBlocks + kNLED*kNGAIN;
28 // RCU 1: FEE + 2*NTRUChanBlocks
29 NChannelsPerRCU[1] = kNFEEChannelsPerRCU + 2*kNTRUChanBlocks;
31 const int kMaxHWAddress = (1 << 11) // branch
37 const int kNSides = 2;
38 char * sideStr[] = {"A", "C"};
40 const int kFirstFEC = 1;
41 const int kNFECPerGTL = 9; // NFEC/NGTL
43 int makeHWAddress(int ibranch, int ifec, int ichip, int ichan) {
44 int addr = (ibranch << 11) // branch
46 | (ichip << 4) // Altro
51 // HERE STARTS THE MAIN METHOD..
52 void WriteRCUs(const char *filename="map.root")
54 TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
56 f = new TFile(filename);
58 TTree *tree = (TTree*)gDirectory->Get("tree");
60 const int kNTOW = 32; // per FEC
62 //Declaration of leaves types
74 Int_t lowGainChan[kNTOW];
75 Int_t highGainChan[kNTOW];
76 Int_t towerCol[kNTOW];
77 Int_t towerRow[kNTOW];
78 Int_t towerOrder[kNTOW];
80 // Set branch addresses.
81 tree->SetBranchAddress("iside",&iside);
82 tree->SetBranchAddress("isect",&isect);
83 tree->SetBranchAddress("iSM",&iSM);
84 tree->SetBranchAddress("iFEC",&iFEC);
85 tree->SetBranchAddress("iRCU",&iRCU);
86 tree->SetBranchAddress("iDDLEqId",&iDDLEqId);
87 tree->SetBranchAddress("iBranch",&iBranch);
88 tree->SetBranchAddress("iGTL",&iGTL);
89 tree->SetBranchAddress("nTow",&nTow);
90 tree->SetBranchAddress("CSP",CSP);
91 tree->SetBranchAddress("chip",chip);
92 tree->SetBranchAddress("lowGainChan",lowGainChan);
93 tree->SetBranchAddress("highGainChan",highGainChan);
94 tree->SetBranchAddress("towerCol",towerCol);
95 tree->SetBranchAddress("towerRow",towerRow);
96 tree->SetBranchAddress("towerOrder",towerOrder);
100 // also variables and branch setting for LED TTree
101 TTree *tLED = (TTree*)gDirectory->Get("tLED");
103 //Declaration of leaves types, not already declared
105 Int_t iLEDCSP[kNLED];
106 Int_t iLEDchip[kNLED];
107 Int_t iLEDlowGainChan[kNLED];
108 Int_t iLEDhighGainChan[kNLED];
109 Int_t iLEDStrip[kNLED];
111 // Set branch addresses.
112 tLED->SetBranchAddress("iside",&iside);
113 tLED->SetBranchAddress("isect",&isect);
114 tLED->SetBranchAddress("iSM",&iSM);
115 tLED->SetBranchAddress("iDDLEqId",&iDDLEqId);
116 tLED->SetBranchAddress("iRCU",&iRCU);
117 tLED->SetBranchAddress("iBranch",&iBranch);
118 tLED->SetBranchAddress("iGTL",&iGTL);
119 tLED->SetBranchAddress("nLED",&nLED);
120 tLED->SetBranchAddress("iLEDCSP",iLEDCSP);
121 tLED->SetBranchAddress("iLEDchip",iLEDchip);
122 tLED->SetBranchAddress("iLEDlowGainChan",iLEDlowGainChan);
123 tLED->SetBranchAddress("iLEDhighGainChan",iLEDhighGainChan);
124 tLED->SetBranchAddress("iLEDStrip",iLEDStrip);
127 TTree *tTRU = (TTree*)gDirectory->Get("tTRU");
129 //Declaration of leaves types, not already declared
134 // Set branch addresses.
135 tTRU->SetBranchAddress("iside",&iside);
136 tTRU->SetBranchAddress("isect",&isect);
137 tTRU->SetBranchAddress("iSM",&iSM);
138 tTRU->SetBranchAddress("iDDLEqId",&iDDLEqId);
139 tTRU->SetBranchAddress("iRCU",&iRCU);
140 tTRU->SetBranchAddress("iBranch",&iBranch);
141 tTRU->SetBranchAddress("iGTL",&iGTL);
142 tTRU->SetBranchAddress("iTRUFirstChan",&iTRUFirstChan);
143 tTRU->SetBranchAddress("iTRULastChan",&iTRULastChan);
145 // OK, setup done - let's proceed.. First with the regular data
147 int n[kNRCU][kNSides] = {0};
148 ofstream out[kNRCU][kNSides];
149 ofstream outFinal[kNRCU][kNSides];
151 // Open output files, and provide the necessary header
153 for (iRCU=0; iRCU<kNRCU; iRCU++) {
154 for (iside=0; iside<kNSides; iside++) {
155 sprintf(fname, "RCU%d%s.data.unsorted",iRCU,sideStr[iside]);
156 out[iRCU][iside].open(fname);
158 sprintf(fname, "RCU%d%s.data",iRCU,sideStr[iside]);
159 outFinal[iRCU][iside].open(fname);
161 outFinal[iRCU][iside] << NChannelsPerRCU[iRCU] << endl;
162 outFinal[iRCU][iside] << kMaxHWAddress << endl;
168 int chid[kNGAIN] = {0};
169 int ig = 0; // gain flag
171 // loop over channels
172 for (Long64_t i=0; i<tree->GetEntries();i++) {
173 nbytes += tree->GetEntry(i);
175 if (isect==0) { // just the 1st sector; other sectors will look the same internally (or be a subset in case of the 1/3 size ones)
178 FECs should come in order so let's just worry about channel order
180 DS (Aug 2008): in principle we don't really need to do this anymore,
181 since we anyway call a sort command at the end now, but since it was
182 already coded I kept this for now..
184 // The towerOrder array should have the needed indexing info
185 for (int it = 0; it<kNTOW; it++) {
186 int itow = towerOrder[it];
188 chid[0] = makeHWAddress( iBranch, (iFEC%kNFECPerGTL) + kFirstFEC,
189 chip[itow], lowGainChan[itow] );
190 chid[1] = makeHWAddress( iBranch, (iFEC%kNFECPerGTL) + kFirstFEC,
191 chip[itow], highGainChan[itow] );
193 // cout << " it " << it << " : " << chid[0] << " " << chid[1] << endl;
195 // start with the lowest
196 if (chid[0] < chid[1]) {
203 out[iRCU][iside] << chid[ig] << " "
204 << towerRow[itow] << " "
205 << towerCol[itow] << " " << ig
210 out[iRCU][iside] << chid[ig] << " "
211 << towerRow[itow] << " "
212 << towerCol[itow] << " " << ig
215 } // loop over towers
216 } // sector==0 selection
218 // done, with FEE data
220 // report on counts; just for early debugging..
221 for (iRCU=0; iRCU<kNRCU; iRCU++) {
222 for (iside=0; iside<kNSides; iside++) {
223 cout << " post-FEE count: RCU " << iRCU
224 << " iside " << iside
225 << " n = " << n[iRCU][iside] << endl;
229 // Next, we have the fake ALTRO from the TRU
230 int caloFlag = 2; // from enum AliCaloRawStream::kTRUData
231 int dummyRow = 0; // need to have the right number of fields in print-out
233 for (Long64_t i=0; i<tTRU->GetEntries(); i++) {
234 nbytes += tTRU->GetEntry(i);
235 if (isect==0) { // select just the 1st sector; same motivation as for FEE
236 for (int ichan=iTRUFirstChan; ichan<=iTRULastChan; ichan++) {
237 TRUchid = makeHWAddress( iBranch, iGTL,
238 ichan/16, ichan%16 );
239 out[iRCU][iside] << TRUchid << " "
241 << ichan << " " // channel # coded as Column..
248 // report on counts; just for early debugging..
249 for (iRCU=0; iRCU<kNRCU; iRCU++) {
250 for (iside=0; iside<kNSides; iside++) {
251 cout << " post-TRU count: RCU " << iRCU
252 << " iside " << iside
253 << " n = " << n[iRCU][iside] << endl;
258 caloFlag = 3; // from enum AliCaloRawStream::kLEDMonData
259 int LEDchid = 0; // assigned below
261 for (Long64_t i=0; i<tLED->GetEntries(); i++) {
262 nbytes += tLED->GetEntry(i);
263 if (isect==0) { // just the 1st sector
264 for (int il=0; il<nLED; il++) {
268 LEDchid = makeHWAddress( iBranch, iGTL,
269 iLEDchip[il], iLEDlowGainChan[il] );
270 out[iRCU][iside] << LEDchid << " "
271 << ig << " " // gain coded as row..
272 << iLEDStrip[il] << " " // strip # coded as Column..
278 LEDchid = makeHWAddress( iBranch, iGTL,
279 iLEDchip[il], iLEDhighGainChan[il] );
280 out[iRCU][iside] << LEDchid << " "
281 << ig << " " // gain coded as row..
282 << iLEDStrip[il] << " " // strip # coded as Column..
289 // Finally, let's close the output files - we should get the counts we expected
290 for (iRCU=0; iRCU<kNRCU; iRCU++) {
291 for (iside=0; iside<kNSides; iside++) {
292 out[iRCU][iside].close();
293 outFinal[iRCU][iside].close();
294 // report how many entries we encountered
295 cout << " final count: RCU " << iRCU
296 << " iside " << iside
297 << " n = " << n[iRCU][iside]
298 << " expected " << NChannelsPerRCU[iRCU];
299 if (n[iRCU][iside] == NChannelsPerRCU[iRCU]) {
300 cout << " - OK! " << endl;
303 cout << " - Wrong! " << endl;
309 // let's then do a final loop where we sort the lists into the final files
310 // I'm not sure if having the lists ordered is really needed but it is at
311 // least more aestethically pleasing..
313 sprintf(cmd, "mkdir -p tmp"); // provide a temporary storage space - not to pollute the local dir. too much
316 for (iRCU=0; iRCU<kNRCU; iRCU++) {
317 for (iside=0; iside<kNSides; iside++) {
318 sprintf(cmd, "sort -n RCU%d%s.data.unsorted >> RCU%d%s.data",
319 iRCU, sideStr[iside], iRCU, sideStr[iside]);
320 cout << "executing " << cmd << endl;
322 sprintf(cmd, "mv RCU%d%s.data.unsorted tmp/.",
323 iRCU, sideStr[iside]);
324 cout << "executing " << cmd << endl;