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 and reader in ALICE-MUON
19 // This class version 3 (further details could be found in Alice-note)
21 // Implemented non-constant buspatch numbers for tracking
22 // with correct DDL id (first guess)
23 // (Ch. Finck, dec 2005)
26 // Generates raw data for MUON tracker and finally for trigger
27 // Using real mapping (inverse) for tracker
28 // For trigger there is no mapping (mapping could be found in AliMUONTriggerCircuit)
32 // Using real mapping for tracker
33 // Indranil Das (Adapted for runloader: Ch. Finck) july 05
35 ////////////////////////////////////
40 #include <TClonesArray.h>
42 #include "AliLoader.h"
43 #include "AliBitPacking.h"
44 #include "AliRawReader.h"
49 #include "AliMUONRawWriter.h"
50 #include "AliMUONDigit.h"
52 #include "AliMUONConstants.h"
53 #include "AliMUONData.h"
55 #include "AliMUONSubEventTrigger.h"
56 #include "AliMUONDDLTracker.h"
57 #include "AliMUONDDLTrigger.h"
59 #include "AliMUONLocalTrigger.h"
60 #include "AliMUONGlobalTrigger.h"
62 #include "AliMUONGeometrySegmentation.h"
63 #include "AliMUONGeometryModule.h"
64 #include "AliMUONGeometryStore.h"
65 #include "AliMpSegFactory.h"
66 #include "AliMpPlaneType.h"
67 #include "AliMpVSegmentation.h"
68 #include "AliMpHelper.h"
72 ClassImp(AliMUONRawWriter) // Class implementation in ROOT context
73 //__________________________________________________________________________
74 AliMUONRawWriter::AliMUONRawWriter(AliLoader* loader, AliMUONData* data)
77 // Standard Constructor
79 // initialize loader's
82 // initialize segmentation factory
83 fSegFactory = new AliMpSegFactory();
85 // initialize container
86 // fMUONData = new AliMUONData(fLoader,"MUON","MUON");
90 fSubEventArray = new TClonesArray("AliMUONSubEventTracker",1000);
94 fDDLTracker = new AliMUONDDLTracker();
95 fDDLTrigger = new AliMUONDDLTrigger();
97 fBusPatchManager = new AliMpBusPatch();
98 fBusPatchManager->ReadBusPatchFile();
102 //__________________________________________________________________________
103 AliMUONRawWriter::AliMUONRawWriter()
111 // Default Constructor
112 fFile[0] = fFile[1] = 0x0;
116 //_______________________________________________________________________
117 AliMUONRawWriter::AliMUONRawWriter (const AliMUONRawWriter& rhs)
120 // Protected copy constructor
122 AliFatal("Not implemented.");
125 //_______________________________________________________________________
127 AliMUONRawWriter::operator=(const AliMUONRawWriter& rhs)
129 // Protected assignement operator
131 if (this == &rhs) return *this;
133 AliFatal("Not implemented.");
138 //__________________________________________________________________________
139 AliMUONRawWriter::~AliMUONRawWriter(void)
142 fSegFactory->DeleteSegmentations();
146 fSubEventArray->Delete(); //using delete cos allocating memory in copy ctor.
153 fBusPatchManager->Delete();
157 //____________________________________________________________________
158 Int_t AliMUONRawWriter::Digits2Raw()
160 // convert digits of the current event to raw data
165 fLoader->LoadDigits("READ");
167 fMUONData->SetTreeAddress("D,GLT");
172 for (Int_t ich = 0; ich < AliMUONConstants::NTrackingCh(); ich++) {
175 idDDL = ich * 2 + 0x900; // official number for MUON
176 sprintf(name, "MUON_%d.ddl",idDDL);
177 fFile[0] = fopen(name,"w");
179 idDDL = (ich * 2) + 1 + 0x900;
180 sprintf(name, "MUON_%d.ddl",idDDL);
181 fFile[1] = fopen(name,"w");
183 WriteTrackerDDL(ich);
188 fMUONData->ResetDigits();
194 idDDL = 0xA00;// official number for MUTR
195 sprintf(name, "MUTR_%d.ddl",idDDL);
196 fFile[0] = fopen(name,"w");
199 sprintf(name, "MUTR_%d.ddl",idDDL);
200 fFile[1] = fopen(name,"w");
207 fMUONData->ResetTrigger();
209 fLoader->UnloadDigits();
213 //____________________________________________________________________
214 Int_t AliMUONRawWriter::WriteTrackerDDL(Int_t iCh)
216 // writing DDL for tracker
217 // used inverse mapping
220 TClonesArray* muonDigits = 0;
221 fSubEventArray->Clear();
231 AliRawDataHeader header = fDDLTracker->GetHeader();
232 Int_t headerSize = fDDLTracker->GetHeaderSize();
234 // DDL event one per half chamber
235 AliMUONSubEventTracker* subEvent;
240 UChar_t channelId = 0;
242 Int_t busPatchId = 0;
256 const AliMUONDigit* digit;
258 AliDebug(3, Form("WriteDDL chamber %d\n", iCh+1));
261 fMUONData->ResetDigits();
262 fMUONData->GetDigits();
263 muonDigits = fMUONData->Digits(iCh);
265 nDigits = muonDigits->GetEntriesFast();
266 AliDebug(3,Form("ndigits = %d\n",nDigits));
269 for (Int_t idig = 0; idig < nDigits; idig++) {
271 digit = (AliMUONDigit*) muonDigits->UncheckedAt(idig);
273 padX = digit->PadX();
274 padY = digit->PadY();
275 charge = digit->Signal();
277 cathode = digit->Cathode();
278 detElemId = digit->DetElemId();
281 Int_t error = GetInvMapping(digit, busPatchId, manuId, channelId);
284 AliDebug(3,Form("input IdDE %d busPatchId %d PadX %d PadY %d iCath %d \n",
285 detElemId, busPatchId, padX, padY, cathode));
287 AliDebug(3,Form("busPatchId %d, manuId %d channelId %d\n", busPatchId, manuId, channelId ));
290 AliBitPacking::PackWord((UInt_t)parity,word,29,31);
291 AliBitPacking::PackWord((UInt_t)manuId,word,18,28);
292 AliBitPacking::PackWord((UInt_t)channelId,word,12,17);
293 AliBitPacking::PackWord((UInt_t)charge,word,0,11);
296 subEvent = new AliMUONSubEventTracker();
297 subEvent->AddData(word);
298 subEvent->SetBusPatchId(busPatchId);
300 // storing the number of identical buspatches
301 nbInBus[busPatchId]++;
307 // sorting by buspatch
308 fSubEventArray->Sort();
310 // gather datas from same bus patch
311 nEntries = fSubEventArray->GetEntriesFast();
313 for (Int_t i = 0; i < nEntries; i++) {
314 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray->At(i);
315 busPatchId = temp->GetBusPatchId();
317 // add bus patch header, length and total length managed by subevent class
318 temp->SetTriggerWord(0xdeadbeef);
319 for (Int_t j = 0; j < nbInBus[busPatchId]-1; j++) {
320 AliMUONSubEventTracker* temp1 = (AliMUONSubEventTracker*)fSubEventArray->At(++i);
321 temp->AddData(temp1->GetData(0));
322 fSubEventArray->RemoveAt(i) ;
325 fSubEventArray->Compress();
327 if (AliLog::GetGlobalDebugLevel() == 3) {
328 nEntries = fSubEventArray->GetEntriesFast();
329 for (Int_t i = 0; i < nEntries; i++) {
330 AliMUONSubEventTracker* temp = (AliMUONSubEventTracker*)fSubEventArray->At(i);
331 printf("busPatchid back %d\n",temp->GetBusPatchId());
332 for (Int_t j = 0; j < temp->GetLength(); j++) {
333 printf("manuId back %d, ",temp->GetManuId(j));
334 printf("channelId back %d, ",temp->GetChannelId(j));
335 printf("charge back %d\n",temp->GetCharge(j));
341 // getting info for the number of buspatches
344 Int_t iBusPerDSP[5];//number of bus patches per DSP
345 Int_t iDspMax; //number max of DSP per block
348 fBusPatchManager->GetDspInfo(iCh, iDspMax, iBusPerDSP);
350 TArrayI* vec = fBusPatchManager->GetBusfromDE((iCh+1)*100);
352 Int_t iBus0AtCh = vec->At(0); //get first bus patch id for a given ich
354 AliDebug(3,Form("iBus0AtCh %d", iBus0AtCh));
356 iBusPatch = iBus0AtCh - 1; // starting point for each chamber
358 // nEntries = fSubEventArray->GetEntriesFast();
359 AliMUONSubEventTracker* temp = 0x0;
361 // open DDL file, on per 1/2 chamber
362 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
366 buffer = new Int_t [(2048+24)*50]; // 24 words in average for one buspatch and 2048 manu info at most
372 // two blocks A and B per DDL
373 for (Int_t iBlock = 0; iBlock < 2; iBlock++) {
376 length = fDDLTracker->GetBlkHeaderLength();
377 memcpy(&buffer[index],fDDLTracker->GetBlkHeader(),length*4);
381 // 5 DSP's max per block
382 for (Int_t iDsp = 0; iDsp < iDspMax; iDsp++) {
385 length = fDDLTracker->GetDspHeaderLength();
386 memcpy(&buffer[index],fDDLTracker->GetDspHeader(),length*4);
390 //Â 5 buspatches max per DSP
391 for (Int_t i = 0; i < iBusPerDSP[iDsp]; i++) {
394 if ((fBusPatchManager->GetDDLfromBus(iBusPatch) % 2) == 1) // comparing to DDL file
399 AliDebug(3,Form("iCh %d iDDL %d iBlock %d iDsp %d busPatchId %d", iCh, iDDL, iBlock, iDsp, iBusPatch));
401 nEntries = fSubEventArray->GetEntriesFast();
403 for (Int_t iEntries = 0; iEntries < nEntries; iEntries++) { // method "bourrique"...
404 temp = (AliMUONSubEventTracker*)fSubEventArray->At(iEntries);
405 busPatchId = temp->GetBusPatchId();
406 if (busPatchId == iBusPatch) break;
408 AliDebug(3,Form("busPatchId %d", temp->GetBusPatchId()));
411 // check if buspatchid has digit
412 if (busPatchId != -1) {
413 // add bus patch structure
414 length = temp->GetHeaderLength();
415 memcpy(&buffer[index],temp->GetAddress(),length*4);
417 for (Int_t j = 0; j < temp->GetLength(); j++) {
418 buffer[index++] = temp->GetData(j);
419 AliDebug(3,Form("busPatchId %d, manuId %d channelId %d\n", temp->GetBusPatchId(),
420 temp->GetManuId(j), temp->GetChannelId(j) ));
422 // fSubEventArray->RemoveAt(iEntries);
423 // fSubEventArray->Compress();
425 // writting anyhow buspatch structure (empty ones)
426 buffer[index++] = 4; // total length
427 buffer[index++] = 0; // raw data length
428 buffer[index++] = iBusPatch; // bus patch
429 buffer[index++] = 0xdeadbeef; // trigger word
432 buffer[indexDsp] = index - indexDsp; // dsp length
433 buffer[indexDsp+1] = index - indexDsp - fDDLTracker->GetDspHeaderLength();
434 if ((index - indexDsp) % 2 == 0)
435 buffer[indexDsp+7] = 0;
437 buffer[indexDsp+7] = 1;
439 buffer[indexBlk] = index - indexBlk; // block length
440 buffer[indexBlk+1] = index - indexBlk - fDDLTracker->GetBlkHeaderLength();
445 header.fSize = (index + headerSize) * 4;// total length in bytes
446 fwrite((char*)(&header),headerSize*4,1,fFile[iFile]);
447 fwrite(buffer,sizeof(int),index,fFile[iFile]);
454 //____________________________________________________________________
455 Int_t AliMUONRawWriter::WriteTriggerDDL()
458 // DDL event one per half chamber
459 AliMUONSubEventTrigger* subEvent = 0x0;
462 // stored local id number
463 TArrayI isFired(256);
468 AliRawDataHeader header = fDDLTrigger->GetHeader();
469 Int_t headerSize = fDDLTrigger->GetHeaderSize();
471 TClonesArray* localTrigger;
472 TClonesArray* globalTrigger;
473 AliMUONGlobalTrigger* gloTrg;
474 AliMUONLocalTrigger* locTrg = 0x0;
476 // getting information from trigger
477 fMUONData->GetTriggerD();
479 // global trigger for trigger pattern
480 globalTrigger = fMUONData->GlobalTrigger();
481 gloTrg = (AliMUONGlobalTrigger*)globalTrigger->UncheckedAt(0);
482 Int_t gloTrigPat = GetGlobalTriggerPattern(gloTrg);
485 localTrigger = fMUONData->LocalTrigger();
491 Int_t iLocCard, locCard;
492 Char_t locDec, trigY, posY, posX,regOut;
494 Int_t version = 1; // software version
495 Int_t eventType = 1; // trigger type: 1 for physics ?
496 Int_t serialNb = 0xF; // serial nb of card: all bits on for the moment
497 Int_t globalFlag = 1; // set to 2 if global info present in DDL else set to 1
499 Int_t nEntries = (Int_t) (localTrigger->GetEntries());// 234 local cards
500 // stored the local card id that's fired
501 for (Int_t i = 0; i < nEntries; i++) {
502 locTrg = (AliMUONLocalTrigger*)localTrigger->At(i);
503 isFired[locTrg->LoCircuit()] = 1; // storing local boards with informations
507 AliError("No Trigger information available");
509 buffer = new Int_t [672]; // [16(local)*5 words + 3 words]*8(reg) + 8 words = 672
511 // open DDL file, on per 1/2 chamber
512 for (Int_t iDDL = 0; iDDL < 2; iDDL++) {
516 // DDL enhanced header
518 AliBitPacking::PackWord((UInt_t)iDDL+1,word,28,31); //see AliMUONDDLTrigger.h for details
519 AliBitPacking::PackWord((UInt_t)serialNb,word,24,27);
520 AliBitPacking::PackWord((UInt_t)version,word,16,23);
521 AliBitPacking::PackWord((UInt_t)eventType,word,12,15);
523 if (iDDL == 0) // suppose global info in DDL one
527 AliBitPacking::PackWord((UInt_t)globalFlag,word,8,11);
528 fDDLTrigger->SetDDLWord(word);
531 fDDLTrigger->SetGlobalOutput(gloTrigPat);// no global input for the moment....
533 fDDLTrigger->SetGlobalOutput(0);
534 length = fDDLTrigger->GetHeaderLength();
535 memcpy(&buffer[index],fDDLTrigger->GetEnhancedHeader(),length*4);
538 // 8 regional cards per DDL
539 for (Int_t iReg = 0; iReg < 8; iReg++) {
541 subEvent = new AliMUONSubEventTrigger();
543 // Regional card header
546 AliBitPacking::PackWord((UInt_t)serialNb,word,24,28); //see AliMUONSubEventTrigger.h for details
547 AliBitPacking::PackWord((UInt_t)version,word,16,23);
548 AliBitPacking::PackWord((UInt_t)iReg,word,12,15);
549 AliBitPacking::PackWord((UInt_t)regOut,word,0,7); // whenever regional output will be implemented
551 subEvent->SetRegWord(word);
552 memcpy(&buffer[index++],subEvent->GetAddress(),4);
554 buffer[index++] = 0;// 2 words of regional input
557 // 16 local card per regional board
558 for (Int_t iLoc = 0; iLoc < 16; iLoc++) {
560 iLocCard = iLoc + iReg*16 + iDDL*128;
562 if (isFired[iLocCard]) {
563 locTrg = (AliMUONLocalTrigger*)localTrigger->At(iEntries);
564 locCard = locTrg->LoCircuit();
565 locDec = locTrg->GetLoDecision();
567 posY = locTrg->LoStripY();
568 posX = locTrg->LoStripX();
569 devX = locTrg->LoDev();
570 AliDebug(4,Form("loctrg %d, posX %d, posY %d, devX %d\n",
571 locTrg->LoCircuit(),locTrg->LoStripX(),locTrg->LoStripY(),locTrg->LoDev()));
572 } else { //no trigger (see PRR chpt 3.4)
583 AliBitPacking::PackWord((UInt_t)(iLocCard % 16),word,19,22); //card id number in crate
584 AliBitPacking::PackWord((UInt_t)locDec,word,15,18);
585 AliBitPacking::PackWord((UInt_t)trigY,word,14,14);
586 AliBitPacking::PackWord((UInt_t)posY,word,10,13);
587 AliBitPacking::PackWord((UInt_t)devX,word,5,9);
588 AliBitPacking::PackWord((UInt_t)posX,word,0,4);
590 if (locCard == iLocCard) {
591 // add local cards structure
592 buffer[index++] = (locTrg->GetX1Pattern() | (locTrg->GetX2Pattern() << 16));
593 buffer[index++] = (locTrg->GetX3Pattern() | (locTrg->GetX4Pattern() << 16));
594 buffer[index++] = (locTrg->GetY1Pattern() | (locTrg->GetY2Pattern() << 16));
595 buffer[index++] = (locTrg->GetY3Pattern() | (locTrg->GetY4Pattern() << 16));
596 buffer[index++] = (Int_t)word; // data word
597 if (iEntries < nEntries-1)
600 buffer[index++] = 0; // 4 words for x1, x2, y1, y2
604 buffer[index++] = (Int_t)word; // data word
613 buffer[index++] = fDDLTrigger->GetEoD(); // End of DDL word
614 buffer[index++] = fDDLTrigger->GetEoD(); // End of DDL word for 64 bits transfer purpose
616 // writting onto disk
618 header.fSize = (index + headerSize) * 4;// total length in bytes
619 fwrite((char*)(&header),headerSize*4,1,fFile[iDDL]);
620 fwrite(buffer,sizeof(int),index,fFile[iDDL]);
628 //____________________________________________________________________
629 Int_t AliMUONRawWriter::GetInvMapping(const AliMUONDigit* digit,
630 Int_t &busPatchId, UShort_t &manuId, UChar_t &channelId)
633 // Inverse mapping for tracker
635 // information from digits
636 Int_t iCath = digit->Cathode();
637 Int_t idDE = digit->DetElemId();
638 Int_t padX = digit->PadX();
639 Int_t padY = digit->PadY();
641 if (idDE >= 500) { // Since in AliMpSlat pads begin at (0,0)
642 padX--; // while in AliMUONSt345Seg. they begin at (1,1)
647 AliMpPlaneType plane;
648 AliMpPlaneType plane1 = kBendingPlane;
649 AliMpPlaneType plane2 = kNonBendingPlane;
651 if (idDE < 500) { // should use GetDirection somehow (ChF)
652 if ( ((idDE % 100) % 2) != 0 ) {
653 plane1 = kNonBendingPlane;
654 plane2 = kBendingPlane;
657 // station 345 bending == cath0 for the moment
658 plane = (iCath == 0) ? plane1 : plane2;
660 //AliMpVSegmentation* seg = AliMUONSegmentationManager::Segmentation(idDE, plane);
661 AliMpVSegmentation* seg = fSegFactory->CreateMpSegmentation(idDE, iCath);
662 AliMpPad pad = seg->PadByIndices(AliMpIntPair(padX,padY),kTRUE);
665 AliWarning(Form("No elec. for idDE: %d, padx: %d pady %d, charge: %d\n",
666 idDE, digit->PadX(), digit->PadY(), digit->Signal()));
671 manuId = pad.GetLocation().GetFirst();
672 manuId &= 0x7FF; // 11 bits
674 // Getting channel id
675 channelId = pad.GetLocation().GetSecond();
676 channelId &= 0x3F; // 6 bits
678 // Getting buspatch id
679 TArrayI* vec = fBusPatchManager->GetBusfromDE(idDE);
682 if (idDE < 500) { // station 1 & 2
683 // set 32 manus for one bus patch ? (ChF)
686 // offset of 100 in manuId for following bus patch
690 // if (pos >(int_t) vec.size())
691 // AliWarning("pos greater than size\n");
692 busPatchId = vec->At(pos);
694 if (plane == kNonBendingPlane) // for Non-Bending manuid+= 1000;
695 manuId += 1000; // tmp solution til one finds something better (ChF)
697 AliDebug(3,Form("idDE: %d, busPatchId %d, manuId: %d, channelId:%d\n",
698 idDE, busPatchId, manuId, channelId));
700 AliDebug(3,Form("idDE: %d, busPatchId %d, manuId: %d, channelId: %d, padx: %d pady: %d, charge: %d\n",
701 idDE, busPatchId, manuId, channelId, digit->PadX(), digit->PadY(), digit->Signal()));
703 return kFALSE; // no error
706 //____________________________________________________________________
707 Int_t AliMUONRawWriter::GetGlobalTriggerPattern(const AliMUONGlobalTrigger* gloTrg) const
709 // global trigger pattern calculation
711 Int_t gloTrigPat = 0;
713 if (gloTrg->SinglePlusLpt()) gloTrigPat|= 0x1;
714 if (gloTrg->SinglePlusHpt()) gloTrigPat|= 0x2;
715 if (gloTrg->SinglePlusApt()) gloTrigPat|= 0x4;
717 if (gloTrg->SingleMinusLpt()) gloTrigPat|= 0x8;
718 if (gloTrg->SingleMinusHpt()) gloTrigPat|= 0x10;
719 if (gloTrg->SingleMinusApt()) gloTrigPat|= 0x20;
721 if (gloTrg->SingleUndefLpt()) gloTrigPat|= 0x40;
722 if (gloTrg->SingleUndefHpt()) gloTrigPat|= 0x80;
723 if (gloTrg->SingleUndefApt()) gloTrigPat|= 0x100;
725 if (gloTrg->PairUnlikeLpt()) gloTrigPat|= 0x200;
726 if (gloTrg->PairUnlikeHpt()) gloTrigPat|= 0x400;
727 if (gloTrg->PairUnlikeApt()) gloTrigPat|= 0x800;
729 if (gloTrg->PairLikeLpt()) gloTrigPat|= 0x1000;
730 if (gloTrg->PairLikeHpt()) gloTrigPat|= 0x2000;
731 if (gloTrg->PairLikeApt()) gloTrigPat|= 0x4000;