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 tarcklet part is not yet touched.
78 The default raw version is 2.
86 #include "AliTRDmcmSim.h"
87 #include "AliTRDfeeParam.h"
88 #include "AliTRDSimParam.h"
89 #include "AliTRDgeometry.h"
90 #include "AliTRDcalibDB.h"
92 ClassImp(AliTRDmcmSim)
94 //_____________________________________________________________________________
95 AliTRDmcmSim::AliTRDmcmSim() :TObject()
116 // AliTRDmcmSim default constructor
119 // By default, nothing is initialized.
120 // It is necessary to issue Init before use.
123 //_____________________________________________________________________________
124 AliTRDmcmSim::~AliTRDmcmSim()
127 // AliTRDmcmSim destructor
129 if( fADCR != NULL ) {
130 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
131 delete [] fADCR[iadc];
132 delete [] fADCF[iadc];
133 delete [] fZSM [iadc];
143 //_____________________________________________________________________________
144 void AliTRDmcmSim::Init( Int_t cha_id, Int_t rob_pos, Int_t mcm_pos )
146 // Initialize the class with new geometry information
147 // fADC array will be reused with filled by zero
149 fFeeParam = AliTRDfeeParam::Instance();
150 fSimParam = AliTRDSimParam::Instance();
151 fCal = AliTRDcalibDB::Instance();
152 fGeo = new AliTRDgeometry();
154 fSector = fGeo->GetSector( fChaId );
155 fStack = fGeo->GetChamber( fChaId );
156 fLayer = fGeo->GetPlane( fChaId );
159 fNADC = fFeeParam->GetNadcMcm();
160 fNTimeBin = fCal->GetNumberOfTimeBins();
161 fRow = fFeeParam->GetPadRowFromMCM( fRobPos, fMcmPos );
163 // Allocate ADC data memory if not yet done
164 if( fADCR == NULL ) {
165 fADCR = new Int_t *[fNADC];
166 fADCF = new Int_t *[fNADC];
167 fZSM = new Int_t *[fNADC];
168 fZSM1Dim = new Int_t [fNADC];
169 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
170 fADCR[iadc] = new Int_t[fNTimeBin];
171 fADCF[iadc] = new Int_t[fNTimeBin];
172 fZSM [iadc] = new Int_t[fNTimeBin];
176 // Initialize ADC data
177 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
178 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
181 fZSM [iadc][it] = 1; // Default unread = 1
183 fZSM1Dim[iadc] = 1; // Default unread = 1
186 fInitialized = kTRUE;
189 //_____________________________________________________________________________
190 Bool_t AliTRDmcmSim::CheckInitialized()
192 if( ! fInitialized ) {
193 AliDebug(2, Form ("AliTRDmcmSim is not initialized but function other than Init() is called."));
198 //_____________________________________________________________________________
199 void AliTRDmcmSim::SetData( Int_t iadc, Int_t *adc )
201 // Store ADC data into array of raw data
203 if( !CheckInitialized() ) return;
205 if( iadc < 0 || iadc >= fNADC ) {
206 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
210 for( int it = 0 ; it < fNTimeBin ; it++ ) {
211 fADCR[iadc][it] = (Int_t)(adc[it]);
215 //_____________________________________________________________________________
216 void AliTRDmcmSim::SetData( Int_t iadc, Int_t it, Int_t adc )
218 // Store ADC data into array of raw data
220 if( !CheckInitialized() ) return;
222 if( iadc < 0 || iadc >= fNADC ) {
223 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
227 fADCR[iadc][it] = adc;
230 //_____________________________________________________________________________
231 void AliTRDmcmSim::SetDataPedestal( Int_t iadc )
233 // Store ADC data into array of raw data
235 if( !CheckInitialized() ) return;
237 if( iadc < 0 || iadc >= fNADC ) {
238 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
242 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
243 fADCR[iadc][it] = fSimParam->GetADCbaseline();
247 //_____________________________________________________________________________
248 Int_t AliTRDmcmSim::GetCol( Int_t iadc )
250 // Return column id of the pad for the given ADC channel
251 if( !CheckInitialized() ) return -1;
253 return fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, iadc);
259 //_____________________________________________________________________________
260 Int_t AliTRDmcmSim::ProduceRawStream( UInt_t *buf, Int_t maxSize )
262 // Produce raw data stream from this MCM and put in buf
263 // Returns number of words filled, or negative value with -1 * number of overflowed words
267 Int_t nw = 0; // Number of written words
268 Int_t of = 0; // Number of overflowed words
269 Int_t rawVer = fFeeParam->GetRAWversion();
272 if( !CheckInitialized() ) return 0;
274 if( fFeeParam->GetRAWstoreRaw() ) {
280 // Produce MCM header
281 x = ((fRobPos * fFeeParam->GetNmcmRob() + fMcmPos) << 24) | ((iEv % 0x100000) << 4) | 0xC;
292 for( Int_t iAdc = 0 ; iAdc < fNADC ; iAdc++ ) {
293 if( fZSM1Dim[iAdc] == 0 ) { // 0 means not suppressed
305 // Produce ADC data. 3 timebins are packed into one 32 bits word
306 // In this version, different ADC channel will NOT share the same word
308 UInt_t aa=0, a1=0, a2=0, a3=0;
310 for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
311 if( rawVer>= 3 && fZSM1Dim[iAdc] != 0 ) continue; // suppressed
312 aa = !(iAdc & 1) + 2;
313 for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
314 a1 = ((iT ) < fNTimeBin ) ? adc[iAdc][iT ] : 0;
315 a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] : 0;
316 a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] : 0;
317 x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
327 if( of != 0 ) return -of; else return nw;
331 //_____________________________________________________________________________
332 void AliTRDmcmSim::Filter()
334 // Apply digital filter
336 if( !CheckInitialized() ) return;
338 // Initialize filtered data array with raw data
339 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
340 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
341 fADCF[iadc][it] = fADCR[iadc][it];
345 // Then apply fileters one by one to filtered data array
346 if( fFeeParam->isPFon() ) FilterPedestal();
347 if( fFeeParam->isGFon() ) FilterGain();
348 if( fFeeParam->isTFon() ) FilterTail();
351 //_____________________________________________________________________________
352 void AliTRDmcmSim::FilterPedestal()
354 // Apply pedestal filter
356 Int_t ap = fSimParam->GetADCbaseline(); // ADC instrinsic pedestal
357 Int_t ep = fFeeParam->GetPFeffectPedestal(); // effective pedestal
358 Int_t tc = fFeeParam->GetPFtimeConstant(); // this makes no sense yet
360 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
361 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
362 fADCF[iadc][it] = fADCF[iadc][it] - ap + ep;
367 //_____________________________________________________________________________
368 void AliTRDmcmSim::FilterGain()
370 // Apply gain filter (not implemented)
371 // Later it will be implemented because gain digital filiter will
372 // increase noise level.
375 //_____________________________________________________________________________
376 void AliTRDmcmSim::FilterTail()
378 // Apply exponential tail filter (Bogdan's version)
380 Double_t *dtarg = new Double_t[fNTimeBin];
381 Int_t *itarg = new Int_t[fNTimeBin];
382 Int_t nexp = fFeeParam->GetTFnExp();
383 Int_t tftype = fFeeParam->GetTFtype();
387 case 0: // Exponential Filter Analog Bogdan
388 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
389 FilterSimDeConvExpA( fADCF[iCol], dtarg, fNTimeBin, nexp);
390 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
391 fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
396 case 1: // Exponential filter digital Bogdan
397 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
398 FilterSimDeConvExpD( fADCF[iCol], itarg, fNTimeBin, nexp);
399 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
400 fADCF[iCol][iTime] = itarg[iTime];
405 case 2: // Exponential filter Marian special
406 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
407 FilterSimDeConvExpMI( fADCF[iCol], dtarg, fNTimeBin);
408 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
409 fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
415 AliError(Form("Invalid filter type %d ! \n", tftype ));
423 //_____________________________________________________________________________
424 void AliTRDmcmSim::ZSMapping()
426 // Zero Suppression Mapping implemented in TRAP chip
428 // See detail TRAP manual "Data Indication" section:
429 // http://www.kip.uni-heidelberg.de/ti/TRD/doc/trap/TRAP-UserManual.pdf
431 Int_t EBIS = fFeeParam->GetEBsglIndThr(); // TRAP default = 0x4 (Tis=4)
432 Int_t EBIT = fFeeParam->GetEBsumIndThr(); // TRAP default = 0x28 (Tit=40)
433 Int_t EBIL = fFeeParam->GetEBindLUT(); // TRAP default = 0xf0 (lookup table accept (I2,I1,I0)=(111) or (110) or (101) or (100))
434 Int_t EBIN = fFeeParam->GetEBignoreNeighbour(); // TRAP default = 1 (no neighbor sensitivity)
435 Int_t ep = AliTRDfeeParam::GetPFeffectPedestal();
437 if( !CheckInitialized() ) return;
439 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) {
440 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
442 // Get ADC data currently in filter buffer
443 Int_t Ap = fADCF[iadc-1][it] - ep; // previous
444 Int_t Ac = fADCF[iadc ][it] - ep; // current
445 Int_t An = fADCF[iadc+1][it] - ep; // next
447 // evaluate three conditions
448 Int_t I0 = ( Ac >= Ap && Ac >= An ) ? 0 : 1; // peak center detection
449 Int_t I1 = ( Ap + Ac + An > EBIT ) ? 0 : 1; // cluster
450 Int_t I2 = ( Ac > EBIS ) ? 0 : 1; // absolute large peak
452 Int_t I = I2 * 4 + I1 * 2 + I0; // Bit position in lookup table
453 Int_t D = (EBIL >> I) & 1; // Looking up (here D=0 means true and D=1 means false according to TRAP manual)
456 if( EBIN == 0 ) { // turn on neighboring ADCs
457 fZSM[iadc-1][it] &= D;
458 fZSM[iadc+1][it] &= D;
463 // do 1 dim projection
464 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
465 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
466 fZSM1Dim[iadc] &= fZSM[iadc][it];
471 //_____________________________________________________________________________
472 void AliTRDmcmSim::DumpData( char *f, char *target )
474 // Dump data stored (for debugging).
475 // target should contain one or multiple of the following characters
477 // F for filtered data
478 // Z for zero suppression map
480 // other characters are simply ignored
481 UInt_t tempbuf[1024];
483 if( !CheckInitialized() ) return;
485 std::ofstream of( f, std::ios::out | std::ios::app );
486 of << Form("AliTRDmcmSim::DumpData det=%03d sm=%02d stack=%d layer=%d rob=%d mcm=%02d\n",
487 fChaId, fSector, fStack, fLayer, fRobPos, fMcmPos );
489 for( int t=0 ; target[t] != 0 ; t++ ) {
490 switch( target[t] ) {
493 of << Form("fADCR (raw ADC data)\n");
494 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
495 of << Form(" ADC %02d: ", iadc);
496 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
497 of << Form("% 4d", fADCR[iadc][it]);
504 of << Form("fADCF (filtered ADC data)\n");
505 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
506 of << Form(" ADC %02d: ", iadc);
507 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
508 of << Form("% 4d", fADCF[iadc][it]);
515 of << Form("fZSM and fZSM1Dim (Zero Suppression Map)\n");
516 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
517 of << Form(" ADC %02d: ", iadc);
518 if( fZSM1Dim[iadc] == 0 ) { of << " R " ; } else { of << " . "; } // R:read .:suppressed
519 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
520 if( fZSM[iadc][it] == 0 ) { of << " R"; } else { of << " ."; } // R:read .:suppressed
527 Int_t s = ProduceRawStream( tempbuf, 1024 );
528 of << Form("Stream for Raw Simulation size=%d rawver=%d\n", s, fFeeParam->GetRAWversion());
529 of << Form(" address data\n");
530 for( int i = 0 ; i < s ; i++ ) {
531 of << Form(" %04x %08x\n", i, tempbuf[i]);
537 //_____________________________________________________________________________
538 void AliTRDmcmSim::FilterSimDeConvExpA(Int_t *source, Double_t *target, Int_t n, Int_t nexp)
541 // Exponential filter "analog"
542 // source will not be changed
547 Double_t reminder[2];
551 Double_t coefficients[2];
553 // Initialize (coefficient = alpha, rates = lambda)
554 // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
556 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
557 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
558 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
559 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
561 coefficients[0] = c1;
562 coefficients[1] = c2;
565 rates[0] = TMath::Exp(-dt/(r1));
566 rates[1] = TMath::Exp(-dt/(r2));
568 // Attention: computation order is important
570 for (k = 0; k < nexp; k++) {
574 for (i = 0; i < n; i++) {
576 result = ((Double_t)source[i] - correction); // no rescaling
579 for (k = 0; k < nexp; k++) {
580 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
584 for (k = 0; k < nexp; k++) {
585 correction += reminder[k];
590 //_____________________________________________________________________________
591 void AliTRDmcmSim::FilterSimDeConvExpD(Int_t *source, Int_t *target, Int_t n, Int_t nexp)
594 // Exponential filter "digital"
595 // source will not be changed
605 // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
606 // initialize (coefficient = alpha, rates = lambda)
609 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
610 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
611 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
612 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
614 Int_t fLambdaL = (Int_t)((TMath::Exp(-dt/r1) - 0.75) * 2048.0);
615 Int_t fLambdaS = (Int_t)((TMath::Exp(-dt/r2) - 0.25) * 2048.0);
616 Int_t iLambdaL = fLambdaL & 0x01FF; iLambdaL |= 0x0600; // 9 bit paramter + fixed bits
617 Int_t iLambdaS = fLambdaS & 0x01FF; iLambdaS |= 0x0200; // 9 bit paramter + fixed bits
620 fAlphaL = (Int_t) (c1 * 2048.0);
621 iAlphaL = fAlphaL & 0x03FF; // 10 bit paramter
624 fAlphaL = (Int_t) (c1 * 2048.0);
625 fAlphaS = (Int_t) ((c2 - 0.5) * 2048.0);
626 iAlphaL = fAlphaL & 0x03FF; // 10 bit paramter
627 iAlphaS = fAlphaS & 0x03FF; iAlphaS |= 0x0400; // 10 bit paramter + fixed bits
630 Double_t iAl = iAlphaL / 2048.0; // alpha L: correspondence to floating point numbers
631 Double_t iAs = iAlphaS / 2048.0; // alpha S: correspondence to floating point numbers
632 Double_t iLl = iLambdaL / 2048.0; // lambda L: correspondence to floating point numbers
633 Double_t iLs = iLambdaS / 2048.0; // lambda S: correspondence to floating point numbers
641 Int_t iFactor = ((Int_t) fFeeParam->GetPFeffectPedestal() ) << 2;
643 Double_t xi = 1 - (iLl*iAs + iLs*iAl); // Calculation of equilibrium values of the
644 rem1 = (Int_t) ((iFactor/xi) * ((1-iLs)*iLl*iAl)); // Internal registers to prevent switch on effects.
645 rem2 = (Int_t) ((iFactor/xi) * ((1-iLl)*iLs*iAs));
647 // further initialization
648 if ((rem1 + rem2) > 0x0FFF) {
652 correction = (rem1 + rem2) & 0x0FFF;
655 fTailPed = iFactor - correction;
657 for (i = 0; i < n; i++) {
659 result = (source[i] - correction);
660 if (result < 0) { // Too much undershoot
666 h1 = (rem1 + ((iAlphaL * result) >> 11));
674 h2 = (rem2 + ((iAlphaS * result) >> 11));
682 rem1 = (iLambdaL * h1 ) >> 11;
683 rem2 = (iLambdaS * h2 ) >> 11;
685 if ((rem1 + rem2) > 0x0FFF) {
689 correction = (rem1 + rem2) & 0x0FFF;
695 //_____________________________________________________________________________
696 void AliTRDmcmSim::FilterSimDeConvExpMI(Int_t *source, Double_t *target, Int_t n)
699 // Exponential filter (M. Ivanov)
700 // source will not be changed
708 for (i = 0; i < n; i++) {
709 sig1[i] = (Double_t)source[i];
713 Float_t lambda0 = (1.0 / fFeeParam->GetTFr2()) * dt;
714 Float_t lambda1 = (1.0 / fFeeParam->GetTFr1()) * dt;
716 FilterSimTailMakerSpline( sig1, sig2, lambda0, n);
717 FilterSimTailCancelationMI( sig2, sig3, 0.7, lambda1, n);
719 for (i = 0; i < n; i++) {
725 //______________________________________________________________________________
726 void AliTRDmcmSim::FilterSimTailMakerSpline(Double_t *ampin, Double_t *ampout, Double_t lambda, Int_t n)
729 // Special filter (M. Ivanov)
733 Double_t l = TMath::Exp(-lambda*0.5);
737 // Initialize in[] and out[] goes 0 ... 2*n+19
738 for (i = 0; i < n*2+20; i++) {
744 in[1] = (ampin[0] + ampin[1]) * 0.5;
746 // Add charge to the end
747 for (i = 0; i < 22; i++) {
748 in[2*(n-1)+i] = ampin[n-1]; // in[] goes 2*n-2, 2*n-1, ... , 2*n+19
751 // Use arithmetic mean
752 for (i = 1; i < n-1; i++) {
753 in[2*i] = ampin[i]; // in[] goes 2, 3, ... , 2*n-4, 2*n-3
754 in[2*i+1] = ((ampin[i]+ampin[i+1]))/2.;
760 for (i = 2*n; i >= 0; i--) {
761 out[i] = in[i] + temp;
762 temp = l*(temp+in[i]);
765 for (i = 0; i < n; i++){
766 //ampout[i] = out[2*i+1]; // org
767 ampout[i] = out[2*i];
772 //______________________________________________________________________________
773 void AliTRDmcmSim::FilterSimTailCancelationMI(Double_t *ampin, Double_t *ampout, Double_t norm, Double_t lambda, Int_t n)
776 // Special filter (M. Ivanov)
781 Double_t l = TMath::Exp(-lambda*0.5);
782 Double_t k = l*(1.0 - norm*lambda*0.5);
786 // Initialize in[] and out[] goes 0 ... 2*n+19
787 for (i = 0; i < n*2+20; i++) {
793 in[1] = (ampin[0]+ampin[1])*0.5;
795 // Add charge to the end
796 for (i =-2; i < 22; i++) {
797 // in[] goes 2*n-4, 2*n-3, ... , 2*n+19
798 in[2*(n-1)+i] = ampin[n-1];
801 for (i = 1; i < n-2; i++) {
802 // in[] goes 2, 3, ... , 2*n-6, 2*n-5
804 in[2*i+1] = (9.0 * (ampin[i]+ampin[i+1]) - (ampin[i-1]+ampin[i+2])) / 16.0;
805 //in[2*i+1] = ((ampin[i]+ampin[i+1]))/2.0;
811 for (i = 1; i <= 2*n; i++) {
812 out[i] = in[i] + (k-l)*temp;
813 temp = in[i] + k *temp;
816 for (i = 0; i < n; i++) {
817 //ampout[i] = out[2*i+1]; // org
818 //ampout[i] = TMath::Max(out[2*i+1],0.0); // org
819 ampout[i] = TMath::Max(out[2*i],0.0);