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 //
19 // which simulated the TRAP processing after the AD-conversion //
20 // The relevant parameters (i.e. configuration registers of the TRAP //
21 // configuration are taken from AliTRDtrapConfig. //
23 ///////////////////////////////////////////////////////////////////////////////
25 #include <fstream> // needed for raw data dump
34 #include <TClonesArray.h>
38 #include "AliRunLoader.h"
39 #include "AliLoader.h"
40 #include "AliTRDdigit.h"
42 #include "AliTRDfeeParam.h"
43 #include "AliTRDtrapConfig.h"
44 #include "AliTRDSimParam.h"
45 #include "AliTRDgeometry.h"
46 #include "AliTRDcalibDB.h"
47 #include "AliTRDdigitsManager.h"
48 #include "AliTRDarrayADC.h"
49 #include "AliTRDpadPlane.h"
50 #include "AliTRDtrackletMCM.h"
51 #include "AliTRDmcmSim.h"
53 ClassImp(AliTRDmcmSim)
55 //_____________________________________________________________________________
56 AliTRDmcmSim::AliTRDmcmSim() : TObject()
85 // AliTRDmcmSim default constructor
86 // By default, nothing is initialized.
87 // It is necessary to issue Init before use.
90 AliTRDmcmSim::~AliTRDmcmSim()
93 // AliTRDmcmSim destructor
97 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
98 delete [] fADCR[iadc];
99 delete [] fADCF[iadc];
100 delete [] fZSM [iadc];
109 delete [] fGainCounterA;
110 delete [] fGainCounterB;
111 delete [] fTailAmplLong;
112 delete [] fTailAmplShort;
115 fTrackletArray->Delete();
116 delete fTrackletArray;
121 void AliTRDmcmSim::Init( Int_t det, Int_t robPos, Int_t mcmPos, Bool_t /* newEvent */ )
124 // Initialize the class with new geometry information
125 // fADC array will be reused with filled by zero
129 fFeeParam = AliTRDfeeParam::Instance();
130 fTrapConfig = AliTRDtrapConfig::Instance();
131 fSimParam = AliTRDSimParam::Instance();
132 fCal = AliTRDcalibDB::Instance();
133 fGeo = new AliTRDgeometry();
139 fNADC = fFeeParam->GetNadcMcm();
140 fNTimeBin = fCal->GetNumberOfTimeBins();
141 fRow = fFeeParam->GetPadRowFromMCM( fRobPos, fMcmPos );
142 fMaxTracklets = fFeeParam->GetMaxNrOfTracklets();
145 fADCR = new Int_t *[fNADC];
146 fADCF = new Int_t *[fNADC];
147 fZSM = new Int_t *[fNADC];
148 fZSM1Dim = new Int_t [fNADC];
149 fGainCounterA = new UInt_t[fNADC];
150 fGainCounterB = new UInt_t[fNADC];
151 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
152 fADCR[iadc] = new Int_t[fNTimeBin];
153 fADCF[iadc] = new Int_t[fNTimeBin];
154 fZSM [iadc] = new Int_t[fNTimeBin];
158 fPedAcc = new UInt_t[fNADC]; // accumulator for pedestal filter
159 fTailAmplLong = new UShort_t[fNADC];
160 fTailAmplShort = new UShort_t[fNADC];
162 // tracklet calculation
163 fFitReg = new FitReg_t[fNADC];
164 fTrackletArray = new TClonesArray("AliTRDtrackletMCM", fMaxTracklets);
166 fMCMT = new UInt_t[fMaxTracklets];
169 fInitialized = kTRUE;
174 void AliTRDmcmSim::Reset()
176 // Resets the data values and internal filter registers
177 // by re-initialising them
179 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
180 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
183 fZSM [iadc][it] = 1; // Default unread = 1
185 fZSM1Dim[iadc] = 1; // Default unread = 1
186 fGainCounterA[iadc] = 0;
187 fGainCounterB[iadc] = 0;
190 for(Int_t i = 0; i < fMaxTracklets; i++) {
194 FilterPedestalInit();
196 FilterTailInit(fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP)); //??? not really correct if gain filter is active
199 Bool_t AliTRDmcmSim::LoadMCM(AliRunLoader *runloader, Int_t det, Int_t rob, Int_t mcm)
201 // loads the ADC data as obtained from the digitsManager for the specified MCM
203 if (!CheckInitialized())
207 AliError("No Runloader given");
211 AliLoader *trdLoader = runloader->GetLoader("TRDLoader");
213 AliError("Could not get TRDLoader");
217 trdLoader->LoadDigits();
218 AliTRDdigitsManager *digMgr = new AliTRDdigitsManager();
219 digMgr->SetSDigits(0);
220 digMgr->CreateArrays();
221 digMgr->ReadDigits(trdLoader->TreeD());
222 AliTRDarrayADC *digits = (AliTRDarrayADC*) digMgr->GetDigits(det);
223 if (!digits->HasData())
227 Int_t padrow = fFeeParam->GetPadRowFromMCM(rob, mcm);
229 for (Int_t ch = 0; ch < fNADC; ch++) {
230 for (Int_t tb = 0; tb < fNTimeBin; tb++) {
231 padcol = fFeeParam->GetPadColFromADC(rob, mcm, ch);
237 if (digits->GetData(padrow,padcol, tb) < 0) {
242 fADCR[ch][tb] = digits->GetData(padrow, padcol, tb) << fgkAddDigits;
243 fADCF[ch][tb] = digits->GetData(padrow, padcol, tb) << fgkAddDigits;
248 digMgr->RemoveDigits(det);
254 void AliTRDmcmSim::NoiseTest(Int_t nsamples, Int_t mean, Int_t sigma, Int_t inputGain, Int_t inputTail)
256 // This function can be used to test the filters.
257 // It feeds nsamples of ADC values with a gaussian distribution specified by mean and sigma.
258 // The filter chain implemented here consists of:
259 // Pedestal -> Gain -> Tail
260 // With inputGain and inputTail the input to the gain and tail filter, respectively,
261 // can be chosen where
263 // 1: pedestal output
265 // The input has to be chosen from a stage before.
266 // The filter behaviour is controlled by the TRAP parameters from AliTRDtrapConfig in the
267 // same way as in normal simulation.
268 // The functions produces four histograms with the values at the different stages.
270 TH1F *h = new TH1F("noise", "Gaussian Noise;sample;ADC count",
271 nsamples, 0, nsamples);
272 TH1F *hfp = new TH1F("pedf", "Noise #rightarrow Pedestal filter;sample;ADC count", nsamples, 0, nsamples);
273 TH1F *hfg = new TH1F("pedg", "Pedestal #rightarrow Gain;sample;ADC count", nsamples, 0, nsamples);
274 TH1F *hft = new TH1F("pedt", "Gain #rightarrow Tail;sample;ADC count", nsamples, 0, nsamples);
276 hfp->SetStats(kFALSE);
277 hfg->SetStats(kFALSE);
278 hft->SetStats(kFALSE);
280 Int_t value; // ADC count with noise (10 bit)
281 Int_t valuep; // pedestal filter output (12 bit)
282 Int_t valueg; // gain filter output (12 bit)
283 Int_t valuet; // tail filter value (12 bit)
285 for (Int_t i = 0; i < nsamples; i++) {
286 value = (Int_t) gRandom->Gaus(mean, sigma); // generate noise with gaussian distribution
287 h->SetBinContent(i, value);
289 valuep = FilterPedestalNextSample(1, 0, ((Int_t) value) << 2);
292 valueg = FilterGainNextSample(1, ((Int_t) value) << 2);
294 valueg = FilterGainNextSample(1, valuep);
297 valuet = FilterTailNextSample(1, ((Int_t) value) << 2);
298 else if (inputTail == 1)
299 valuet = FilterTailNextSample(1, valuep);
301 valuet = FilterTailNextSample(1, valueg);
303 hfp->SetBinContent(i, valuep >> 2);
304 hfg->SetBinContent(i, valueg >> 2);
305 hft->SetBinContent(i, valuet >> 2);
308 TCanvas *c = new TCanvas;
320 Bool_t AliTRDmcmSim::CheckInitialized()
323 // Check whether object is initialized
326 if( ! fInitialized ) {
327 AliDebug(2, Form ("AliTRDmcmSim is not initialized but function other than Init() is called."));
332 void AliTRDmcmSim::Print(Option_t* option) const
334 // Prints the data stored and/or calculated for this MCM.
335 // The output is controlled by option which can be a sequence of any of
336 // the following characters:
337 // R - prints raw ADC data
338 // F - prints filtered data
339 // H - prints detected hits
340 // T - prints found tracklets
341 // The later stages are only useful when the corresponding calculations
342 // have been performed.
344 printf("MCM %i on ROB %i in detector %i\n", fMcmPos, fRobPos, fDetector);
346 TString opt = option;
347 if (opt.Contains("U")) {
348 printf("Raw ADC data (10 bit):\n");
349 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
350 for (Int_t iChannel = 0; iChannel < fNADC; iChannel++) {
351 printf("%5i", fADCR[iChannel][iTimeBin] >> fgkAddDigits);
357 if (opt.Contains("F")) {
358 printf("Filtered data (12 bit):\n");
359 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
360 for (Int_t iChannel = 0; iChannel < fNADC; iChannel++) {
361 printf("%5i", fADCF[iChannel][iTimeBin]);
367 if (opt.Contains("H")) {
368 printf("Found %i hits:\n", fNHits);
369 for (Int_t iHit = 0; iHit < fNHits; iHit++) {
370 printf("Hit %3i in timebin %2i, ADC %2i has charge %3i and position %3i\n",
371 iHit, fHits[iHit].timebin, fHits[iHit].channel, fHits[iHit].qtot, fHits[iHit].ypos);
375 if (opt.Contains("T")) {
376 printf("Tracklets:\n");
377 for (Int_t iTrkl = 0; iTrkl < fTrackletArray->GetEntriesFast(); iTrkl++) {
378 printf("tracklet %i: 0x%08x\n", iTrkl, ((AliTRDtrackletMCM*) (*fTrackletArray)[iTrkl])->GetTrackletWord());
383 void AliTRDmcmSim::Draw(Option_t* option)
385 // Plots the data stored in a 2-dim. timebin vs. ADC channel plot.
386 // The option selects what data is plotted and can be a sequence of
387 // the following characters:
388 // R - plot raw data (default)
389 // F - plot filtered data (meaningless if R is specified)
390 // In addition to the ADC values:
392 // T - plot tracklets
394 TString opt = option;
396 TH2F *hist = new TH2F("mcmdata", Form("Data of MCM %i on ROB %i in detector %i", \
397 fMcmPos, fRobPos, fDetector), \
398 fNADC, -0.5, fNADC-.5, fNTimeBin, -.5, fNTimeBin-.5);
399 hist->GetXaxis()->SetTitle("ADC Channel");
400 hist->GetYaxis()->SetTitle("Timebin");
401 hist->SetStats(kFALSE);
403 if (opt.Contains("R")) {
404 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
405 for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
406 hist->SetBinContent(iAdc+1, iTimeBin+1, fADCR[iAdc][iTimeBin] >> fgkAddDigits);
411 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
412 for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
413 hist->SetBinContent(iAdc+1, iTimeBin+1, fADCF[iAdc][iTimeBin] >> fgkAddDigits);
419 if (opt.Contains("H")) {
420 TGraph *grHits = new TGraph();
421 for (Int_t iHit = 0; iHit < fNHits; iHit++) {
422 grHits->SetPoint(iHit,
423 fHits[iHit].channel + 1 + fHits[iHit].ypos/256.,
424 fHits[iHit].timebin);
429 if (opt.Contains("T")) {
430 TLine *trklLines = new TLine[4];
431 for (Int_t iTrkl = 0; iTrkl < 4; iTrkl++) {
432 if (fMCMT[iTrkl] == 0x10001000)
434 AliTRDpadPlane *pp = fGeo->GetPadPlane(fDetector);
435 AliTRDtrackletMCM *trkl = (AliTRDtrackletMCM*) (*fTrackletArray)[iTrkl];
436 Float_t offset = pp->GetColPos(fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, 19)) + 19 * pp->GetWidthIPad();
437 trklLines[iTrkl].SetX1((offset - trkl->GetY()) / pp->GetWidthIPad());
438 trklLines[iTrkl].SetY1(0);
439 trklLines[iTrkl].SetX2((offset - (trkl->GetY() + ((Float_t) trkl->GetdY())*140e-4)) / pp->GetWidthIPad());
440 trklLines[iTrkl].SetY2(fNTimeBin - 1);
441 trklLines[iTrkl].SetLineColor(2);
442 trklLines[iTrkl].SetLineWidth(2);
443 printf("Tracklet %i: y = %f, dy = %f, offset = %f\n", iTrkl, trkl->GetY(), (trkl->GetdY() * 140e-4), offset);
444 trklLines[iTrkl].Draw();
449 void AliTRDmcmSim::SetData( Int_t iadc, Int_t *adc )
452 // Store ADC data into array of raw data
455 if( !CheckInitialized() ) return;
457 if( iadc < 0 || iadc >= fNADC ) {
458 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
462 for( int it = 0 ; it < fNTimeBin ; it++ ) {
463 fADCR[iadc][it] = (Int_t) (adc[it]) << fgkAddDigits;
464 fADCF[iadc][it] = (Int_t) (adc[it]) << fgkAddDigits;
468 void AliTRDmcmSim::SetData( Int_t iadc, Int_t it, Int_t adc )
471 // Store ADC data into array of raw data
474 if( !CheckInitialized() ) return;
476 if( iadc < 0 || iadc >= fNADC ) {
477 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
481 fADCR[iadc][it] = adc << fgkAddDigits;
482 fADCF[iadc][it] = adc << fgkAddDigits;
485 void AliTRDmcmSim::SetData(AliTRDarrayADC *adcArray)
488 AliError("Called uninitialized! Aborting!");
493 Int_t lastAdc = fNADC-1;
495 if (GetCol(firstAdc) > 143) {
496 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
497 fADCR[firstAdc][iTimeBin] = fSimParam->GetADCbaseline() << fgkAddDigits;
498 fADCF[firstAdc][iTimeBin] = fSimParam->GetADCbaseline() << fgkAddDigits;
503 if (GetCol(lastAdc) < 0) {
504 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
505 fADCR[lastAdc][iTimeBin] = fSimParam->GetADCbaseline() << fgkAddDigits;
506 fADCF[lastAdc][iTimeBin] = fSimParam->GetADCbaseline() << fgkAddDigits;
511 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
512 for (Int_t iAdc = firstAdc; iAdc < lastAdc; iAdc++) {
513 Int_t value = adcArray->GetData(GetRow(), GetCol(iAdc), iTimeBin);
515 fADCR[iAdc][iTimeBin] = 0;
516 fADCF[iAdc][iTimeBin] = 0;
519 fADCR[iAdc][iTimeBin] = adcArray->GetData(GetRow(), GetCol(iAdc), iTimeBin) << fgkAddDigits;
520 fADCF[iAdc][iTimeBin] = adcArray->GetData(GetRow(), GetCol(iAdc), iTimeBin) << fgkAddDigits;
526 void AliTRDmcmSim::SetDataPedestal( Int_t iadc )
529 // Store ADC data into array of raw data
532 if( !CheckInitialized() ) return;
534 if( iadc < 0 || iadc >= fNADC ) {
535 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
539 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
540 fADCR[iadc][it] = fSimParam->GetADCbaseline() << fgkAddDigits;
541 fADCF[iadc][it] = fSimParam->GetADCbaseline() << fgkAddDigits;
545 Int_t AliTRDmcmSim::GetCol( Int_t iadc )
548 // Return column id of the pad for the given ADC channel
551 if( !CheckInitialized() ) return -1;
553 return fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, iadc);
556 Int_t AliTRDmcmSim::ProduceRawStream( UInt_t *buf, Int_t maxSize, UInt_t iEv)
559 // Produce raw data stream from this MCM and put in buf
560 // Returns number of words filled, or negative value
561 // with -1 * number of overflowed words
565 Int_t nw = 0; // Number of written words
566 Int_t of = 0; // Number of overflowed words
567 Int_t rawVer = fFeeParam->GetRAWversion();
569 Int_t nActiveADC = 0; // number of activated ADC bits in a word
571 if( !CheckInitialized() ) return 0;
573 if( fFeeParam->GetRAWstoreRaw() ) {
579 // Produce MCM header
580 x = (1<<31) | (fRobPos << 28) | (fMcmPos << 24) | ((iEv % 0x100000) << 4) | 0xC;
584 //printf("\nMCM header: %X ",x);
590 // Produce ADC mask : nncc cccm mmmm mmmm mmmm mmmm mmmm 1100
591 // n : unused , c : ADC count, m : selected ADCs
594 for( Int_t iAdc = 0 ; iAdc < fNADC ; iAdc++ ) {
595 if( fZSM1Dim[iAdc] == 0 ) { // 0 means not suppressed
596 x = x | (1 << (iAdc+4) ); // last 4 digit reserved for 1100=0xc
597 nActiveADC++; // number of 1 in mmm....m
600 x = x | (1 << 30) | ( ( 0x3FFFFFFC ) & (~(nActiveADC) << 25) ) | 0xC; // nn = 01, ccccc are inverted, 0xc=1100
601 //printf("nActiveADC=%d=%08X, inverted=%X ",nActiveADC,nActiveADC,x );
605 //printf("ADC mask: %X nMask=%d ADC data: ",x,nActiveADC);
612 // Produce ADC data. 3 timebins are packed into one 32 bits word
613 // In this version, different ADC channel will NOT share the same word
615 UInt_t aa=0, a1=0, a2=0, a3=0;
617 for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
618 if( rawVer>= 3 && fZSM1Dim[iAdc] != 0 ) continue; // Zero Suppression, 0 means not suppressed
619 aa = !(iAdc & 1) + 2;
620 for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
621 a1 = ((iT ) < fNTimeBin ) ? adc[iAdc][iT ] >> fgkAddDigits : 0;
622 a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] >> fgkAddDigits : 0;
623 a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] >> fgkAddDigits : 0;
624 x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
635 if( of != 0 ) return -of; else return nw;
638 Int_t AliTRDmcmSim::ProduceTrackletStream( UInt_t *buf, Int_t maxSize )
641 // Produce tracklet data stream from this MCM and put in buf
642 // Returns number of words filled, or negative value
643 // with -1 * number of overflowed words
647 Int_t nw = 0; // Number of written words
648 Int_t of = 0; // Number of overflowed words
650 if( !CheckInitialized() ) return 0;
652 // Produce tracklet data. A maximum of four 32 Bit words will be written per MCM
653 // fMCMT is filled continuously until no more tracklet words available
656 while ( (wd < fMaxTracklets) && (fMCMT[wd] > 0) ){
667 if( of != 0 ) return -of; else return nw;
670 void AliTRDmcmSim::Filter()
673 // Filter the raw ADC values. The active filter stages and their
674 // parameters are taken from AliTRDtrapConfig.
675 // The raw data is stored separate from the filtered data. Thus,
676 // it is possible to run the filters on a set of raw values
677 // sequentially for parameter tuning.
680 if( !CheckInitialized() ) {
681 AliError("got called before initialization! Nothing done!");
685 // Apply filters sequentially. Bypass is handled by filters
686 // since counters and internal registers may be updated even
687 // if the filter is bypassed.
688 // The first filter takes the data from fADCR and
691 // Non-linearity filter not implemented.
695 // Crosstalk filter not implemented.
698 void AliTRDmcmSim::FilterPedestalInit()
700 // Initializes the pedestal filter assuming that the input has
701 // been constant for a long time (compared to the time constant).
703 // UShort_t fpnp = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP); // 0..511 -> 0..127.75, pedestal at the output
704 UShort_t fptc = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPTC); // 0..3, 0 - fastest, 3 - slowest
705 UShort_t shifts[4] = {11, 14, 17, 21}; //??? where to take shifts from?
707 for (Int_t iAdc = 0; iAdc < fNADC; iAdc++)
708 fPedAcc[iAdc] = (fSimParam->GetADCbaseline() << 2) * (1<<shifts[fptc]);
711 UShort_t AliTRDmcmSim::FilterPedestalNextSample(Int_t adc, Int_t timebin, UShort_t value)
713 // Returns the output of the pedestal filter given the input value.
714 // The output depends on the internal registers and, thus, the
715 // history of the filter.
717 UShort_t fpnp = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPNP); // 0..511 -> 0..127.75, pedestal at the output
718 UShort_t fptc = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPTC); // 0..3, 0 - fastest, 3 - slowest
719 UShort_t fpby = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFPBY); // 0..1 the bypass, active low
720 UShort_t shifts[4] = {11, 14, 17, 21}; //??? where to come from
722 UShort_t accumulatorShifted;
726 inpAdd = value + fpnp;
728 if (fpby == 0) //??? before or after update of accumulator
731 accumulatorShifted = (fPedAcc[adc] >> shifts[fptc]) & 0x3FF; // 10 bits
732 if (timebin == 0) // the accumulator is disabled in the drift time
734 correction = (value & 0x3FF) - accumulatorShifted;
735 fPedAcc[adc] = (fPedAcc[adc] + correction) & 0x7FFFFFFF; // 31 bits
738 if (inpAdd <= accumulatorShifted)
742 inpAdd = inpAdd - accumulatorShifted;
750 void AliTRDmcmSim::FilterPedestal()
753 // Apply pedestal filter
755 // As the first filter in the chain it reads data from fADCR
756 // and outputs to fADCF.
757 // It has only an effect if previous samples have been fed to
758 // find the pedestal. Currently, the simulation assumes that
759 // the input has been stable for a sufficiently long time.
761 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
762 for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
763 fADCF[iAdc][iTimeBin] = FilterPedestalNextSample(iAdc, iTimeBin, fADCR[iAdc][iTimeBin]);
768 void AliTRDmcmSim::FilterGainInit()
770 // Initializes the gain filter. In this case, only threshold
771 // counters are reset.
773 for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
774 // these are counters which in hardware continue
775 // until maximum or reset
776 fGainCounterA[iAdc] = 0;
777 fGainCounterB[iAdc] = 0;
781 UShort_t AliTRDmcmSim::FilterGainNextSample(Int_t adc, UShort_t value)
783 // Apply the gain filter to the given value.
784 // BEGIN_LATEX O_{i}(t) = #gamma_{i} * I_{i}(t) + a_{i} END_LATEX
785 // The output depends on the internal registers and, thus, the
786 // history of the filter.
788 UShort_t fgby = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFGBY); // bypass, active low
789 UShort_t fgf = fTrapConfig->GetTrapReg(AliTRDtrapConfig::TrapReg_t(AliTRDtrapConfig::kFGF0 + adc)); // 0x700 + (0 & 0x1ff);
790 UShort_t fga = fTrapConfig->GetTrapReg(AliTRDtrapConfig::TrapReg_t(AliTRDtrapConfig::kFGA0 + adc)); // 40;
791 UShort_t fgta = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFGTA); // 20;
792 UShort_t fgtb = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFGTB); // 2060;
797 tmp = (value * fgf) >> 11;
798 if (tmp > 0xFFF) tmp = 0xFFF;
801 value = AddUintClipping(tmp, fga, 12);
803 // Update threshold counters
804 // not really useful as they are cleared with every new event
805 if ((fGainCounterA[adc] == 0x3FFFFFF) || (fGainCounterB[adc] == 0x3FFFFFF))
808 fGainCounterB[adc]++;
809 else if (value >= fgta)
810 fGainCounterA[adc]++;
816 void AliTRDmcmSim::FilterGain()
818 // Read data from fADCF and apply gain filter.
820 for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
821 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
822 fADCF[iAdc][iTimeBin] = FilterGainNextSample(iAdc, fADCF[iAdc][iTimeBin]);
827 void AliTRDmcmSim::FilterTailInit(Int_t baseline)
829 // Initializes the tail filter assuming that the input has
830 // been at the baseline value (configured by FTFP) for a
831 // sufficiently long time.
833 // exponents and weight calculated from configuration
834 UShort_t alphaLong = 0x3ff & fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTAL); // the weight of the long component
835 UShort_t lambdaLong = (1 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLL) & 0x1FF); // the multiplier
836 UShort_t lambdaShort = (0 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLS) & 0x1FF); // the multiplier
838 Float_t lambdaL = lambdaLong * 1.0 / (1 << 11);
839 Float_t lambdaS = lambdaShort * 1.0 / (1 << 11);
840 Float_t alphaL = alphaLong * 1.0 / (1 << 11);
842 qup = (1 - lambdaL) * (1 - lambdaS);
843 qdn = 1 - lambdaS * alphaL - lambdaL * (1 - alphaL);
844 Float_t kdc = qup/qdn;
850 aout = baseline - (UShort_t) kt;
851 ql = lambdaL * (1 - lambdaS) * alphaL;
852 qs = lambdaS * (1 - lambdaL) * (1 - alphaL);
854 for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
855 fTailAmplLong[iAdc] = (UShort_t) (aout * ql / (ql + qs));
856 fTailAmplShort[iAdc] = (UShort_t) (aout * qs / (ql + qs));
860 UShort_t AliTRDmcmSim::FilterTailNextSample(Int_t adc, UShort_t value)
862 // Returns the output of the tail filter for the given input value.
863 // The output depends on the internal registers and, thus, the
864 // history of the filter.
866 // exponents and weight calculated from configuration
867 UShort_t alphaLong = 0x3ff & fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTAL); // the weight of the long component
868 UShort_t lambdaLong = (1 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLL) & 0x1FF); // the multiplier
869 UShort_t lambdaShort = (0 << 10) | (1 << 9) | (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTLS) & 0x1FF); // the multiplier
871 Float_t lambdaL = lambdaLong * 1.0 / (1 << 11);
872 Float_t lambdaS = lambdaShort * 1.0 / (1 << 11);
873 Float_t alphaL = alphaLong * 1.0 / (1 << 11);
875 qup = (1 - lambdaL) * (1 - lambdaS);
876 qdn = 1 - lambdaS * alphaL - lambdaL * (1 - alphaL);
877 // Float_t kdc = qup/qdn;
884 UShort_t inp_volt = value & 0xFFF; // 12 bits
886 if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kFTBY) == 0) // bypass mode, active low
890 // add the present generator outputs
891 aQ = AddUintClipping(fTailAmplLong[adc], fTailAmplShort[adc], 12);
893 // calculate the difference between the input the generated signal
895 aDiff = inp_volt - aQ;
899 // the inputs to the two generators, weighted
900 alInpv = (aDiff * alphaLong) >> 11;
902 // the new values of the registers, used next time
904 tmp = AddUintClipping(fTailAmplLong[adc], alInpv, 12);
905 tmp = (tmp * lambdaLong) >> 11;
906 fTailAmplLong[adc] = tmp & 0xFFF;
908 tmp = AddUintClipping(fTailAmplShort[adc], aDiff - alInpv, 12);
909 tmp = (tmp * lambdaShort) >> 11;
910 fTailAmplShort[adc] = tmp & 0xFFF;
912 // the output of the filter
917 void AliTRDmcmSim::FilterTail()
921 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
922 for (Int_t iAdc = 0; iAdc < fNADC; iAdc++) {
923 fADCF[iAdc][iTimeBin] = FilterTailNextSample(iAdc, fADCF[iAdc][iTimeBin]);
928 void AliTRDmcmSim::ZSMapping()
931 // Zero Suppression Mapping implemented in TRAP chip
933 // See detail TRAP manual "Data Indication" section:
934 // http://www.kip.uni-heidelberg.de/ti/TRD/doc/trap/TRAP-UserManual.pdf
937 //??? values should come from TRAPconfig
938 Int_t eBIS = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIS); // TRAP default = 0x4 (Tis=4)
939 Int_t eBIT = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIT); // TRAP default = 0x28 (Tit=40)
940 Int_t eBIL = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIL); // TRAP default = 0xf0
941 // (lookup table accept (I2,I1,I0)=(111)
942 // or (110) or (101) or (100))
943 Int_t eBIN = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBIN); // TRAP default = 1 (no neighbor sensitivity)
944 Int_t ep = AliTRDfeeParam::GetPFeffectPedestal();
948 if( !CheckInitialized() ) {
949 AliError("got called uninitialized! Aborting!");
953 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
954 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) {
956 // Get ADC data currently in filter buffer
957 Int_t ap = adc[iadc-1][it] - ep; // previous
958 Int_t ac = adc[iadc ][it] - ep; // current
959 Int_t an = adc[iadc+1][it] - ep; // next
961 // evaluate three conditions
962 Int_t i0 = ( ac >= ap && ac >= an ) ? 0 : 1; // peak center detection
963 Int_t i1 = ( ap + ac + an > eBIT ) ? 0 : 1; // cluster
964 Int_t i2 = ( ac > eBIS ) ? 0 : 1; // absolute large peak
966 Int_t i = i2 * 4 + i1 * 2 + i0; // Bit position in lookup table
967 Int_t d = (eBIL >> i) & 1; // Looking up (here d=0 means true
968 // and d=1 means false according to TRAP manual)
971 if( eBIN == 0 ) { // turn on neighboring ADCs
972 fZSM[iadc-1][it] &= d;
973 fZSM[iadc+1][it] &= d;
978 // do 1 dim projection
979 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
980 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
981 fZSM1Dim[iadc] &= fZSM[iadc][it];
987 void AliTRDmcmSim::DumpData( char *f, char *target )
990 // Dump data stored (for debugging).
991 // target should contain one or multiple of the following characters
993 // F for filtered data
994 // Z for zero suppression map
996 // other characters are simply ignored
999 UInt_t tempbuf[1024];
1001 if( !CheckInitialized() ) return;
1003 std::ofstream of( f, std::ios::out | std::ios::app );
1004 of << Form("AliTRDmcmSim::DumpData det=%03d sm=%02d stack=%d layer=%d rob=%d mcm=%02d\n",
1005 fDetector, fGeo->GetSector(fDetector), fGeo->GetStack(fDetector),
1006 fGeo->GetSector(fDetector), fRobPos, fMcmPos );
1008 for( int t=0 ; target[t] != 0 ; t++ ) {
1009 switch( target[t] ) {
1012 of << Form("fADCR (raw ADC data)\n");
1013 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
1014 of << Form(" ADC %02d: ", iadc);
1015 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
1016 of << Form("% 4d", fADCR[iadc][it]);
1023 of << Form("fADCF (filtered ADC data)\n");
1024 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
1025 of << Form(" ADC %02d: ", iadc);
1026 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
1027 of << Form("% 4d", fADCF[iadc][it]);
1034 of << Form("fZSM and fZSM1Dim (Zero Suppression Map)\n");
1035 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
1036 of << Form(" ADC %02d: ", iadc);
1037 if( fZSM1Dim[iadc] == 0 ) { of << " R " ; } else { of << " . "; } // R:read .:suppressed
1038 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
1039 if( fZSM[iadc][it] == 0 ) { of << " R"; } else { of << " ."; } // R:read .:suppressed
1046 Int_t s = ProduceRawStream( tempbuf, 1024 );
1047 of << Form("Stream for Raw Simulation size=%d rawver=%d\n", s, fFeeParam->GetRAWversion());
1048 of << Form(" address data\n");
1049 for( int i = 0 ; i < s ; i++ ) {
1050 of << Form(" %04x %08x\n", i, tempbuf[i]);
1056 void AliTRDmcmSim::AddHitToFitreg(Int_t adc, UShort_t timebin, UShort_t qtot, Short_t ypos, Int_t label)
1058 // Add the given hit to the fit register which is lateron used for
1059 // the tracklet calculation.
1060 // In addition to the fit sums in the fit register MC information
1063 if ((timebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0)) &&
1064 (timebin < fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE0)))
1065 fFitReg[adc].Q0 += qtot;
1067 if ((timebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS1)) &&
1068 (timebin < fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1)))
1069 fFitReg[adc].Q1 += qtot;
1071 if ((timebin >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFS) ) &&
1072 (timebin < fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFE)))
1074 fFitReg[adc].SumX += timebin;
1075 fFitReg[adc].SumX2 += timebin*timebin;
1076 fFitReg[adc].Nhits++;
1077 fFitReg[adc].SumY += ypos;
1078 fFitReg[adc].SumY2 += ypos*ypos;
1079 fFitReg[adc].SumXY += timebin*ypos;
1082 // register hits (MC info)
1083 fHits[fNHits].channel = adc;
1084 fHits[fNHits].qtot = qtot;
1085 fHits[fNHits].ypos = ypos;
1086 fHits[fNHits].timebin = timebin;
1087 fHits[fNHits].label = label;
1091 void AliTRDmcmSim::CalcFitreg()
1094 // Detect the hits and fill the fit registers.
1095 // Requires 12-bit data from fADCF which means Filter()
1096 // has to be called before even if all filters are bypassed.
1100 const uint16_t LUT_POS[128] = { // move later to some other file
1101 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15,
1102 16, 16, 16, 17, 17, 18, 18, 19, 19, 19, 20, 20, 20, 21, 21, 22, 22, 22, 23, 23, 23, 24, 24, 24, 24, 25, 25, 25, 26, 26, 26, 26,
1103 27, 27, 27, 27, 27, 27, 27, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 28, 27, 27, 27, 27, 26,
1104 26, 26, 26, 25, 25, 25, 24, 24, 23, 23, 22, 22, 21, 21, 20, 20, 19, 18, 18, 17, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 7};
1106 //??? to be clarified:
1107 UInt_t adc_mask = 0xfffff;
1109 UShort_t timebin, adcch, adc_left, adc_cent, adc_right, hit_qual, timebin1, timebin2, Qtot_tmp;
1110 Short_t ypos, fromLeft, fromRight, found;
1111 UShort_t Qtot[19]; // the last is dummy
1112 UShort_t marked[6], Qmarked[6], worse1, worse2;
1114 timebin1 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFS);
1115 if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0)
1117 timebin1 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQS0);
1118 timebin2 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFE);
1119 if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1)
1121 timebin2 = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPQE1);
1123 // reset the fit registers
1125 for (adcch = 0; adcch < fNADC-2; adcch++) // due to border channels
1127 fFitReg[adcch].Nhits = 0;
1128 fFitReg[adcch].Q0 = 0;
1129 fFitReg[adcch].Q1 = 0;
1130 fFitReg[adcch].SumX = 0;
1131 fFitReg[adcch].SumY = 0;
1132 fFitReg[adcch].SumX2 = 0;
1133 fFitReg[adcch].SumY2 = 0;
1134 fFitReg[adcch].SumXY = 0;
1137 for (timebin = timebin1; timebin < timebin2; timebin++)
1139 // first find the hit candidates and store the total cluster charge in Qtot array
1140 // in case of not hit store 0 there.
1141 for (adcch = 0; adcch < fNADC-2; adcch++) {
1142 if ( ( (adc_mask >> adcch) & 7) == 7) //??? all 3 channels are present in case of ZS
1144 adc_left = fADCF[adcch ][timebin];
1145 adc_cent = fADCF[adcch+1][timebin];
1146 adc_right = fADCF[adcch+2][timebin];
1147 if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPVBY) == 1)
1148 hit_qual = ( (adc_left * adc_right) <
1149 (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPVT) * adc_cent) );
1152 // The accumulated charge is with the pedestal!!!
1153 Qtot_tmp = adc_left + adc_cent + adc_right;
1155 (Qtot_tmp >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPHT)) &&
1156 (adc_left <= adc_cent) &&
1157 (adc_cent > adc_right) )
1158 Qtot[adcch] = Qtot_tmp;
1161 //printf("ch %2d Qtot %5d\n",adcch, Qtot[adcch]);
1164 Qtot[adcch] = 0; //jkl
1170 marked[4] = 19; // invalid channel
1171 marked[5] = 19; // invalid channel
1173 while ((adcch < 16) && (found < 3))
1175 if (Qtot[adcch] > 0)
1178 marked[2*found+1]=adcch;
1187 while ((adcch > 2) && (found < 3))
1189 if (Qtot[adcch] > 0)
1191 marked[2*found]=adcch;
1198 //printf("Fromleft=%d, Fromright=%d\n",fromLeft, fromRight);
1199 // here mask the hit candidates in the middle, if any
1200 if ((fromLeft >= 0) && (fromRight >= 0) && (fromLeft < fromRight))
1201 for (adcch = fromLeft+1; adcch < fromRight; adcch++)
1205 for (adcch = 0; adcch < 19; adcch++)
1206 if (Qtot[adcch] > 0) found++;
1209 if (found > 4) // sorting like in the TRAP in case of 5 or 6 candidates!
1211 if (marked[4] == marked[5]) marked[5] = 19;
1212 for (found=0; found<6; found++)
1214 Qmarked[found] = Qtot[marked[found]] >> 4;
1215 //printf("ch_%d Qtot %d Qtots %d |",marked[found],Qtot[marked[found]],Qmarked[found]);
1219 Sort6To2Worst(marked[0], marked[3], marked[4], marked[1], marked[2], marked[5],
1227 // Now mask the two channels with the smallest charge
1231 //printf("Kill ch %d\n",worse1);
1236 //printf("Kill ch %d\n",worse2);
1240 for (adcch = 0; adcch < 19; adcch++) {
1241 if (Qtot[adcch] > 0) // the channel is marked for processing
1243 adc_left = fADCF[adcch ][timebin];
1244 adc_cent = fADCF[adcch+1][timebin];
1245 adc_right = fADCF[adcch+2][timebin];
1246 // hit detected, in TRAP we have 4 units and a hit-selection, here we proceed all channels!
1247 // subtract the pedestal TPFP, clipping instead of wrapping
1249 Int_t TPFP = fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPFP);
1250 // printf("Hit found, time=%d, adcch=%d/%d/%d, adc values=%d/%d/%d, TPFP=%d, TPHT=%d\n",
1251 // timebin, adcch, adcch+1, adcch+2, adc_left, adc_cent, adc_right, TPFP,
1252 // fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPHT));
1254 if (adc_left < TPFP) adc_left = 0; else adc_left -= TPFP;
1255 if (adc_cent < TPFP) adc_cent = 0; else adc_cent -= TPFP;
1256 if (adc_right < TPFP) adc_right = 0; else adc_right -= TPFP;
1257 // Calculate the center of gravity
1258 ypos = 128*(adc_left - adc_right) / adc_cent;
1259 if (ypos < 0) ypos = -ypos;
1260 // make the correction using the LUT
1261 ypos = ypos + LUT_POS[ypos & 0x7F];
1262 if (adc_left > adc_right) ypos = -ypos;
1263 AddHitToFitreg(adcch, timebin, Qtot[adcch], ypos, -1);
1269 void AliTRDmcmSim::TrackletSelection()
1271 // Select up to 4 tracklet candidates from the fit registers
1272 // and assign them to the CPUs.
1274 UShort_t adc_idx, i, j, ntracks, tmp;
1275 UShort_t track_p[18][2]; // store the adcch[0] and number of hits[1] for all tracklet candidates
1278 for (adc_idx = 0; adc_idx < 18; adc_idx++) // ADCs
1279 if ( (fFitReg[adc_idx].Nhits
1280 >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPCL)) &&
1281 (fFitReg[adc_idx].Nhits+fFitReg[adc_idx+1].Nhits
1282 >= fTrapConfig->GetTrapReg(AliTRDtrapConfig::kTPCT)))
1284 track_p[ntracks][0] = adc_idx;
1285 track_p[ntracks][1] = fFitReg[adc_idx].Nhits+fFitReg[adc_idx+1].Nhits;
1286 //printf("%d %2d %4d\n", ntracks, track_p[ntracks][0], track_p[ntracks][1]);
1290 // for (i=0; i<ntracks;i++) printf("%d %d %d\n",i,track_p[i][0], track_p[i][1]);
1294 // primitive sorting according to the number of hits
1295 for (j = 0; j < (ntracks-1); j++)
1297 for (i = j+1; i < ntracks; i++)
1299 if ( (track_p[j][1] < track_p[i][1]) ||
1300 ( (track_p[j][1] == track_p[i][1]) && (track_p[j][0] < track_p[i][0]) ) )
1303 tmp = track_p[j][1];
1304 track_p[j][1] = track_p[i][1];
1305 track_p[i][1] = tmp;
1306 tmp = track_p[j][0];
1307 track_p[j][0] = track_p[i][0];
1308 track_p[i][0] = tmp;
1312 ntracks = 4; // cut the rest, 4 is the max
1314 // else is not necessary to sort
1316 // now sort, so that the first tracklet going to CPU0 corresponds to the highest adc channel - as in the TRAP
1317 for (j = 0; j < (ntracks-1); j++)
1319 for (i = j+1; i < ntracks; i++)
1321 if (track_p[j][0] < track_p[i][0])
1324 tmp = track_p[j][1];
1325 track_p[j][1] = track_p[i][1];
1326 track_p[i][1] = tmp;
1327 tmp = track_p[j][0];
1328 track_p[j][0] = track_p[i][0];
1329 track_p[i][0] = tmp;
1333 for (i = 0; i < ntracks; i++) // CPUs with tracklets.
1334 fFitPtr[i] = track_p[i][0]; // pointer to the left channel with tracklet for CPU[i]
1335 for (i = ntracks; i < 4; i++) // CPUs without tracklets
1336 fFitPtr[i] = 31; // pointer to the left channel with tracklet for CPU[i] = 31 (invalid)
1337 // printf("found %i tracklet candidates\n", ntracks);
1340 void AliTRDmcmSim::FitTracklet()
1342 // Perform the actual tracklet fit based on the fit sums
1343 // which have been filled in the fit registers.
1345 // parameters in fitred.asm (fit program)
1346 Int_t decPlaces = 5;
1349 rndAdd = (1 << (decPlaces-1)) + 1;
1350 else if (decPlaces == 1)
1353 // should come from trapConfig (DMEM)
1354 AliTRDpadPlane *pp = fGeo->GetPadPlane(fDetector);
1355 Long64_t shift = ((Long64_t) 1 << 32);
1356 UInt_t scale_y = (UInt_t) (shift * (pp->GetWidthIPad() / (256 * 160e-4)));
1357 UInt_t scale_d = (UInt_t) (shift * (pp->GetWidthIPad() / (256 * 140e-4)));
1358 int padrow = fFeeParam->GetPadRowFromMCM(fRobPos, fMcmPos);
1359 int yoffs = (fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, 19) - fFeeParam->GetNcol()/2) << (8 + decPlaces);
1360 int ndrift = 20; //??? value in simulation?
1361 int defl_cor = 0; // -370;
1362 int minslope = -10000; // no pt-cut so far
1363 int maxslope = 10000; // no pt-cut so far
1365 // local variables for calculation
1366 Long64_t mult, temp, denom; //???
1367 UInt_t q0, q1, qTotal; // charges in the two windows and total charge
1368 UShort_t nHits; // number of hits
1369 Int_t slope, offset; // slope and offset of the tracklet
1370 Int_t sumX, sumY, sumXY, sumX2; // fit sums from fit registers
1371 //int32_t SumY2; // not used in the current TRAP program
1372 FitReg_t *fit0, *fit1; // pointers to relevant fit registers
1374 // const uint32_t OneDivN[32] = { // 2**31/N : exactly like in the TRAP, the simple division here gives the same result!
1375 // 0x00000000, 0x80000000, 0x40000000, 0x2AAAAAA0, 0x20000000, 0x19999990, 0x15555550, 0x12492490,
1376 // 0x10000000, 0x0E38E380, 0x0CCCCCC0, 0x0BA2E8B0, 0x0AAAAAA0, 0x09D89D80, 0x09249240, 0x08888880,
1377 // 0x08000000, 0x07878780, 0x071C71C0, 0x06BCA1A0, 0x06666660, 0x06186180, 0x05D17450, 0x0590B210,
1378 // 0x05555550, 0x051EB850, 0x04EC4EC0, 0x04BDA120, 0x04924920, 0x0469EE50, 0x04444440, 0x04210840};
1380 for (Int_t cpu = 0; cpu < 4; cpu++) {
1381 if (fFitPtr[cpu] == 31)
1383 fMCMT[cpu] = 0x10001000; //??? AliTRDfeeParam::GetTrackletEndmarker();
1387 fit0 = &fFitReg[fFitPtr[cpu] ];
1388 fit1 = &fFitReg[fFitPtr[cpu]+1]; // next channel
1391 mult = mult << (32 + decPlaces);
1395 nHits = fit0->Nhits + fit1->Nhits; // number of hits
1396 sumX = fit0->SumX + fit1->SumX;
1397 sumX2 = fit0->SumX2 + fit1->SumX2;
1398 denom = nHits*sumX2 - sumX*sumX;
1400 mult = mult / denom; // exactly like in the TRAP program
1401 q0 = fit0->Q0 + fit1->Q0;
1402 q1 = fit0->Q1 + fit1->Q1;
1403 sumY = fit0->SumY + fit1->SumY + 256*fit1->Nhits;
1404 sumXY = fit0->SumXY + fit1->SumXY + 256*fit1->SumX;
1406 slope = nHits*sumXY - sumX * sumY;
1407 offset = sumX2*sumY - sumX * sumXY;
1408 temp = mult * slope;
1409 slope = temp >> 32; // take the upper 32 bits
1410 temp = mult * offset;
1411 offset = temp >> 32; // take the upper 32 bits
1413 offset = offset + yoffs + (18 << (8 + decPlaces));
1414 slope = slope * ndrift + defl_cor;
1415 offset = offset - (fFitPtr[cpu] << (8 + decPlaces));
1417 if ((slope < minslope) || (slope > maxslope))
1419 fMCMT[cpu] = 0x10001000; //??? AliTRDfeeParam::GetTrackletEndmarker();
1424 temp = temp * scale_d;
1425 slope = (temp >> 32);
1428 temp = temp * scale_y;
1429 offset = (temp >> 32);
1431 // rounding, like in the TRAP
1432 slope = (slope + rndAdd) >> decPlaces;
1433 offset = (offset + rndAdd) >> decPlaces;
1435 if (slope > 0x3f || slope < -0x3f)
1436 AliWarning("Overflow in slope");
1437 slope = slope & 0x7F; // 7 bit
1439 if (offset > 0xfff || offset < 0xfff)
1440 AliWarning("Overflow in offset");
1441 offset = offset & 0x1FFF; // 13 bit
1443 qTotal = (q1 / nHits) >> 1;
1445 AliWarning("Overflow in charge");
1446 qTotal = qTotal & 0xFF; // 8 bit, exactly like in the TRAP program
1448 // assemble and store the tracklet word
1449 fMCMT[cpu] = (qTotal << 24) | (padrow << 20) | (slope << 13) | offset;
1450 new ((*fTrackletArray)[cpu]) AliTRDtrackletMCM((UInt_t) fMCMT[cpu], fDetector*2 + fRobPos%2, fRobPos, fMcmPos);
1456 void AliTRDmcmSim::Tracklet()
1458 if (!fInitialized) {
1459 AliError("Called uninitialized! Aborting!");
1463 fTrackletArray->Delete();
1466 TrackletSelection();
1469 AliRunLoader *rl = AliRunLoader::Instance();
1470 AliDataLoader *dl = 0x0;
1472 dl = rl->GetLoader("TRDLoader")->GetDataLoader("tracklets");
1474 AliError("Could not get the tracklets data loader!");
1477 TTree *trackletTree = dl->Tree();
1480 trackletTree = dl->Tree();
1482 AliTRDtrackletMCM *trkl = 0x0;
1483 TBranch *trkbranch = trackletTree->GetBranch("mcmtrklbranch");
1485 trkbranch = trackletTree->Branch("mcmtrklbranch", "AliTRDtrackletMCM", &trkl, 32000);
1486 // trkbranch = trackletTree->Branch("mcmtrklbranch", &fTrackletArray, 32000, 2);
1488 for (Int_t iTracklet = 0; iTracklet < fTrackletArray->GetEntriesFast(); iTracklet++) {
1489 trkl = ((AliTRDtrackletMCM*) (*fTrackletArray)[iTracklet]);
1490 trkbranch->SetAddress(&trkl);
1491 // printf("filling tracklet 0x%08x\n", trkl->GetTrackletWord());
1494 dl->WriteData("OVERWRITE");
1498 void AliTRDmcmSim::WriteData(AliTRDarrayADC *digits)
1500 // write back the processed data configured by EBSF
1501 // EBSF = 1: unfiltered data; EBSF = 0: filtered data
1502 // zero-suppressed valued are written as -1 to digits
1504 if (!fInitialized) {
1505 AliError("Called uninitialized! Aborting!");
1510 Int_t lastAdc = fNADC - 1;
1512 if (GetCol(firstAdc) > 143)
1515 if (GetCol(lastAdc) < 0)
1516 lastAdc = fNADC - 2;
1518 if (fTrapConfig->GetTrapReg(AliTRDtrapConfig::kEBSF) != 0) // store unfiltered data
1520 for (Int_t iAdc = firstAdc; iAdc < lastAdc; iAdc++) {
1521 if (fZSM1Dim[iAdc] == 1) {
1522 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
1523 digits->SetData(GetRow(), GetCol(iAdc), iTimeBin, -1);
1524 // printf("suppressed: %i, %i, %i, %i, now: %i\n", fDetector, GetRow(), GetCol(iAdc), iTimeBin,
1525 // digits->GetData(GetRow(), GetCol(iAdc), iTimeBin));
1531 for (Int_t iAdc = firstAdc; iAdc < lastAdc; iAdc++) {
1532 if (fZSM1Dim[iAdc] == 0) {
1533 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
1534 digits->SetData(GetRow(), GetCol(iAdc), iTimeBin, fADCF[iAdc][iTimeBin] >> fgkAddDigits);
1538 for (Int_t iTimeBin = 0; iTimeBin < fNTimeBin; iTimeBin++) {
1539 digits->SetData(GetRow(), GetCol(iAdc), iTimeBin, -1);
1540 // printf("suppressed: %i, %i, %i, %i\n", fDetector, GetRow(), GetCol(iAdc), iTimeBin);
1547 // help functions, to be cleaned up
1549 UInt_t AliTRDmcmSim::AddUintClipping(UInt_t a, UInt_t b, UInt_t nbits)
1552 // This function adds a and b (unsigned) and clips to
1553 // the specified number of bits.
1559 UInt_t maxv = (1 << nbits) - 1;;
1565 if ((sum < a) || (sum < b))
1571 void AliTRDmcmSim::Sort2(uint16_t idx1i, uint16_t idx2i, \
1572 uint16_t val1i, uint16_t val2i, \
1573 uint16_t *idx1o, uint16_t *idx2o, \
1574 uint16_t *val1o, uint16_t *val2o)
1593 void AliTRDmcmSim::Sort3(uint16_t idx1i, uint16_t idx2i, uint16_t idx3i, \
1594 uint16_t val1i, uint16_t val2i, uint16_t val3i, \
1595 uint16_t *idx1o, uint16_t *idx2o, uint16_t *idx3o, \
1596 uint16_t *val1o, uint16_t *val2o, uint16_t *val3o)
1601 if (val1i > val2i) sel=4; else sel=0;
1602 if (val2i > val3i) sel=sel + 2;
1603 if (val3i > val1i) sel=sel + 1;
1604 //printf("input channels %d %d %d, charges %d %d %d sel=%d\n",idx1i, idx2i, idx3i, val1i, val2i, val3i, sel);
1607 case 6 : // 1 > 2 > 3 => 1 2 3
1608 case 0 : // 1 = 2 = 3 => 1 2 3 : in this case doesn't matter, but so is in hardware!
1617 case 4 : // 1 > 2, 2 <= 3, 3 <= 1 => 1 3 2
1626 case 2 : // 1 <= 2, 2 > 3, 3 <= 1 => 2 1 3
1635 case 3 : // 1 <= 2, 2 > 3, 3 > 1 => 2 3 1
1644 case 1 : // 1 <= 2, 2 <= 3, 3 > 1 => 3 2 1
1653 case 5 : // 1 > 2, 2 <= 3, 3 > 1 => 3 1 2
1662 default: // the rest should NEVER happen!
1663 printf("ERROR in Sort3!!!\n");
1666 // printf("output channels %d %d %d, charges %d %d %d \n",*idx1o, *idx2o, *idx3o, *val1o, *val2o, *val3o);
1669 void AliTRDmcmSim::Sort6To4(uint16_t idx1i, uint16_t idx2i, uint16_t idx3i, uint16_t idx4i, uint16_t idx5i, uint16_t idx6i, \
1670 uint16_t val1i, uint16_t val2i, uint16_t val3i, uint16_t val4i, uint16_t val5i, uint16_t val6i, \
1671 uint16_t *idx1o, uint16_t *idx2o, uint16_t *idx3o, uint16_t *idx4o, \
1672 uint16_t *val1o, uint16_t *val2o, uint16_t *val3o, uint16_t *val4o)
1675 uint16_t idx21s, idx22s, idx23s, dummy;
1676 uint16_t val21s, val22s, val23s;
1677 uint16_t idx23as, idx23bs;
1678 uint16_t val23as, val23bs;
1680 Sort3(idx1i, idx2i, idx3i, val1i, val2i, val3i,
1681 idx1o, &idx21s, &idx23as,
1682 val1o, &val21s, &val23as);
1684 Sort3(idx4i, idx5i, idx6i, val4i, val5i, val6i,
1685 idx2o, &idx22s, &idx23bs,
1686 val2o, &val22s, &val23bs);
1688 Sort2(idx23as, idx23bs, val23as, val23bs, &idx23s, &dummy, &val23s, &dummy);
1690 Sort3(idx21s, idx22s, idx23s, val21s, val22s, val23s,
1691 idx3o, idx4o, &dummy,
1692 val3o, val4o, &dummy);
1696 void AliTRDmcmSim::Sort6To2Worst(uint16_t idx1i, uint16_t idx2i, uint16_t idx3i, uint16_t idx4i, uint16_t idx5i, uint16_t idx6i, \
1697 uint16_t val1i, uint16_t val2i, uint16_t val3i, uint16_t val4i, uint16_t val5i, uint16_t val6i, \
1698 uint16_t *idx5o, uint16_t *idx6o)
1701 uint16_t idx21s, idx22s, idx23s, dummy1, dummy2, dummy3, dummy4, dummy5;
1702 uint16_t val21s, val22s, val23s;
1703 uint16_t idx23as, idx23bs;
1704 uint16_t val23as, val23bs;
1706 Sort3(idx1i, idx2i, idx3i, val1i, val2i, val3i,
1707 &dummy1, &idx21s, &idx23as,
1708 &dummy2, &val21s, &val23as);
1710 Sort3(idx4i, idx5i, idx6i, val4i, val5i, val6i,
1711 &dummy1, &idx22s, &idx23bs,
1712 &dummy2, &val22s, &val23bs);
1714 Sort2(idx23as, idx23bs, val23as, val23bs, &idx23s, idx5o, &val23s, &dummy1);
1716 Sort3(idx21s, idx22s, idx23s, val21s, val22s, val23s,
1717 &dummy1, &dummy2, idx6o,
1718 &dummy3, &dummy4, &dummy5);
1719 // printf("idx21s=%d, idx23as=%d, idx22s=%d, idx23bs=%d, idx5o=%d, idx6o=%d\n",
1720 // idx21s, idx23as, idx22s, idx23bs, *idx5o, *idx6o);