ROOT logo
/*
ROOT Macro to generate ascii files for AliCaloAltroMapping; offline decoder
- based on the map file produced by EMCALNumbering.C

Update: 20 Aug 2008 - update to write separate files for A and C sides +
   added TRU and LED channels also.. 

LED channels look like regular FEE data; just from rcu=0, branch=0, FEC=0
TRU data has one block of data from the whole TRU; all other FEC=0 slots
   (rcu, branch) = (0,1), (1,0), (1,1)

Some further documentation is available at:
http://cern.ch/dsilverm/mapping/emcal_mapping.html

Author: David Silvermyr, ORNL; silvermy@mail.phy.ornl.gov
*/

// First we define some constants - the main method WriteRCUs comes later
const int kNTRU = 3; // per SM
const int kNTRUChanBlocks = 128; // max. per TRU 
const int kNLED = 24; // one per StripModule

const int kNGAIN = 2; // low (0) and high (1)
const int kNFEEChannelsPerRCU = 1152;
int NChannelsPerRCU[2];
// RCU 0: FEE + NTRUChanBlocks + NLED*NGAIN 
NChannelsPerRCU[0] = kNFEEChannelsPerRCU + kNTRUChanBlocks + kNLED*kNGAIN; 
// RCU 1: FEE + 2*NTRUChanBlocks
NChannelsPerRCU[1] = kNFEEChannelsPerRCU + 2*kNTRUChanBlocks; 

const int kMaxHWAddress = (1 << 11) // branch
  | (9 << 7) // FEC
  | (4 << 4) // Altro
  | 0xf; // channel

const int kNRCU = 2;
const int kNSides = 2;
char * sideStr[] = {"A", "C"};

const int kFirstFEC = 1;
const int kNFECPerGTL = 9; // NFEC/NGTL

int makeHWAddress(int ibranch, int ifec, int ichip, int ichan) {
  int addr = (ibranch << 11) // branch
    | (ifec << 7) // FEC
    | (ichip << 4) // Altro
    | ichan; // channel
  return addr;
}

