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
20 const int kNTRUChanBlocks = 16; // per TRU - info from Dong and Hans, July 22, 2008
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("iTRUchip",&iTRUchip);
143 tTRU->SetBranchAddress("iTRUFirstChan",&iTRUFirstChan);
144 tTRU->SetBranchAddress("iTRULastChan",&iTRULastChan);
146 // OK, setup done - let's proceed.. First with the regular data
148 int n[kNRCU][kNSides] = {0};
149 ofstream out[kNRCU][kNSides];
150 ofstream outFinal[kNRCU][kNSides];
152 // Open output files, and provide the necessary header
154 for (iRCU=0; iRCU<kNRCU; iRCU++) {
155 for (iside=0; iside<kNSides; iside++) {
156 sprintf(fname, "RCU%d%s.data.unsorted",iRCU,sideStr[iside]);
157 out[iRCU][iside].open(fname);
159 sprintf(fname, "RCU%d%s.data",iRCU,sideStr[iside]);
160 outFinal[iRCU][iside].open(fname);
162 outFinal[iRCU][iside] << NChannelsPerRCU[iRCU] << endl;
163 outFinal[iRCU][iside] << kMaxHWAddress << endl;
169 int chid[kNGAIN] = {0};
170 int ig = 0; // gain flag
172 // loop over channels
173 for (Long64_t i=0; i<tree->GetEntries();i++) {
174 nbytes += tree->GetEntry(i);
176 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)
179 FECs should come in order so let's just worry about channel order
181 DS (Aug 2008): in principle we don't really need to do this anymore,
182 since we anyway call a sort command at the end now, but since it was
183 already coded I kept this for now..
185 // The towerOrder array should have the needed indexing info
186 for (int it = 0; it<kNTOW; it++) {
187 int itow = towerOrder[it];
189 chid[0] = makeHWAddress( iBranch, (iFEC%kNFECPerGTL) + kFirstFEC,
190 chip[itow], lowGainChan[itow] );
191 chid[1] = makeHWAddress( iBranch, (iFEC%kNFECPerGTL) + kFirstFEC,
192 chip[itow], highGainChan[itow] );
194 // cout << " it " << it << " : " << chid[0] << " " << chid[1] << endl;
196 // start with the lowest
197 if (chid[0] < chid[1]) {
204 out[iRCU][iside] << chid[ig] << " "
205 << towerRow[itow] << " "
206 << towerCol[itow] << " " << ig
211 out[iRCU][iside] << chid[ig] << " "
212 << towerRow[itow] << " "
213 << towerCol[itow] << " " << ig
216 } // loop over towers
217 } // sector==0 selection
219 // done, with FEE data
221 // report on counts; just for early debugging..
222 for (iRCU=0; iRCU<kNRCU; iRCU++) {
223 for (iside=0; iside<kNSides; iside++) {
224 cout << " post-FEE count: RCU " << iRCU
225 << " iside " << iside
226 << " n = " << n[iRCU][iside] << endl;
230 // Next, we have the fake ALTRO from the TRU
231 int caloFlag = 2; // from enum AliCaloRawStream::kTRUData
232 int dummyRow = 0; // need to have the right number of fields in print-out
234 for (Long64_t i=0; i<tTRU->GetEntries(); i++) {
235 nbytes += tTRU->GetEntry(i);
236 if (isect==0) { // select just the 1st sector; same motivation as for FEE
237 for (int ichan=iTRUFirstChan; ichan<=iTRULastChan; ichan++) {
238 TRUchid = makeHWAddress( iBranch, iGTL,
240 out[iRCU][iside] << TRUchid << " "
242 << ichan << " " // channel # coded as Column..
249 // report on counts; just for early debugging..
250 for (iRCU=0; iRCU<kNRCU; iRCU++) {
251 for (iside=0; iside<kNSides; iside++) {
252 cout << " post-TRU count: RCU " << iRCU
253 << " iside " << iside
254 << " n = " << n[iRCU][iside] << endl;
259 caloFlag = 3; // from enum AliCaloRawStream::kLEDMonData
260 int LEDchid = 0; // assigned below
262 for (Long64_t i=0; i<tLED->GetEntries(); i++) {
263 nbytes += tLED->GetEntry(i);
264 if (isect==0) { // just the 1st sector
265 for (int il=0; il<nLED; il++) {
269 LEDchid = makeHWAddress( iBranch, iGTL,
270 iLEDchip[il], iLEDlowGainChan[il] );
271 out[iRCU][iside] << LEDchid << " "
272 << ig << " " // gain coded as row..
273 << iLEDStrip[il] << " " // strip # coded as Column..
279 LEDchid = makeHWAddress( iBranch, iGTL,
280 iLEDchip[il], iLEDhighGainChan[il] );
281 out[iRCU][iside] << LEDchid << " "
282 << ig << " " // gain coded as row..
283 << iLEDStrip[il] << " " // strip # coded as Column..
290 // Finally, let's close the output files - we should get the counts we expected
291 for (iRCU=0; iRCU<kNRCU; iRCU++) {
292 for (iside=0; iside<kNSides; iside++) {
293 out[iRCU][iside].close();
294 outFinal[iRCU][iside].close();
295 // report how many entries we encountered
296 cout << " final count: RCU " << iRCU
297 << " iside " << iside
298 << " n = " << n[iRCU][iside]
299 << " expected " << NChannelsPerRCU[iRCU];
300 if (n[iRCU][iside] == NChannelsPerRCU[iRCU]) {
301 cout << " - OK! " << endl;
304 cout << " - Wrong! " << endl;
310 // let's then do a final loop where we sort the lists into the final files
311 // I'm not sure if having the lists ordered is really needed but it is at
312 // least more aestethically pleasing..
314 sprintf(cmd, "mkdir -p tmp"); // provide a temporary storage space - not to pollute the local dir. too much
317 for (iRCU=0; iRCU<kNRCU; iRCU++) {
318 for (iside=0; iside<kNSides; iside++) {
319 sprintf(cmd, "sort -n RCU%d%s.data.unsorted >> RCU%d%s.data",
320 iRCU, sideStr[iside], iRCU, sideStr[iside]);
321 cout << "executing " << cmd << endl;
323 sprintf(cmd, "mv RCU%d%s.data.unsorted tmp/.",
324 iRCU, sideStr[iside]);
325 cout << "executing " << cmd << endl;