]>
Commit | Line | Data |
---|---|---|
5cfb4b82 | 1 | /* |
2 | ROOT Macro to generate ascii files for AliCaloAltroMapping; offline decoder | |
3 | - based on the map file produced by EMCALNumbering.C | |
4 | ||
5 | Update: 20 Aug 2008 - update to write separate files for A and C sides + | |
6 | added TRU and LED channels also.. | |
7 | ||
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) | |
11 | ||
12 | Some further documentation is available at: | |
13 | http://cern.ch/dsilverm/mapping/emcal_mapping.html | |
14 | ||
15 | Author: David Silvermyr, ORNL; silvermy@mail.phy.ornl.gov | |
16 | */ | |
17 | ||
18 | // First we define some constants - the main method WriteRCUs comes later | |
6d3af2f0 | 19 | const int kNTRU = 3; // per SM |
20 | const int kNTRUChanBlocks = 128; // max. per TRU | |
5cfb4b82 | 21 | const int kNLED = 24; // one per StripModule |
22 | ||
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; | |
30 | ||
31 | const int kMaxHWAddress = (1 << 11) // branch | |
32 | | (9 << 7) // FEC | |
33 | | (4 << 4) // Altro | |
34 | | 0xf; // channel | |
35 | ||
36 | const int kNRCU = 2; | |
37 | const int kNSides = 2; | |
38 | char * sideStr[] = {"A", "C"}; | |
39 | ||
40 | const int kFirstFEC = 1; | |
41 | const int kNFECPerGTL = 9; // NFEC/NGTL | |
42 | ||
43 | int makeHWAddress(int ibranch, int ifec, int ichip, int ichan) { | |
44 | int addr = (ibranch << 11) // branch | |
45 | | (ifec << 7) // FEC | |
46 | | (ichip << 4) // Altro | |
47 | | ichan; // channel | |
48 | return addr; | |
49 | } | |
50 | ||
51 | // HERE STARTS THE MAIN METHOD.. | |
52 | void WriteRCUs(const char *filename="map.root") | |
53 | { | |
54 | TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename); | |
55 | if (!f) { | |
56 | f = new TFile(filename); | |
57 | } | |
58 | TTree *tree = (TTree*)gDirectory->Get("tree"); | |
59 | ||
60 | const int kNTOW = 32; // per FEC | |
61 | ||
62 | //Declaration of leaves types | |
63 | Int_t iside; | |
64 | Int_t isect; | |
65 | Int_t iSM; | |
66 | Int_t iFEC; | |
67 | Int_t iRCU; | |
68 | Int_t iDDLEqId; | |
69 | Int_t iBranch; | |
70 | Int_t iGTL; | |
71 | Int_t nTow; | |
72 | Int_t CSP[kNTOW]; | |
73 | Int_t chip[kNTOW]; | |
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]; | |
79 | ||
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); | |
97 | ||
98 | Int_t nbytes = 0; | |
99 | ||
100 | // also variables and branch setting for LED TTree | |
101 | TTree *tLED = (TTree*)gDirectory->Get("tLED"); | |
102 | ||
103 | //Declaration of leaves types, not already declared | |
104 | Int_t nLED; | |
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]; | |
110 | ||
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); | |
125 | ||
126 | // and TRU TTree | |
127 | TTree *tTRU = (TTree*)gDirectory->Get("tTRU"); | |
128 | ||
129 | //Declaration of leaves types, not already declared | |
130 | Int_t iTRUchip; | |
131 | Int_t iTRUFirstChan; | |
132 | Int_t iTRULastChan; | |
133 | ||
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); | |
5cfb4b82 | 142 | tTRU->SetBranchAddress("iTRUFirstChan",&iTRUFirstChan); |
143 | tTRU->SetBranchAddress("iTRULastChan",&iTRULastChan); | |
144 | ||
145 | // OK, setup done - let's proceed.. First with the regular data | |
146 | ||
147 | int n[kNRCU][kNSides] = {0}; | |
148 | ofstream out[kNRCU][kNSides]; | |
149 | ofstream outFinal[kNRCU][kNSides]; | |
150 | ||
151 | // Open output files, and provide the necessary header | |
152 | char fname[100]; | |
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); | |
157 | ||
158 | sprintf(fname, "RCU%d%s.data",iRCU,sideStr[iside]); | |
159 | outFinal[iRCU][iside].open(fname); | |
160 | ||
161 | outFinal[iRCU][iside] << NChannelsPerRCU[iRCU] << endl; | |
162 | outFinal[iRCU][iside] << kMaxHWAddress << endl; | |
163 | ||
164 | n[iRCU][iside] = 0; | |
165 | } | |
166 | } | |
167 | ||
168 | int chid[kNGAIN] = {0}; | |
169 | int ig = 0; // gain flag | |
170 | ||
171 | // loop over channels | |
172 | for (Long64_t i=0; i<tree->GetEntries();i++) { | |
173 | nbytes += tree->GetEntry(i); | |
174 | ||
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) | |
176 | ||
177 | /* | |
178 | FECs should come in order so let's just worry about channel order | |
179 | within an FEC | |
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.. | |
183 | */ | |
184 | // The towerOrder array should have the needed indexing info | |
185 | for (int it = 0; it<kNTOW; it++) { | |
186 | int itow = towerOrder[it]; | |
187 | ||
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] ); | |
192 | ||
193 | // cout << " it " << it << " : " << chid[0] << " " << chid[1] << endl; | |
194 | ||
195 | // start with the lowest | |
196 | if (chid[0] < chid[1]) { | |
197 | ig = 0; | |
198 | } | |
199 | else { | |
200 | ig = 1; | |
201 | } | |
202 | ||
203 | out[iRCU][iside] << chid[ig] << " " | |
204 | << towerRow[itow] << " " | |
205 | << towerCol[itow] << " " << ig | |
206 | << endl; | |
207 | n[iRCU][iside]++; | |
208 | // and then the next | |
209 | ig = 1 -ig; | |
210 | out[iRCU][iside] << chid[ig] << " " | |
211 | << towerRow[itow] << " " | |
212 | << towerCol[itow] << " " << ig | |
213 | << endl; | |
214 | n[iRCU][iside]++; | |
215 | } // loop over towers | |
216 | } // sector==0 selection | |
217 | } | |
218 | // done, with FEE data | |
219 | ||
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; | |
226 | } | |
227 | } | |
228 | ||
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 | |
232 | int TRUchid = 0; | |
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, | |
6d3af2f0 | 238 | ichan/16, ichan%16 ); |
5cfb4b82 | 239 | out[iRCU][iside] << TRUchid << " " |
240 | << dummyRow << " " | |
241 | << ichan << " " // channel # coded as Column.. | |
242 | << caloFlag << endl; | |
243 | n[iRCU][iside]++; | |
244 | } | |
245 | } | |
246 | } | |
247 | ||
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; | |
254 | } | |
255 | } | |
256 | ||
257 | // Then. LED data | |
258 | caloFlag = 3; // from enum AliCaloRawStream::kLEDMonData | |
259 | int LEDchid = 0; // assigned below | |
260 | ||
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++) { | |
265 | ||
266 | // first low gain | |
267 | ig = 0; | |
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.. | |
273 | << caloFlag << endl; | |
274 | n[iRCU][iside]++; | |
275 | ||
276 | // then high gain | |
277 | ig = 1; | |
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.. | |
283 | << caloFlag << endl; | |
284 | n[iRCU][iside]++; | |
285 | } | |
286 | } | |
287 | } | |
288 | ||
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; | |
301 | } | |
302 | else { | |
303 | cout << " - Wrong! " << endl; | |
304 | } | |
305 | ||
306 | } | |
307 | } | |
308 | ||
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.. | |
312 | char cmd[200]; | |
313 | sprintf(cmd, "mkdir -p tmp"); // provide a temporary storage space - not to pollute the local dir. too much | |
314 | gSystem->Exec(cmd); | |
315 | ||
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; | |
321 | gSystem->Exec(cmd); | |
322 | sprintf(cmd, "mv RCU%d%s.data.unsorted tmp/.", | |
323 | iRCU, sideStr[iside]); | |
324 | cout << "executing " << cmd << endl; | |
325 | gSystem->Exec(cmd); | |
326 | } | |
327 | } | |
328 | ||
329 | } |