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 // TRD MCM (Multi Chip Module) simulator //
20 ///////////////////////////////////////////////////////////////////////////////
26 New release on 2007/08/17
28 AliTRDmcmSim is now stably working and zero suppression function seems ok.
29 From now, the default version of raw data is set to 3 in AliTRDfeeParam.
31 The following internal parameters were abolished because it is useless and
37 GetCol member was modified accordingly.
39 New member function DumpData was prepared for diagnostics.
41 ZSMapping member function was debugged. It was causing crash due to
42 wrong indexing in 1 dimensional numbering. Also code was shaped up better.
46 /*Semi-final version of TRD raw data simulation code with zero suppression (ZS)
47 similar to TRD FEE. ZS is realized by the class group:
53 AliTRDfeeParam has been modified to have more parameters like raw data
54 production version and so on. AliTRDmcmSim is new class and this is the core
55 of MCM (PASA+TRAP) simulator. It has still very simple function and it will be
56 another project to improve this to make it closer to the reall FEE.
57 AliTRDrawData has been modified to use new class AliTRDmcmSim.
59 These modifications were tested on Aug. 02 HEAD version that code itself
60 compiles. I'm sure there must be still bugs and we need testing by as many as
61 possible persons now. Especially it seems HLT part is impacted by problems
62 because some parameters were moved from AliTRDrawData to AliTRDfeeParam (like
63 fRawVersion disappeared from AliTRDrawData).
65 In TRD definition, we have now 4 raw data versions.
67 0 very old offline version (by Bogdan)
68 1 test version (no zero suppression)
69 2 final version (no zero suppression)
70 3 test version (with zero suppression)
72 The default is still set to 2 in AliTRDfeeParam::fgkRAWversion and it uses
73 previously existing codes. If you set this to 3, AliTRDrawData changes behavior
74 to use AliTRDmcmSim with ZS.
76 Plan is after we make sure it works stably, we delete AliTRDmcm which is obsolete.
77 However it still take time because tracklet part is not yet touched.
78 The default raw version is 2.
83 // if no histo is drawn, these are obsolete
87 // only needed if I/O of tracklets is activated
99 #include "AliTRDmcmSim.h"
100 #include "AliTRDfeeParam.h"
101 #include "AliTRDSimParam.h"
102 #include "AliTRDCommonParam.h"
103 #include "AliTRDgeometry.h"
104 #include "AliTRDcalibDB.h"
105 #include "AliTRDdigitsManager.h"
106 #include "AliTRDarrayADC.h"
107 // additional for new tail filter and/or tracklet
108 #include "AliTRDtrapAlu.h"
109 #include "AliTRDpadPlane.h"
110 #include "AliTRDtrackletMCM.h"
113 #include "AliLoader.h"
115 ClassImp(AliTRDmcmSim)
117 //_____________________________________________________________________________
118 AliTRDmcmSim::AliTRDmcmSim() :TObject()
119 ,fInitialized(kFALSE)
144 // AliTRDmcmSim default constructor
147 // By default, nothing is initialized.
148 // It is necessary to issue Init before use.
151 //_____________________________________________________________________________
152 AliTRDmcmSim::AliTRDmcmSim(const AliTRDmcmSim &m)
154 ,fInitialized(kFALSE)
180 // AliTRDmcmSim copy constructor
183 // By default, nothing is initialized.
184 // It is necessary to issue Init before use.
187 //_____________________________________________________________________________
188 AliTRDmcmSim::~AliTRDmcmSim()
191 // AliTRDmcmSim destructor
194 if( fADCR != NULL ) {
195 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
196 delete [] fADCR[iadc];
197 delete [] fADCF[iadc];
198 delete [] fADCT[iadc];
199 delete [] fZSM [iadc];
217 //_____________________________________________________________________________
218 AliTRDmcmSim &AliTRDmcmSim::operator=(const AliTRDmcmSim &m)
221 // Assignment operator
225 ((AliTRDmcmSim &) m).Copy(*this);
231 //_____________________________________________________________________________
232 void AliTRDmcmSim::Copy(TObject &m) const
237 ((AliTRDmcmSim &) m).fNextEvent = 0; //new
238 ((AliTRDmcmSim &) m).fMaxTracklets = 0; //new
239 ((AliTRDmcmSim &) m).fInitialized = 0;
240 ((AliTRDmcmSim &) m).fChaId = 0;
241 ((AliTRDmcmSim &) m).fSector = 0;
242 ((AliTRDmcmSim &) m).fStack = 0;
243 ((AliTRDmcmSim &) m).fLayer = 0;
244 ((AliTRDmcmSim &) m).fRobPos = 0;
245 ((AliTRDmcmSim &) m).fMcmPos = 0;
246 ((AliTRDmcmSim &) m).fNADC = 0;
247 ((AliTRDmcmSim &) m).fNTimeBin = 0;
248 ((AliTRDmcmSim &) m).fRow = 0;
249 ((AliTRDmcmSim &) m).fADCR = 0;
250 ((AliTRDmcmSim &) m).fADCF = 0;
251 ((AliTRDmcmSim &) m).fADCT = 0; //new
252 ((AliTRDmcmSim &) m).fPosLUT = 0; //new
253 ((AliTRDmcmSim &) m).fMCMT = 0; //new
254 ((AliTRDmcmSim &) m).fZSM = 0;
255 ((AliTRDmcmSim &) m).fZSM1Dim = 0;
256 ((AliTRDmcmSim &) m).fFeeParam = 0;
257 ((AliTRDmcmSim &) m).fSimParam = 0;
258 ((AliTRDmcmSim &) m).fCal = 0;
259 ((AliTRDmcmSim &) m).fGeo = 0;
263 //_____________________________________________________________________________
265 //void AliTRDmcmSim::Init( Int_t chaId, Int_t robPos, Int_t mcmPos )
266 void AliTRDmcmSim::Init( Int_t chaId, Int_t robPos, Int_t mcmPos, Bool_t newEvent = kFALSE ) // only for readout tree (new event)
269 // Initialize the class with new geometry information
270 // fADC array will be reused with filled by zero
274 fFeeParam = AliTRDfeeParam::Instance();
275 fSimParam = AliTRDSimParam::Instance();
276 fCal = AliTRDcalibDB::Instance();
277 fGeo = new AliTRDgeometry();
279 fSector = fGeo->GetSector( fChaId );
280 fStack = fGeo->GetStack( fChaId );
281 fLayer = fGeo->GetLayer( fChaId );
284 fNADC = fFeeParam->GetNadcMcm();
285 fNTimeBin = fCal->GetNumberOfTimeBins();
286 fRow = fFeeParam->GetPadRowFromMCM( fRobPos, fMcmPos );
288 fMaxTracklets = fFeeParam->GetMaxNrOfTracklets();
293 if (newEvent == kTRUE) {
299 // Allocate ADC data memory if not yet done
300 if( fADCR == NULL ) {
301 fADCR = new Int_t *[fNADC];
302 fADCF = new Int_t *[fNADC];
303 fADCT = new Int_t *[fNADC]; //new
304 fZSM = new Int_t *[fNADC];
305 fZSM1Dim = new Int_t [fNADC];
306 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
307 fADCR[iadc] = new Int_t[fNTimeBin];
308 fADCF[iadc] = new Int_t[fNTimeBin];
309 fADCT[iadc] = new Int_t[fNTimeBin]; //new
310 fZSM [iadc] = new Int_t[fNTimeBin];
314 // Initialize ADC data
315 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
316 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
319 fADCT[iadc][it] = -1; //new
320 fZSM [iadc][it] = 1; // Default unread = 1
322 fZSM1Dim[iadc] = 1; // Default unread = 1
326 fPosLUT = new Int_t[128];
327 for(Int_t i = 0; i<128; i++){
331 fMCMT = new UInt_t[fMaxTracklets];
332 for(Int_t i = 0; i < fMaxTracklets; i++) {
337 fInitialized = kTRUE;
340 //_____________________________________________________________________________
341 Bool_t AliTRDmcmSim::CheckInitialized()
344 // Check whether object is initialized
347 if( ! fInitialized ) {
348 AliDebug(2, Form ("AliTRDmcmSim is not initialized but function other than Init() is called."));
353 //_____________________________________________________________________________
356 void AliTRDmcmSim::SetPosLUT() {
357 Double_t iHi = (Double_t)fCal->GetPRFhi();
358 Double_t iLo = (Double_t)fCal->GetPRFlo();
359 Int_t nBin = fCal->GetPRFbin();
360 Int_t iOff = fLayer * nBin;
361 Int_t kNlayer = fGeo->Nlayer();
363 Float_t *sPRFsmp = new Float_t[nBin*kNlayer];
364 Double_t *sPRFlayer = new Double_t[nBin];
367 for(Int_t i = 0; i<nBin*kNlayer; i++){
369 //printf("%f\n",fCal->GetSampledPRF()[i]);
370 sPRFsmp[i] = fCal->GetSampledPRF()[i];
374 Double_t sWidth = (iHi-iLo)/((Double_t) nBin);
375 Int_t sPad = (Int_t) (1.0/sWidth);
377 // get the PRF for actual layer (interpolated to ibin data-points; 61 measured)
378 for(Int_t iBin = 0; iBin < nBin; iBin++){
379 sPRFlayer[iBin] = (Double_t)sPRFsmp[iOff+iBin];
382 Int_t bin0 = (Int_t)(-iLo / sWidth - 0.5); // bin-nr. for pad-position 0
384 Int_t bin1 = (Int_t)((Double_t)(0.5 - iLo) / sWidth - 0.5); // bin-nr. for pad-position 0.5
386 bin0 = bin0 + 1; //avoid negative values in aYest (start right of symmetry center)
387 while (bin0-sPad<0) {
390 while (bin1+sPad>=nBin) {
394 Double_t* aYest = new Double_t[bin1-bin0+1];
396 /*TH1F* hist1 = new TH1F("h1","yest(y)",128,0,0.5);
397 TH1F* hist2 = new TH1F("h2","y(yest)",128,0,0.5);
398 TH1F* hist3 = new TH1F("h3","y(yest)-yest",128,0,0.5);
399 TH1F* hist4 = new TH1F("h4","y(yest)-yest,discrete",128,0,0.5);
401 TCanvas *c1 = new TCanvas("c1","c1",800,1000);
403 TCanvas *c2 = new TCanvas("c2","c2",800,1000);
405 TCanvas *c3 = new TCanvas("c3","c3",800,1000);
407 TCanvas *c4 = new TCanvas("c4","c4",800,1000);
410 for(Int_t iBin = bin0; iBin <= bin1; iBin++){
411 aYest[iBin-bin0] = 0.5*(sPRFlayer[iBin-sPad] - sPRFlayer[iBin+sPad])/(sPRFlayer[iBin]); // estimated position from PRF; between 0 and 1
412 //Double_t position = ((Double_t)(iBin)+0.5)*sWidth+iLo;
413 // hist1->Fill(position,aYest[iBin-bin0]);
418 Double_t aY[128]; // reversed function
423 for(Int_t j = 0; j<128; j++) { // loop over all Yest; LUT has 128 entries;
424 Double_t yest = ((Double_t)j)/256;
427 while (yest>aYest[iBin] && iBin<(bin1-bin0)) {
430 if((iBin == bin1 - bin0)&&(yest>aYest[iBin])) {
431 aY[j] = 0.5; // yest too big
432 //hist2->Fill(yest,aY[j]);
436 Int_t bin_d = iBin + bin0 - 1;
437 Int_t bin_u = iBin + bin0;
438 Double_t y_d = ((Double_t)bin_d + 0.5)*sWidth + iLo; // lower y
439 Double_t y_u = ((Double_t)bin_u + 0.5)*sWidth + iLo; // upper y
440 Double_t yest_d = aYest[iBin-1]; // lower estimated y
441 Double_t yest_u = aYest[iBin]; // upper estimated y
443 aY[j] = ((yest-yest_d)/(yest_u-yest_d))*(y_u-y_d) + y_d;
444 //hist2->Fill(yest,aY[j]);
447 aY[j] = aY[j] - yest;
448 //hist3->Fill(yest,aY[j]);
450 a.AssignDouble(aY[j]);
452 fPosLUT[j] = a.GetValue(); // 1+8Bit value;128 entries;LUT is steered by abs(Q(i+1)-Q(i-1))/Q(i)=COG and gives the correction to COG/2
453 //hist4->Fill(yest,fPosLUT[j]);
466 //_____________________________________________________________________________
467 Int_t* AliTRDmcmSim::GetPosLUT(){
473 void AliTRDmcmSim::SetData( Int_t iadc, Int_t *adc )
476 // Store ADC data into array of raw data
479 if( !CheckInitialized() ) return;
481 if( iadc < 0 || iadc >= fNADC ) {
482 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
486 for( int it = 0 ; it < fNTimeBin ; it++ ) {
487 fADCR[iadc][it] = (Int_t)(adc[it]);
491 //_____________________________________________________________________________
492 void AliTRDmcmSim::SetData( Int_t iadc, Int_t it, Int_t adc )
495 // Store ADC data into array of raw data
498 if( !CheckInitialized() ) return;
500 if( iadc < 0 || iadc >= fNADC ) {
501 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
505 fADCR[iadc][it] = adc;
508 //_____________________________________________________________________________
509 void AliTRDmcmSim::SetDataPedestal( Int_t iadc )
512 // Store ADC data into array of raw data
515 if( !CheckInitialized() ) return;
517 if( iadc < 0 || iadc >= fNADC ) {
518 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
522 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
523 fADCR[iadc][it] = fSimParam->GetADCbaseline();
527 //_____________________________________________________________________________
528 Int_t AliTRDmcmSim::GetCol( Int_t iadc )
531 // Return column id of the pad for the given ADC channel
534 if( !CheckInitialized() ) return -1;
536 return fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, iadc);
539 //_____________________________________________________________________________
540 Int_t AliTRDmcmSim::ProduceRawStream( UInt_t *buf, Int_t maxSize )
543 // Produce raw data stream from this MCM and put in buf
544 // Returns number of words filled, or negative value
545 // with -1 * number of overflowed words
550 Int_t nw = 0; // Number of written words
551 Int_t of = 0; // Number of overflowed words
552 Int_t rawVer = fFeeParam->GetRAWversion();
555 if( !CheckInitialized() ) return 0;
557 if( fFeeParam->GetRAWstoreRaw() ) {
563 // Produce MCM header
564 x = ((fRobPos * fFeeParam->GetNmcmRob() + fMcmPos) << 24) | ((iEv % 0x100000) << 4) | 0xC;
575 for( Int_t iAdc = 0 ; iAdc < fNADC ; iAdc++ ) {
576 if( fZSM1Dim[iAdc] == 0 ) { // 0 means not suppressed
588 // Produce ADC data. 3 timebins are packed into one 32 bits word
589 // In this version, different ADC channel will NOT share the same word
591 UInt_t aa=0, a1=0, a2=0, a3=0;
593 for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
594 if( rawVer>= 3 && fZSM1Dim[iAdc] != 0 ) continue; // suppressed
595 aa = !(iAdc & 1) + 2;
596 for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
597 a1 = ((iT ) < fNTimeBin ) ? adc[iAdc][iT ] : 0;
598 a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] : 0;
599 a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] : 0;
600 x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
610 if( of != 0 ) return -of; else return nw;
613 //_____________________________________________________________________________
614 Int_t AliTRDmcmSim::ProduceRawStreamV2( UInt_t *buf, Int_t maxSize, UInt_t iEv )
617 // Produce raw data stream from this MCM and put in buf
618 // Returns number of words filled, or negative value
619 // with -1 * number of overflowed words
624 Int_t nw = 0; // Number of written words
625 Int_t of = 0; // Number of overflowed words
626 Int_t rawVer = fFeeParam->GetRAWversion();
628 Int_t nActiveADC = 0; // number of activated ADC bits in a word
630 if( !CheckInitialized() ) return 0;
632 if( fFeeParam->GetRAWstoreRaw() ) {
638 // Produce MCM header : xrrr mmmm eeee eeee eeee eeee eeee 1100
639 // x : 0 before , 1 since 10.2007
640 // r : Readout board position (Alice numbering)
642 // e : Event counter from 1
643 //x = (1<<31) | ((fRobPos * fFeeParam->GetNmcmRob() + fMcmPos) << 24) | ((iEv % 0x100000) << 4) | 0xC;
644 x = (1<<31) | (fRobPos << 28) | (fMcmPos << 24) | ((iEv % 0x100000) << 4) | 0xC;
647 //printf("\nMCM header: %X ",x);
653 // Produce ADC mask : nncc cccm mmmm mmmm mmmm mmmm mmmm 1100
654 // n : unused , c : ADC count, m : selected ADCs
657 for( Int_t iAdc = 0 ; iAdc < fNADC ; iAdc++ ) {
658 if( fZSM1Dim[iAdc] == 0 ) { // 0 means not suppressed
659 x = x | (1 << (iAdc+4) ); // last 4 digit reserved for 1100=0xc
660 nActiveADC++; // number of 1 in mmm....m
663 x = x | (1 << 30) | ( ( 0x3FFFFFFC ) & (~(nActiveADC) << 25) ) | 0xC; // nn = 01, ccccc are inverted, 0xc=1100
664 //printf("nActiveADC=%d=%08X, inverted=%X ",nActiveADC,nActiveADC,x );
668 //printf("ADC mask: %X nMask=%d ADC data: ",x,nActiveADC);
675 // Produce ADC data. 3 timebins are packed into one 32 bits word
676 // In this version, different ADC channel will NOT share the same word
678 UInt_t aa=0, a1=0, a2=0, a3=0;
680 for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
681 if( rawVer>= 3 && fZSM1Dim[iAdc] != 0 ) continue; // Zero Suppression, 0 means not suppressed
682 aa = !(iAdc & 1) + 2; // 3 for the even ADC channel , 2 for the odd ADC channel
683 for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
684 a1 = ((iT ) < fNTimeBin ) ? adc[iAdc][iT ] : 0;
685 a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] : 0;
686 a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] : 0;
687 x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
698 if( of != 0 ) return -of; else return nw;
701 //_____________________________________________________________________________
702 Int_t AliTRDmcmSim::ProduceTrackletStream( UInt_t *buf, Int_t maxSize )
705 // Produce tracklet data stream from this MCM and put in buf
706 // Returns number of words filled, or negative value
707 // with -1 * number of overflowed words
711 Int_t nw = 0; // Number of written words
712 Int_t of = 0; // Number of overflowed words
714 if( !CheckInitialized() ) return 0;
716 // Produce tracklet data. A maximum of four 32 Bit words will be written per MCM
717 // fMCMT is filled continuously until no more tracklet words available
720 while ( (wd < fMaxTracklets) && (fMCMT[wd] > 0) ){
731 if( of != 0 ) return -of; else return nw;
735 //_____________________________________________________________________________
736 void AliTRDmcmSim::Filter()
739 // Apply digital filter
742 if( !CheckInitialized() ) return;
744 // Initialize filtered data array with raw data
745 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
746 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
747 fADCF[iadc][it] = fADCR[iadc][it];
751 // Then apply fileters one by one to filtered data array
752 if( fFeeParam->IsPFon() ) FilterPedestal();
753 if( fFeeParam->IsGFon() ) FilterGain();
754 if( fFeeParam->IsTFon() ) FilterTail();
757 //_____________________________________________________________________________
758 void AliTRDmcmSim::FilterPedestal()
763 // Apply pedestal filter
766 Int_t ap = fSimParam->GetADCbaseline(); // ADC instrinsic pedestal
767 Int_t ep = fFeeParam->GetPFeffectPedestal(); // effective pedestal
768 //Int_t tc = fFeeParam->GetPFtimeConstant(); // this makes no sense yet
770 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
771 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
772 fADCF[iadc][it] = fADCF[iadc][it] - ap + ep;
777 //_____________________________________________________________________________
778 void AliTRDmcmSim::FilterGain()
781 // Apply gain filter (not implemented)
782 // Later it will be implemented because gain digital filiter will
783 // increase noise level.
788 //_____________________________________________________________________________
789 void AliTRDmcmSim::FilterTail()
792 // Apply exponential tail filter (Bogdan's version)
795 Double_t *dtarg = new Double_t[fNTimeBin];
796 Int_t *itarg = new Int_t[fNTimeBin];
797 Int_t nexp = fFeeParam->GetTFnExp();
798 Int_t tftype = fFeeParam->GetTFtype();
802 case 0: // Exponential Filter Analog Bogdan
803 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
804 FilterSimDeConvExpA( fADCF[iCol], dtarg, fNTimeBin, nexp);
805 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
806 fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
811 case 1: // Exponential filter digital Bogdan
812 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
813 FilterSimDeConvExpD( fADCF[iCol], itarg, fNTimeBin, nexp);
814 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
815 fADCF[iCol][iTime] = itarg[iTime];
820 case 2: // Exponential filter Marian special
821 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
822 FilterSimDeConvExpMI( fADCF[iCol], dtarg, fNTimeBin);
823 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
824 fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
830 case 3: // Exponential filter using AliTRDtrapAlu class
831 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
832 FilterSimDeConvExpEl( fADCF[iCol], itarg, fNTimeBin, nexp);
833 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
834 fADCF[iCol][iTime] = itarg[iTime]>>2; // to be used for raw-data
835 fADCT[iCol][iTime] = itarg[iTime]; // 12bits; to be used for tracklet; tracklet will have own container;
842 AliError(Form("Invalid filter type %d ! \n", tftype ));
851 //_____________________________________________________________________________
852 void AliTRDmcmSim::ZSMapping()
855 // Zero Suppression Mapping implemented in TRAP chip
857 // See detail TRAP manual "Data Indication" section:
858 // http://www.kip.uni-heidelberg.de/ti/TRD/doc/trap/TRAP-UserManual.pdf
861 Int_t eBIS = fFeeParam->GetEBsglIndThr(); // TRAP default = 0x4 (Tis=4)
862 Int_t eBIT = fFeeParam->GetEBsumIndThr(); // TRAP default = 0x28 (Tit=40)
863 Int_t eBIL = fFeeParam->GetEBindLUT(); // TRAP default = 0xf0
864 // (lookup table accept (I2,I1,I0)=(111)
865 // or (110) or (101) or (100))
866 Int_t eBIN = fFeeParam->GetEBignoreNeighbour(); // TRAP default = 1 (no neighbor sensitivity)
867 Int_t ep = AliTRDfeeParam::GetPFeffectPedestal();
869 if( !CheckInitialized() ) return;
871 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) {
872 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
874 // Get ADC data currently in filter buffer
875 Int_t ap = fADCF[iadc-1][it] - ep; // previous
876 Int_t ac = fADCF[iadc ][it] - ep; // current
877 Int_t an = fADCF[iadc+1][it] - ep; // next
879 // evaluate three conditions
880 Int_t i0 = ( ac >= ap && ac >= an ) ? 0 : 1; // peak center detection
881 Int_t i1 = ( ap + ac + an > eBIT ) ? 0 : 1; // cluster
882 Int_t i2 = ( ac > eBIS ) ? 0 : 1; // absolute large peak
884 Int_t i = i2 * 4 + i1 * 2 + i0; // Bit position in lookup table
885 Int_t d = (eBIL >> i) & 1; // Looking up (here d=0 means true
886 // and d=1 means false according to TRAP manual)
889 if( eBIN == 0 ) { // turn on neighboring ADCs
890 fZSM[iadc-1][it] &= d;
891 fZSM[iadc+1][it] &= d;
897 // do 1 dim projection
898 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
899 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
900 fZSM1Dim[iadc] &= fZSM[iadc][it];
906 //_____________________________________________________________________________
907 void AliTRDmcmSim::DumpData( char *f, char *target )
910 // Dump data stored (for debugging).
911 // target should contain one or multiple of the following characters
913 // F for filtered data
914 // Z for zero suppression map
916 // other characters are simply ignored
919 UInt_t tempbuf[1024];
921 if( !CheckInitialized() ) return;
923 std::ofstream of( f, std::ios::out | std::ios::app );
924 of << Form("AliTRDmcmSim::DumpData det=%03d sm=%02d stack=%d layer=%d rob=%d mcm=%02d\n",
925 fChaId, fSector, fStack, fLayer, fRobPos, fMcmPos );
927 for( int t=0 ; target[t] != 0 ; t++ ) {
928 switch( target[t] ) {
931 of << Form("fADCR (raw ADC data)\n");
932 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
933 of << Form(" ADC %02d: ", iadc);
934 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
935 of << Form("% 4d", fADCR[iadc][it]);
942 of << Form("fADCF (filtered ADC data)\n");
943 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
944 of << Form(" ADC %02d: ", iadc);
945 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
946 of << Form("% 4d", fADCF[iadc][it]);
953 of << Form("fZSM and fZSM1Dim (Zero Suppression Map)\n");
954 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
955 of << Form(" ADC %02d: ", iadc);
956 if( fZSM1Dim[iadc] == 0 ) { of << " R " ; } else { of << " . "; } // R:read .:suppressed
957 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
958 if( fZSM[iadc][it] == 0 ) { of << " R"; } else { of << " ."; } // R:read .:suppressed
965 Int_t s = ProduceRawStream( tempbuf, 1024 );
966 of << Form("Stream for Raw Simulation size=%d rawver=%d\n", s, fFeeParam->GetRAWversion());
967 of << Form(" address data\n");
968 for( int i = 0 ; i < s ; i++ ) {
969 of << Form(" %04x %08x\n", i, tempbuf[i]);
975 //_____________________________________________________________________________
976 void AliTRDmcmSim::FilterSimDeConvExpA(Int_t *source, Double_t *target
977 , Int_t n, Int_t nexp)
980 // Exponential filter "analog"
981 // source will not be changed
986 Double_t reminder[2];
990 Double_t coefficients[2];
992 // Initialize (coefficient = alpha, rates = lambda)
993 // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
995 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
996 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
997 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
998 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
1000 coefficients[0] = c1;
1001 coefficients[1] = c2;
1004 rates[0] = TMath::Exp(-dt/(r1));
1005 rates[1] = TMath::Exp(-dt/(r2));
1007 // Attention: computation order is important
1009 for (k = 0; k < nexp; k++) {
1013 for (i = 0; i < n; i++) {
1015 result = ((Double_t)source[i] - correction); // no rescaling
1018 for (k = 0; k < nexp; k++) {
1019 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1023 for (k = 0; k < nexp; k++) {
1024 correction += reminder[k];
1029 //_____________________________________________________________________________
1030 void AliTRDmcmSim::FilterSimDeConvExpD(Int_t *source, Int_t *target, Int_t n
1034 // Exponential filter "digital"
1035 // source will not be changed
1045 // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
1046 // initialize (coefficient = alpha, rates = lambda)
1049 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
1050 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
1051 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
1052 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
1054 Int_t fLambdaL = (Int_t)((TMath::Exp(-dt/r1) - 0.75) * 2048.0);
1055 Int_t fLambdaS = (Int_t)((TMath::Exp(-dt/r2) - 0.25) * 2048.0);
1056 Int_t iLambdaL = fLambdaL & 0x01FF; iLambdaL |= 0x0600; // 9 bit paramter + fixed bits
1057 Int_t iLambdaS = fLambdaS & 0x01FF; iLambdaS |= 0x0200; // 9 bit paramter + fixed bits
1060 fAlphaL = (Int_t) (c1 * 2048.0);
1061 iAlphaL = fAlphaL & 0x03FF; // 10 bit paramter
1064 fAlphaL = (Int_t) (c1 * 2048.0);
1065 fAlphaS = (Int_t) ((c2 - 0.5) * 2048.0);
1066 iAlphaL = fAlphaL & 0x03FF; // 10 bit paramter
1067 iAlphaS = fAlphaS & 0x03FF; iAlphaS |= 0x0400; // 10 bit paramter + fixed bits
1070 Double_t iAl = iAlphaL / 2048.0; // alpha L: correspondence to floating point numbers
1071 Double_t iAs = iAlphaS / 2048.0; // alpha S: correspondence to floating point numbers
1072 Double_t iLl = iLambdaL / 2048.0; // lambda L: correspondence to floating point numbers
1073 Double_t iLs = iLambdaS / 2048.0; // lambda S: correspondence to floating point numbers
1081 Int_t iFactor = ((Int_t) fFeeParam->GetPFeffectPedestal() ) << 2;
1083 Double_t xi = 1 - (iLl*iAs + iLs*iAl); // Calculation of equilibrium values of the
1084 rem1 = (Int_t) ((iFactor/xi) * ((1-iLs)*iLl*iAl)); // Internal registers to prevent switch on effects.
1085 rem2 = (Int_t) ((iFactor/xi) * ((1-iLl)*iLs*iAs));
1087 // further initialization
1088 if ((rem1 + rem2) > 0x0FFF) {
1089 correction = 0x0FFF;
1092 correction = (rem1 + rem2) & 0x0FFF;
1095 fTailPed = iFactor - correction;
1097 for (i = 0; i < n; i++) {
1099 result = (source[i] - correction);
1100 if (result < 0) { // Too much undershoot
1106 h1 = (rem1 + ((iAlphaL * result) >> 11));
1114 h2 = (rem2 + ((iAlphaS * result) >> 11));
1122 rem1 = (iLambdaL * h1 ) >> 11;
1123 rem2 = (iLambdaS * h2 ) >> 11;
1125 if ((rem1 + rem2) > 0x0FFF) {
1126 correction = 0x0FFF;
1129 correction = (rem1 + rem2) & 0x0FFF;
1136 //_____________________________________________________________________________
1137 void AliTRDmcmSim::FilterSimDeConvExpMI(Int_t *source, Double_t *target
1141 // Exponential filter (M. Ivanov)
1142 // source will not be changed
1150 for (i = 0; i < n; i++) {
1151 sig1[i] = (Double_t)source[i];
1155 Float_t lambda0 = (1.0 / fFeeParam->GetTFr2()) * dt;
1156 Float_t lambda1 = (1.0 / fFeeParam->GetTFr1()) * dt;
1158 FilterSimTailMakerSpline( sig1, sig2, lambda0, n);
1159 FilterSimTailCancelationMI( sig2, sig3, 0.7, lambda1, n);
1161 for (i = 0; i < n; i++) {
1162 target[i] = sig3[i];
1167 //______________________________________________________________________________
1168 void AliTRDmcmSim::FilterSimTailMakerSpline(Double_t *ampin, Double_t *ampout
1169 , Double_t lambda, Int_t n)
1172 // Special filter (M. Ivanov)
1176 Double_t l = TMath::Exp(-lambda*0.5);
1180 // Initialize in[] and out[] goes 0 ... 2*n+19
1181 for (i = 0; i < n*2+20; i++) {
1187 in[1] = (ampin[0] + ampin[1]) * 0.5;
1189 // Add charge to the end
1190 for (i = 0; i < 22; i++) {
1191 in[2*(n-1)+i] = ampin[n-1]; // in[] goes 2*n-2, 2*n-1, ... , 2*n+19
1194 // Use arithmetic mean
1195 for (i = 1; i < n-1; i++) {
1196 in[2*i] = ampin[i]; // in[] goes 2, 3, ... , 2*n-4, 2*n-3
1197 in[2*i+1] = ((ampin[i]+ampin[i+1]))/2.;
1203 for (i = 2*n; i >= 0; i--) {
1204 out[i] = in[i] + temp;
1205 temp = l*(temp+in[i]);
1208 for (i = 0; i < n; i++){
1209 //ampout[i] = out[2*i+1]; // org
1210 ampout[i] = out[2*i];
1215 //______________________________________________________________________________
1216 void AliTRDmcmSim::FilterSimTailCancelationMI(Double_t *ampin, Double_t *ampout
1217 , Double_t norm, Double_t lambda
1221 // Special filter (M. Ivanov)
1226 Double_t l = TMath::Exp(-lambda*0.5);
1227 Double_t k = l*(1.0 - norm*lambda*0.5);
1231 // Initialize in[] and out[] goes 0 ... 2*n+19
1232 for (i = 0; i < n*2+20; i++) {
1238 in[1] = (ampin[0]+ampin[1])*0.5;
1240 // Add charge to the end
1241 for (i =-2; i < 22; i++) {
1242 // in[] goes 2*n-4, 2*n-3, ... , 2*n+19
1243 in[2*(n-1)+i] = ampin[n-1];
1246 for (i = 1; i < n-2; i++) {
1247 // in[] goes 2, 3, ... , 2*n-6, 2*n-5
1249 in[2*i+1] = (9.0 * (ampin[i]+ampin[i+1]) - (ampin[i-1]+ampin[i+2])) / 16.0;
1250 //in[2*i+1] = ((ampin[i]+ampin[i+1]))/2.0;
1256 for (i = 1; i <= 2*n; i++) {
1257 out[i] = in[i] + (k-l)*temp;
1258 temp = in[i] + k *temp;
1261 for (i = 0; i < n; i++) {
1262 //ampout[i] = out[2*i+1]; // org
1263 //ampout[i] = TMath::Max(out[2*i+1],0.0); // org
1264 ampout[i] = TMath::Max(out[2*i],0.0);
1269 //_____________________________________________________________________________________
1270 //the following filter uses AliTRDtrapAlu-class
1272 void AliTRDmcmSim::FilterSimDeConvExpEl(Int_t *source, Int_t *target, Int_t n, Int_t nexp) {
1273 //static Int_t count = 0;
1276 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
1277 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
1278 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
1279 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
1283 //it is assumed that r1,r2,c1,c2 are given such, that the configuration values are in the ranges according to TRAP-manual
1284 //parameters need to be adjusted
1285 AliTRDtrapAlu lambdaL;
1286 AliTRDtrapAlu lambdaS;
1287 AliTRDtrapAlu alphaL;
1288 AliTRDtrapAlu alphaS;
1290 AliTRDtrapAlu correction;
1291 AliTRDtrapAlu result;
1295 AliTRDtrapAlu bSource;
1304 lambdaL.AssignDouble(TMath::Exp(-dt/r1));
1305 lambdaS.AssignDouble(TMath::Exp(-dt/r2));
1306 alphaL.AssignDouble(c1); // in AliTRDfeeParam the number of exponentials is set and also the according time constants
1307 alphaS.AssignDouble(c2); // later it should be: alphaS=1-alphaL
1309 //data is enlarged to 12 bits, including 2 bits after the comma; class AliTRDtrapAlu is used to handle arithmetics correctly
1310 correction.Init(10,2);
1316 for(Int_t i = 0; i < n; i++) {
1317 bSource.AssignInt(source[i]);
1318 result = bSource - correction; // subtraction can produce an underflow
1319 if(result.GetSign() == kTRUE) {
1320 result.AssignInt(0);
1323 //target[i] = result.GetValuePre(); // later, target and source should become AliTRDtrapAlu,too in order to simulate the 10+2Bits through the filter properly
1325 target[i] = result.GetValue(); // 12 bit-value; to get the corresponding integer value, target must be shifted: target>>2
1327 //printf("target-Wert zur Zeit %d : %d",i,target[i]);
1330 bufL = bufL + (result * alphaL);
1331 bufL = bufL * lambdaL;
1333 bufS = bufS + (result * alphaS);
1334 bufS = bufS * lambdaS; // eventually this should look like:
1335 // bufS = (bufS + (result - result * alphaL)) * lambdaS // alphaS=1-alphaL; then alphaS-variable is not needed any more
1337 correction = bufL + bufS; //check for overflow intrinsic; if overflowed, correction is set to 0x03FF
1349 //__________________________________________________________________________________
1352 // in order to use the Tracklets, please first
1353 // -- set AliTRDfeeParam::fgkTracklet to kTRUE, in order to switch on Tracklet-calculation
1354 // -- set AliTRDfeeParam::fgkTFtype to 3, in order to use the new tail cancellation filter
1355 // currently tracklets from filtered digits are only given when setting fgkTFtype (AliTRDfeeParam) to 3
1356 // -- set AliTRDfeeParam::fgkMCTrackletOutput to kTRUE, if you want to use the Tracklet output container with information about the Tracklet position (MCM, channel number)
1358 // The code is designed such that the less possible calculations with AliTRDtrapAlu class-objects are performed; whenever possible calculations are done with doubles or integers and the results are transformed into the right format
1360 void AliTRDmcmSim::Tracklet(){
1361 // tracklet calculation
1362 // if you use this code after a simulation, please make sure the same filter-settings as in the simulation are set in AliTRDfeeParam
1364 if(!CheckInitialized()){ return; }
1366 Bool_t filtered = kTRUE;
1372 if(fADCT[0][0]==-1){ // check if filter was applied
1374 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
1375 for( Int_t iT = 0 ; iT < fNTimeBin ; iT++ ) {
1376 data.AssignInt(fADCR[iadc][iT]);
1377 fADCT[iadc][iT] = data.GetValue(); // all incoming values are positive 10+2 bit values; if el.filter was called, this is done correctly
1383 // the online ordering of mcm's is reverse to the TRAP-manual-ordering! reverse fADCT (to be consistent to TRAP), then do all calculations
1385 Int_t** rev0 = new Int_t *[fNADC];
1386 Int_t** rev1 = new Int_t *[fNADC];
1388 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
1389 rev0[iadc] = new Int_t[fNTimeBin];
1390 rev1[iadc] = new Int_t[fNTimeBin];
1391 for( Int_t iT = 0; iT < fNTimeBin; iT++) {
1392 if( iadc <= fNADC-iadc-1 ) {
1393 rev0[iadc][iT] = fADCT[fNADC-iadc-1][iT];
1394 rev1[iadc][iT] = fADCT[iadc][iT];
1395 fADCT[iadc][iT] = rev0[iadc][iT];
1398 rev0[iadc][iT] = rev1[fNADC-iadc-1][iT];
1399 fADCT[iadc][iT] = rev0[iadc][iT];
1403 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
1404 delete[] rev0[iadc];
1405 delete[] rev1[iadc];
1414 // get the filtered pedestal; supports only electronic tail-cancellation filter
1415 AliTRDtrapAlu filPed;
1417 Int_t *ieffped = new Int_t[fNTimeBin];
1418 for(Int_t iT = 0; iT < fNTimeBin; iT++){
1422 if( filtered == kTRUE ) {
1423 if( fFeeParam->IsPFon() ){
1424 ep = fFeeParam->GetPFeffectPedestal();
1426 Int_t nexp = fFeeParam->GetTFnExp();
1427 Int_t *isource = new Int_t[fNTimeBin];
1429 filPed.AssignInt(ep);
1430 Int_t epf = filPed.GetValue();
1431 for(Int_t iT = 0; iT < fNTimeBin; iT++){
1436 if( fFeeParam->IsTFon() ) {
1437 FilterSimDeConvExpEl( isource, ieffped, fNTimeBin, nexp);
1443 //the following values should go to AliTRDfeeParam once they are defined; then they have to be read in properly
1444 //naming follows conventions in TRAP-manual
1447 Bool_t bVBY = kTRUE; // cluster-verification bypass
1449 Double_t cQTParam = 0; // cluster quality threshold; granularity 2^-10; range: 0<=cQT/2^-10<=2^-4 - 2^-10
1450 AliTRDtrapAlu cQTAlu;
1451 cQTAlu.Init(1,10,0,63);
1452 cQTAlu.AssignDouble(cQTParam);
1453 Int_t cQT = cQTAlu.GetValue();
1456 Int_t tFS = fFeeParam->GetLinearFitStart(); // linear fit start
1457 Int_t tFE = fFeeParam->GetLinearFitEnd(); // linear fit stop
1459 // charge accumulators
1460 Int_t tQS0 = fFeeParam->GetQacc0Start(); // start-time for charge-accumulator 0
1461 Int_t tQE0 = fFeeParam->GetQacc0End(); // stop-time for charge-accumulator 0
1462 Int_t tQS1 = fFeeParam->GetQacc1Start(); // start-time for charge-accumulator 1
1463 Int_t tQE1 = fFeeParam->GetQacc1End(); // stop-time for charge-accumulator 1
1464 // values set such that tQS0=tFS; tQE0=tQS1-1; tFE=tQE1; want to do (QS0+QS1)/N
1466 Double_t cTHParam = (Double_t)fFeeParam->GetMinClusterCharge(); // cluster charge threshold
1467 AliTRDtrapAlu cTHAlu;
1469 cTHAlu.AssignDouble(cTHParam);
1470 Int_t cTH = cTHAlu.GetValue(); // cTH used for comparison
1478 List_t selection[7]; // list with 7 elements
1479 List_t *list = NULL;
1480 List_t *listLeft = NULL;
1482 Int_t* qsum = new Int_t[fNADC];
1485 AliTRDtrapAlu qsumAlu;
1486 qsumAlu.Init(12,2); // charge sum will be 12+2 bits
1487 AliTRDtrapAlu dCOGAlu;
1488 dCOGAlu.Init(1,7,0,127); // COG will be 1+7 Bits; maximum 1 - 2^-7 for LUT
1489 AliTRDtrapAlu yrawAlu;
1490 yrawAlu.Init(1,8,-1,255);
1492 yAlu.Init(1,16,-1,0xFF00); // only first 8 past-comma bits filled;additional 8 bits for accuracy;maximum 1 - 2^-8; sign is given by + or -
1494 xAlu.Init(5,8); // 8 past-comma bits because value will be added/multiplied to another value with this accuracy
1495 AliTRDtrapAlu xxAlu;
1497 AliTRDtrapAlu yyAlu;
1498 yyAlu.Init(1,16,0,0xFFFF); // maximum is 2^16-1; 16Bit for past-commas
1499 AliTRDtrapAlu xyAlu;
1503 AliTRDtrapAlu XXAlu;
1506 YAlu.Init(5,8); // 14 bit, 1 is sign-bit; therefore only 13 bit
1507 AliTRDtrapAlu YYAlu;
1509 AliTRDtrapAlu XYAlu;
1510 XYAlu.Init(8,8); // 17 bit, 1 is sign-bit; therefore only 16 bit
1511 AliTRDtrapAlu qtruncAlu;
1512 qtruncAlu.Init(12,0);
1513 AliTRDtrapAlu QT0Alu;
1515 AliTRDtrapAlu QT1Alu;
1518 AliTRDtrapAlu oneAlu;
1522 AliTRDtrapAlu inverseNAlu;
1523 inverseNAlu.Init(1,8); // simulates the LUT for 1/N
1524 AliTRDtrapAlu MeanChargeAlu; // mean charge in ADC counts
1525 MeanChargeAlu.Init(8,0);
1526 AliTRDtrapAlu TotalChargeAlu;
1527 TotalChargeAlu.Init(17,8);
1528 //nr of post comma bits should be the same for inverseN and TotalCharge
1531 SetPosLUT(); // initialize the position correction LUT for this MCM;
1534 // fit-sums; remapping!; 0,1,2->0; 1,2,3->1; ... 18,19,20->18
1535 Int_t *X = new Int_t[fNADC-2];
1536 Int_t *XX = new Int_t[fNADC-2];
1537 Int_t *Y = new Int_t[fNADC-2];
1538 Int_t *YY = new Int_t[fNADC-2];
1539 Int_t *XY = new Int_t[fNADC-2];
1540 Int_t *N = new Int_t[fNADC-2];
1541 Int_t *QT0 = new Int_t[fNADC-2]; // accumulated charge
1542 Int_t *QT1 = new Int_t[fNADC-2]; // accumulated charge
1544 for (Int_t iCol = 0; iCol < fNADC-2; iCol++) {
1546 // initialize fit-sums
1558 filPed.Init(7,2); // convert filtered pedestal into 7+2Bits
1560 for(Int_t iT = 0; iT < fNTimeBin; iT++){
1562 if(iT<tFS || iT>=tFE) continue; // linear fit yes/no?
1565 Int_t portChannel[4] = {-1,-1,-1,-1};
1566 Int_t clusterCharge[4] = {0,0,0,0};
1567 Int_t leftCharge[4] = {0,0,0,0};
1568 Int_t centerCharge[4] = {0,0,0,0};
1569 Int_t rightCharge[4] = {0,0,0,0};
1573 filPed.AssignFormatted(ieffped[iT]); // no size-checking when using AssignFormatted; ieffped>=0
1574 filPed = filPed; // this checks the size
1576 ieffped[iT] = filPed.GetValue();
1578 for(Int_t i = 0; i<7; i++){
1579 selection[i].next = NULL;
1580 selection[i].iadc = -1; // value of -1: invalid adc
1581 selection[i].value = 0;
1584 // selection[0] is starting list-element; just for pointing
1586 // loop over inner adc's
1587 for (Int_t iCol = 1; iCol < fNADC-1; iCol++) {
1589 Int_t left = fADCT[iCol-1][iT];
1590 Int_t center = fADCT[iCol][iT];
1591 Int_t right = fADCT[iCol+1][iT];
1593 Int_t sum = left + center + right; // cluster charge sum
1594 qsumAlu.AssignFormatted(sum);
1595 qsumAlu = qsumAlu; // size-checking; redundant
1597 qsum[iCol] = qsumAlu.GetValue();
1599 //hit detection and masking
1602 if(qsum[iCol]>=(cTH + 3*ieffped[iT])){ // effective pedestal of all three channels must be added to cTH(+20); this is not parallel to TRAP manual; maybe cTH has to be adjusted in fFeeParam; therefore channels are not yet reduced by their pedestal
1603 mark |= 1; // marker
1612 // get selection of 6 adc's and sort,starting with greatest values
1614 //read three from right side and sort (primitive sorting algorithm)
1615 Int_t i = 0; // adc number
1616 Int_t j = 1; // selection number
1617 while(i<fNADC-2 && j<=3){
1619 if( ((mark>>(i-1)) & 1) == 1) {
1620 selection[j].iadc = fNADC-1-i;
1621 selection[j].value = qsum[fNADC-1-i]>>6; // for hit-selection only the first 8 out of the 14 Bits are used for comparison
1623 // insert into sorted list
1624 listLeft = &selection[0];
1625 list = listLeft->next;
1628 while((list->next != NULL) && (selection[j].value <= list->value)){
1633 if(selection[j].value<=list->value){
1634 selection[j].next = list->next;
1635 list->next = &selection[j];
1638 listLeft->next = &selection[j];
1639 selection[j].next = list;
1643 listLeft->next = &selection[j];
1644 selection[j].next = list;
1652 // read three from left side
1654 while(k>i && j<=6) {
1655 if( ((mark>>(k-1)) & 1) == 1) {
1656 selection[j].iadc = fNADC-1-k;
1657 selection[j].value = qsum[fNADC-1-k]>>6;
1659 listLeft = &selection[0];
1660 list = listLeft->next;
1663 while((list->next != NULL) && (selection[j].value <= list->value)){
1668 if(selection[j].value<=list->value){
1669 selection[j].next = list->next;
1670 list->next = &selection[j];
1673 listLeft->next = &selection[j];
1674 selection[j].next = list;
1678 listLeft->next = &selection[j];
1679 selection[j].next = list;
1687 // get the four with greatest charge-sum
1688 list = &selection[0];
1689 for(i = 0; i<4; i++){
1690 if(list->next == NULL) continue;
1692 if(list->iadc == -1) continue;
1693 Int_t adc = list->iadc; // channel number with selected hit
1695 // the following arrays contain the four chosen channels in 1 time-bin
1696 portChannel[i] = adc;
1697 clusterCharge[i] = qsum[adc];
1698 leftCharge[i] = fADCT[adc-1][iT] - ieffped[iT]; // reduce by filtered pedestal (pedestal is part of the signal)
1699 centerCharge[i] = fADCT[adc][iT] - ieffped[iT];
1700 rightCharge[i] = fADCT[adc+1][iT] - ieffped[iT];
1705 // cluster verification
1707 for(i = 0; i<4; i++){
1708 Int_t lr = leftCharge[i]*rightCharge[i]*1024;
1709 Int_t cc = centerCharge[i]*centerCharge[i]*cQT;
1711 portChannel[i] = -1; // set to invalid address
1712 clusterCharge[i] = 0;
1717 // fit-sums of valid channels
1718 // local hit position
1719 for(i = 0; i<4; i++){
1720 if (centerCharge[i] == 0) {
1721 portChannel[i] = -1;
1722 }// prevent division by 0
1724 if (portChannel[i] == -1) continue;
1726 Double_t dCOG = (Double_t)(rightCharge[i]-leftCharge[i])/centerCharge[i];
1728 Bool_t sign = (dCOG>=0.0) ? kFALSE : kTRUE;
1729 dCOG = (sign == kFALSE) ? dCOG : -dCOG; // AssignDouble doesn't allow for signed doubles
1730 dCOGAlu.AssignDouble(dCOG);
1731 Int_t iLUTpos = dCOGAlu.GetValue(); // steers position in LUT
1734 yrawAlu.AssignDouble(dCOG);
1735 Int_t iCOG = yrawAlu.GetValue();
1736 Int_t y = iCOG + fPosLUT[iLUTpos % 128]; // local position in pad-units
1737 yrawAlu.AssignFormatted(y); // 0<y<1
1738 yAlu = yrawAlu; // convert to 16 past-comma bits
1740 if(sign == kTRUE) yAlu.SetSign(-1); // buffer width of 9 bits; sign on real (not estimated) position
1741 xAlu.AssignInt(iT); // buffer width of 5 bits
1744 xxAlu = xAlu * xAlu; // buffer width of 10 bits -> fulfilled by x*x
1746 yyAlu = yAlu * yAlu; // buffer width of 16 bits
1748 xyAlu = xAlu * yAlu; // buffer width of 14 bits
1750 Int_t adc = portChannel[i]-1; // remapping! port-channel contains channel-nr. of inner adc's (1..19; mapped to 0..18)
1752 // calculate fit-sums recursively
1753 // interpretation of their bit-length is given as comment
1755 // be aware that the accuracy of the result of a calculation is always determined by the accuracy of the less accurate value
1757 XAlu.AssignFormatted(X[adc]);
1758 XAlu = XAlu + xAlu; // buffer width of 9 bits
1759 X[adc] = XAlu.GetValue();
1761 XXAlu.AssignFormatted(XX[adc]);
1762 XXAlu = XXAlu + xxAlu; // buffer width of 14 bits
1763 XX[adc] = XXAlu.GetValue();
1766 YAlu.AssignFormatted(-Y[adc]); // make sure that only positive values are assigned; sign-setting must be done by hand
1770 YAlu.AssignFormatted(Y[adc]);
1774 YAlu = YAlu + yAlu; // buffer width of 14 bits (8 past-comma);
1775 Y[adc] = YAlu.GetSignedValue();
1777 YYAlu.AssignFormatted(YY[adc]);
1778 YYAlu = YYAlu + yyAlu; // buffer width of 21 bits (16 past-comma)
1779 YY[adc] = YYAlu.GetValue();
1782 XYAlu.AssignFormatted(-XY[adc]);
1786 XYAlu.AssignFormatted(XY[adc]);
1790 XYAlu = XYAlu + xyAlu; // buffer allows 17 bits (8 past-comma)
1791 XY[adc] = XYAlu.GetSignedValue();
1793 N[adc] = N[adc] + 1;
1796 // accumulated charge
1797 qsumAlu.AssignFormatted(qsum[adc+1]); // qsum was not remapped!
1798 qtruncAlu = qsumAlu;
1800 if(iT>=tQS0 && iT<=tQE0){
1801 QT0Alu.AssignFormatted(QT0[adc]);
1802 QT0Alu = QT0Alu + qtruncAlu;
1803 QT0[adc] = QT0Alu.GetValue();
1804 //interpretation of QT0 as 12bit-value (all pre-comma); is this as it should be done?; buffer allows 15 Bit
1807 if(iT>=tQS1 && iT<=tQE1){
1808 QT1Alu.AssignFormatted(QT1[adc]);
1809 QT1Alu = QT1Alu + qtruncAlu;
1810 QT1[adc] = QT1Alu.GetValue();
1811 //interpretation of QT1 as 12bit-value; buffer allows 16 Bit
1815 // remapping is done!!
1821 // tracklet-assembly
1823 // put into AliTRDfeeParam and take care that values are in proper range
1824 const Int_t cTCL = 1; // left adc: number of hits; 8<=TCL<=31 (?? 1<=cTCL<+8 ??)
1825 const Int_t cTCT = 8; // joint number of hits; 8<=TCT<=31; note that according to TRAP manual this number cannot be lower than 8; however it should be adjustable to the number of hits in the fit time range (40%)
1827 Int_t mPair = 0; // marker for possible tracklet pairs
1828 Int_t* hitSum = new Int_t[fNADC-3];
1829 // hitSum[0] means: hit sum of remapped channels 0 and 1; hitSum[17]: 17 and 18;
1831 // check for all possible tracklet-pairs of adjacent channels (two are merged); mark the left channel of the chosen pairs
1832 for (Int_t iCol = 0; iCol < fNADC-3; iCol++) {
1833 hitSum[iCol] = N[iCol] + N[iCol+1];
1834 if ((N[iCol]>=cTCL) && (hitSum[iCol]>=cTCT)) {
1835 mPair |= 1; // mark as possible channel-pair
1842 List_t* selectPair = new List_t[fNADC-2]; // list with 18 elements (0..18) containing the left channel-nr and hit sums
1843 // selectPair[18] is starting list-element just for pointing
1844 for(Int_t k = 0; k<fNADC-2; k++){
1845 selectPair[k].next = NULL;
1846 selectPair[k].iadc = -1; // invalid adc
1847 selectPair[k].value = 0;
1854 // read marker and sort according to hit-sum
1856 Int_t adcL = 0; // left adc-channel-number (remapped)
1857 Int_t selNr = 0; // current number in list
1859 // insert marked channels into list and sort according to hit-sum
1860 while(adcL < fNADC-3 && selNr < fNADC-3){
1862 if( ((mPair>>((fNADC-4)-(adcL))) & 1) == 1) {
1863 selectPair[selNr].iadc = adcL;
1864 selectPair[selNr].value = hitSum[adcL];
1866 listLeft = &selectPair[fNADC-3];
1867 list = listLeft->next;
1870 while((list->next != NULL) && (selectPair[selNr].value <= list->value)){
1875 if(selectPair[selNr].value <= list->value){
1876 selectPair[selNr].next = list->next;
1877 list->next = &selectPair[selNr];
1880 listLeft->next = &selectPair[selNr];
1881 selectPair[selNr].next = list;
1886 listLeft->next = &selectPair[selNr];
1887 selectPair[selNr].next = list;
1895 //select up to 4 channels with maximum number of hits
1896 Int_t lpairChannel[4] = {-1,-1,-1,-1}; // save the left channel-numbers of pairs with most hit-sum
1897 Int_t rpairChannel[4] = {-1,-1,-1,-1}; // save the right channel, too; needed for detecting double tracklets
1898 list = &selectPair[fNADC-3];
1900 for (Int_t i = 0; i<4; i++) {
1901 if(list->next == NULL) continue;
1903 if(list->iadc == -1) continue;
1904 lpairChannel[i] = list->iadc; // channel number with selected hit
1905 rpairChannel[i] = lpairChannel[i]+1;
1908 // avoid submission of double tracklets
1909 for (Int_t i = 3; i>0; i--) {
1910 for (Int_t j = i-1; j>-1; j--) {
1911 if(lpairChannel[i] == rpairChannel[j]) {
1912 lpairChannel[i] = -1;
1913 rpairChannel[i] = -1;
1916 /* if(rpairChannel[i] == lpairChannel[j]) {
1917 lpairChannel[i] = -1;
1918 rpairChannel[i] = -1;
1924 // merging of the fit-sums of the remainig channels
1925 // assume same data-word-width as for fit-sums for 1 channel
1938 Int_t mMeanCharge[4];
1943 for (Int_t i = 0; i<4; i++){
1944 mADC[i] = -1; // set to invalid number
1958 oneAlu.AssignInt(1);
1959 one = oneAlu.GetValue(); // one with 8 past comma bits
1961 for (Int_t i = 0; i<4; i++){
1964 mADC[i] = lpairChannel[i]; // mapping of merged sums to left channel nr. (0,1->0; 1,2->1; ... 17,18->17)
1965 // the adc and pad-mapping should now be one to one: adc i is linked to pad i; TRAP-numbering
1966 Int_t madc = mADC[i];
1967 if (madc == -1) continue;
1969 YAlu.AssignInt(N[rpairChannel[i]]);
1970 Int_t wpad = YAlu.GetValue(); // enlarge hit counter of right channel by 8 past-comma bits; YAlu can have 5 pre-comma bits (values up to 63); hit counter<=nr of time bins (24)
1972 mN[i] = hitSum[madc];
1974 // don't merge fit sums in case of a stand-alone tracklet (consisting of only 1 channel); in that case only left channel makes up the fit sums
1975 if (N[madc+1] == 0) {
1976 mQT0[i] = QT0[madc];
1977 mQT1[i] = QT1[madc];
1982 // is it ok to do the size-checking for the merged fit-sums with the same format as for single-channel fit-sums?
1984 mQT0[i] = QT0[madc] + QT0[madc+1];
1985 QT0Alu.AssignFormatted(mQT0[i]);
1986 QT0Alu = QT0Alu; // size-check
1987 mQT0[i] = QT0Alu.GetValue(); // write back
1989 mQT1[i] = QT1[madc] + QT1[madc+1];
1990 QT1Alu.AssignFormatted(mQT1[i]);
1992 mQT1[i] = QT1Alu.GetValue();
1995 // calculate the mean charge in adc values; later to be replaced by electron likelihood
1996 mMeanCharge[i] = mQT0[i] + mQT1[i]; // total charge
1997 mMeanCharge[i] = mMeanCharge[i]>>2; // losing of accuracy; accounts for high mean charge
1998 // simulate LUT for 1/N; LUT is fed with the double-accurate pre-calculated value of 1/N; accuracy of entries has to be adjusted to real TRAP
2000 inverseNAlu.AssignDouble(invN);
2001 inverseN = inverseNAlu.GetValue();
2002 mMeanCharge[i] = mMeanCharge[i] * inverseN; // now to be interpreted with 8 past-comma bits
2003 TotalChargeAlu.AssignFormatted(mMeanCharge[i]);
2004 TotalChargeAlu = TotalChargeAlu;
2005 MeanChargeAlu = TotalChargeAlu;
2006 mMeanCharge[i] = MeanChargeAlu.GetValue();
2008 // this check is not necessary; it is just for efficiency reasons
2009 if (N[madc+1] == 0) {
2018 mX[i] = X[madc] + X[madc+1];
2019 XAlu.AssignFormatted(mX[i]);
2021 mX[i] = XAlu.GetValue();
2023 mXX[i] = XX[madc] + XX[madc+1];
2024 XXAlu.AssignFormatted(mXX[i]);
2026 mXX[i] = XXAlu.GetValue();
2029 mY[i] = Y[madc] + Y[madc+1] + wpad;
2031 YAlu.AssignFormatted(-mY[i]);
2035 YAlu.AssignFormatted(mY[i]);
2039 mY[i] = YAlu.GetSignedValue();
2041 mXY[i] = XY[madc] + XY[madc+1] + X[madc+1]*one; // multiplication by one to maintain the data format
2044 XYAlu.AssignFormatted(-mXY[i]);
2048 XYAlu.AssignFormatted(mXY[i]);
2052 mXY[i] = XYAlu.GetSignedValue();
2054 mYY[i] = YY[madc] + YY[madc+1] + 2*Y[madc+1]*one+ wpad*one;
2056 YYAlu.AssignFormatted(-mYY[i]);
2060 YYAlu.AssignFormatted(mYY[i]);
2065 mYY[i] = YYAlu.GetSignedValue();
2070 // calculation of offset and slope from the merged fit-sums;
2071 // YY is needed for some error measure only; still to be done
2072 // be aware that all values are relative values (scale: timebin-width; pad-width) and are integer values on special scale
2074 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2075 // !!important note: the offset is calculated from hits in the time bin range between tFS and tFE; it corresponds to the value at the height of the time bin tFS which does NOT need to correspond to the upper side of the drift !!
2076 // !!volume (cathode wire plane). The offset cannot be rescaled as long as it is unknown which is the first time bin that contains hits from the drift region and thus to which distance from the cathode plane tFS corresponds. !!
2077 // !!This has to be taken into account by the GTU. Furthermore a Lorentz correction might have to be applied to the offset (see below). !!
2078 // !!In this implementation it is assumed that no miscalibration containing changing drift velocities in the amplification region is used. !!
2079 // !!The corrections to the offset (e.g. no ExB correction applied as offset is supposed to be on top of drift region; however not at anode wire, so some inclination of drifting clusters due to Lorentz angle exists) are only !!
2080 // !!valid (in approximation) if tFS is close to the beginning of the drift region. !!
2081 // !!The slope however can be converted to a deflection length between electrode and cathode wire plane as it is clear that the drift region is sampled 20 times !!
2082 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2084 // which formats should be chosen?
2085 AliTRDtrapAlu denomAlu;
2086 denomAlu.Init(20,8);
2087 AliTRDtrapAlu numAlu;
2089 // is this enough pre-comma place? covers the range of the 13 bit-word of the transmitted offset
2090 // offset measured in coord. of left channel must be between -0.5 and 1.5; 14 pre-comma bits because numerator can be big
2092 for (Int_t i = 0; i<4; i++) {
2093 if (mADC[i] == -1) continue;
2095 Int_t num0 = (mN[i]*mXX[i]-mX[i]*mX[i]);
2097 denomAlu.AssignInt(-num0); // num0 does not have to be interpreted as having past-comma bits -> AssignInt
2098 denomAlu.SetSign(-1);
2101 denomAlu.AssignInt(num0);
2102 denomAlu.SetSign(1);
2105 Int_t num1 = mN[i]*mXY[i] - mX[i]*mY[i];
2107 numAlu.AssignFormatted(-num1); // value of num1 is already formatted to have 8 past-comma bits
2111 numAlu.AssignFormatted(num1);
2114 numAlu = numAlu/denomAlu;
2115 mSlope[i] = numAlu.GetSignedValue();
2117 Int_t num2 = mXX[i]*mY[i] - mX[i]*mXY[i];
2120 numAlu.AssignFormatted(-num2);
2124 numAlu.AssignFormatted(num2);
2128 numAlu = numAlu/denomAlu;
2131 mOffset[i] = numAlu.GetSignedValue();
2133 denomAlu.SetSign(1);
2136 //numAlu.AssignInt(mADC[i]+1); // according to TRAP-manual but trafo not to middle of chamber (0.5 channels away)
2137 numAlu.AssignDouble((Double_t)mADC[i] + 1.5); // numAlu has enough pre-comma place for that; correct trafo, best values
2138 mOffset[i] = mOffset[i] + numAlu.GetValue(); // transform offset to a coord.system relative to chip; +1 to avoid neg. values
2140 // up to here: adc-mapping according to TRAP manual and in line with pad-col mapping
2141 // reverse adc-counting to be again in line with the online mapping
2142 mADC[i] = fNADC - 4 - mADC[i]; // fNADC-4-mADC[i]: 0..17; remapping necessary;
2143 mADC[i] = mADC[i] + 2;
2144 // +2: mapping onto original ADC-online-counting: inner adc's corresponding to a chip's pasa: number 2..19
2147 // adc-counting is corresponding to online mapping; use AliTRDfeeParam::GetPadColFromADC to get the pad to which adc is connected;
2148 // pad-column mapping is reverse to adc-online mapping; TRAP adc-mapping is in line with pad-mapping (increase in same direction);
2150 // transform parameters to the local coordinate-system of a stack (used by GTU)
2151 AliTRDpadPlane* padPlane = fGeo->CreatePadPlane(fLayer,fStack);
2153 Double_t padWidthI = padPlane->GetWidthIPad()*10.0; // get values in cm; want them in mm
2154 //Double_t padWidthO = padPlane->GetWidthOPad()*10; // difference between outer pad-widths not included; in real TRAP??
2156 // difference between width of inner and outer pads of a row is not accounted for;
2158 Double_t magField = 0.4; // z-component of magnetic field in Tesla; adjust to current simulation!!; magnetic field can hardly be evaluated for the position of each mcm
2159 Double_t eCharge = 0.3; // unit charge in (GeV/c)/m*T
2160 Double_t ptMin = 2.3; // minimum transverse momentum (GeV/c); to be adjusted(?)
2162 Double_t granularityOffset = 0.160; // granularity for offset in mm
2163 Double_t granularitySlope = 0.140; // granularity for slope in mm
2165 // get the coordinates in SM-system; parameters:
2167 Double_t zPos = (padPlane->GetRowPos(fRow))*10.0; // z-position of the MCM; fRow is counted on a chamber; SM consists of 5
2168 // zPos is position of pad-borders;
2169 Double_t zOffset = 0.0;
2170 if ( fRow == 0 || fRow == 15 ) {
2171 zOffset = padPlane->GetLengthOPad();
2174 zOffset = padPlane->GetLengthIPad();
2176 zOffset = (-1.0) * zOffset/2.0;
2177 // turn zPos to be z-coordinate at middle of pad-row
2178 zPos = zPos + zOffset;
2181 Double_t xPos = 0.0; // x-position of the upper border of the drift-chamber of actual layer
2182 Int_t icol = 0; // column-number of adc-channel
2183 Double_t yPos[4]; // y-position of the pad to which ADC is connected
2184 Double_t dx = 30.0; // height of drift-chamber in mm; maybe retrieve from AliTRDGeometry
2185 Double_t freqSample = fFeeParam->GetSamplingFrequency(); // retrieve the sampling frequency (10.019750 MHz)
2186 Double_t vdrift = fCal->GetVdriftAverage(fChaId); // averaged drift velocity for this detector (1.500000 cm/us)
2187 Int_t nrOfDriftTimeBins = Int_t(dx/10.0*freqSample/vdrift); // the number of time bins in the drift region (20)
2188 Int_t nrOfAmplTimeBins = 2; // the number of time bins between anode wire and cathode wires in ampl.region (3.5mm)(guess)(suppose v_drift+3.5cm/us there=>all clusters arrive at anode wire within one time bin (100ns))
2189 Int_t nrOfOffsetCorrTimeBins = tFS - nrOfAmplTimeBins - 1; // -1 is to be conservative; offset correction will not remove the shift but is supposed to improve it; if tFS = 5, 2 drift time bins before tFS are assumed
2190 if(nrOfOffsetCorrTimeBins < 0) nrOfOffsetCorrTimeBins = 0;// don't apply offset correction if no drift time bins before tFS can be assumed
2191 Double_t lorTan = AliTRDCommonParam::Instance()->GetOmegaTau(vdrift); // tan of the Lorentz-angle for this detector; could be evaluated and set as a parameter for each mcm
2192 //Double_t lorAngle = 7.0; // Lorentz-angle in degrees
2193 Double_t tiltAngle = padPlane->GetTiltingAngle(); // sign-respecting tilting angle of pads in actual layer
2194 Double_t tiltTan = TMath::Tan(TMath::Pi()/180.0 * tiltAngle);
2195 //Double_t lorTan = TMath::Tan(TMath::Pi()/180.0 * lorAngle);
2197 Double_t alphaMax[4]; // maximum deflection from the direction to the primary vertex; granularity of hit pads
2198 Double_t slopeMin[4]; // local limits for the deflection
2199 Double_t slopeMax[4];
2200 Int_t mslopeMin[4]; // in granularity units; to be compared to mSlope[i]
2204 // x coord. of upper side of drift chambers in local SM-system (in mm)
2205 // obtained by evaluating the x-range of the hits; should be crosschecked; only drift, not amplification region taken into account (30mm);
2206 // the y-deflection is given as difference of y between lower and upper side of drift-chamber, not pad-plane;
2229 // calculation of offset-correction n:
2231 Int_t nCorrectOffset = (fRobPos % 2 == 0) ? ((fMcmPos % 4)) : ( 4 + (fMcmPos % 4));
2233 nCorrectOffset = (nCorrectOffset - 4)*18 - 1;
2234 if (nCorrectOffset < 0) {
2235 numAlu.AssignInt(-nCorrectOffset);
2239 numAlu.AssignInt(nCorrectOffset);
2242 nCorrectOffset = numAlu.GetSignedValue();
2244 // the Lorentz correction to the offset
2245 Double_t lorCorrectOffset = lorTan *(Double_t)nrOfOffsetCorrTimeBins*vdrift*10.0/freqSample; // Lorentz offset correction in mm
2248 lorCorrectOffset = lorCorrectOffset/padWidthI; // Lorentz correction in pad width units
2250 if(lorCorrectOffset < 0) {
2251 numAlu.AssignDouble(-lorCorrectOffset);
2255 numAlu.AssignDouble(lorCorrectOffset);
2259 Int_t mlorCorrectOffset = numAlu.GetSignedValue();
2262 Double_t mCorrectOffset = padWidthI/granularityOffset; // >= 0.0
2264 // calculation of slope-correction
2266 // this is only true for tracks coming (approx.) from primary vertex
2267 // everything is evaluated for a tracklet covering the whole drift chamber
2268 Double_t cCorrectSlope = (-lorTan*dx + zPos/xPos*dx*tiltTan)/granularitySlope;
2269 // Double_t cCorrectSlope = zPos/xPos*dx*tiltTan/granularitySlope;
2270 // zPos can be negative! for track from primary vertex: zOut-zIn > 0 <=> zPos > 0
2272 if (cCorrectSlope < 0) {
2273 numAlu.AssignDouble(-cCorrectSlope);
2277 numAlu.AssignDouble(cCorrectSlope);
2280 cCorrectSlope = numAlu.GetSignedValue();
2282 // convert slope to deflection between upper and lower drift-chamber position (slope is given in pad-unit/time-bins)
2283 // different pad-width of outer pads of a pad-plane not taken into account
2284 // note that the fit was only done in the range tFS to tFE, however this range does not need to cover the whole drift region (neither start nor end of it)
2285 // however the tracklets are supposed to be a fit in the drift region thus the linear function is stretched to fit the drift region of 30 mm
2288 Double_t mCorrectSlope = (Double_t)(nrOfDriftTimeBins)*padWidthI/granularitySlope; // >= 0.0
2290 AliTRDtrapAlu correctAlu;
2291 correctAlu.Init(20,8);
2293 AliTRDtrapAlu offsetAlu;
2294 offsetAlu.Init(13,0,-0x1000,0x0FFF); // 13 bit-word; 2-complement (1 sign-bit); asymmetric range
2296 AliTRDtrapAlu slopeAlu;
2297 slopeAlu.Init(7,0,-0x40,0x3F); // 7 bit-word; 2-complement (1 sign-bit);
2299 for (Int_t i = 0; i<4; i++) {
2301 if (mADC[i] == -1) continue;
2303 icol = fFeeParam->GetPadColFromADC(fRobPos,fMcmPos,mADC[i]); // be aware that mADC[i] contains the ADC-number according to online-mapping
2304 yPos[i] = (padPlane->GetColPos(icol))*10.0;
2309 correctAlu.AssignDouble(mCorrectOffset); // done because max. accuracy is 8 bit
2310 mCorrectOffset = correctAlu.GetValueWhole(); // cut offset correction to 8 past-comma bit accuracy
2311 mOffset[i] = (Int_t)((mCorrectOffset)*(Double_t)(mOffset[i] + nCorrectOffset - mlorCorrectOffset));
2312 //mOffset[i] = mOffset[i]*(-1); // adjust to direction of y-axes in online simulation
2314 if (mOffset[i] < 0) {
2315 numAlu.AssignFormatted(-mOffset[i]);
2319 numAlu.AssignFormatted(mOffset[i]);
2324 mOffset[i] = offsetAlu.GetSignedValue();
2329 correctAlu.AssignDouble(mCorrectSlope);
2330 mCorrectSlope = correctAlu.GetValueWhole();
2332 mSlope[i] = (Int_t)((mCorrectSlope*(Double_t)mSlope[i]) + cCorrectSlope);
2334 if (mSlope[i] < 0) {
2335 numAlu.AssignFormatted(-mSlope[i]);
2339 numAlu.AssignFormatted(mSlope[i]);
2343 slopeAlu = numAlu; // here all past-comma values are cut, not rounded; alternatively add +0.5 before cutting (means rounding)
2344 mSlope[i] = slopeAlu.GetSignedValue();
2346 // local (LTU) limits for the deflection
2347 // ATan returns angles in radian
2348 alphaMax[i] = TMath::ASin(eCharge*magField/(2.0*ptMin)*(TMath::Sqrt(xPos*xPos + yPos[i]*yPos[i]))/1000.0); // /1000: mm->m
2349 slopeMin[i] = dx*(TMath::Tan(TMath::ATan(yPos[i]/xPos) - alphaMax[i]))/granularitySlope;
2350 slopeMax[i] = dx*(TMath::Tan(TMath::ATan(yPos[i]/xPos) + alphaMax[i]))/granularitySlope;
2352 if (slopeMin[i] < 0) {
2353 slopeAlu.AssignDouble(-slopeMin[i]);
2354 slopeAlu.SetSign(-1);
2357 slopeAlu.AssignDouble(slopeMin[i]);
2358 slopeAlu.SetSign(1);
2360 mslopeMin[i] = slopeAlu.GetSignedValue(); // the borders should lie inside the range of mSlope -> usage of slopeAlu again
2362 if (slopeMax[i] < 0) {
2363 slopeAlu.AssignDouble(-slopeMax[i]);
2364 slopeAlu.SetSign(-1);
2367 slopeAlu.AssignDouble(slopeMax[i]);
2368 slopeAlu.SetSign(1);
2370 mslopeMax[i] = slopeAlu.GetSignedValue();
2373 // suppress submission of tracks with low stiffness
2374 // put parameters in 32bit-word and submit (write to file as root-file; sort after SM, stack, layer, chamber)
2376 // sort tracklet-words in ascending y-order according to the offset (according to mADC would also be possible)
2377 // up to now they are sorted according to maximum hit sum
2378 // is the sorting really done in the TRAP-chip?
2380 Int_t order[4] = {-1,-1,-1,-1};
2381 Int_t wordnr = 0; // number of tracklet-words
2383 for(Int_t j = 0; j < fMaxTracklets; j++) {
2384 //if( mADC[j] == -1) continue;
2385 if( (mADC[j] == -1) || (mSlope[j] < mslopeMin[j]) || (mSlope[j] > mslopeMax[j])) continue; // this applies a pt-cut
2387 if( wordnr-1 == 0) {
2391 // wordnr-1>0, wordnr-1<4
2392 order[wordnr-1] = j;
2393 for( Int_t k = 0; k < wordnr-1; k++) {
2394 if( mOffset[j] < mOffset[order[k]] ) {
2395 for( Int_t l = wordnr-1; l > k; l-- ) {
2396 order[l] = order[l-1];
2405 // fill the bit-words in ascending order and without gaps
2406 UInt_t bitWord[4] = {0,0,0,0}; // attention: unsigned int to have real 32 bits (no 2-complement)
2407 for(Int_t j = 0; j < wordnr; j++) { // only "wordnr" tracklet-words
2408 //Bool_t rem1 = kTRUE;
2411 //bit-word is 2-complement and therefore without sign
2412 bitWord[j] = 1; // this is the starting 1 of the bit-word (at 33rd position); the 1 must be ignored
2420 /*printf("mean charge: %d\n",mMeanCharge[i]);
2421 printf("row: %d\n",fRow);
2422 printf("slope: %d\n",mSlope[i]);
2423 printf("pad position: %d\n",mOffset[i]);
2424 printf("channel: %d\n",mADC[i]);*/
2426 // electron probability (currently not implemented; the mean charge is just scaled)
2427 shift = (UInt_t)mMeanCharge[i];
2428 for(Int_t iBit = 0; iBit < 8; iBit++) {
2429 bitWord[j] = bitWord[j]<<1;
2430 bitWord[j] |= (shift>>(7-iBit))&1;
2435 shift = (UInt_t)fRow;
2436 for(Int_t iBit = 0; iBit < 4; iBit++) {
2437 bitWord[j] = bitWord[j]<<1;
2438 bitWord[j] |= (shift>>(3-iBit))&1;
2439 //printf("%d", (fRow>>(3-iBit))&1);
2442 // deflection length
2444 shift = (UInt_t)(-mSlope[i]);
2445 // shift2 is 2-complement of shift
2447 for(Int_t iBit = 1; iBit < 7; iBit++) {
2449 shift2 |= (1- (((shift)>>(6-iBit))&1) );
2450 //printf("%d",(1-((-mSlope[i])>>(6-iBit))&1));
2452 shift2 = shift2 + 1;
2454 for(Int_t iBit = 0; iBit < 7; iBit++) {
2455 bitWord[j] = bitWord[j]<<1;
2456 bitWord[j] |= (shift2>>(6-iBit))&1;
2457 //printf("%d",(1-((-mSlope[i])>>(6-iBit))&1));
2461 shift = (UInt_t)(mSlope[i]);
2462 bitWord[j] = bitWord[j]<<1;
2465 for(Int_t iBit = 1; iBit < 7; iBit++) {
2466 bitWord[j] = bitWord[j]<<1;
2467 bitWord[j] |= (shift>>(6-iBit))&1;
2468 //printf("%d",(mSlope[i]>>(6-iBit))&1);
2473 if(mOffset[i] < 0) {
2474 shift = (UInt_t)(-mOffset[i]);
2476 for(Int_t iBit = 1; iBit < 13; iBit++) {
2478 shift2 |= (1-(((shift)>>(12-iBit))&1));
2479 //printf("%d",(1-((-mOffset[i])>>(12-iBit))&1));
2481 shift2 = shift2 + 1;
2483 for(Int_t iBit = 0; iBit < 13; iBit++) {
2484 bitWord[j] = bitWord[j]<<1;
2485 bitWord[j] |= (shift2>>(12-iBit))&1;
2486 //printf("%d",(1-((-mSlope[i])>>(6-iBit))&1));
2490 shift = (UInt_t)mOffset[i];
2491 bitWord[j] = bitWord[j]<<1;
2494 for(Int_t iBit = 1; iBit < 13; iBit++) {
2495 bitWord[j] = bitWord[j]<<1;
2496 bitWord[j] |= (shift>>(12-iBit))&1;
2497 //printf("%d",(mOffset[i]>>(12-iBit))&1);
2503 //printf("bitWord: %u\n",bitWord[j]);
2504 //printf("adc: %d\n",mADC[i]);
2505 fMCMT[j] = bitWord[j];
2524 delete [] selectPair;
2528 //if you want to activate the MC tracklet output, set fgkMCTrackletOutput=kTRUE in AliTRDfeeParam
2530 if (!fFeeParam->GetMCTrackletOutput())
2533 AliLog::SetClassDebugLevel("AliTRDmcmSim", 10);
2534 AliLog::SetFileOutput("../log/tracklet.log");
2536 // testing for wordnr in order to speed up the simulation
2540 UInt_t *trackletWord = new UInt_t[fMaxTracklets];
2541 Int_t *adcChannel = new Int_t[fMaxTracklets];
2542 Int_t *trackRef = new Int_t[fMaxTracklets];
2546 AliTRDdigitsManager *digman = new AliTRDdigitsManager();
2547 digman->ReadDigits(AliRunLoader::Instance()->GetLoader("TRDLoader")->TreeD());
2548 digman->SetUseDictionaries(kTRUE);
2549 AliTRDfeeParam *feeParam = AliTRDfeeParam::Instance();
2551 for (Int_t j = 0; j < fMaxTracklets; j++) {
2553 trackletWord[j] = 0;
2555 if (bitWord[j]!=0) {
2556 trackletWord[u] = bitWord[j];
2557 adcChannel[u] = mADC[i]; // mapping onto the original adc-array to be in line with the digits-adc-ordering (21 channels in total on 1 mcm, 18 belonging to pads); mADC[i] should be >-1 in case bitWord[i]>0
2559 // Finding label of MC track
2560 TH1F *hTrkRef = new TH1F("trackref", "trackref", 100000, 0, 100000);
2562 Int_t padcol = feeParam->GetPadColFromADC(fRobPos, fMcmPos, adcChannel[u]);
2563 Int_t padcol_ngb = feeParam->GetPadColFromADC(fRobPos, fMcmPos, adcChannel[u] - 1);
2564 Int_t padrow = 4 * (fRobPos / 2) + fMcmPos / 4;
2565 Int_t det = 30 * fSector + 6 * fStack + fLayer;
2566 for(Int_t iTimebin = feeParam->GetLinearFitStart(); iTimebin < feeParam->GetLinearFitEnd(); iTimebin++) {
2567 track[0] = digman->GetTrack(0, padrow, padcol, iTimebin, det);
2568 track[1] = digman->GetTrack(1, padrow, padcol, iTimebin, det);
2569 track[2] = digman->GetTrack(2, padrow, padcol, iTimebin, det);
2570 hTrkRef->Fill(track[0]);
2571 if (track[1] != track[0] && track[1] != -1)
2572 hTrkRef->Fill(track[1]);
2573 if (track[2] != track[0] && track[2] != track[1] && track[2] != -1)
2574 hTrkRef->Fill(track[2]);
2575 if (padcol_ngb >= 0) {
2576 track[0] = digman->GetTrack(0, padrow, padcol, iTimebin, det);
2577 track[1] = digman->GetTrack(1, padrow, padcol, iTimebin, det);
2578 track[2] = digman->GetTrack(2, padrow, padcol, iTimebin, det);
2579 hTrkRef->Fill(track[0]);
2580 if (track[1] != track[0] && track[1] != -1)
2581 hTrkRef->Fill(track[1]);
2582 if (track[2] != track[0] && track[2] != track[1] && track[2] != -1)
2583 hTrkRef->Fill(track[2]);
2586 trackRef[u] = hTrkRef->GetMaximumBin() - 1;
2592 AliDataLoader *dl = AliRunLoader::Instance()->GetLoader("TRDLoader")->GetDataLoader("tracklets");
2594 AliError("Could not get the tracklets data loader!");
2597 TTree *trackletTree = dl->Tree();
2600 trackletTree = dl->Tree();
2602 AliTRDtrackletMCM *trkl = new AliTRDtrackletMCM();
2603 TBranch *trkbranch = trackletTree->GetBranch("mcmtrklbranch");
2605 trkbranch = trackletTree->Branch("mcmtrklbranch", "AliTRDtrackletMCM", &trkl, 32000);
2606 trkbranch->SetAddress(&trkl);
2608 for (Int_t iTracklet = 0; iTracklet < fMaxTracklets; iTracklet++) {
2609 if (trackletWord[iTracklet] == 0)
2611 trkl->SetTrackletWord(trackletWord[iTracklet]);
2612 trkl->SetDetector(30*fSector + 6*fStack + fLayer);
2613 trkl->SetROB(fRobPos);
2614 trkl->SetMCM(fMcmPos);
2615 trkl->SetLabel(trackRef[iTracklet]);
2616 trackletTree->Fill();
2619 dl->WriteData("OVERWRITE");
2622 delete [] trackletWord;
2623 delete [] adcChannel;
2628 // error measure for quality of fit (not necessarily needed for the trigger)
2629 // cluster quality threshold (not yet set)
2630 // electron probability
2632 //_____________________________________________________________________________________
2633 void AliTRDmcmSim::GeneratefZSM1Dim()
2636 // Generate the array fZSM1Dim necessary
2637 // for the method ProduceRawStream
2641 // Supressed zeros indicated by -1 in digits array
2642 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ )
2644 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2647 if(fADCF[iadc][it]==-1) // If is a supressed value
2651 else // Not suppressed
2658 // Make the 1 dim projection
2659 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ )
2661 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2663 fZSM1Dim[iadc] &= fZSM[iadc][it];
2667 //_______________________________________________________________________________________
2668 void AliTRDmcmSim::CopyArrays()
2671 // Initialize filtered data array with raw data
2672 // Method added for internal consistency
2675 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ )
2677 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2679 fADCF[iadc][it] = fADCR[iadc][it];
2683 //_______________________________________________________________________________________
2684 void AliTRDmcmSim::StartfastZS(Int_t pads, Int_t timebins)
2687 // Initialize just the necessary elements to perform
2688 // the zero suppression in the digitizer
2691 fFeeParam = AliTRDfeeParam::Instance();
2692 fSimParam = AliTRDSimParam::Instance();
2694 fNTimeBin = timebins;
2698 fADCR = new Int_t *[fNADC];
2699 fADCF = new Int_t *[fNADC];
2700 fADCT = new Int_t *[fNADC];
2701 fZSM = new Int_t *[fNADC];
2702 fZSM1Dim = new Int_t [fNADC];
2703 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ )
2705 fADCR[iadc] = new Int_t[fNTimeBin];
2706 fADCF[iadc] = new Int_t[fNTimeBin];
2707 fADCT[iadc] = new Int_t[fNTimeBin];
2708 fZSM [iadc] = new Int_t[fNTimeBin];
2712 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ )
2714 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2716 fADCR[iadc][it] = 0;
2717 fADCF[iadc][it] = 0;
2718 fADCT[iadc][it] = -1;
2719 fZSM [iadc][it] = 1;
2724 fInitialized = kTRUE;
2726 //_______________________________________________________________________________________
2727 void AliTRDmcmSim::FlagDigitsArray(AliTRDarrayADC *tempdigs, Int_t valrow)
2730 // Modify the digits array to flag suppressed values
2733 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ )
2735 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2737 if(fZSM[iadc][it]==1)
2739 tempdigs->SetData(valrow,iadc,it,-1);
2744 //_______________________________________________________________________________________
2745 void AliTRDmcmSim::RestoreZeros()
2748 // Restore the zero-suppressed values (set as -1) to the value 0
2751 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ )
2753 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2756 if(fADCF[iadc][it]==-1) //if is a supressed zero, reset to zero