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 **************************************************************************/
20 ///////////////////////////////////////////////////////////////////////////////
22 // TRD MCM (Multi Chip Module) simulator //
24 ///////////////////////////////////////////////////////////////////////////////
29 #include "AliTRDmcmSim.h"
30 #include "AliTRDfeeParam.h"
31 #include "AliTRDgeometry.h"
33 ClassImp(AliTRDmcmSim)
35 //_____________________________________________________________________________
36 AliTRDmcmSim::AliTRDmcmSim() :TObject()
57 // AliTRDmcmSim default constructor
60 // By default, nothing is initialized.
61 // It is necessary to issue Init before use.
64 //_____________________________________________________________________________
65 AliTRDmcmSim::~AliTRDmcmSim()
68 // AliTRDmcmSim destructor
71 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
84 //_____________________________________________________________________________
85 void AliTRDmcmSim::Init( Int_t cha_id, Int_t rob_pos, Int_t mcm_pos )
87 // Initialize the class with new geometry information
88 // fADC array will be reused with filled by zero
90 fFeeParam = AliTRDfeeParam::Instance();
91 fGeo = new AliTRDgeometry();
93 fSector = fGeo->GetSector( fChaId );
94 fStack = fGeo->GetChamber( fChaId );
95 fLayer = fGeo->GetPlane( fChaId );
98 fNADC = fFeeParam->GetNadcMcm();
99 fNTimeBin = fFeeParam->GetNtimebin();
100 fRow = fFeeParam->GetPadRowFromMCM( fRobPos, fMcmPos );
101 fColOfADCbeg = fFeeParam->GetPadColFromADC( fRobPos, fMcmPos, 0 );
102 fColOfADCend = fFeeParam->GetPadColFromADC( fRobPos, fMcmPos, fNADC-1 );
104 // Allocate ADC data memory if not yet done
105 if( fADCR == NULL ) {
106 fADCR = new Int_t *[fNADC];
107 fADCF = new Int_t *[fNADC];
108 fZSM = new Int_t *[fNADC];
109 fZSM1Dim = new Int_t [fNADC];
110 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
111 fADCR[iadc] = new Int_t[fNTimeBin];
112 fADCF[iadc] = new Int_t[fNTimeBin];
113 fZSM [iadc] = new Int_t[fNTimeBin];
117 // Initialize ADC data
118 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
119 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
122 fZSM [iadc][it] = 1; // Default unread = 1
124 fZSM1Dim[iadc] = 1; // Default unread = 1
127 fInitialized = kTRUE;
130 //_____________________________________________________________________________
131 void AliTRDmcmSim::SetData( Int_t iadc, Int_t *adc )
133 // Store ADC data into array of raw data
135 if( ! fInitialized ) {
136 //Log (Form ("Error: AliTRDmcmSim is not initialized but setData is called."));
140 if( iadc < 0 || iadc >= fNADC ) {
141 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
145 for( int it = 0 ; it < fNTimeBin ; it++ ) {
146 fADCR[iadc][it] = (Int_t)(adc[it]);
150 //_____________________________________________________________________________
151 void AliTRDmcmSim::SetData( Int_t iadc, Int_t it, Int_t adc )
153 // Store ADC data into array of raw data
155 if( ! fInitialized ) {
156 //Log (Form ("Error: AliTRDmcmSim is not initialized but setData is called."));
160 if( iadc < 0 || iadc >= fNADC ) {
161 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
165 fADCR[iadc][it] = adc;
168 //_____________________________________________________________________________
169 void AliTRDmcmSim::SetDataPedestal( Int_t iadc )
171 // Store ADC data into array of raw data
173 if( ! fInitialized ) {
174 //Log (Form ("Error: AliTRDmcmSim is not initialized but setData is called."));
178 if( iadc < 0 || iadc >= fNADC ) {
179 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
183 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
184 fADCR[iadc][it] = fFeeParam->GetADCpedestal();
188 //_____________________________________________________________________________
189 Int_t AliTRDmcmSim::GetCol( Int_t iadc )
191 // Return column id of the pad for the given ADC channel
193 return (fColOfADCbeg - iadc);
199 //_____________________________________________________________________________
200 Int_t AliTRDmcmSim::ProduceRawStream( UInt_t *buf, Int_t maxSize )
202 // Produce raw data stream from this MCM and put in buf
203 // Returns number of words filled, or negative value with -1 * number of overflowed words
207 Int_t nw = 0; // Number of written words
208 Int_t of = 0; // Number of overflowed words
209 Int_t rawVer = fFeeParam->GetRAWversion();
212 if( fFeeParam->GetRAWstoreRaw() ) {
218 // Produce MCM header
219 x = ((fRobPos * fFeeParam->GetNmcmRob() + fMcmPos) << 24) | ((iEv % 0x100000) << 4) | 0xC;
230 for( Int_t iAdc = 0 ; iAdc < fNADC ; iAdc++ ) {
231 if( fZSM1Dim[iAdc] == 0 ) { // 0 means not suppressed
243 // Produce ADC data. 3 timebins are packed into one 32 bits word
244 // In this version, different ADC channel will NOT share the same word
246 UInt_t aa=0, a1=0, a2=0, a3=0;
248 for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
249 if( rawVer>= 3 && fZSM1Dim[iAdc] == 1 ) continue; // suppressed
250 aa = !(iAdc & 1) + 2;
251 for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
252 a1 = ((iT ) < fNTimeBin ) ? adc[iAdc][iT ] : 0;
253 a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] : 0;
254 a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] : 0;
256 x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
265 if( of != 0 ) return -of; else return nw;
269 //_____________________________________________________________________________
270 void AliTRDmcmSim::Filter()
272 // Apply digital filter
274 if( ! fInitialized ) {
275 // Log (Form ("Error: AliTRDmcmSim is not initialized but setData is called."));
279 // Initialize filtered data array with raw data
280 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
281 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
282 fADCF[iadc][it] = fADCR[iadc][it];
286 // Then apply fileters one by one to filtered data array
287 if( fFeeParam->isPFon() ) FilterPedestal();
288 if( fFeeParam->isGFon() ) FilterGain();
289 if( fFeeParam->isTFon() ) FilterTail();
292 //_____________________________________________________________________________
293 void AliTRDmcmSim::FilterPedestal()
295 // Apply pedestal filter
297 Int_t ap = fFeeParam->GetADCpedestal(); // ADC instrinsic pedestal
298 Int_t ep = fFeeParam->GetPFeffectPedestal(); // effective pedestal
299 Int_t tc = fFeeParam->GetPFtimeConstant(); // this makes no sense yet
301 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
302 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
303 fADCF[iadc][it] = fADCF[iadc][it] - ap + ep;
308 //_____________________________________________________________________________
309 void AliTRDmcmSim::FilterGain()
311 // Apply gain filter (not implemented)
314 //_____________________________________________________________________________
315 void AliTRDmcmSim::FilterTail()
317 // Apply exponential tail filter (Bogdan's version)
319 Double_t *dtarg = new Double_t[fNTimeBin];
320 Int_t *itarg = new Int_t[fNTimeBin];
321 Int_t nexp = fFeeParam->GetTFnExp();
322 Int_t tftype = fFeeParam->GetTFtype();
326 case 0: // Exponential Filter Analog Bogdan
327 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
328 FilterSimDeConvExpA( fADCF[iCol], dtarg, fNTimeBin, nexp);
329 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
330 fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
335 case 1: // Exponential filter digital Bogdan
336 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
337 FilterSimDeConvExpD( fADCF[iCol], itarg, fNTimeBin, nexp);
338 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
339 fADCF[iCol][iTime] = itarg[iTime];
344 case 2: // Exponential filter Marian special
345 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
346 FilterSimDeConvExpMI( fADCF[iCol], dtarg, fNTimeBin);
347 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
348 fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
354 AliError(Form("Invalid filter type %d ! \n", tftype ));
362 //_____________________________________________________________________________
363 void AliTRDmcmSim::ZSMapping()
365 // Zero Suppression Mapping implemented in TRAP chip
367 // See detail TRAP manual "Data Indication" section:
368 // http://www.kip.uni-heidelberg.de/ti/TRD/doc/trap/TRAP-UserManual.pdf
370 Int_t EBIS = fFeeParam->GetEBsglIndThr(); // TRAP default = 0x4 (Tis=4)
371 Int_t EBIT = fFeeParam->GetEBsumIndThr(); // TRAP default = 0x28 (Tit=40)
372 Int_t EBIL = fFeeParam->GetEBindLUT(); // TRAP default = 0xf0 (lookup table accept (I2,I1,I0)=(111) or (110) or (101) or (100))
373 Int_t EBIN = fFeeParam->GetEBignoreNeighbour(); // TRAP default = 1 (no neighbor sensitivity)
375 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) {
376 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
378 // evaluate three conditions
379 Int_t I0 = ( fADCF[iadc][it] >= fADCF[iadc-1][it] && fADCF[iadc][it] >= fADCF[iadc+1][it] ) ? 0 : 1; // peak center detection
380 Int_t I1 = ( (fADCF[iadc-1][it] + fADCF[iadc][it] + fADCF[iadc+1][it]) > EBIT ) ? 0 : 1; // cluster
381 Int_t I2 = ( fADCF[iadc][it] > EBIS ) ? 0 : 1; // absolute large peak
383 Int_t I = I2 * 4 + I1 * 2 + I0; // Bit position in lookup table
384 Int_t D = (EBIL >> I) & 1; // Looking up (here D=0 means true and D=1 means false according to TRAP manual)
387 if( EBIN == 0 ) { // turn on neighboring ADCs
388 fZSM[iadc-1][it] &= D;
389 fZSM[iadc+1][it] &= D;
394 // do 1 dim projection
395 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
396 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
397 fZSM1Dim[iadc] &= fZSM[iadc+1][it];
402 //_____________________________________________________________________________
403 void AliTRDmcmSim::FilterSimDeConvExpA(Int_t *source, Double_t *target, Int_t n, Int_t nexp)
406 // Exponential filter "analog"
407 // source will not be changed
412 Double_t reminder[2];
416 Double_t coefficients[2];
418 // Initialize (coefficient = alpha, rates = lambda)
419 // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
421 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
422 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
423 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
424 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
426 coefficients[0] = c1;
427 coefficients[1] = c2;
430 rates[0] = TMath::Exp(-dt/(r1));
431 rates[1] = TMath::Exp(-dt/(r2));
433 // Attention: computation order is important
435 for (k = 0; k < nexp; k++) {
439 for (i = 0; i < n; i++) {
441 result = ((Double_t)source[i] - correction); // no rescaling
444 for (k = 0; k < nexp; k++) {
445 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
449 for (k = 0; k < nexp; k++) {
450 correction += reminder[k];
455 //_____________________________________________________________________________
456 void AliTRDmcmSim::FilterSimDeConvExpD(Int_t *source, Int_t *target, Int_t n, Int_t nexp)
459 // Exponential filter "digital"
460 // source will not be changed
476 // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
477 // initialize (coefficient = alpha, rates = lambda)
480 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
481 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
482 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
483 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
485 fLambdaL = (Int_t)((TMath::Exp(-dt/r1) - 0.75) * 2048.0);
486 fLambdaS = (Int_t)((TMath::Exp(-dt/r2) - 0.25) * 2048.0);
487 iLambdaL = fLambdaL & 0x01FF; iLambdaL |= 0x0600; // 9 bit paramter + fixed bits
488 iLambdaS = fLambdaS & 0x01FF; iLambdaS |= 0x0200; // 9 bit paramter + fixed bits
491 fAlphaL = (Int_t) (c1 * 2048.0);
492 iAlphaL = fAlphaL & 0x03FF; // 10 bit paramter
495 fAlphaL = (Int_t) (c1 * 2048.0);
496 fAlphaS = (Int_t) ((c2 - 0.5) * 2048.0);
497 iAlphaL = fAlphaL & 0x03FF; // 10 bit paramter
498 iAlphaS = fAlphaS & 0x03FF; iAlphaS |= 0x0400; // 10 bit paramter + fixed bits
501 Double_t iAl = iAlphaL / 2048.0; // alpha L: correspondence to floating point numbers
502 Double_t iAs = iAlphaS / 2048.0; // alpha S: correspondence to floating point numbers
503 Double_t iLl = iLambdaL / 2048.0; // lambda L: correspondence to floating point numbers
504 Double_t iLs = iLambdaS / 2048.0; // lambda S: correspondence to floating point numbers
512 Int_t iFactor = ((Int_t) fFeeParam->GetPFeffectPedestal() ) << 2;
514 Double_t xi = 1 - (iLl*iAs + iLs*iAl); // Calculation of equilibrium values of the
515 rem1 = (Int_t) ((iFactor/xi) * ((1-iLs)*iLl*iAl)); // Internal registers to prevent switch on effects.
516 rem2 = (Int_t) ((iFactor/xi) * ((1-iLl)*iLs*iAs));
518 // further initialization
519 if ((rem1 + rem2) > 0x0FFF) {
523 correction = (rem1 + rem2) & 0x0FFF;
526 fTailPed = iFactor - correction;
528 for (i = 0; i < n; i++) {
530 result = (source[i] - correction);
537 h1 = (rem1 + ((iAlphaL * result) >> 11));
545 h2 = (rem2 + ((iAlphaS * result) >> 11));
553 rem1 = (iLambdaL * h1 ) >> 11;
554 rem2 = (iLambdaS * h2 ) >> 11;
556 if ((rem1 + rem2) > 0x0FFF) {
560 correction = (rem1 + rem2) & 0x0FFF;
566 //_____________________________________________________________________________
567 void AliTRDmcmSim::FilterSimDeConvExpMI(Int_t *source, Double_t *target, Int_t n)
570 // Exponential filter (M. Ivanov)
571 // source will not be changed
579 for (i = 0; i < n; i++) {
580 sig1[i] = (Double_t)source[i];
584 Float_t lambda0 = (1.0 / fFeeParam->GetTFr2()) * dt;
585 Float_t lambda1 = (1.0 / fFeeParam->GetTFr1()) * dt;
587 FilterSimTailMakerSpline( sig1, sig2, lambda0, n);
588 FilterSimTailCancelationMI( sig2, sig3, 0.7, lambda1, n);
590 for (i = 0; i < n; i++) {
596 //______________________________________________________________________________
597 void AliTRDmcmSim::FilterSimTailMakerSpline(Double_t *ampin, Double_t *ampout, Double_t lambda, Int_t n)
600 // Special filter (M. Ivanov)
604 Double_t l = TMath::Exp(-lambda*0.5);
608 // Initialize in[] and out[] goes 0 ... 2*n+19
609 for (i = 0; i < n*2+20; i++) {
615 in[1] = (ampin[0] + ampin[1]) * 0.5;
617 // Add charge to the end
618 for (i = 0; i < 22; i++) {
619 in[2*(n-1)+i] = ampin[n-1]; // in[] goes 2*n-2, 2*n-1, ... , 2*n+19
622 // Use arithmetic mean
623 for (i = 1; i < n-1; i++) {
624 in[2*i] = ampin[i]; // in[] goes 2, 3, ... , 2*n-4, 2*n-3
625 in[2*i+1] = ((ampin[i]+ampin[i+1]))/2.;
631 for (i = 2*n; i >= 0; i--) {
632 out[i] = in[i] + temp;
633 temp = l*(temp+in[i]);
636 for (i = 0; i < n; i++){
637 //ampout[i] = out[2*i+1]; // org
638 ampout[i] = out[2*i];
643 //______________________________________________________________________________
644 void AliTRDmcmSim::FilterSimTailCancelationMI(Double_t *ampin, Double_t *ampout, Double_t norm, Double_t lambda, Int_t n)
647 // Special filter (M. Ivanov)
652 Double_t l = TMath::Exp(-lambda*0.5);
653 Double_t k = l*(1.0 - norm*lambda*0.5);
657 // Initialize in[] and out[] goes 0 ... 2*n+19
658 for (i = 0; i < n*2+20; i++) {
664 in[1] = (ampin[0]+ampin[1])*0.5;
666 // Add charge to the end
667 for (i =-2; i < 22; i++) {
668 // in[] goes 2*n-4, 2*n-3, ... , 2*n+19
669 in[2*(n-1)+i] = ampin[n-1];
672 for (i = 1; i < n-2; i++) {
673 // in[] goes 2, 3, ... , 2*n-6, 2*n-5
675 in[2*i+1] = (9.0 * (ampin[i]+ampin[i+1]) - (ampin[i-1]+ampin[i+2])) / 16.0;
676 //in[2*i+1] = ((ampin[i]+ampin[i+1]))/2.0;
682 for (i = 1; i <= 2*n; i++) {
683 out[i] = in[i] + (k-l)*temp;
684 temp = in[i] + k *temp;
687 for (i = 0; i < n; i++) {
688 //ampout[i] = out[2*i+1]; // org
689 //ampout[i] = TMath::Max(out[2*i+1],0.0); // org
690 ampout[i] = TMath::Max(out[2*i],0.0);