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
20 // This class version 1 (further details could be found in Alice-note coming soon right in our direction)
21 // Generates raw data for MUON tracker and finally for trigger
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.
25 // For trigger there is no mapping (mapping could be found in AliMUONTriggerCircuit)
26 // don't need for digits2raw but needed in raw2Reco
27 // the position are given per local card
28 ////////////////////////////////////
30 #include <TClonesArray.h>
31 #include "AliMUONRawData.h"
32 #include "AliMUONDigit.h"
34 #include "AliMUONConstants.h"
35 #include "AliMUONData.h"
36 #include "AliLoader.h"
37 #include "AliBitPacking.h"
39 #include "AliMUONSubEventTrigger.h"
40 #include "AliMUONDDLTracker.h"
41 #include "AliMUONDDLTrigger.h"
43 #include "AliMUONLocalTrigger.h"
44 #include "AliMUONGlobalTrigger.h"
47 const Int_t AliMUONRawData::fgkDefaultPrintLevel = 0;
49 ClassImp(AliMUONRawData) // Class implementation in ROOT context
51 //__________________________________________________________________________
52 AliMUONRawData::AliMUONRawData(AliLoader* loader)
56 // Standard Constructor
58 fPrintLevel = fgkDefaultPrintLevel;
60 // initialize loader's
63 // initialize container
64 fMUONData = new AliMUONData(fLoader,"MUON","MUON");
66 // trigger decision, temp solution, local & global has to move to Digits Tree
67 // fTrigDec = new AliMUONTriggerDecision(fLoader);
68 // fTrigData = fTrigDec->GetMUONData();
71 fSubEventArray[0] = new TClonesArray("AliMUONSubEventTracker",1000);
72 fSubEventArray[1] = new TClonesArray("AliMUONSubEventTracker",1000);
75 fSubEventTrigArray[0] = new TClonesArray("AliMUONSubEventTrigger",1000);
76 fSubEventTrigArray[1] = new TClonesArray("AliMUONSubEventTrigger",1000);
79 fDDLTracker = new AliMUONDDLTracker();
80 fDDLTrigger= new AliMUONDDLTrigger();
83 //__________________________________________________________________________
84 AliMUONRawData::AliMUONRawData()
87 fPrintLevel(fgkDefaultPrintLevel),
91 // Default Constructor
94 //_______________________________________________________________________
95 AliMUONRawData::AliMUONRawData (const AliMUONRawData& rhs)
98 // Protected copy constructor
100 AliFatal("Not implemented.");
103 //_______________________________________________________________________
105 AliMUONRawData::operator=(const AliMUONRawData& rhs)
107 // Protected assignement operator
109 if (this == &rhs) return *this;
111 AliFatal("Not implemented.");
116 //__________________________________________________________________________
117 AliMUONRawData::~AliMUONRawData(void)
121 if (fSubEventArray[0])
122 fSubEventArray[0]->Delete(); //using delete cos allocating memory in copy ctor.
123 if (fSubEventArray[1])
124 fSubEventArray[1]->Delete();
126 if (fSubEventTrigArray[0])
127 fSubEventTrigArray[0]->Delete();
128 if (fSubEventTrigArray[1])
129 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,GLT");
153 for (Int_t ich = 0; ich < AliMUONConstants::NTrackingCh(); ich++) {
156 idDDL = ich * 2 + 0x900;
157 sprintf(name, "MUON_%d.ddl",idDDL);
158 fFile1 = fopen(name,"w");
160 idDDL = (ich * 2) + 1 + 0x900;
161 sprintf(name, "MUON_%d.ddl",idDDL);
162 fFile2 = fopen(name,"w");
164 WriteTrackerDDL(ich);
169 fMUONData->ResetDigits();
176 sprintf(name, "MUTR_%d.ddl",idDDL);
177 fFile1 = fopen(name,"w");
180 sprintf(name, "MUTR_%d.ddl",idDDL);
181 fFile2 = fopen(name,"w");
188 fMUONData->ResetTrigger();
190 fLoader->UnloadDigits();
194 //____________________________________________________________________
195 Int_t AliMUONRawData::WriteTrackerDDL(Int_t iCh)
198 TClonesArray* muonDigits = 0;
199 fSubEventArray[0]->Clear();
200 fSubEventArray[1]->Clear();
205 nbInBus[0].Set(5000);
206 nbInBus[1].Set(5000);
212 AliRawDataHeader header = fDDLTracker->GetHeader();
213 Int_t headerSize = fDDLTracker->GetHeaderSize();
215 // DDL event one per half chamber
216 AliMUONSubEventTracker* subEvent;
221 UChar_t channelId = 0;
223 Int_t busPatchId = 0;
233 const AliMUONDigit* digit;
235 if (fPrintLevel == 1)
236 printf("WriteDDL chamber %d\n", iCh+1);
238 for (Int_t iCath = 0; iCath < 2; iCath++) {
240 fMUONData->ResetDigits();
241 fMUONData->GetCathode(iCath);
242 muonDigits = fMUONData->Digits(iCh);
244 nDigits = muonDigits->GetEntriesFast();
245 if (fPrintLevel == 2)
246 printf("ndigits = %d\n",nDigits);
248 // open DDL file, on per 1/2 chamber
250 for (Int_t idig = 0; idig < nDigits; idig++) {
252 digit = (AliMUONDigit*) muonDigits->UncheckedAt(idig);
255 GetDummyMapping(iCh, iCath, digit, busPatchId, manuId, channelId, charge);
258 AliBitPacking::PackWord((UInt_t)parity,word,29,31);
259 AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
260 AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
261 AliBitPacking::PackWord((UInt_t)charge,word,0,11);
264 subEvent = new AliMUONSubEventTracker();
265 subEvent->AddData(word);
266 subEvent->SetBusPatchId(busPatchId);
267 if (digit->PadX() > 0) {
268 nbInBus[0][busPatchId]++;
271 nbInBus[1][busPatchId]++;
277 fSubEventArray[0]->Sort();
278 fSubEventArray[1]->Sort();
280 // gather datas from same bus patch
281 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
282 nEntries = fSubEventArray[iDDL]->GetEntriesFast();
284 for (Int_t i = 0; i < nEntries; i++) {
285 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(i);
286 busPatchId = temp->GetBusPatchId();
288 // add bus patch header, length and total length managed by subevent class
289 temp->SetTriggerWord(0xdeadbeef);
290 for (Int_t j = 0; j < nbInBus[iDDL][busPatchId]-1; j++) {
291 AliMUONSubEventTracker* temp1 = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(++i);
292 temp->AddData(temp1->GetData(0));
293 fSubEventArray[iDDL]->RemoveAt(i) ;
296 fSubEventArray[iDDL]->Compress();
298 if (fPrintLevel == 3) {
299 nEntries = fSubEventArray[iDDL]->GetEntriesFast();
300 for (Int_t i = 0; i < nEntries; i++) {
301 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(i);
302 printf("busPatchid back %d\n",temp->GetBusPatchId());
303 for (Int_t j = 0; j < temp->GetLength(); j++) {
304 printf("manuId back %d, ",temp->GetManuId(j));
305 printf("channelId back %d, ",temp->GetChannelId(j));
306 printf("charge back %d\n",temp->GetCharge(j));
317 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
321 nEntries = fSubEventArray[iDDL]->GetEntriesFast();
322 buffer = new Int_t [(2048+24)*50]; // 24 words in average for one buspatch and 2048 manu info at most
330 for (Int_t iBlock = 0; iBlock < 2; iBlock++) {
333 fDDLTracker->SetTotalBlkLength(0xFFFFFFFF);
334 memcpy(&buffer[index],fDDLTracker->GetBlkHeader(),32);
338 for (Int_t iDsp = 0; iDsp < 5; iDsp++) {
341 fDDLTracker->SetTotalDspLength(0xEEEEEEEE);
342 memcpy(&buffer[index],fDDLTracker->GetDspHeader(),32);
346 for (Int_t i = 0; i < 5; i++) {
348 iBusPatch = i + iBlock*25 + iDsp*5 + 50*(2*iCh + iDDL);
350 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(iEntries);
352 busPatchId = temp->GetBusPatchId();
356 if (busPatchId == iBusPatch) {
357 // add bus patch structure
358 memcpy(&buffer[index],temp->GetAddress(),16);
360 for (Int_t j = 0; j < temp->GetLength(); j++)
361 buffer[index++] = temp->GetData(j);
362 if (iEntries < nEntries-1)
365 buffer[index++] = 4; // total length
366 buffer[index++] = 0; // raw data length
367 buffer[index++] = iBusPatch; // bus patch
368 buffer[index++] = 0xdeadbeef; // trigger word
371 buffer[indexDsp] = index - indexDsp;
372 buffer[indexDsp+1] = index - indexDsp -8;
373 if ((index - indexDsp) % 2 == 0)
374 buffer[indexDsp+7] = 0;
376 buffer[indexDsp+7] = 1;
378 buffer[indexBlk] = index - indexBlk;
379 buffer[indexBlk+1] = index - indexBlk -8;
383 header.fSize = index + headerSize;// total length in word
384 fwrite((char*)(&header),headerSize*4,1,fFile1);
385 fwrite(buffer,sizeof(int),index,fFile1);
389 header.fSize = index + headerSize;// total length in word
390 fwrite((char*)(&header),headerSize*4,1,fFile2);
391 fwrite(buffer,sizeof(int),index,fFile2);
398 //____________________________________________________________________
399 Int_t AliMUONRawData::WriteTriggerDDL()
402 // DDL event one per half chamber
403 AliMUONSubEventTrigger* subEvent = 0x0;
406 // stored local id number
407 TArrayI isFired(256);
412 AliRawDataHeader header = fDDLTrigger->GetHeader();
413 Int_t headerSize = fDDLTrigger->GetHeaderSize();
415 TClonesArray* localTrigger;
416 TClonesArray* globalTrigger;
417 AliMUONGlobalTrigger* gloTrg;
418 AliMUONLocalTrigger* locTrg = 0x0;
420 fMUONData->GetTriggerD();
422 // global trigger for trigger pattern
423 globalTrigger = fMUONData->GlobalTrigger();
424 gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
425 Int_t gloTrigPat = GetGlobalTriggerPattern(gloTrg);
428 localTrigger = fMUONData->LocalTrigger();
434 Int_t iLocCard, locCard;
435 Char_t locDec, trigY, posY, devX, posX;
436 Int_t version = 1; // software version
437 Int_t eventType =1; // trigger type: 1 for physics ?
438 Int_t serialNb = 0xF; // serial nb of card: all bits on for the moment
440 Int_t nEntries = (Int_t) (localTrigger->GetEntries());// 234 local cards
441 // stored the local card id that's fired
442 for (Int_t i = 0; i < nEntries; i++) {
443 locTrg = (AliMUONLocalTrigger*)localTrigger->At(i);
444 isFired[locTrg->LoCircuit()] = 1;
448 AliError("No Trigger information available");
450 buffer = new Int_t [680]; // [16(local)*5 words + 4 words]*8(reg) + 8 words = 680
452 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
456 // DDL enhanced header
458 AliBitPacking::PackWord((UInt_t)iDDL+1,word,30,31); //see AliMUONDDLTrigger.h for details
459 AliBitPacking::PackWord((UInt_t)version,word,22,29);
460 AliBitPacking::PackWord((UInt_t)serialNb,word,18,21);
461 AliBitPacking::PackWord((UInt_t)eventType,word,14,17);
463 fDDLTrigger->SetDDLWord(word);
464 fDDLTrigger->SetGlobalOutput(gloTrigPat);
465 memcpy(&buffer[index],fDDLTrigger->GetEnhancedHeader(),24);
468 for (Int_t iReg = 0; iReg < 8; iReg++) {
470 subEvent = new AliMUONSubEventTrigger();
472 // Regional card header
474 AliBitPacking::PackWord((UInt_t)serialNb,word,27,31); //see AliMUONSubEventTrigger.h for details
475 AliBitPacking::PackWord((UInt_t)iReg,word,22,26);
476 AliBitPacking::PackWord((UInt_t)version,word,14,21);
477 subEvent->SetRegWord(word);
478 memcpy(&buffer[index++],subEvent->GetAddress(),4);
480 for (Int_t iLoc = 0; iLoc < 16; iLoc++) {
482 iLocCard = iLoc + iReg*16 + iDDL*128;
484 if (isFired[iLocCard]) {
485 locTrg = (AliMUONLocalTrigger*)localTrigger->At(iEntries);
486 locCard = locTrg->LoCircuit();
487 locDec = locTrg->GetLoDecision();
489 posY = locTrg->LoStripY();
490 posX = locTrg->LoStripX();
491 devX = locTrg->LoDev();
492 if (fPrintLevel == 4)
493 printf("loctrg %d, posX %d, posY %d, devX %d\n",
494 locTrg-> LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev());
495 } else { //no trigger (see PRR chpt 3.4)
506 AliBitPacking::PackWord((UInt_t)(iLocCard % 16),word,19,22); //card id number in crate
507 AliBitPacking::PackWord((UInt_t)locDec,word,15,18);
508 AliBitPacking::PackWord((UInt_t)trigY,word,14,14);
509 AliBitPacking::PackWord((UInt_t)posY,word,10,13);
510 AliBitPacking::PackWord((UInt_t)devX,word,5,9);
511 AliBitPacking::PackWord((UInt_t)posX,word,0,4);
513 if (locCard == iLocCard) {
514 // add local cards structure
515 buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
516 buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
517 buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
518 buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
519 buffer[index++] = (Int_t)word; // data word
520 if (iEntries < nEntries-1)
523 buffer[index++] = 0; // 4 words for x1, x2, y1, y2
527 buffer[index++] = (Int_t)word; // data word
531 buffer[index++] = 0;// 2 words of regional input
533 buffer[index++] = 0;// regional output
539 buffer[index++] = fDDLTrigger->GetEoD(); // End of DDL word
540 buffer[index++] = fDDLTrigger->GetEoD(); // End of DDL word for 64 bits transfer purpose
545 header.fSize = index + headerSize;// total length in word
546 fwrite((char*)(&header),headerSize*4,1,fFile1);
547 fwrite(buffer,sizeof(int),index,fFile1);
551 header.fSize = index + headerSize;// total length in word
552 fwrite((char*)(&header),headerSize*4,1,fFile2);
553 fwrite(buffer,sizeof(int),index,fFile2);
560 //____________________________________________________________________
561 void AliMUONRawData::GetDummyMapping(Int_t iCh, Int_t iCath, const AliMUONDigit* digit,
562 Int_t &busPatchId, UShort_t &manuId, UChar_t &channelId, UShort_t &charge)
564 // Dummy mapping for tracker
566 Int_t offsetX = 0; // offet row
567 Int_t offsetY = 0; // offset columns
568 Int_t offsetCath = 0; //offset from one cathod to the other
569 Int_t maxChannel = 0; // maximum nb of channel in 1/2 chamber
579 maxChannel = (offsetY * offsetX + 2* offsetY + offsetCath);
590 maxChannel = (256 * offsetX + offsetX + offsetCath);
594 // manu Id directly from a matrix 8*8, same segmentation for B and NB
595 // 50 buspatches for 1/2 chamber
597 id = (TMath::Abs(digit->PadX()) * offsetX + digit->PadY() + offsetY +
599 Int_t chPerBus = maxChannel/50;
600 busPatchId = id/chPerBus; // start at zero
601 if (digit->PadX() > 0)
602 busPatchId += 50*iCh*2;
604 busPatchId += 50*(2*iCh+1);
605 // 64 manu cards for one buspatch
606 manuId = (id % chPerBus)/64; //start at zero
607 manuId &= 0x7FF; // 11 bits
610 channelId = (id % chPerBus) % 64; //start at zero
611 channelId &= 0x3F; // 6 bits
613 // id = (TMath::Abs(digit->PadX()) * offsetX + digit->PadY() + offsetY +
614 // offsetCath * iCath);
615 // busPatchId = id/50;
617 // Int_t inBusId = id - (maxChannel/50 * busPatchId);// id channel in buspatch
618 // Int_t manuPerBus = (maxChannel/(50*64)); // number of manus per buspatch
620 // // 64 manu cards for one buspatch
621 // manuId = inBusId/manuPerBus;
622 // manuId &= 0x7FF; // 11 bits
625 // channelId = (inBusId % manuPerBus);
626 // channelId &= 0x3F; // 6 bits
628 if (fPrintLevel == 2)
629 printf("id: %d, busPatchId %d, manuId: %d, channelId: %d, maxchannel: %d, chPerBus %d\n",
630 id, busPatchId, manuId, channelId, maxChannel, chPerBus);
632 charge = digit->Signal();
635 if (fPrintLevel == 2)
636 printf("id: %d, busPatchId %d, manuId: %d, channelId: %d, padx: %d pady %d, charge %d\n",
637 id, busPatchId, manuId, channelId, digit->PadX(), digit->PadY(), digit->Signal());
641 //____________________________________________________________________
642 Int_t AliMUONRawData::GetGlobalTriggerPattern(const AliMUONGlobalTrigger* gloTrg)
644 // global trigger pattern calculation
646 Int_t gloTrigPat = 0;
648 if (gloTrg->SinglePlusLpt()) gloTrigPat|= 0x1;
649 if (gloTrg->SinglePlusHpt()) gloTrigPat|= 0x2;
650 if (gloTrg->SinglePlusApt()) gloTrigPat|= 0x4;
652 if (gloTrg->SingleMinusLpt()) gloTrigPat|= 0x8;
653 if (gloTrg->SingleMinusHpt()) gloTrigPat|= 0x10;
654 if (gloTrg->SingleMinusApt()) gloTrigPat|= 0x20;
656 if (gloTrg->SingleUndefLpt()) gloTrigPat|= 0x40;
657 if (gloTrg->SingleUndefHpt()) gloTrigPat|= 0x80;
658 if (gloTrg->SingleUndefApt()) gloTrigPat|= 0x100;
660 if (gloTrg->PairUnlikeLpt()) gloTrigPat|= 0x200;
661 if (gloTrg->PairUnlikeHpt()) gloTrigPat|= 0x400;
662 if (gloTrg->PairUnlikeApt()) gloTrigPat|= 0x800;
664 if (gloTrg->PairLikeLpt()) gloTrigPat|= 0x1000;
665 if (gloTrg->PairLikeHpt()) gloTrigPat|= 0x2000;
666 if (gloTrg->PairLikeApt()) gloTrigPat|= 0x4000;