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"
35 #include "AliMUONChamber.h"
36 #include "AliMUONConstants.h"
37 #include "AliMUONData.h"
38 #include "AliLoader.h"
39 #include "AliBitPacking.h"
41 #include "AliMUONSubEventTrigger.h"
42 #include "AliMUONDDLTracker.h"
43 #include "AliMUONDDLTrigger.h"
45 #include "AliMUONLocalTrigger.h"
46 #include "AliMUONGlobalTrigger.h"
48 #include "AliMUONGeometrySegmentation.h"
49 #include "AliMUONSegmentManuIndex.h"
53 const Int_t AliMUONRawData::fgkDefaultPrintLevel = 0;
55 ClassImp(AliMUONRawData) // Class implementation in ROOT context
57 //__________________________________________________________________________
58 AliMUONRawData::AliMUONRawData(AliLoader* loader)
62 // Standard Constructor
64 fPrintLevel = fgkDefaultPrintLevel;
66 // initialize loader's
69 // initialize container
70 fMUONData = new AliMUONData(fLoader,"MUON","MUON");
73 fSubEventArray[0] = new TClonesArray("AliMUONSubEventTracker",1000);
74 fSubEventArray[1] = new TClonesArray("AliMUONSubEventTracker",1000);
76 // initialize array not used for the moment
77 fSubEventTrigArray[0] = new TClonesArray("AliMUONSubEventTrigger",1000);
78 fSubEventTrigArray[1] = new TClonesArray("AliMUONSubEventTrigger",1000);
81 fDDLTracker = new AliMUONDDLTracker();
82 fDDLTrigger = new AliMUONDDLTrigger();
85 //__________________________________________________________________________
86 AliMUONRawData::AliMUONRawData()
89 fPrintLevel(fgkDefaultPrintLevel),
93 // Default Constructor
96 //_______________________________________________________________________
97 AliMUONRawData::AliMUONRawData (const AliMUONRawData& rhs)
100 // Protected copy constructor
102 AliFatal("Not implemented.");
105 //_______________________________________________________________________
107 AliMUONRawData::operator=(const AliMUONRawData& rhs)
109 // Protected assignement operator
111 if (this == &rhs) return *this;
113 AliFatal("Not implemented.");
118 //__________________________________________________________________________
119 AliMUONRawData::~AliMUONRawData(void)
123 if (fSubEventArray[0])
124 fSubEventArray[0]->Delete(); //using delete cos allocating memory in copy ctor.
125 if (fSubEventArray[1])
126 fSubEventArray[1]->Delete();
128 if (fSubEventTrigArray[0])
129 fSubEventTrigArray[0]->Delete();
130 if (fSubEventTrigArray[1])
131 fSubEventTrigArray[1]->Delete();
140 //____________________________________________________________________
141 Int_t AliMUONRawData::WriteRawData()
143 // convert digits of the current event to raw data
148 fLoader->LoadDigits("READ");
150 fMUONData->SetTreeAddress("D,GLT");
155 for (Int_t ich = 0; ich < AliMUONConstants::NTrackingCh(); ich++) {
158 idDDL = ich * 2 + 0x900;
159 sprintf(name, "MUON_%d.ddl",idDDL);
160 fFile1 = fopen(name,"w");
162 idDDL = (ich * 2) + 1 + 0x900;
163 sprintf(name, "MUON_%d.ddl",idDDL);
164 fFile2 = fopen(name,"w");
166 WriteTrackerDDL(ich);
171 fMUONData->ResetDigits();
178 sprintf(name, "MUTR_%d.ddl",idDDL);
179 fFile1 = fopen(name,"w");
182 sprintf(name, "MUTR_%d.ddl",idDDL);
183 fFile2 = fopen(name,"w");
190 fMUONData->ResetTrigger();
192 fLoader->UnloadDigits();
196 //____________________________________________________________________
197 Int_t AliMUONRawData::WriteTrackerDDL(Int_t iCh)
200 TClonesArray* muonDigits = 0;
201 fSubEventArray[0]->Clear();
202 fSubEventArray[1]->Clear();
207 nbInBus[0].Set(5000);
208 nbInBus[1].Set(5000);
214 AliRawDataHeader header = fDDLTracker->GetHeader();
215 Int_t headerSize = fDDLTracker->GetHeaderSize();
217 // DDL event one per half chamber
218 AliMUONSubEventTracker* subEvent;
223 UChar_t channelId = 0;
225 Int_t busPatchId = 0;
238 const AliMUONDigit* digit;
241 AliMUONChamber* iChamber = 0x0;
242 AliMUONGeometrySegmentation* segmentation2[2];
244 segmentation2[0]=iChamber->SegmentationModel2(1); // cathode 0
245 segmentation2[1]=iChamber->SegmentationModel2(2); // cathode 1
247 pMUON = (AliMUON*) gAlice->GetModule("MUON");
248 iChamber = &(pMUON->Chamber(iCh));
251 AliDebug(1, Form("WriteDDL chamber %d\n", iCh+1));
253 for (Int_t iCath = 0; iCath < 2; iCath++) {
255 fMUONData->ResetDigits();
256 fMUONData->GetCathode(iCath);
257 muonDigits = fMUONData->Digits(iCh);
259 nDigits = muonDigits->GetEntriesFast();
260 if (fPrintLevel == 2)
261 printf("ndigits = %d\n",nDigits);
263 // open DDL file, on per 1/2 chamber
265 for (Int_t idig = 0; idig < nDigits; idig++) {
267 digit = (AliMUONDigit*) muonDigits->UncheckedAt(idig);
269 padX = digit->PadX();
270 padY = digit->PadY();
271 charge = digit->Signal();
273 cathode = digit->Cathode();
274 detElemId = digit->DetElemId();
277 if (detElemId == 0) {
278 AliWarning("\ndetElemId = 0, old segmentation !\n");
279 GetDummyMapping(iCh, iCath, digit, busPatchId, manuId, channelId);
281 // mapping (not far from real one)
282 AliMUONSegmentManuIndex* connect = segmentation2[iCath]->GetMpConnection(detElemId, padX, padY);
283 if (connect != 0x0) {
284 busPatchId = connect->GetBusPatchId();
285 manuId = connect->GetManuId();
286 channelId = connect->GetManuChannelId();
287 AliDebug(3,Form("busPatchId %d, manuId: %d, channelId: %d\n", busPatchId, manuId, channelId));
296 AliBitPacking::PackWord((UInt_t)parity,word,29,31);
297 AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
298 AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
299 AliBitPacking::PackWord((UInt_t)charge,word,0,11);
302 subEvent = new AliMUONSubEventTracker();
303 subEvent->AddData(word);
304 subEvent->SetBusPatchId(busPatchId);
305 if (digit->PadX() > 0) {
306 nbInBus[0][busPatchId]++;
309 nbInBus[1][busPatchId]++;
315 fSubEventArray[0]->Sort();
316 fSubEventArray[1]->Sort();
318 // gather datas from same bus patch
319 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
320 nEntries = fSubEventArray[iDDL]->GetEntriesFast();
322 for (Int_t i = 0; i < nEntries; i++) {
323 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(i);
324 busPatchId = temp->GetBusPatchId();
326 // add bus patch header, length and total length managed by subevent class
327 temp->SetTriggerWord(0xdeadbeef);
328 for (Int_t j = 0; j < nbInBus[iDDL][busPatchId]-1; j++) {
329 AliMUONSubEventTracker* temp1 = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(++i);
330 temp->AddData(temp1->GetData(0));
331 fSubEventArray[iDDL]->RemoveAt(i) ;
334 fSubEventArray[iDDL]->Compress();
336 if (fPrintLevel == 3) {
337 nEntries = fSubEventArray[iDDL]->GetEntriesFast();
338 for (Int_t i = 0; i < nEntries; i++) {
339 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(i);
340 printf("busPatchid back %d\n",temp->GetBusPatchId());
341 for (Int_t j = 0; j < temp->GetLength(); j++) {
342 printf("manuId back %d, ",temp->GetManuId(j));
343 printf("channelId back %d, ",temp->GetChannelId(j));
344 printf("charge back %d\n",temp->GetCharge(j));
356 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
360 nEntries = fSubEventArray[iDDL]->GetEntriesFast();
361 buffer = new Int_t [(2048+24)*50]; // 24 words in average for one buspatch and 2048 manu info at most
369 for (Int_t iBlock = 0; iBlock < 2; iBlock++) {
372 // fDDLTracker->SetTotalBlkLength(0xFFFFFFFF);
373 length = fDDLTracker->GetBlkHeaderLength();
374 memcpy(&buffer[index],fDDLTracker->GetBlkHeader(),length*4);
378 for (Int_t iDsp = 0; iDsp < 5; iDsp++) {
381 // fDDLTracker->SetTotalDspLength(0xEEEEEEEE);
382 length = fDDLTracker->GetDspHeaderLength();
383 memcpy(&buffer[index],fDDLTracker->GetDspHeader(),length*4);
387 for (Int_t i = 0; i < 5; i++) {
389 iBusPatch = i + iBlock*25 + iDsp*5 + 50*(2*iCh + iDDL);
391 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray[iDDL]->At(iEntries);
393 busPatchId = temp->GetBusPatchId();
397 if (busPatchId == iBusPatch) {
398 // add bus patch structure
399 length = temp->GetHeaderLength();
400 memcpy(&buffer[index],temp->GetAddress(),length*4);
402 for (Int_t j = 0; j < temp->GetLength(); j++)
403 buffer[index++] = temp->GetData(j);
404 if (iEntries < nEntries-1)
407 buffer[index++] = 4; // total length
408 buffer[index++] = 0; // raw data length
409 buffer[index++] = iBusPatch; // bus patch
410 buffer[index++] = 0xdeadbeef; // trigger word
413 buffer[indexDsp] = index - indexDsp; // dsp length
414 buffer[indexDsp+1] = index - indexDsp - fDDLTracker->GetDspHeaderLength();
415 if ((index - indexDsp) % 2 == 0)
416 buffer[indexDsp+7] = 0;
418 buffer[indexDsp+7] = 1;
420 buffer[indexBlk] = index - indexBlk; // block length
421 buffer[indexBlk+1] = index - indexBlk - fDDLTracker->GetBlkHeaderLength();
425 header.fSize = (index + headerSize) * 4;// total length in bytes
426 fwrite((char*)(&header),headerSize*4,1,fFile1);
427 fwrite(buffer,sizeof(int),index,fFile1);
431 header.fSize = (index + headerSize) * 4;// total length in bytes
432 fwrite((char*)(&header),headerSize*4,1,fFile2);
433 fwrite(buffer,sizeof(int),index,fFile2);
440 //____________________________________________________________________
441 Int_t AliMUONRawData::WriteTriggerDDL()
444 // DDL event one per half chamber
445 AliMUONSubEventTrigger* subEvent = 0x0;
448 // stored local id number
449 TArrayI isFired(256);
454 AliRawDataHeader header = fDDLTrigger->GetHeader();
455 Int_t headerSize = fDDLTrigger->GetHeaderSize();
457 TClonesArray* localTrigger;
458 TClonesArray* globalTrigger;
459 AliMUONGlobalTrigger* gloTrg;
460 AliMUONLocalTrigger* locTrg = 0x0;
462 fMUONData->GetTriggerD();
464 // global trigger for trigger pattern
465 globalTrigger = fMUONData->GlobalTrigger();
466 gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
467 Int_t gloTrigPat = GetGlobalTriggerPattern(gloTrg);
470 localTrigger = fMUONData->LocalTrigger();
476 Int_t iLocCard, locCard;
477 Char_t locDec, trigY, posY, devX, posX,regOut;
478 Int_t version = 1; // software version
479 Int_t eventType = 1; // trigger type: 1 for physics ?
480 Int_t serialNb = 0xF; // serial nb of card: all bits on for the moment
481 Int_t globalFlag = 1; // set to 2 if global info present in DDL else set to 1
483 Int_t nEntries = (Int_t) (localTrigger->GetEntries());// 234 local cards
484 // stored the local card id that's fired
485 for (Int_t i = 0; i < nEntries; i++) {
486 locTrg = (AliMUONLocalTrigger*)localTrigger->At(i);
487 isFired[locTrg->LoCircuit()] = 1;
491 AliError("No Trigger information available");
493 buffer = new Int_t [672]; // [16(local)*5 words + 3 words]*8(reg) + 8 words = 672
495 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
499 // DDL enhanced header
501 AliBitPacking::PackWord((UInt_t)iDDL+1,word,28,31); //see AliMUONDDLTrigger.h for details
502 AliBitPacking::PackWord((UInt_t)serialNb,word,24,27);
503 AliBitPacking::PackWord((UInt_t)version,word,16,23);
504 AliBitPacking::PackWord((UInt_t)eventType,word,12,15);
506 if (iDDL == 0) // suppose global info in DDL one
510 AliBitPacking::PackWord((UInt_t)globalFlag,word,8,11);
511 fDDLTrigger->SetDDLWord(word);
514 fDDLTrigger->SetGlobalOutput(gloTrigPat);// no global input for the moment....
516 fDDLTrigger->SetGlobalOutput(0);
517 length = fDDLTrigger->GetHeaderLength();
518 memcpy(&buffer[index],fDDLTrigger->GetEnhancedHeader(),length*4);
521 for (Int_t iReg = 0; iReg < 8; iReg++) {
523 subEvent = new AliMUONSubEventTrigger();
525 // Regional card header
528 AliBitPacking::PackWord((UInt_t)serialNb,word,24,28); //see AliMUONSubEventTrigger.h for details
529 AliBitPacking::PackWord((UInt_t)version,word,16,23);
530 AliBitPacking::PackWord((UInt_t)iReg,word,12,15);
531 AliBitPacking::PackWord((UInt_t)regOut,word,0,7); // whenever regional output will be implemented
533 subEvent->SetRegWord(word);
534 memcpy(&buffer[index++],subEvent->GetAddress(),4);
536 buffer[index++] = 0;// 2 words of regional input
539 for (Int_t iLoc = 0; iLoc < 16; iLoc++) {
541 iLocCard = iLoc + iReg*16 + iDDL*128;
543 if (isFired[iLocCard]) {
544 locTrg = (AliMUONLocalTrigger*)localTrigger->At(iEntries);
545 locCard = locTrg->LoCircuit();
546 locDec = locTrg->GetLoDecision();
548 posY = locTrg->LoStripY();
549 posX = locTrg->LoStripX();
550 devX = locTrg->LoDev();
551 if (fPrintLevel == 4)
552 printf("loctrg %d, posX %d, posY %d, devX %d\n",
553 locTrg-> LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev());
554 } else { //no trigger (see PRR chpt 3.4)
565 AliBitPacking::PackWord((UInt_t)(iLocCard % 16),word,19,22); //card id number in crate
566 AliBitPacking::PackWord((UInt_t)locDec,word,15,18);
567 AliBitPacking::PackWord((UInt_t)trigY,word,14,14);
568 AliBitPacking::PackWord((UInt_t)posY,word,10,13);
569 AliBitPacking::PackWord((UInt_t)devX,word,5,9);
570 AliBitPacking::PackWord((UInt_t)posX,word,0,4);
572 if (locCard == iLocCard) {
573 // add local cards structure
574 buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
575 buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
576 buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
577 buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
578 buffer[index++] = (Int_t)word; // data word
579 if (iEntries < nEntries-1)
582 buffer[index++] = 0; // 4 words for x1, x2, y1, y2
586 buffer[index++] = (Int_t)word; // data word
595 buffer[index++] = fDDLTrigger->GetEoD(); // End of DDL word
596 buffer[index++] = fDDLTrigger->GetEoD(); // End of DDL word for 64 bits transfer purpose
601 header.fSize = (index + headerSize) * 4;// total length in bytes
602 fwrite((char*)(&header),headerSize*4,1,fFile1);
603 fwrite(buffer,sizeof(int),index,fFile1);
607 header.fSize = (index + headerSize) * 4;// total length in bytes
608 fwrite((char*)(&header),headerSize*4,1,fFile2);
609 fwrite(buffer,sizeof(int),index,fFile2);
616 //____________________________________________________________________
617 void AliMUONRawData::GetDummyMapping(Int_t iCh, Int_t iCath, const AliMUONDigit* digit,
618 Int_t &busPatchId, UShort_t &manuId, UChar_t &channelId)
620 // Dummy mapping for tracker
622 Int_t offsetX = 0; // offet row
623 Int_t offsetY = 0; // offset columns
624 Int_t offsetCath = 0; //offset from one cathod to the other
625 Int_t maxChannel = 0; // maximum nb of channel in 1/2 chamber
635 maxChannel = (offsetY * offsetX + 2* offsetY + offsetCath);
646 maxChannel = (256 * offsetX + offsetX + offsetCath);
650 // manu Id directly from a matrix 8*8, same segmentation for B and NB
651 // 50 buspatches for 1/2 chamber
653 id = (TMath::Abs(digit->PadX()) * offsetX + digit->PadY() + offsetY +
655 Int_t chPerBus = maxChannel/50;
656 busPatchId = id/chPerBus; // start at zero
657 if (digit->PadX() > 0)
658 busPatchId += 50*iCh*2;
660 busPatchId += 50*(2*iCh+1);
661 // 64 manu cards for one buspatch
662 manuId = (id % chPerBus)/64; //start at zero
663 manuId &= 0x7FF; // 11 bits
666 channelId = (id % chPerBus) % 64; //start at zero
667 channelId &= 0x3F; // 6 bits
670 AliDebug(2,Form("id: %d, busPatchId %d, manuId: %d, channelId: %d, maxchannel: %d, chPerBus %d\n",
671 id, busPatchId, manuId, channelId, maxChannel, chPerBus));
673 AliDebug(2,Form("id: %d, busPatchId %d, manuId: %d, channelId: %d, padx: %d pady %d, charge %d\n",
674 id, busPatchId, manuId, channelId, digit->PadX(), digit->PadY(), digit->Signal()));
678 //____________________________________________________________________
679 Int_t AliMUONRawData::GetGlobalTriggerPattern(const AliMUONGlobalTrigger* gloTrg)
681 // global trigger pattern calculation
683 Int_t gloTrigPat = 0;
685 if (gloTrg->SinglePlusLpt()) gloTrigPat|= 0x1;
686 if (gloTrg->SinglePlusHpt()) gloTrigPat|= 0x2;
687 if (gloTrg->SinglePlusApt()) gloTrigPat|= 0x4;
689 if (gloTrg->SingleMinusLpt()) gloTrigPat|= 0x8;
690 if (gloTrg->SingleMinusHpt()) gloTrigPat|= 0x10;
691 if (gloTrg->SingleMinusApt()) gloTrigPat|= 0x20;
693 if (gloTrg->SingleUndefLpt()) gloTrigPat|= 0x40;
694 if (gloTrg->SingleUndefHpt()) gloTrigPat|= 0x80;
695 if (gloTrg->SingleUndefApt()) gloTrigPat|= 0x100;
697 if (gloTrg->PairUnlikeLpt()) gloTrigPat|= 0x200;
698 if (gloTrg->PairUnlikeHpt()) gloTrigPat|= 0x400;
699 if (gloTrg->PairUnlikeApt()) gloTrigPat|= 0x800;
701 if (gloTrg->PairLikeLpt()) gloTrigPat|= 0x1000;
702 if (gloTrg->PairLikeHpt()) gloTrigPat|= 0x2000;
703 if (gloTrg->PairLikeApt()) gloTrigPat|= 0x4000;