1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
16 ////////////////////////////////////
18 // MUON Raw Data generator in ALICE-MUON
21 // * generates raw data for MUON tracker only (for the moment)
22 // * a simple mapping is used (see below)
23 // * the bus patch id is calculated with an absolute number 0 - 999
24 // one DDL per 1/2 chamber is created for both cathode.
26 ////////////////////////////////////
27 #include <TClonesArray.h>
28 #include "AliMUONRawData.h"
29 #include "AliMUONDigit.h"
30 #include "AliMUONTriggerDecision.h"
31 #include "AliMUONConstants.h"
32 #include "AliMUONData.h"
34 #include "AliRunLoader.h"
35 #include "AliLoader.h"
36 #include "AliBitPacking.h"
37 #include "AliMUONDDLTracker.h"
38 #include "AliMUONDDLTrigger.h"
40 // #include "AliMUON.h"
41 // #include "AliMUONLocalTrigger.h"
42 // #include "AliMUONGlobalTrigger.h"
43 // #include "AliMUONTriggerCircuit.h"
45 const Int_t AliMUONRawData::fgkDefaultPrintLevel = 0;
47 ClassImp(AliMUONRawData) // Class implementation in ROOT context
49 //__________________________________________________________________________
50 AliMUONRawData::AliMUONRawData(AliLoader* loader)
54 // Standard Constructor
56 fPrintLevel = fgkDefaultPrintLevel;
58 // initialize loader's
61 // initialize container
62 fMUONData = new AliMUONData(fLoader,"MUON","MUON");
64 // trigger decision, temp solution, local & global has to move to Digits Tree
65 // fTrigDec = new AliMUONTriggerDecision(fLoader);
66 // fTrigData = fTrigDec->GetMUONData();
69 fSubEventArray[0] = new TClonesArray("AliMUONSubEventTracker",1000);
70 fSubEventArray[1] = new TClonesArray("AliMUONSubEventTracker",1000);
73 fSubEventTrigArray[0] = new TClonesArray("AliMUONSubEventTrigger",1000);
74 fSubEventTrigArray[1] = new TClonesArray("AliMUONSubEventTrigger",1000);
77 fDDLTracker = new AliMUONDDLTracker();
78 fDDLTrigger= new AliMUONDDLTrigger();
81 //__________________________________________________________________________
82 AliMUONRawData::AliMUONRawData()
85 fPrintLevel(fgkDefaultPrintLevel),
89 // Default Constructor
92 //_______________________________________________________________________
93 AliMUONRawData::AliMUONRawData (const AliMUONRawData& rhs)
96 // Protected copy constructor
98 Fatal("AliMUONRawData", "Not implemented.");
101 //_______________________________________________________________________
103 AliMUONRawData::operator=(const AliMUONRawData& rhs)
105 // Protected assignement operator
107 if (this == &rhs) return *this;
109 Fatal("operator=", "Not implemented.");
114 //__________________________________________________________________________
115 AliMUONRawData::~AliMUONRawData(void)
119 if (fSubEventArray[0])
120 fSubEventArray[0]->Delete(); //using delete cos allocating memory in copy ctor.
121 if (fSubEventArray[1])
122 fSubEventArray[1]->Delete();
124 if (fSubEventTrigArray[0])
125 fSubEventTrigArray[0]->Delete();
126 if (fSubEventTrigArray[1])
127 fSubEventTrigArray[1]->Delete();
138 //____________________________________________________________________
139 Int_t AliMUONRawData::WriteRawData()
141 // convert digits of the current event to raw data
146 fLoader->LoadDigits("READ");
148 fMUONData->SetTreeAddress("D");
150 for (Int_t ich = 0; ich < AliMUONConstants::NTrackingCh(); ich++) {
151 // for (Int_t ich = 0; ich < 2; ich++) {
154 DDLId = ich * 2 + 0x900;
155 sprintf(name, "MUON_%d.ddl",DDLId);
156 fFile1 = fopen(name,"w");
158 DDLId = (ich * 2) + 1 + 0x900;
159 sprintf(name, "MUON_%d.ddl",DDLId);
160 fFile2 = fopen(name,"w");
162 WriteTrackerDDL(ich);
167 fMUONData->ResetDigits();
175 // sprintf(name, "MUTR_%d.ddl",DDLId);
176 // fFile1 = fopen(name,"w");
178 // DDLId = 0xA00 + 1;
179 // sprintf(name, "MUTR_%d.ddl",DDLId);
180 // fFile2 = fopen(name,"w");
182 // WriteTriggerDDL();
184 // // reset and close
187 fLoader->UnloadDigits();
191 //____________________________________________________________________
192 Int_t AliMUONRawData::WriteTrackerDDL(Int_t iCh)
195 TClonesArray* muonDigits = 0;
196 fSubEventArray[0]->Clear();
197 fSubEventArray[1]->Clear();
202 nbInBus[0].Set(5000);
203 nbInBus[1].Set(5000);
209 AliRawDataHeader header = fDDLTracker->GetHeader();
210 Int_t headerSize = fDDLTracker->GetHeaderSize();
212 // DDL event one per half chamber
213 AliMUONSubEventTracker* subEvent;
218 UChar_t channelId = 0;
220 Int_t busPatchId = 0;
230 const AliMUONDigit* digit;
233 printf("WriteDDL chamber %d\n", iCh+1);
235 for (Int_t iCath = 0; iCath < 2; iCath++) {
237 fMUONData->ResetDigits();
238 fMUONData->GetCathode(iCath);
239 muonDigits = fMUONData->Digits(iCh);
241 nDigits = muonDigits->GetEntriesFast();
242 if (fPrintLevel == 2)
243 printf("ndigits = %d\n",nDigits);
245 // open DDL file, on per 1/2 chamber
247 for (Int_t idig = 0; idig < nDigits; idig++) {
249 digit = (AliMUONDigit*) muonDigits->UncheckedAt(idig);
252 GetDummyMapping(iCh, iCath, digit, busPatchId, manuId, channelId, charge);
255 AliBitPacking::PackWord((UInt_t)parity,word,29,31);
256 AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
257 AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
258 AliBitPacking::PackWord((UInt_t)charge,word,0,11);
261 subEvent = new AliMUONSubEventTracker();
262 subEvent->AddData(word);
263 subEvent->SetBusPatchId(busPatchId);
264 if (digit->PadX() > 0) {
265 nbInBus[0][busPatchId]++;
268 nbInBus[1][busPatchId]++;
274 fSubEventArray[0]->Sort();
275 fSubEventArray[1]->Sort();
277 // gather datas from same bus patch
278 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
279 nEntries = fSubEventArray[iDDL]->GetEntriesFast();
281 for (Int_t i = 0; i < nEntries; i++) {
282 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(i);
283 busPatchId = temp->GetBusPatchId();
285 // add bus patch header, length and total length managed by subevent class
286 temp->SetTriggerWord(0xdeadbeef);
287 for (Int_t j = 0; j < nbInBus[iDDL][busPatchId]-1; j++) {
288 AliMUONSubEventTracker* temp1 = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(++i);
289 temp->AddData(temp1->GetData(0));
290 fSubEventArray[iDDL]->RemoveAt(i) ;
293 fSubEventArray[iDDL]->Compress();
295 if (fPrintLevel == 3) {
296 nEntries = fSubEventArray[iDDL]->GetEntriesFast();
297 for (Int_t i = 0; i < nEntries; i++) {
298 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(i);
299 printf("busPatchid back %d\n",temp->GetBusPatchId());
300 for (Int_t j = 0; j < temp->GetLength(); j++) {
301 printf("manuId back %d, ",temp->GetManuId(j));
302 printf("channelId back %d, ",temp->GetChannelId(j));
303 printf("charge back %d\n",temp->GetCharge(j));
314 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
318 nEntries = fSubEventArray[iDDL]->GetEntriesFast();
319 buffer = new Int_t [(2048+24)*50]; // 24 words in average for one buspatch and 2048 manu info at most
327 for (Int_t iBlock = 0; iBlock < 2; iBlock++) {
330 fDDLTracker->SetTotalBlkLength(0xFFFFFFFF);
331 memcpy(&buffer[index],fDDLTracker->GetBlkHeader(),32);
335 for (Int_t iDsp = 0; iDsp < 5; iDsp++) {
338 fDDLTracker->SetTotalDspLength(0xEEEEEEEE);
339 memcpy(&buffer[index],fDDLTracker->GetDspHeader(),32);
343 for (Int_t i = 0; i < 5; i++) {
345 iBusPatch = i + iBlock*25 + iDsp*5 + 50*(2*iCh + iDDL);
347 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(iEntries);
349 busPatchId = temp->GetBusPatchId();
353 if (busPatchId == iBusPatch) {
354 // add bus patch structure
355 memcpy(&buffer[index],temp->GetAddress(),16);
357 for (Int_t j = 0; j < temp->GetLength(); j++)
358 buffer[index++] = temp->GetData(j);
359 if (iEntries < nEntries-1)
362 buffer[index++] = 4; // total length
363 buffer[index++] = 0; // raw data length
364 buffer[index++] = iBusPatch; // bus patch
365 buffer[index++] = 0xdeadbeef; // trigger word
368 buffer[indexDsp] = index - indexDsp;
369 buffer[indexDsp+1] = index - indexDsp -8;
370 if ((index - indexDsp) % 2 == 0)
371 buffer[indexDsp+7] = 0;
373 buffer[indexDsp+7] = 1;
375 buffer[indexBlk] = index - indexBlk;
376 buffer[indexBlk+1] = index - indexBlk -8;
380 header.fSize = index + headerSize;// total length in word
381 fwrite((char*)(&header),headerSize*4,1,fFile1);
382 fwrite(buffer,sizeof(int),index,fFile1);
386 header.fSize = index + headerSize;// total length in word
387 fwrite((char*)(&header),headerSize*4,1,fFile2);
388 fwrite(buffer,sizeof(int),index,fFile2);
395 //____________________________________________________________________
396 Int_t AliMUONRawData::WriteTriggerDDL()
399 // Long_t gloTrigPat;
400 // TClonesArray *localTrigger;
401 // TClonesArray *globalTrigger;
402 // AliMUONLocalTrigger *locTrg;
403 // AliMUONGlobalTrigger *gloTrg;
404 // AliMUONTriggerCircuit *circuit;
406 // fTrigData->SetTreeAddress("D,GLT");
407 // fTrigDec->Digits2Trigger();
410 // AliMUON * pMUON = (AliMUON *) gAlice->GetDetector("MUON");
412 // // global trigger for trigger pattern
415 // globalTrigger = fMUONData->GlobalTrigger();
417 // gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
418 // if (gloTrg->SinglePlusLpt()) gloTrigPat|= 0x1;
419 // if (gloTrg->SinglePlusHpt()) gloTrigPat|= 0x2;
420 // if (gloTrg->SinglePlusApt()) gloTrigPat|= 0x4;
422 // if (gloTrg->SingleMinusLpt()) gloTrigPat|= 0x8;
423 // if (gloTrg->SingleMinusHpt()) gloTrigPat|= 0x10;
424 // if (gloTrg->SingleMinusApt()) gloTrigPat|= 0x20;
426 // if (gloTrg->SingleUndefLpt()) gloTrigPat|= 0x40;
427 // if (gloTrg->SingleUndefHpt()) gloTrigPat|= 0x80;
428 // if (gloTrg->SingleUndefApt()) gloTrigPat|= 0x100;
430 // if (gloTrg->PairUnlikeLpt()) gloTrigPat|= 0x200;
431 // if (gloTrg->PairUnlikeHpt()) gloTrigPat|= 0x400;
432 // if (gloTrg->PairUnlikeApt()) gloTrigPat|= 0x800;
434 // if (gloTrg->PairLikeLpt()) gloTrigPat|= 0x1000;
435 // if (gloTrg->PairLikeHpt()) gloTrigPat|= 0x2000;
436 // if (gloTrg->PairLikeApt()) gloTrigPat|= 0x4000;
439 // localTrigger = fMUONData->LocalTrigger();
440 // Int_t nlocals = (Int_t) (localTrigger->GetEntries());// 234 local cards
442 // for (Int_t i=0; i<nlocals; i++) { // loop on Local Trigger
443 // locTrg = (AliMUONLocalTrigger*)localTrigger->UncheckedAt(i);
444 // circuit = &(pMUON->TriggerCircuit(locTrg->LoCircuit()));
445 // Float_t y11 = circuit->GetY11Pos(locTrg->LoStripX());
446 // Int_t stripX21 = locTrg->LoStripX()+locTrg->LoDev()+1;
447 // Float_t y21 = circuit->GetY21Pos(stripX21);
448 // Float_t x11 = circuit->GetX11Pos(locTrg->LoStripY());
449 // y11 = y21 = x11 = 0.;
452 // fTrigData->ResetTrigger();
453 // fTrigData->ResetDigits();
457 //____________________________________________________________________
458 void AliMUONRawData::GetDummyMapping(Int_t iCh, Int_t iCath, const AliMUONDigit* digit,
459 Int_t &busPatchId, UShort_t &manuId, UChar_t &channelId, UShort_t &charge)
462 Int_t offsetX = 0; // offet row
463 Int_t offsetY = 0; // offset columns
464 Int_t offsetCath = 0; //offset from one cathod to the other
465 Int_t maxChannel = 0; // maximum nb of channel in 1/2 chamber
475 maxChannel = (offsetY * offsetX + 2* offsetY + offsetCath);
486 maxChannel = (256 * offsetX + offsetX + offsetCath);
490 // manu Id directly from a matrix 8*8, same segmentation for B and NB
491 // 50 buspatches for 1/2 chamber
493 id = (TMath::Abs(digit->PadX()) * offsetX + digit->PadY() + offsetY +
495 Int_t chPerBus = maxChannel/50;
496 busPatchId = id/chPerBus; // start at zero
497 if (digit->PadX() > 0)
498 busPatchId += 50*iCh*2;
500 busPatchId += 50*(2*iCh+1);
501 // 64 manu cards for one buspatch
502 manuId = (id % chPerBus)/64; //start at zero
503 manuId &= 0x7FF; // 11 bits
506 channelId = (id % chPerBus) % 64; //start at zero
507 channelId &= 0x3F; // 6 bits
509 // id = (TMath::Abs(digit->PadX()) * offsetX + digit->PadY() + offsetY +
510 // offsetCath * iCath);
511 // busPatchId = id/50;
513 // Int_t inBusId = id - (maxChannel/50 * busPatchId);// id channel in buspatch
514 // Int_t manuPerBus = (maxChannel/(50*64)); // number of manus per buspatch
516 // // 64 manu cards for one buspatch
517 // manuId = inBusId/manuPerBus;
518 // manuId &= 0x7FF; // 11 bits
521 // channelId = (inBusId % manuPerBus);
522 // channelId &= 0x3F; // 6 bits
524 if (fPrintLevel == 2)
525 printf("id: %d, busPatchId %d, manuId: %d, channelId: %d, maxchannel: %d, chPerBus %d\n",
526 id, busPatchId, manuId, channelId, maxChannel, chPerBus);
528 charge = digit->Signal();
531 if (fPrintLevel == 2)
532 printf("id: %d, busPatchId %d, manuId: %d, channelId: %d, padx: %d pady %d, charge %d\n",
533 id, busPatchId, manuId, channelId, digit->PadX(), digit->PadY(), digit->Signal());