]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/mapping/EMCalNumbering.C
Added new class needed for refactoring of the
[u/mrichter/AliRoot.git] / EMCAL / mapping / EMCalNumbering.C
1 /* 
2 ROOT Macro to generate all numbering believed to be relevant for EMCAL
3 - at least as far as electronics is concerned.
4 Includes FEE, TRU and LED information. Sorry if this macro does not quite 
5 adher to ALICE coding conventions (but on the other hand it is not used in AliRoot)
6
7 Some further documentation is available at:
8 http://cern.ch/dsilverm/mapping/emcal_mapping.html
9
10 Author: David Silvermyr, ORNL; silvermy@mail.phy.ornl.gov
11 */
12
13 /* 
14 First we define a number of constants; the main method EMCALNumbering starts below 
15 */
16
17 const int kDDLEqIdOffsetEMCAL = 0x1200; /* From AliDAQ; first equipment Id # for EMCAL*/
18
19 // global arrays for chip, channel and CSP numbering
20 // - in the area covered by a single FEC (32 CSPs covering a 4x8 tower area)
21 const int kNROWS = 8;
22 const int kNCOLS = 4;
23 const int kNCSP = 32;
24
25 // the way CSPs are populated, as seen from the back where we
26 // plug in the T-cards
27 const int kCspMap[kNROWS][kNCOLS] = {
28   0, 16,  8, 24, // 7
29   1, 17,  9, 25, // |
30   2, 18, 10, 26, // |
31   3, 19, 11, 27, // row
32   4, 20, 12, 28, // |
33   5, 21, 13, 29, // |
34   6, 22, 14, 30, // |
35   7, 23, 15, 31  // 0
36   // 0 <-col-> 3
37 };
38 // i.e. the highest row comes first, and this map should thus be indexed as [NROWS-1-irow][icol]
39 // - Csp help array is constructed below.
40
41 /*
42   The rest of the global Chan/Chip arrays are either fixed
43   from the Altro mapping, or a function of the CspMap above
44 */
45
46 // Altro mapping for chips and channels, high and low gain
47 const int kChip[kNCSP] = {
48   2,   2,   2,   2,   3,   3,   3,   3, 
49   0,   0,   0,   0,   4,   4,   4,   4, 
50   2,   2,   2,   2,   3,   3,   3,   3, 
51   0,   0,   0,   0,   4,   4,   4,   4 
52 };
53
54 const int kChanHigh[kNCSP] = {
55   10,  14,   5,   1,   1,   5,  14,  10, 
56   10,  14,   5,   1,   1,   5,  14,  10, 
57    8,  12,   7,   3,   3,   7,  12,   8, 
58    8,  12,   7,   3,   3,   7,  12,   8 
59 };
60
61 const int kChanLow[kNCSP] = {
62   11,  15,   4,   0,   0,   4,  15,  11, 
63   11,  15,   4,   0,   0,   4,  15,  11, 
64    9,  13,   6,   2,   2,   6,  13,   9, 
65    9,  13,   6,   2,   2,   6,  13,   9 
66 };
67
68 // Order that CSPs appear in the data 
69 const int kCspOrder[kNCSP] = { // just from ALTRO mapping of chips/channels to CSP
70  11,  27,  10,  26,  24,   8,  25,   9, 
71   3,  19,   2,  18,  16,   0,  17,   1, 
72   4,  20,   5,  21,  23,   7,  22,   6, 
73  12,  28,  13,  29,  31,  15,  30,  14 
74 };
75
76 // LED reference info:
77 const int kNLED = 24; // per SuperModule; equals number of StripModules per SuperModule
78 const int kNLEDPerTCard = kNLED / 2;
79 // CSPs and LED are connected on a special T-card with only 12 connectors
80 // Half of the StripModules in a SuperModule will be connected to the Top
81 // (and half to the Bottom) T-card
82 // First Top
83 const int kCspMapLEDTop[kNLEDPerTCard] = {
84   1, 17, // Strips  0, 1
85   2, 18, // Strips  2, 3
86   3, 19, // Strips  4, 5
87   4, 20, // Strips  6, 7
88   5, 21, // Strips  8, 9
89   6, 22  // Strips 10,11
90 };
91 const int kStripModuleMapLEDTop[kNLEDPerTCard] = {
92   0, 1,
93   2, 3,
94   4, 5,
95   6, 7,
96   8, 9,
97  10,11
98 };
99
100 // Then Bottom
101 const int kCspMapLEDBottom[kNLEDPerTCard] = {
102    9, 25, // Strips 12,13
103   10, 26, // Strips 14,15
104   11, 27, // Strips 16,17
105   12, 28, // Strips 18,19
106   13, 29, // Strips 20,21
107   14, 30  // Strips 22,23
108 };
109 const int kStripModuleMapLEDBottom[kNLEDPerTCard] = {
110   12,13,
111   14,15,
112   16,17,
113   18,19,
114   20,21,
115   22,23
116 };
117
118 // let's make some simpler/normal help index arrays too, that we'll use later on
119 int ROW[kNCSP];
120 int COL[kNCSP];
121 int Csp[kNROWS][kNCOLS];
122
123 // Order that Towers, appear in the data 
124 int towerOrder[kNCSP];
125
126 void initTowers()
127 {
128   for(int icol=0; icol<kNCOLS; icol++){
129     for(int irow=0; irow<kNROWS; irow++){
130       int csp = kCspMap[kNROWS-1-irow][icol];
131       COL[csp] = icol;
132       ROW[csp] = irow;
133       Csp[irow][icol] = csp;
134
135       cout << " icol " << icol
136            << " irow " << irow
137            << " csp " << csp << endl;
138     }
139   }
140
141   // let's also give the order that Towers appear in the data
142   for (int ic=0; ic<kNCSP; ic++) {
143     int towerid = ROW[kCspOrder[ic]]*kNCOLS + COL[kCspOrder[ic]];
144     towerOrder[ic] = towerid;
145   }
146
147 }
148
149 // help functions for TRU mapping:
150 int getTRUADC(int iFEC) { // iFEC is a number 0-35, within a SM
151   // ADC channel 1-12 on TRU as a function of connected iFEC
152   return (iFEC%12 + 1); 
153 }
154
155 int getTRUADCChan(int iCSP) { // iCSP is from 0 to 31
156   int bottom = (iCSP%16)/8; // 0 for top, 1 for bottom T-card
157   int iADCChan = (iCSP%8)/2 + 1; // within a T-card; 1-4
158   return (iADCChan + bottom*4);
159 }
160 // ok, done with TRU help methods also; let's do what needs to be done
161
162 // HERE STARTS THE MAIN METHOD..
163 void EMCalNumbering()
164 {
165   /*
166     General coord. info: ALICE-INT-2003-038 EDMS doc.
167
168     z goes in the beam direction from RB26 (side C,where the muon arm is,Gex), 
169     to RB24 (side A, Bellegarde), i.e. away from muon arm.
170
171     x is horizontal, perpendicular to the beam direction and points to the 
172     accelerator (LHC ring) centre. 
173     [visual aid.: pos. x = Saleve; Inside/I, negative = Jura; Outside/O]
174
175     y is vertical, perpendicular to z and x. Positive y points upward.    
176     [pos. y = Up/U. neg. y = Down/D]
177
178     The usual relation to r, phi(-pi, pi), theta (0,pi) applies:
179     x = r * sin(theta) * cos(phi);
180     y = r * sin(theta) * sin(phi);
181     z = r * cos(theta)
182   
183     r = sqrt(x*x + y*y +z*z);
184     theta = TMath::ACos(z/r);
185     phi = TMath::ATan2(y, x);
186   */
187
188   /* Numbering rules: ALICE-INT-2003-038 EDMS doc.
189
190   All numbering starts from 0.
191
192   Rotational Numbering: follows phi direction
193   [looks counter-clockwise from A, and clockwise from C]
194
195   Linear numbering: follows _reverse_ z-direction from A to C, 
196   without interruption at z=0
197   [presumably to have a reasonable numbering in the muon system]
198
199   Radial numbering increases outwards, but EMCAL only has one layer.
200   so doesn't matter for us.
201    */
202
203   // EMCAL specifics
204
205   initTowers(); // prepare setup
206
207   // global info on sectors
208   const int kNFullSect = 5;
209   const int kNThirdSect = 1;
210   const int kNSides = 2; // supermodules for both positive and negative Z
211   // let's call side A '0', and side C '1'
212
213   // Number of SuperModules and DDLs total
214   const int kNSM = (kNFullSect + kNThirdSect)*kNSides; // 12
215   //  const int NDDL = NSides*(NFullSect * 2 + NThirdSect*1); // 22
216
217   // per supermodule info
218   const int kNTowersZ = 48;
219   const int kNTowersPhi = 24;
220   const int kNTowersPerFEC = 32;
221   const int kNFEC = 36;
222   const int kNGTL = 4; 
223   const int kNRCU = 2;
224   const int kNTRU = 3;
225
226   const int kNTowersSM = kNTowersZ*kNTowersPhi; // 1152
227
228   const int kNModulesZ = kNTowersZ/2; // 24
229   const int kNModulesPhi = kNTowersPhi/2; // 12
230   const int kNModulesSM = kNTowersSM/4; // 288
231
232   // per GTL
233   const int kNFECPerGTL = kNFEC/kNGTL; // 9
234   // per RCU
235   const int kNFECPerRCU = kNFEC/kNRCU; // 18
236   // per TRU
237   const int kNFECPerTRU = kNFEC/kNTRU; // 12
238
239   // and per FrontEndCard:
240   // 2 T-cards, each with 16 towers, per FEC
241   const int kNTCards = 2;
242   // each T-card covers a 2x8 tower area
243   const int kNTowersPhiTC = 8; 
244   const int kNTowersZTC = 2; 
245
246   // OK, that was all the setup and definitions of constants..
247
248   /* Now, how do we populate the Supermodule and it's GTL space?
249      Simplest seems to be to have 3 rows of 12 FECs each,
250      where each FEC's 2 T-cards cover a 4(z)*8(phi) tower area. 
251      Do the coverage in order..
252   */
253   const int kNFECPerRow = kNFEC/3; // 12 
254
255   TFile *f = new TFile("map.root","RECREATE");
256
257   // global variables
258   int iside = 0; // A=0, C=1
259   int isect = 0; // 0-5
260   int iSM = 0;   // 0-11, offline SuperModule index
261   int iDDLEqId = 0;  // kDDLEqIdOffsetEMCAL = 0x1200 upwards (NDDL) 
262  
263   // within SM
264   int iFEC = 0;  // 0
265   int iTRU = 0;  // 0-2, within SM
266   int iTRUADC = 0;  // 1-8, within TRU
267   int iRCU = 0;  // 0-1, within SM
268   int iBranch = 0; // A=0, B=1
269   int iGTL = 0;   // address 1-9; TRU is in address slot 0
270   // within FEC
271   int nTow = kNCSP; // # of towers, per  FEC
272   int CSP[kNCSP] = {0};
273   int chip[kNCSP] = {0};
274   int lowGainChan[kNCSP] = {0};
275   int highGainChan[kNCSP] = {0};
276   int towerCol[kNCSP] = {0};
277   int towerRow[kNCSP] = {0};
278   int iTRUADCChan[kNCSP] = {0};
279
280   TTree *t = new TTree("tree","ALICE EMCal tower map");
281   t->Branch("iside",&iside,"iside/I");
282   t->Branch("isect",&isect,"isect/I");
283   t->Branch("iSM",&iSM,"iSM/I");
284   t->Branch("iDDLEqId",&iDDLEqId,"iDDLEqId/I");
285   t->Branch("iFEC",&iFEC,"iFEC/I");
286   t->Branch("iTRU",&iTRU,"iTRU/I");
287   t->Branch("iTRUADC",&iTRUADC,"iTRUADC/I");
288   t->Branch("iRCU",&iRCU,"iRCU/I");
289   t->Branch("iBranch",&iBranch,"iBranch/I");
290   t->Branch("iGTL",&iGTL,"iGTL/I");
291   t->Branch("nTow",&nTow,"nTow/I");
292   t->Branch("CSP",CSP,"CSP[nTow]/I");
293   t->Branch("chip",chip,"chip[nTow]/I");
294   t->Branch("lowGainChan",lowGainChan,"lowGainChan[nTow]/I");
295   t->Branch("highGainChan",highGainChan,"highGainChan[nTow]/I");
296   t->Branch("towerCol",towerCol,"towerCol[nTow]/I");
297   t->Branch("towerRow",towerRow,"towerRow[nTow]/I");
298   t->Branch("towerOrder",towerOrder,"towerOrder[nTow]/I");
299   t->Branch("iTRUADCChan",iTRUADCChan,"iTRUADCChan[nTow]/I");
300
301   // LED TTree
302   TTree *tLED = new TTree("tLED","ALICE EMCal LED reference map");
303   tLED->Branch("iside",&iside,"iside/I");
304   tLED->Branch("isect",&isect,"isect/I");
305   tLED->Branch("iSM",&iSM,"iSM/I");
306   tLED->Branch("iDDLEqId",&iDDLEqId,"iDDLEqId/I");
307   tLED->Branch("iRCU",&iRCU,"iRCU/I");
308   tLED->Branch("iBranch",&iBranch,"iBranch/I");
309   tLED->Branch("iGTL",&iGTL,"iGTL/I");
310   int nLED = kNLED; 
311   tLED->Branch("nLED",&nLED,"nLED/I");
312   int iLEDCSP[kNLED] = {0};
313   int iLEDchip[kNLED] = {0};
314   int iLEDhighGainChan[kNLED] = {0};
315   int iLEDlowGainChan[kNLED] = {0};
316   int iLEDStrip[kNLED] = {0};
317   tLED->Branch("iLEDCSP",iLEDCSP,"iLEDCSP[nLED]/I");
318   tLED->Branch("iLEDchip",iLEDchip,"iLEDchip[nLED]/I");
319   tLED->Branch("iLEDlowGainChan",iLEDlowGainChan,"iLEDlowGainChan[nLED]/I");
320   tLED->Branch("iLEDhighGainChan",iLEDhighGainChan,"iLEDhighGainChan[nLED]/I");
321   tLED->Branch("iLEDStrip",iLEDStrip,"iLEDStrip[nLED]/I");
322
323   // TRU TTree
324   TTree *tTRU = new TTree("tTRU","ALICE EMCal TRU fake-altro map");
325   tTRU->Branch("iside",&iside,"iside/I");
326   tTRU->Branch("isect",&isect,"isect/I");
327   tTRU->Branch("iSM",&iSM,"iSM/I");
328   tTRU->Branch("iDDLEqId",&iDDLEqId,"iDDLEqId/I");
329   tTRU->Branch("iRCU",&iRCU,"iRCU/I");
330   tTRU->Branch("iBranch",&iBranch,"iBranch/I");
331   tTRU->Branch("iGTL",&iGTL,"iGTL/I");
332   // TRU is identified by (GTL==0 && !(Branch==0 && RCU==0))
333   int iTRUFirstChan = 0; 
334   int iTRULastChan = 127; // maximum allowed number of fake ALTRO channels=128 from TRU
335   tTRU->Branch("iTRUFirstChan",&iTRUFirstChan,"iTRUFirstChan/I");
336   tTRU->Branch("iTRULastChan",&iTRULastChan,"iTRULastChan/I");
337
338   for (isect = 0; isect<(kNFullSect+kNThirdSect); isect++) { 
339     for (iside=0; iside<kNSides; iside++) { // A or C sides
340       // half sector only has one third of the FECs
341       int MINFEC = 0;
342       int MAXFEC = kNFEC;
343       int MINTRU = 0;
344       int MAXTRU = kNTRU;
345       if (isect==kNFullSect) { // meaning last third-size-sector
346         if (iside==0) { // A side
347           MAXFEC = kNFEC / 3;
348           MAXTRU = 1;
349         }
350         else if (iside==1) { // C side
351           MINFEC = 2 * kNFEC / 3;
352           MINTRU = 2;
353         }
354       }
355
356       iSM = isect*2 + iside;
357       for (iFEC=MINFEC; iFEC<MAXFEC; iFEC++) {
358
359         // ok, where does this FEC belong? Use the local iFEC index which starts with 0
360         // closest to the crate and revert to global z and phi index at the end..
361
362         iTRU = iFEC / (kNFECPerTRU);
363         iTRUADC = getTRUADC(iFEC); 
364         iRCU = iFEC / (kNFECPerRCU); 
365         iBranch = (iFEC%kNFECPerRCU) / kNFECPerGTL; // local index inside RCU
366         iGTL = iFEC % kNFECPerGTL + 1;
367
368         iDDLEqId = kDDLEqIdOffsetEMCAL + iSM*kNRCU + iRCU;
369
370         // tower limits/indices 
371         int tcolLow = (iFEC%kNFECPerRow)*kNCOLS;
372         int trowLow = (iFEC/kNFECPerRow)*kNROWS;
373         /*
374         printf("iside %d iSM %d: FEC %02d RCU %d Branch %d iGTL\n",
375                iside, iSM, iFEC, iRCU, iBranch, iGTL);
376         */
377         for (int col=0; col<kNCOLS; col++) {
378           for (int row=0; row<kNROWS; row++) {
379             int tcol = col + tcolLow;
380             int trow = row + trowLow;
381
382             int itow = row*kNCOLS + col;
383
384             CSP[itow] = Csp[row][col];
385             chip[itow] = kChip[CSP[itow]];
386             lowGainChan[itow] = kChanLow[CSP[itow]];
387             highGainChan[itow] = kChanHigh[CSP[itow]];
388
389             iTRUADCChan[itow] = getTRUADCChan(CSP[itow]); 
390
391             // we need to switch to global indices if we are on side C
392             if (iside==1) {
393               tcol =  kNTowersZ-1 - tcol; // flip axis 
394               trow = kNTowersPhi-1 - trow; // just flip axis
395             }
396
397             towerCol[itow] = tcol;
398             towerRow[itow] = trow;
399
400           } // row
401         }// col
402         tree->Fill();
403       } // iFEC
404
405       // also handle special LED and TRU mapping
406       iGTL = 0; // they are all in GTL/FEC slot 0
407
408       // start with LED..
409       iRCU = 0; iBranch = 0; 
410       iDDLEqId = kDDLEqIdOffsetEMCAL + iSM*kNRCU + iRCU;
411
412       /* for the special 'half'/third sector, side C, there is
413          no RCU=0.. So we put the LED in RCU=1 instead then.
414          There is only 1 TRU in this sector (RCU=1, branch=1), so no problem..
415       */
416       if (MINTRU == 2) { // key for this special sector
417         iRCU++;
418         iDDLEqId++;
419       }
420
421       // loop over attached CSPs
422       // First Top
423       for (int iled = 0; iled<kNLEDPerTCard; iled++) {
424         int il = iled;
425         iLEDCSP[il] = kCspMapLEDTop[iled];
426         iLEDStrip[il] = kStripModuleMapLEDTop[iled];
427         /*
428         cout << " LED CSP " << iLEDCSP[il]
429              << " Strip " << iLEDStrip[il] << endl;
430         */
431         iLEDchip[il] = kChip[iLEDCSP[il]];
432         iLEDlowGainChan[il] = kChanLow[iLEDCSP[il]];
433         iLEDhighGainChan[il] = kChanHigh[iLEDCSP[il]];
434       }
435       // Then Bottom
436       for (int iled = 0; iled<kNLEDPerTCard; iled++) {
437         int il = iled + kNLEDPerTCard; // just a convenient index
438         iLEDCSP[il] = kCspMapLEDBottom[iled];
439         iLEDStrip[il] = kStripModuleMapLEDBottom[iled];
440         /*
441         cout << " LED CSP " << iLEDCSP[il]
442              << " Strip " << iLEDStrip[il] << endl;
443         */
444         iLEDchip[il] = kChip[iLEDCSP[il]];
445         iLEDlowGainChan[il] = kChanLow[iLEDCSP[il]];
446         iLEDhighGainChan[il] = kChanHigh[iLEDCSP[il]];
447       }
448       tLED->Fill();
449
450       // then we also have the TRUs (fake ALTRO)
451       for (iTRU=MINTRU; iTRU<MAXTRU; iTRU++) {
452
453         if (iTRU == 0) { iRCU = 0; iBranch = 1; } 
454         else if (iTRU == 1) { iRCU = 1; iBranch = 0; } 
455         else if (iTRU == 2) { iRCU = 1; iBranch = 1; } 
456         /*
457         cout << " TRU " << iTRU
458              << " RCU " << iRCU
459              << " Branch " << iBranch << endl;
460         */
461         iDDLEqId = kDDLEqIdOffsetEMCAL + iSM*kNRCU + iRCU;
462         /* 
463            last sector only has 1 TRU, but it's probably called TRU 0 on A
464            and TRU 2 on C side..
465            This is handled via MINFEC/MAXFEC and MINTRU/MAXTRU at the start
466            of this loop.
467         */
468         tTRU->Fill();
469
470       }
471
472     } // isect / iSM
473   } // iside
474
475   f->Write();
476 }