// HERE STARTS THE MAIN METHOD..
void WriteRCUs(const char *filename="map.root")
{
  TFile *f = (TFile*)gROOT->GetListOfFiles()->FindObject(filename);
  if (!f) {
    f = new TFile(filename);
  }
  TTree *tree = (TTree*)gDirectory->Get("tree");

  const int kNTOW = 32; // per FEC
  
  //Declaration of leaves types
  Int_t           iside;
  Int_t           isect;
  Int_t           iSM;
  Int_t           iFEC;
  Int_t           iRCU;
  Int_t           iDDLEqId;
  Int_t           iBranch;
  Int_t           iGTL;
  Int_t           nTow;
  Int_t           CSP[kNTOW];
  Int_t           chip[kNTOW];
  Int_t           lowGainChan[kNTOW];
  Int_t           highGainChan[kNTOW];
  Int_t           towerCol[kNTOW];
  Int_t           towerRow[kNTOW];
  Int_t           towerOrder[kNTOW];
  
  // Set branch addresses.
  tree->SetBranchAddress("iside",&iside);
  tree->SetBranchAddress("isect",&isect);
  tree->SetBranchAddress("iSM",&iSM);
  tree->SetBranchAddress("iFEC",&iFEC);
  tree->SetBranchAddress("iRCU",&iRCU);
  tree->SetBranchAddress("iDDLEqId",&iDDLEqId);
  tree->SetBranchAddress("iBranch",&iBranch);
  tree->SetBranchAddress("iGTL",&iGTL);
  tree->SetBranchAddress("nTow",&nTow);
  tree->SetBranchAddress("CSP",CSP);
  tree->SetBranchAddress("chip",chip);
  tree->SetBranchAddress("lowGainChan",lowGainChan);
  tree->SetBranchAddress("highGainChan",highGainChan);
  tree->SetBranchAddress("towerCol",towerCol);
  tree->SetBranchAddress("towerRow",towerRow);
  tree->SetBranchAddress("towerOrder",towerOrder);
  
  Int_t nbytes = 0;

  // also variables and branch setting for LED TTree
  TTree *tLED = (TTree*)gDirectory->Get("tLED");

  //Declaration of leaves types, not already declared
  Int_t           nLED;
  Int_t           iLEDCSP[kNLED];
  Int_t           iLEDchip[kNLED];
  Int_t           iLEDlowGainChan[kNLED];
  Int_t           iLEDhighGainChan[kNLED];
  Int_t           iLEDStrip[kNLED];

  // Set branch addresses.
  tLED->SetBranchAddress("iside",&iside);
  tLED->SetBranchAddress("isect",&isect);
  tLED->SetBranchAddress("iSM",&iSM);
  tLED->SetBranchAddress("iDDLEqId",&iDDLEqId);
  tLED->SetBranchAddress("iRCU",&iRCU);
  tLED->SetBranchAddress("iBranch",&iBranch);
  tLED->SetBranchAddress("iGTL",&iGTL);
  tLED->SetBranchAddress("nLED",&nLED);
  tLED->SetBranchAddress("iLEDCSP",iLEDCSP);
  tLED->SetBranchAddress("iLEDchip",iLEDchip);
  tLED->SetBranchAddress("iLEDlowGainChan",iLEDlowGainChan);
  tLED->SetBranchAddress("iLEDhighGainChan",iLEDhighGainChan);
  tLED->SetBranchAddress("iLEDStrip",iLEDStrip);

  // and TRU TTree
  TTree *tTRU = (TTree*)gDirectory->Get("tTRU");

  //Declaration of leaves types, not already declared
  Int_t           iTRUchip;
  Int_t           iTRUFirstChan;
  Int_t           iTRULastChan;
  
   // Set branch addresses.
  tTRU->SetBranchAddress("iside",&iside);
  tTRU->SetBranchAddress("isect",&isect);
  tTRU->SetBranchAddress("iSM",&iSM);
  tTRU->SetBranchAddress("iDDLEqId",&iDDLEqId);
  tTRU->SetBranchAddress("iRCU",&iRCU);
  tTRU->SetBranchAddress("iBranch",&iBranch);
  tTRU->SetBranchAddress("iGTL",&iGTL);
  tTRU->SetBranchAddress("iTRUFirstChan",&iTRUFirstChan);
  tTRU->SetBranchAddress("iTRULastChan",&iTRULastChan);

   // OK, setup done - let's proceed.. First with the regular data

  int n[kNRCU][kNSides] = {0};
  ofstream out[kNRCU][kNSides];
  ofstream outFinal[kNRCU][kNSides];

  // Open output files, and provide the necessary header
  char fname[100];
  for (iRCU=0; iRCU<kNRCU; iRCU++) {
    for (iside=0; iside<kNSides; iside++) {
      sprintf(fname, "RCU%d%s.data.unsorted",iRCU,sideStr[iside]);
      out[iRCU][iside].open(fname);

      sprintf(fname, "RCU%d%s.data",iRCU,sideStr[iside]);
      outFinal[iRCU][iside].open(fname);

      outFinal[iRCU][iside] << NChannelsPerRCU[iRCU] << endl;
      outFinal[iRCU][iside] << kMaxHWAddress  << endl;

      n[iRCU][iside] = 0;
    }
  }

  int chid[kNGAIN] = {0};
  int ig = 0; // gain flag

  // loop over channels
  for (Long64_t i=0; i<tree->GetEntries();i++) { 
    nbytes += tree->GetEntry(i);

    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)

      /*
	FECs should come in order so let's just worry about channel order
	within an FEC
	DS (Aug 2008): in principle we don't really need to do this anymore, 
	since we anyway call a sort command at the end now, but since it was
	already coded I kept this for now..
      */
      // The towerOrder array should have the needed indexing info
      for (int it = 0; it<kNTOW; it++) {
	int itow = towerOrder[it];

	chid[0] = makeHWAddress( iBranch, (iFEC%kNFECPerGTL) + kFirstFEC, 
				 chip[itow], lowGainChan[itow] );
	chid[1] = makeHWAddress( iBranch, (iFEC%kNFECPerGTL) + kFirstFEC, 
				 chip[itow], highGainChan[itow] );

	// cout << " it " << it << " : " << chid[0] << " " << chid[1] << endl;

	// start with the lowest
	if (chid[0] < chid[1]) {
	  ig = 0;
	}
	else {
	  ig = 1;
	}
	
	out[iRCU][iside] << chid[ig] << " " 
			 << towerRow[itow] << " "
			 << towerCol[itow] << " " << ig
			 << endl;
	n[iRCU][iside]++;
	// and then the next
	ig = 1 -ig;
	out[iRCU][iside] << chid[ig] << " " 
			 << towerRow[itow] << " "
			 << towerCol[itow] << " " << ig
			 << endl;
	n[iRCU][iside]++;
      } // loop over towers      
    } // sector==0 selection
  }
  // done, with FEE data

  // report on counts; just for early debugging..
  for (iRCU=0; iRCU<kNRCU; iRCU++) {
    for (iside=0; iside<kNSides; iside++) {
      cout << " post-FEE count: RCU " << iRCU
	   << " iside " << iside
	   << " n = " << n[iRCU][iside] << endl;
    }
  }
  
  // Next, we have the fake ALTRO from the TRU
  int caloFlag = 2; // from enum AliCaloRawStream::kTRUData
  int dummyRow = 0; // need to have the right number of fields in print-out
  int TRUchid = 0;
  for (Long64_t i=0; i<tTRU->GetEntries(); i++) { 
    nbytes += tTRU->GetEntry(i);
    if (isect==0) { // select just the 1st sector; same motivation as for FEE
      for (int ichan=iTRUFirstChan; ichan<=iTRULastChan; ichan++) {
	TRUchid = makeHWAddress( iBranch, iGTL, 
				 ichan/16, ichan%16 );
	out[iRCU][iside] << TRUchid << " " 
			 << dummyRow << " "
			 << ichan << " " // channel # coded as Column.. 
			 << caloFlag << endl;
	n[iRCU][iside]++;
      }
    }
  }

  // report on counts; just for early debugging..
  for (iRCU=0; iRCU<kNRCU; iRCU++) {
    for (iside=0; iside<kNSides; iside++) {
      cout << " post-TRU count: RCU " << iRCU
	   << " iside " << iside
	   << " n = " << n[iRCU][iside] << endl;
    }
  }

  // Then. LED data
  caloFlag = 3; // from enum AliCaloRawStream::kLEDMonData
  int LEDchid = 0; // assigned below

  for (Long64_t i=0; i<tLED->GetEntries(); i++) { 
    nbytes += tLED->GetEntry(i);
    if (isect==0) { // just the 1st sector
      for (int il=0; il<nLED; il++) {

	// first low gain
	ig = 0; 
	LEDchid = makeHWAddress( iBranch, iGTL, 
				 iLEDchip[il], iLEDlowGainChan[il] );
	out[iRCU][iside] << LEDchid << " " 
			 << ig << " " // gain coded as row..
			 << iLEDStrip[il] << " " // strip # coded as Column.. 
			 << caloFlag << endl;
	n[iRCU][iside]++;
	
	// then high gain
	ig = 1; 
	LEDchid = makeHWAddress( iBranch, iGTL, 
				 iLEDchip[il], iLEDhighGainChan[il] );
	out[iRCU][iside] << LEDchid << " " 
			 << ig << " " // gain coded as row..
			 << iLEDStrip[il] << " " // strip # coded as Column.. 
			 << caloFlag << endl;
	n[iRCU][iside]++;
      }
    }
  }

  // Finally, let's close the output files - we should get the counts we expected
  for (iRCU=0; iRCU<kNRCU; iRCU++) {
    for (iside=0; iside<kNSides; iside++) {
      out[iRCU][iside].close();
      outFinal[iRCU][iside].close();
      // report how many entries we encountered
      cout << " final count: RCU " << iRCU
	   << " iside " << iside
	   << " n = " << n[iRCU][iside] 
	   << " expected " << NChannelsPerRCU[iRCU];
      if (n[iRCU][iside] == NChannelsPerRCU[iRCU]) {
	cout << " - OK! " << endl;
      }
      else {
	cout << " - Wrong! " << endl;
      }

    }
  }

  // let's then do a final loop where we sort the lists into the final files
  // I'm not sure if having the lists ordered is really needed but it is at 
  // least more aestethically pleasing..
  char cmd[200];
  sprintf(cmd, "mkdir -p tmp"); // provide a temporary storage space - not to pollute the local dir. too much
  gSystem->Exec(cmd);

  for (iRCU=0; iRCU<kNRCU; iRCU++) {
    for (iside=0; iside<kNSides; iside++) {
      sprintf(cmd, "sort -n RCU%d%s.data.unsorted >> RCU%d%s.data", 
	      iRCU, sideStr[iside], iRCU, sideStr[iside]);
      cout << "executing " << cmd << endl;
      gSystem->Exec(cmd);
      sprintf(cmd, "mv RCU%d%s.data.unsorted tmp/.", 
	      iRCU, sideStr[iside]);
      cout << "executing " << cmd << endl;
      gSystem->Exec(cmd);
    }
  }

}
 WriteRCUs.C:1
 WriteRCUs.C:2
 WriteRCUs.C:3
 WriteRCUs.C:4
 WriteRCUs.C:5
 WriteRCUs.C:6
 WriteRCUs.C:7
 WriteRCUs.C:8
 WriteRCUs.C:9
 WriteRCUs.C:10
 WriteRCUs.C:11
 WriteRCUs.C:12
 WriteRCUs.C:13
 WriteRCUs.C:14
 WriteRCUs.C:15
 WriteRCUs.C:16
 WriteRCUs.C:17
 WriteRCUs.C:18
 WriteRCUs.C:19
 WriteRCUs.C:20
 WriteRCUs.C:21
 WriteRCUs.C:22
 WriteRCUs.C:23
 WriteRCUs.C:24
 WriteRCUs.C:25
 WriteRCUs.C:26
 WriteRCUs.C:27
 WriteRCUs.C:28
 WriteRCUs.C:29
 WriteRCUs.C:30
 WriteRCUs.C:31
 WriteRCUs.C:32
 WriteRCUs.C:33
 WriteRCUs.C:34
 WriteRCUs.C:35
 WriteRCUs.C:36
 WriteRCUs.C:37
 WriteRCUs.C:38
 WriteRCUs.C:39
 WriteRCUs.C:40
 WriteRCUs.C:41
 WriteRCUs.C:42
 WriteRCUs.C:43
 WriteRCUs.C:44
 WriteRCUs.C:45
 WriteRCUs.C:46
 WriteRCUs.C:47
 WriteRCUs.C:48
 WriteRCUs.C:49
 WriteRCUs.C:50
 WriteRCUs.C:51
 WriteRCUs.C:52
 WriteRCUs.C:53
 WriteRCUs.C:54
 WriteRCUs.C:55
 WriteRCUs.C:56
 WriteRCUs.C:57
 WriteRCUs.C:58
 WriteRCUs.C:59
 WriteRCUs.C:60
 WriteRCUs.C:61
 WriteRCUs.C:62
 WriteRCUs.C:63
 WriteRCUs.C:64
 WriteRCUs.C:65
 WriteRCUs.C:66
 WriteRCUs.C:67
 WriteRCUs.C:68
 WriteRCUs.C:69
 WriteRCUs.C:70
 WriteRCUs.C:71
 WriteRCUs.C:72
 WriteRCUs.C:73
 WriteRCUs.C:74
 WriteRCUs.C:75
 WriteRCUs.C:76
 WriteRCUs.C:77
 WriteRCUs.C:78
 WriteRCUs.C:79
 WriteRCUs.C:80
 WriteRCUs.C:81
 WriteRCUs.C:82
 WriteRCUs.C:83
 WriteRCUs.C:84
 WriteRCUs.C:85
 WriteRCUs.C:86
 WriteRCUs.C:87
 WriteRCUs.C:88
 WriteRCUs.C:89
 WriteRCUs.C:90
 WriteRCUs.C:91
 WriteRCUs.C:92
 WriteRCUs.C:93
 WriteRCUs.C:94
 WriteRCUs.C:95
 WriteRCUs.C:96
 WriteRCUs.C:97
 WriteRCUs.C:98
 WriteRCUs.C:99
 WriteRCUs.C:100
 WriteRCUs.C:101
 WriteRCUs.C:102
 WriteRCUs.C:103
 WriteRCUs.C:104
 WriteRCUs.C:105
 WriteRCUs.C:106
 WriteRCUs.C:107
 WriteRCUs.C:108
 WriteRCUs.C:109
 WriteRCUs.C:110
 WriteRCUs.C:111
 WriteRCUs.C:112
 WriteRCUs.C:113
 WriteRCUs.C:114
 WriteRCUs.C:115
 WriteRCUs.C:116
 WriteRCUs.C:117
 WriteRCUs.C:118
 WriteRCUs.C:119
 WriteRCUs.C:120
 WriteRCUs.C:121
 WriteRCUs.C:122
 WriteRCUs.C:123
 WriteRCUs.C:124
 WriteRCUs.C:125
 WriteRCUs.C:126
 WriteRCUs.C:127
 WriteRCUs.C:128
 WriteRCUs.C:129
 WriteRCUs.C:130
 WriteRCUs.C:131
 WriteRCUs.C:132
 WriteRCUs.C:133
 WriteRCUs.C:134
 WriteRCUs.C:135
 WriteRCUs.C:136
 WriteRCUs.C:137
 WriteRCUs.C:138
 WriteRCUs.C:139
 WriteRCUs.C:140
 WriteRCUs.C:141
 WriteRCUs.C:142
 WriteRCUs.C:143
 WriteRCUs.C:144
 WriteRCUs.C:145
 WriteRCUs.C:146
 WriteRCUs.C:147
 WriteRCUs.C:148
 WriteRCUs.C:149
 WriteRCUs.C:150
 WriteRCUs.C:151
 WriteRCUs.C:152
 WriteRCUs.C:153
 WriteRCUs.C:154
 WriteRCUs.C:155
 WriteRCUs.C:156
 WriteRCUs.C:157
 WriteRCUs.C:158
 WriteRCUs.C:159
 WriteRCUs.C:160
 WriteRCUs.C:161
 WriteRCUs.C:162
 WriteRCUs.C:163
 WriteRCUs.C:164
 WriteRCUs.C:165
 WriteRCUs.C:166
 WriteRCUs.C:167
 WriteRCUs.C:168
 WriteRCUs.C:169
 WriteRCUs.C:170
 WriteRCUs.C:171
 WriteRCUs.C:172
 WriteRCUs.C:173
 WriteRCUs.C:174
 WriteRCUs.C:175
 WriteRCUs.C:176
 WriteRCUs.C:177
 WriteRCUs.C:178
 WriteRCUs.C:179
 WriteRCUs.C:180
 WriteRCUs.C:181
 WriteRCUs.C:182
 WriteRCUs.C:183
 WriteRCUs.C:184
 WriteRCUs.C:185
 WriteRCUs.C:186
 WriteRCUs.C:187
 WriteRCUs.C:188
 WriteRCUs.C:189
 WriteRCUs.C:190
 WriteRCUs.C:191
 WriteRCUs.C:192
 WriteRCUs.C:193
 WriteRCUs.C:194
 WriteRCUs.C:195
 WriteRCUs.C:196
 WriteRCUs.C:197
 WriteRCUs.C:198
 WriteRCUs.C:199
 WriteRCUs.C:200
 WriteRCUs.C:201
 WriteRCUs.C:202
 WriteRCUs.C:203
 WriteRCUs.C:204
 WriteRCUs.C:205
 WriteRCUs.C:206
 WriteRCUs.C:207
 WriteRCUs.C:208
 WriteRCUs.C:209
 WriteRCUs.C:210
 WriteRCUs.C:211
 WriteRCUs.C:212
 WriteRCUs.C:213
 WriteRCUs.C:214
 WriteRCUs.C:215
 WriteRCUs.C:216
 WriteRCUs.C:217
 WriteRCUs.C:218
 WriteRCUs.C:219
 WriteRCUs.C:220
 WriteRCUs.C:221
 WriteRCUs.C:222
 WriteRCUs.C:223
 WriteRCUs.C:224
 WriteRCUs.C:225
 WriteRCUs.C:226
 WriteRCUs.C:227
 WriteRCUs.C:228
 WriteRCUs.C:229
 WriteRCUs.C:230
 WriteRCUs.C:231
 WriteRCUs.C:232
 WriteRCUs.C:233
 WriteRCUs.C:234
 WriteRCUs.C:235
 WriteRCUs.C:236
 WriteRCUs.C:237
 WriteRCUs.C:238
 WriteRCUs.C:239
 WriteRCUs.C:240
 WriteRCUs.C:241
 WriteRCUs.C:242
 WriteRCUs.C:243
 WriteRCUs.C:244
 WriteRCUs.C:245
 WriteRCUs.C:246
 WriteRCUs.C:247
 WriteRCUs.C:248
 WriteRCUs.C:249
 WriteRCUs.C:250
 WriteRCUs.C:251
 WriteRCUs.C:252
 WriteRCUs.C:253
 WriteRCUs.C:254
 WriteRCUs.C:255
 WriteRCUs.C:256
 WriteRCUs.C:257
 WriteRCUs.C:258
 WriteRCUs.C:259
 WriteRCUs.C:260
 WriteRCUs.C:261
 WriteRCUs.C:262
 WriteRCUs.C:263
 WriteRCUs.C:264
 WriteRCUs.C:265
 WriteRCUs.C:266
 WriteRCUs.C:267
 WriteRCUs.C:268
 WriteRCUs.C:269
 WriteRCUs.C:270
 WriteRCUs.C:271
 WriteRCUs.C:272
 WriteRCUs.C:273
 WriteRCUs.C:274
 WriteRCUs.C:275
 WriteRCUs.C:276
 WriteRCUs.C:277
 WriteRCUs.C:278
 WriteRCUs.C:279
 WriteRCUs.C:280
 WriteRCUs.C:281
 WriteRCUs.C:282
 WriteRCUs.C:283
 WriteRCUs.C:284
 WriteRCUs.C:285
 WriteRCUs.C:286
 WriteRCUs.C:287
 WriteRCUs.C:288
 WriteRCUs.C:289
 WriteRCUs.C:290
 WriteRCUs.C:291
 WriteRCUs.C:292
 WriteRCUs.C:293
 WriteRCUs.C:294
 WriteRCUs.C:295
 WriteRCUs.C:296
 WriteRCUs.C:297
 WriteRCUs.C:298
 WriteRCUs.C:299
 WriteRCUs.C:300
 WriteRCUs.C:301
 WriteRCUs.C:302
 WriteRCUs.C:303
 WriteRCUs.C:304
 WriteRCUs.C:305
 WriteRCUs.C:306
 WriteRCUs.C:307
 WriteRCUs.C:308
 WriteRCUs.C:309
 WriteRCUs.C:310
 WriteRCUs.C:311
 WriteRCUs.C:312
 WriteRCUs.C:313
 WriteRCUs.C:314
 WriteRCUs.C:315
 WriteRCUs.C:316
 WriteRCUs.C:317
 WriteRCUs.C:318
 WriteRCUs.C:319
 WriteRCUs.C:320
 WriteRCUs.C:321
 WriteRCUs.C:322
 WriteRCUs.C:323
 WriteRCUs.C:324
 WriteRCUs.C:325
 WriteRCUs.C:326
 WriteRCUs.C:327
 WriteRCUs.C:328
 WriteRCUs.C:329
 WriteRCUs.C:330