]> git.uio.no Git - u/mrichter/AliRoot.git/blob - EMCAL/mapping/EMCalNumbering.C
Randomizing particle order in the pair for identical particles
[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   int iTRUchip = 0; // extramarker for TRU, together with (GTL==0 && Branch==0 && RCU==0)
333   int iTRUFirstChan = 0; 
334   int iTRULastChan = 15; // info from Hans and Dong, July 22, 2008
335   tTRU->Branch("iTRUchip",&iTRUchip,"iTRUchip/I");
336   tTRU->Branch("iTRUFirstChan",&iTRUFirstChan,"iTRUFirstChan/I");
337   tTRU->Branch("iTRULastChan",&iTRULastChan,"iTRULastChan/I");
338
339   for (isect = 0; isect<(kNFullSect+kNThirdSect); isect++) { 
340     for (iside=0; iside<kNSides; iside++) { // A or C sides
341       // half sector only has one third of the FECs
342       int MINFEC = 0;
343       int MAXFEC = kNFEC;
344       int MINTRU = 0;
345       int MAXTRU = kNTRU;
346       if (isect==kNFullSect) { // meaning last third-size-sector
347         if (iside==0) { // A side
348           MAXFEC = kNFEC / 3;
349           MAXTRU = 1;
350         }
351         else if (iside==1) { // C side
352           MINFEC = 2 * kNFEC / 3;
353           MINTRU = 2;
354         }
355       }
356
357       iSM = isect*2 + iside;
358       for (iFEC=MINFEC; iFEC<MAXFEC; iFEC++) {
359
360         // ok, where does this FEC belong? Use the local iFEC index which starts with 0
361         // closest to the crate and revert to global z and phi index at the end..
362
363         iTRU = iFEC / (kNFECPerTRU);
364         iTRUADC = getTRUADC(iFEC); 
365         iRCU = iFEC / (kNFECPerRCU); 
366         iBranch = (iFEC%kNFECPerRCU) / kNFECPerGTL; // local index inside RCU
367         iGTL = iFEC % kNFECPerGTL + 1;
368
369         iDDLEqId = kDDLEqIdOffsetEMCAL + iSM*kNRCU + iRCU;
370
371         // tower limits/indices 
372         int tcolLow = (iFEC%kNFECPerRow)*kNCOLS;
373         int trowLow = (iFEC/kNFECPerRow)*kNROWS;
374         /*
375         printf("iside %d iSM %d: FEC %02d RCU %d Branch %d iGTL\n",
376                iside, iSM, iFEC, iRCU, iBranch, iGTL);
377         */
378         for (int col=0; col<kNCOLS; col++) {
379           for (int row=0; row<kNROWS; row++) {
380             int tcol = col + tcolLow;
381             int trow = row + trowLow;
382
383             int itow = row*kNCOLS + col;
384
385             CSP[itow] = Csp[row][col];
386             chip[itow] = kChip[CSP[itow]];
387             lowGainChan[itow] = kChanLow[CSP[itow]];
388             highGainChan[itow] = kChanHigh[CSP[itow]];
389
390             iTRUADCChan[itow] = getTRUADCChan(CSP[itow]); 
391
392             // we need to switch to global indices if we are on side C
393             if (iside==1) {
394               tcol =  kNTowersZ-1 - tcol; // flip axis 
395               trow = kNTowersPhi-1 - trow; // just flip axis
396             }
397
398             towerCol[itow] = tcol;
399             towerRow[itow] = trow;
400
401           } // row
402         }// col
403         tree->Fill();
404       } // iFEC
405
406       // also handle special LED and TRU mapping
407       iGTL = 0; // they are all in GTL/FEC slot 0
408
409       // start with LED..
410       iRCU = 0; iBranch = 0; 
411       iDDLEqId = kDDLEqIdOffsetEMCAL + iSM*kNRCU + iRCU;
412
413       /* for the special 'half'/third sector, side C, there is
414          no RCU=0.. So we put the LED in RCU=1 instead then.
415          There is only 1 TRU in this sector (RCU=1, branch=1), so no problem..
416       */
417       if (MINTRU == 2) { // key for this special sector
418         iRCU++;
419         iDDLEqId++;
420       }
421
422       // loop over attached CSPs
423       // First Top
424       for (int iled = 0; iled<kNLEDPerTCard; iled++) {
425         int il = iled;
426         iLEDCSP[il] = kCspMapLEDTop[iled];
427         iLEDStrip[il] = kStripModuleMapLEDTop[iled];
428         /*
429         cout << " LED CSP " << iLEDCSP[il]
430              << " Strip " << iLEDStrip[il] << endl;
431         */
432         iLEDchip[il] = kChip[iLEDCSP[il]];
433         iLEDlowGainChan[il] = kChanLow[iLEDCSP[il]];
434         iLEDhighGainChan[il] = kChanHigh[iLEDCSP[il]];
435       }
436       // Then Bottom
437       for (int iled = 0; iled<kNLEDPerTCard; iled++) {
438         int il = iled + kNLEDPerTCard; // just a convenient index
439         iLEDCSP[il] = kCspMapLEDBottom[iled];
440         iLEDStrip[il] = kStripModuleMapLEDBottom[iled];
441         /*
442         cout << " LED CSP " << iLEDCSP[il]
443              << " Strip " << iLEDStrip[il] << endl;
444         */
445         iLEDchip[il] = kChip[iLEDCSP[il]];
446         iLEDlowGainChan[il] = kChanLow[iLEDCSP[il]];
447         iLEDhighGainChan[il] = kChanHigh[iLEDCSP[il]];
448       }
449       tLED->Fill();
450
451       // then we also have the TRUs (fake ALTRO)
452       for (iTRU=MINTRU; iTRU<MAXTRU; iTRU++) {
453
454         if (iTRU == 0) { iRCU = 0; iBranch = 1; } 
455         else if (iTRU == 1) { iRCU = 1; iBranch = 0; } 
456         else if (iTRU == 2) { iRCU = 1; iBranch = 1; } 
457         /*
458         cout << " TRU " << iTRU
459              << " RCU " << iRCU
460              << " Branch " << iBranch << endl;
461         */
462         iDDLEqId = kDDLEqIdOffsetEMCAL + iSM*kNRCU + iRCU;
463         /* 
464            last sector only has 1 TRU, but it's probably called TRU 0 on A
465            and TRU 2 on C side..
466            This is handled via MINFEC/MAXFEC and MINTRU/MAXTRU at the start
467            of this loop.
468         */
469         tTRU->Fill();
470
471       }
472
473     } // isect / iSM
474   } // iside
475
476   f->Write();
477 }