]> git.uio.no Git - u/mrichter/AliRoot.git/blame - TRD/AliTRDmcmSim.cxx
remove Fluka related Gstpar parameters. Waiting for new tests.
[u/mrichter/AliRoot.git] / TRD / AliTRDmcmSim.cxx
CommitLineData
dfd03fc3 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
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 **************************************************************************/
15
dfd03fc3 16///////////////////////////////////////////////////////////////////////////////
17// //
18// TRD MCM (Multi Chip Module) simulator //
19// //
20///////////////////////////////////////////////////////////////////////////////
21
ecf39416 22/* $Id$ */
23
24/*
25
26 New release on 2007/08/17
27
28AliTRDmcmSim is now stably working and zero suppression function seems ok.
29From now, the default version of raw data is set to 3 in AliTRDfeeParam.
30
31The following internal parameters were abolished because it is useless and
32made trouble:
33
34 fColOfADCbeg
35 fColOfADCend
36
37GetCol member was modified accordingly.
38
39New member function DumpData was prepared for diagnostics.
40
41ZSMapping member function was debugged. It was causing crash due to
42wrong indexing in 1 dimensional numbering. Also code was shaped up better.
43
44*/
45
46/*Semi-final version of TRD raw data simulation code with zero suppression (ZS)
47similar to TRD FEE. ZS is realized by the class group:
48
49 AliTRDfeeParam
50 AliTRDmcmSim
51 AliTRDrawData
52
53AliTRDfeeParam has been modified to have more parameters like raw data
54production version and so on. AliTRDmcmSim is new class and this is the core
55of MCM (PASA+TRAP) simulator. It has still very simple function and it will be
56another project to improve this to make it closer to the reall FEE.
57AliTRDrawData has been modified to use new class AliTRDmcmSim.
dfd03fc3 58
ecf39416 59These modifications were tested on Aug. 02 HEAD version that code itself
60compiles. I'm sure there must be still bugs and we need testing by as many as
61possible persons now. Especially it seems HLT part is impacted by problems
62because some parameters were moved from AliTRDrawData to AliTRDfeeParam (like
63fRawVersion disappeared from AliTRDrawData).
64
65In TRD definition, we have now 4 raw data versions.
66
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)
71
72The default is still set to 2 in AliTRDfeeParam::fgkRAWversion and it uses
73previously existing codes. If you set this to 3, AliTRDrawData changes behavior
74to use AliTRDmcmSim with ZS.
75
76Plan is after we make sure it works stably, we delete AliTRDmcm which is obsolete.
0c349049 77However it still take time because tracklet part is not yet touched.
ecf39416 78The default raw version is 2.
79
80 Ken Oyama
81*/
82
1d93b218 83// if no histo is drawn, these are obsolete
84#include <TH1.h>
85#include <TCanvas.h>
86
87// only needed if I/O of tracklets is activated
88#include <TObject.h>
89#include <TFile.h>
90#include <TTree.h>
91#include <TSystem.h>
92
ecf39416 93#include <fstream>
0c349049 94
ecf39416 95#include <TMath.h>
0c349049 96
dfd03fc3 97#include "AliLog.h"
0c349049 98
dfd03fc3 99#include "AliTRDmcmSim.h"
100#include "AliTRDfeeParam.h"
ecf39416 101#include "AliTRDSimParam.h"
dfd03fc3 102#include "AliTRDgeometry.h"
ecf39416 103#include "AliTRDcalibDB.h"
4cc89512 104#include "AliTRDdigitsManager.h"
b65e5048 105#include "AliTRDarrayADC.h"
1d93b218 106// additional for new tail filter and/or tracklet
107#include "AliTRDtrapAlu.h"
108#include "AliTRDpadPlane.h"
52c19022 109#include "AliTRDtrackletMCM.h"
1d93b218 110
52c19022 111#include "AliRun.h"
112#include "AliLoader.h"
1d93b218 113
dfd03fc3 114ClassImp(AliTRDmcmSim)
115
116//_____________________________________________________________________________
117AliTRDmcmSim::AliTRDmcmSim() :TObject()
118 ,fInitialized(kFALSE)
96e6312d 119 ,fNextEvent(-1)
23200400 120 ,fMaxTracklets(-1)
6e5d4cb2 121 ,fChaId(-1)
122 ,fSector(-1)
123 ,fStack(-1)
124 ,fLayer(-1)
125 ,fRobPos(-1)
126 ,fMcmPos(-1)
127 ,fNADC(-1)
128 ,fNTimeBin(-1)
23200400 129 ,fRow (-1)
6e5d4cb2 130 ,fADCR(NULL)
131 ,fADCF(NULL)
23200400 132 ,fADCT(NULL)
133 ,fPosLUT(NULL)
134 ,fMCMT(NULL)
6e5d4cb2 135 ,fZSM(NULL)
136 ,fZSM1Dim(NULL)
dfd03fc3 137 ,fFeeParam(NULL)
ecf39416 138 ,fSimParam(NULL)
139 ,fCal(NULL)
dfd03fc3 140 ,fGeo(NULL)
6e5d4cb2 141{
142 //
143 // AliTRDmcmSim default constructor
144 //
145
146 // By default, nothing is initialized.
147 // It is necessary to issue Init before use.
148}
149
150//_____________________________________________________________________________
151AliTRDmcmSim::AliTRDmcmSim(const AliTRDmcmSim &m)
152 :TObject(m)
1d93b218 153 ,fInitialized(kFALSE)
96e6312d 154 ,fNextEvent(-1)
23200400 155 ,fMaxTracklets(-1)
dfd03fc3 156 ,fChaId(-1)
157 ,fSector(-1)
158 ,fStack(-1)
159 ,fLayer(-1)
160 ,fRobPos(-1)
161 ,fMcmPos(-1)
162 ,fNADC(-1)
163 ,fNTimeBin(-1)
164 ,fRow(-1)
dfd03fc3 165 ,fADCR(NULL)
166 ,fADCF(NULL)
23200400 167 ,fADCT(NULL)
168 ,fPosLUT(NULL)
169 ,fMCMT(NULL)
dfd03fc3 170 ,fZSM(NULL)
171 ,fZSM1Dim(NULL)
6e5d4cb2 172 ,fFeeParam(NULL)
173 ,fSimParam(NULL)
174 ,fCal(NULL)
175 ,fGeo(NULL)
1d93b218 176
dfd03fc3 177{
178 //
6e5d4cb2 179 // AliTRDmcmSim copy constructor
dfd03fc3 180 //
181
182 // By default, nothing is initialized.
183 // It is necessary to issue Init before use.
184}
185
186//_____________________________________________________________________________
187AliTRDmcmSim::~AliTRDmcmSim()
188{
189 //
190 // AliTRDmcmSim destructor
191 //
0c349049 192
dfd03fc3 193 if( fADCR != NULL ) {
194 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
16e077d0 195 delete [] fADCR[iadc];
196 delete [] fADCF[iadc];
1d93b218 197 delete [] fADCT[iadc];
16e077d0 198 delete [] fZSM [iadc];
dfd03fc3 199 }
16e077d0 200 delete [] fADCR;
201 delete [] fADCF;
1d93b218 202 delete [] fADCT;
16e077d0 203 delete [] fZSM;
204 delete [] fZSM1Dim;
dfd03fc3 205 }
1d93b218 206
207 if(fInitialized){
208 delete [] fPosLUT;
209 delete [] fMCMT;
210 }
211
dfd03fc3 212 delete fGeo;
6e5d4cb2 213
214}
215
216//_____________________________________________________________________________
217AliTRDmcmSim &AliTRDmcmSim::operator=(const AliTRDmcmSim &m)
218{
219 //
220 // Assignment operator
221 //
222
223 if (this != &m) {
224 ((AliTRDmcmSim &) m).Copy(*this);
225 }
226 return *this;
227
228}
229
230//_____________________________________________________________________________
231void AliTRDmcmSim::Copy(TObject &m) const
232{
233 //
234 // Copy function
235 //
96e6312d 236 ((AliTRDmcmSim &) m).fNextEvent = 0; //new
1d93b218 237 ((AliTRDmcmSim &) m).fMaxTracklets = 0; //new
6e5d4cb2 238 ((AliTRDmcmSim &) m).fInitialized = 0;
239 ((AliTRDmcmSim &) m).fChaId = 0;
240 ((AliTRDmcmSim &) m).fSector = 0;
241 ((AliTRDmcmSim &) m).fStack = 0;
242 ((AliTRDmcmSim &) m).fLayer = 0;
243 ((AliTRDmcmSim &) m).fRobPos = 0;
244 ((AliTRDmcmSim &) m).fMcmPos = 0;
245 ((AliTRDmcmSim &) m).fNADC = 0;
246 ((AliTRDmcmSim &) m).fNTimeBin = 0;
247 ((AliTRDmcmSim &) m).fRow = 0;
248 ((AliTRDmcmSim &) m).fADCR = 0;
249 ((AliTRDmcmSim &) m).fADCF = 0;
1d93b218 250 ((AliTRDmcmSim &) m).fADCT = 0; //new
251 ((AliTRDmcmSim &) m).fPosLUT = 0; //new
252 ((AliTRDmcmSim &) m).fMCMT = 0; //new
6e5d4cb2 253 ((AliTRDmcmSim &) m).fZSM = 0;
254 ((AliTRDmcmSim &) m).fZSM1Dim = 0;
255 ((AliTRDmcmSim &) m).fFeeParam = 0;
256 ((AliTRDmcmSim &) m).fSimParam = 0;
257 ((AliTRDmcmSim &) m).fCal = 0;
258 ((AliTRDmcmSim &) m).fGeo = 0;
259
dfd03fc3 260}
261
262//_____________________________________________________________________________
23200400 263
96e6312d 264//void AliTRDmcmSim::Init( Int_t chaId, Int_t robPos, Int_t mcmPos )
265void AliTRDmcmSim::Init( Int_t chaId, Int_t robPos, Int_t mcmPos, Bool_t newEvent = kFALSE ) // only for readout tree (new event)
dfd03fc3 266{
0c349049 267 //
dfd03fc3 268 // Initialize the class with new geometry information
269 // fADC array will be reused with filled by zero
0c349049 270 //
96e6312d 271
272 fNextEvent = 0;
dfd03fc3 273 fFeeParam = AliTRDfeeParam::Instance();
ecf39416 274 fSimParam = AliTRDSimParam::Instance();
275 fCal = AliTRDcalibDB::Instance();
dfd03fc3 276 fGeo = new AliTRDgeometry();
0c349049 277 fChaId = chaId;
dfd03fc3 278 fSector = fGeo->GetSector( fChaId );
053767a4 279 fStack = fGeo->GetStack( fChaId );
280 fLayer = fGeo->GetLayer( fChaId );
0c349049 281 fRobPos = robPos;
282 fMcmPos = mcmPos;
dfd03fc3 283 fNADC = fFeeParam->GetNadcMcm();
ecf39416 284 fNTimeBin = fCal->GetNumberOfTimeBins();
dfd03fc3 285 fRow = fFeeParam->GetPadRowFromMCM( fRobPos, fMcmPos );
dfd03fc3 286
1d93b218 287 fMaxTracklets = fFeeParam->GetMaxNrOfTracklets();
288
289
290
23200400 291
96e6312d 292 if (newEvent == kTRUE) {
293 fNextEvent = 1;
294 }
23200400 295
1d93b218 296
297
dfd03fc3 298 // Allocate ADC data memory if not yet done
299 if( fADCR == NULL ) {
300 fADCR = new Int_t *[fNADC];
301 fADCF = new Int_t *[fNADC];
1d93b218 302 fADCT = new Int_t *[fNADC]; //new
dfd03fc3 303 fZSM = new Int_t *[fNADC];
304 fZSM1Dim = new Int_t [fNADC];
305 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
306 fADCR[iadc] = new Int_t[fNTimeBin];
307 fADCF[iadc] = new Int_t[fNTimeBin];
1d93b218 308 fADCT[iadc] = new Int_t[fNTimeBin]; //new
dfd03fc3 309 fZSM [iadc] = new Int_t[fNTimeBin];
310 }
311 }
312
313 // Initialize ADC data
314 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
315 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
316 fADCR[iadc][it] = 0;
317 fADCF[iadc][it] = 0;
1d93b218 318 fADCT[iadc][it] = -1; //new
dfd03fc3 319 fZSM [iadc][it] = 1; // Default unread = 1
320 }
321 fZSM1Dim[iadc] = 1; // Default unread = 1
322 }
ecf39416 323
1d93b218 324 //new:
325 fPosLUT = new Int_t[128];
326 for(Int_t i = 0; i<128; i++){
327 fPosLUT[i] = 0;
328 }
329
330 fMCMT = new UInt_t[fMaxTracklets];
331 for(Int_t i = 0; i < fMaxTracklets; i++) {
332 fMCMT[i] = 0;
333 }
334
335
dfd03fc3 336 fInitialized = kTRUE;
337}
338
ecf39416 339//_____________________________________________________________________________
340Bool_t AliTRDmcmSim::CheckInitialized()
341{
0c349049 342 //
343 // Check whether object is initialized
344 //
345
ecf39416 346 if( ! fInitialized ) {
347 AliDebug(2, Form ("AliTRDmcmSim is not initialized but function other than Init() is called."));
348 }
349 return fInitialized;
350}
351
dfd03fc3 352//_____________________________________________________________________________
1d93b218 353
354
355void AliTRDmcmSim::SetPosLUT() {
053767a4 356 Double_t iHi = (Double_t)fCal->GetPRFhi();
357 Double_t iLo = (Double_t)fCal->GetPRFlo();
358 Int_t nBin = fCal->GetPRFbin();
359 Int_t iOff = fLayer * nBin;
360 Int_t kNlayer = fGeo->Nlayer();
1d93b218 361
053767a4 362 Float_t *sPRFsmp = new Float_t[nBin*kNlayer];
1d93b218 363 Double_t *sPRFlayer = new Double_t[nBin];
364
365
053767a4 366 for(Int_t i = 0; i<nBin*kNlayer; i++){
1d93b218 367
368 //printf("%f\n",fCal->GetSampledPRF()[i]);
369 sPRFsmp[i] = fCal->GetSampledPRF()[i];
370
371 }
372
373 Double_t sWidth = (iHi-iLo)/((Double_t) nBin);
374 Int_t sPad = (Int_t) (1.0/sWidth);
375
376 // get the PRF for actual layer (interpolated to ibin data-points; 61 measured)
377 for(Int_t iBin = 0; iBin < nBin; iBin++){
378 sPRFlayer[iBin] = (Double_t)sPRFsmp[iOff+iBin];
379 }
380
381 Int_t bin0 = (Int_t)(-iLo / sWidth - 0.5); // bin-nr. for pad-position 0
382
383 Int_t bin1 = (Int_t)((Double_t)(0.5 - iLo) / sWidth - 0.5); // bin-nr. for pad-position 0.5
384 bin1 = bin1 + 1;
385 bin0 = bin0 + 1; //avoid negative values in aYest (start right of symmetry center)
386 while (bin0-sPad<0) {
387 bin0 = bin0 + 1;
388 }
389 while (bin1+sPad>=nBin) {
390 bin1 = bin1 - 1;
391 }
392
393 Double_t* aYest = new Double_t[bin1-bin0+1];
394
395 /*TH1F* hist1 = new TH1F("h1","yest(y)",128,0,0.5);
396 TH1F* hist2 = new TH1F("h2","y(yest)",128,0,0.5);
397 TH1F* hist3 = new TH1F("h3","y(yest)-yest",128,0,0.5);
398 TH1F* hist4 = new TH1F("h4","y(yest)-yest,discrete",128,0,0.5);
399
400 TCanvas *c1 = new TCanvas("c1","c1",800,1000);
401 hist1->Draw();
402 TCanvas *c2 = new TCanvas("c2","c2",800,1000);
403 hist2->Draw();
404 TCanvas *c3 = new TCanvas("c3","c3",800,1000);
405 hist3->Draw();
406 TCanvas *c4 = new TCanvas("c4","c4",800,1000);
407 hist4->Draw();*/
408
409 for(Int_t iBin = bin0; iBin <= bin1; iBin++){
410 aYest[iBin-bin0] = 0.5*(sPRFlayer[iBin-sPad] - sPRFlayer[iBin+sPad])/(sPRFlayer[iBin]); // estimated position from PRF; between 0 and 1
411 //Double_t position = ((Double_t)(iBin)+0.5)*sWidth+iLo;
412 // hist1->Fill(position,aYest[iBin-bin0]);
413 }
414
415
416
417 Double_t aY[128]; // reversed function
418
419 AliTRDtrapAlu a;
420 a.Init(1,8,0,31);
421
422 for(Int_t j = 0; j<128; j++) { // loop over all Yest; LUT has 128 entries;
423 Double_t yest = ((Double_t)j)/256;
424
425 Int_t iBin = 0;
426 while (yest>aYest[iBin] && iBin<(bin1-bin0)) {
427 iBin = iBin+1;
428 }
429 if((iBin == bin1 - bin0)&&(yest>aYest[iBin])) {
430 aY[j] = 0.5; // yest too big
431 //hist2->Fill(yest,aY[j]);
432
433 }
434 else {
435 Int_t bin_d = iBin + bin0 - 1;
436 Int_t bin_u = iBin + bin0;
437 Double_t y_d = ((Double_t)bin_d + 0.5)*sWidth + iLo; // lower y
438 Double_t y_u = ((Double_t)bin_u + 0.5)*sWidth + iLo; // upper y
439 Double_t yest_d = aYest[iBin-1]; // lower estimated y
440 Double_t yest_u = aYest[iBin]; // upper estimated y
441
442 aY[j] = ((yest-yest_d)/(yest_u-yest_d))*(y_u-y_d) + y_d;
443 //hist2->Fill(yest,aY[j]);
444
445 }
446 aY[j] = aY[j] - yest;
447 //hist3->Fill(yest,aY[j]);
448 // formatting
449 a.AssignDouble(aY[j]);
450 //a.WriteWord();
451 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
452 //hist4->Fill(yest,fPosLUT[j]);
453
454 }
455
456
457
458 delete [] sPRFsmp;
459 delete [] sPRFlayer;
460 delete [] aYest;
461
462}
463
464
465//_____________________________________________________________________________
466Int_t* AliTRDmcmSim::GetPosLUT(){
467 return fPosLUT;
468}
469
470
471
dfd03fc3 472void AliTRDmcmSim::SetData( Int_t iadc, Int_t *adc )
473{
0c349049 474 //
dfd03fc3 475 // Store ADC data into array of raw data
0c349049 476 //
dfd03fc3 477
ecf39416 478 if( !CheckInitialized() ) return;
dfd03fc3 479
480 if( iadc < 0 || iadc >= fNADC ) {
481 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
482 return;
483 }
484
485 for( int it = 0 ; it < fNTimeBin ; it++ ) {
486 fADCR[iadc][it] = (Int_t)(adc[it]);
487 }
488}
489
490//_____________________________________________________________________________
491void AliTRDmcmSim::SetData( Int_t iadc, Int_t it, Int_t adc )
492{
0c349049 493 //
dfd03fc3 494 // Store ADC data into array of raw data
0c349049 495 //
dfd03fc3 496
ecf39416 497 if( !CheckInitialized() ) return;
dfd03fc3 498
499 if( iadc < 0 || iadc >= fNADC ) {
500 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
501 return;
502 }
503
504 fADCR[iadc][it] = adc;
505}
506
507//_____________________________________________________________________________
508void AliTRDmcmSim::SetDataPedestal( Int_t iadc )
509{
0c349049 510 //
dfd03fc3 511 // Store ADC data into array of raw data
0c349049 512 //
dfd03fc3 513
ecf39416 514 if( !CheckInitialized() ) return;
dfd03fc3 515
516 if( iadc < 0 || iadc >= fNADC ) {
517 //Log (Form ("Error: iadc is out of range (should be 0 to %d).", fNADC-1));
518 return;
519 }
520
521 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
ecf39416 522 fADCR[iadc][it] = fSimParam->GetADCbaseline();
dfd03fc3 523 }
524}
525
526//_____________________________________________________________________________
527Int_t AliTRDmcmSim::GetCol( Int_t iadc )
528{
0c349049 529 //
dfd03fc3 530 // Return column id of the pad for the given ADC channel
0c349049 531 //
532
ecf39416 533 if( !CheckInitialized() ) return -1;
dfd03fc3 534
ecf39416 535 return fFeeParam->GetPadColFromADC(fRobPos, fMcmPos, iadc);
dfd03fc3 536}
537
dfd03fc3 538//_____________________________________________________________________________
539Int_t AliTRDmcmSim::ProduceRawStream( UInt_t *buf, Int_t maxSize )
540{
0c349049 541 //
dfd03fc3 542 // Produce raw data stream from this MCM and put in buf
0c349049 543 // Returns number of words filled, or negative value
544 // with -1 * number of overflowed words
545 //
dfd03fc3 546
547 UInt_t x;
548 UInt_t iEv = 0;
549 Int_t nw = 0; // Number of written words
550 Int_t of = 0; // Number of overflowed words
551 Int_t rawVer = fFeeParam->GetRAWversion();
552 Int_t **adc;
553
ecf39416 554 if( !CheckInitialized() ) return 0;
555
dfd03fc3 556 if( fFeeParam->GetRAWstoreRaw() ) {
557 adc = fADCR;
558 } else {
559 adc = fADCF;
560 }
561
562 // Produce MCM header
563 x = ((fRobPos * fFeeParam->GetNmcmRob() + fMcmPos) << 24) | ((iEv % 0x100000) << 4) | 0xC;
564 if (nw < maxSize) {
565 buf[nw++] = x;
566 }
567 else {
568 of++;
569 }
570
571 // Produce ADC mask
572 if( rawVer >= 3 ) {
573 x = 0;
574 for( Int_t iAdc = 0 ; iAdc < fNADC ; iAdc++ ) {
575 if( fZSM1Dim[iAdc] == 0 ) { // 0 means not suppressed
576 x = x | (1 << iAdc);
577 }
578 }
579 if (nw < maxSize) {
580 buf[nw++] = x;
581 }
582 else {
583 of++;
584 }
585 }
586
587 // Produce ADC data. 3 timebins are packed into one 32 bits word
588 // In this version, different ADC channel will NOT share the same word
589
590 UInt_t aa=0, a1=0, a2=0, a3=0;
591
592 for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
ecf39416 593 if( rawVer>= 3 && fZSM1Dim[iAdc] != 0 ) continue; // suppressed
dfd03fc3 594 aa = !(iAdc & 1) + 2;
595 for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
596 a1 = ((iT ) < fNTimeBin ) ? adc[iAdc][iT ] : 0;
597 a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] : 0;
598 a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] : 0;
ecf39416 599 x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
600 if (nw < maxSize) {
601 buf[nw++] = x;
602 }
603 else {
604 of++;
605 }
dfd03fc3 606 }
607 }
608
609 if( of != 0 ) return -of; else return nw;
610}
611
987ba9a3 612//_____________________________________________________________________________
6a04e92b 613Int_t AliTRDmcmSim::ProduceRawStreamV2( UInt_t *buf, Int_t maxSize, UInt_t iEv )
987ba9a3 614{
615 //
616 // Produce raw data stream from this MCM and put in buf
617 // Returns number of words filled, or negative value
618 // with -1 * number of overflowed words
619 //
620
621 UInt_t x;
6a04e92b 622 //UInt_t iEv = 0;
987ba9a3 623 Int_t nw = 0; // Number of written words
624 Int_t of = 0; // Number of overflowed words
625 Int_t rawVer = fFeeParam->GetRAWversion();
626 Int_t **adc;
627 Int_t nActiveADC = 0; // number of activated ADC bits in a word
628
629 if( !CheckInitialized() ) return 0;
630
631 if( fFeeParam->GetRAWstoreRaw() ) {
632 adc = fADCR;
633 } else {
634 adc = fADCF;
635 }
636
6a04e92b 637 // Produce MCM header : xrrr mmmm eeee eeee eeee eeee eeee 1100
638 // x : 0 before , 1 since 10.2007
639 // r : Readout board position (Alice numbering)
640 // m : MCM posi
641 // e : Event counter from 1
642 //x = (1<<31) | ((fRobPos * fFeeParam->GetNmcmRob() + fMcmPos) << 24) | ((iEv % 0x100000) << 4) | 0xC;
643 x = (1<<31) | (fRobPos << 28) | (fMcmPos << 24) | ((iEv % 0x100000) << 4) | 0xC;
987ba9a3 644 if (nw < maxSize) {
645 buf[nw++] = x;
646 //printf("\nMCM header: %X ",x);
647 }
648 else {
649 of++;
650 }
651
652 // Produce ADC mask : nncc cccm mmmm mmmm mmmm mmmm mmmm 1100
653 // n : unused , c : ADC count, m : selected ADCs
654 if( rawVer >= 3 ) {
655 x = 0;
656 for( Int_t iAdc = 0 ; iAdc < fNADC ; iAdc++ ) {
657 if( fZSM1Dim[iAdc] == 0 ) { // 0 means not suppressed
658 x = x | (1 << (iAdc+4) ); // last 4 digit reserved for 1100=0xc
659 nActiveADC++; // number of 1 in mmm....m
660 }
661 }
662 x = x | (1 << 30) | ( ( 0x3FFFFFFC ) & (~(nActiveADC) << 25) ) | 0xC; // nn = 01, ccccc are inverted, 0xc=1100
663 //printf("nActiveADC=%d=%08X, inverted=%X ",nActiveADC,nActiveADC,x );
664
665 if (nw < maxSize) {
666 buf[nw++] = x;
667 //printf("ADC mask: %X nMask=%d ADC data: ",x,nActiveADC);
668 }
669 else {
670 of++;
671 }
672 }
673
674 // Produce ADC data. 3 timebins are packed into one 32 bits word
675 // In this version, different ADC channel will NOT share the same word
676
677 UInt_t aa=0, a1=0, a2=0, a3=0;
678
679 for (Int_t iAdc = 0; iAdc < 21; iAdc++ ) {
680 if( rawVer>= 3 && fZSM1Dim[iAdc] != 0 ) continue; // Zero Suppression, 0 means not suppressed
6a04e92b 681 aa = !(iAdc & 1) + 2; // 3 for the even ADC channel , 2 for the odd ADC channel
987ba9a3 682 for (Int_t iT = 0; iT < fNTimeBin; iT+=3 ) {
683 a1 = ((iT ) < fNTimeBin ) ? adc[iAdc][iT ] : 0;
684 a2 = ((iT + 1) < fNTimeBin ) ? adc[iAdc][iT+1] : 0;
685 a3 = ((iT + 2) < fNTimeBin ) ? adc[iAdc][iT+2] : 0;
686 x = (a3 << 22) | (a2 << 12) | (a1 << 2) | aa;
687 if (nw < maxSize) {
688 buf[nw++] = x;
689 //printf("%08X ",x);
690 }
691 else {
692 of++;
693 }
694 }
695 }
696
697 if( of != 0 ) return -of; else return nw;
698}
699
1d93b218 700//_____________________________________________________________________________
701Int_t AliTRDmcmSim::ProduceTrackletStream( UInt_t *buf, Int_t maxSize )
702{
703 //
704 // Produce tracklet data stream from this MCM and put in buf
705 // Returns number of words filled, or negative value
706 // with -1 * number of overflowed words
707 //
708
709 UInt_t x;
710 Int_t nw = 0; // Number of written words
711 Int_t of = 0; // Number of overflowed words
712
713 if( !CheckInitialized() ) return 0;
714
715 // Produce tracklet data. A maximum of four 32 Bit words will be written per MCM
716 // fMCMT is filled continuously until no more tracklet words available
717
718 Int_t wd = 0;
719 while ( (wd < fMaxTracklets) && (fMCMT[wd] > 0) ){
720 x = fMCMT[wd];
721 if (nw < maxSize) {
722 buf[nw++] = x;
723 }
724 else {
725 of++;
726 }
727 wd++;
728 }
729
730 if( of != 0 ) return -of; else return nw;
731}
732
733
dfd03fc3 734//_____________________________________________________________________________
735void AliTRDmcmSim::Filter()
736{
0c349049 737 //
dfd03fc3 738 // Apply digital filter
0c349049 739 //
dfd03fc3 740
ecf39416 741 if( !CheckInitialized() ) return;
dfd03fc3 742
743 // Initialize filtered data array with raw data
744 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
745 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
746 fADCF[iadc][it] = fADCR[iadc][it];
747 }
748 }
749
750 // Then apply fileters one by one to filtered data array
acc49af9 751 if( fFeeParam->IsPFon() ) FilterPedestal();
752 if( fFeeParam->IsGFon() ) FilterGain();
753 if( fFeeParam->IsTFon() ) FilterTail();
dfd03fc3 754}
755
756//_____________________________________________________________________________
757void AliTRDmcmSim::FilterPedestal()
758{
23200400 759
760
0c349049 761 //
dfd03fc3 762 // Apply pedestal filter
0c349049 763 //
dfd03fc3 764
ecf39416 765 Int_t ap = fSimParam->GetADCbaseline(); // ADC instrinsic pedestal
dfd03fc3 766 Int_t ep = fFeeParam->GetPFeffectPedestal(); // effective pedestal
6e5d4cb2 767 //Int_t tc = fFeeParam->GetPFtimeConstant(); // this makes no sense yet
dfd03fc3 768
769 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
770 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
771 fADCF[iadc][it] = fADCF[iadc][it] - ap + ep;
772 }
773 }
774}
775
776//_____________________________________________________________________________
777void AliTRDmcmSim::FilterGain()
778{
0c349049 779 //
dfd03fc3 780 // Apply gain filter (not implemented)
ecf39416 781 // Later it will be implemented because gain digital filiter will
782 // increase noise level.
0c349049 783 //
784
dfd03fc3 785}
786
787//_____________________________________________________________________________
788void AliTRDmcmSim::FilterTail()
789{
0c349049 790 //
dfd03fc3 791 // Apply exponential tail filter (Bogdan's version)
0c349049 792 //
dfd03fc3 793
794 Double_t *dtarg = new Double_t[fNTimeBin];
795 Int_t *itarg = new Int_t[fNTimeBin];
796 Int_t nexp = fFeeParam->GetTFnExp();
797 Int_t tftype = fFeeParam->GetTFtype();
798
799 switch( tftype ) {
800
801 case 0: // Exponential Filter Analog Bogdan
802 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
803 FilterSimDeConvExpA( fADCF[iCol], dtarg, fNTimeBin, nexp);
804 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
805 fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
806 }
807 }
808 break;
809
810 case 1: // Exponential filter digital Bogdan
811 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
812 FilterSimDeConvExpD( fADCF[iCol], itarg, fNTimeBin, nexp);
813 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
814 fADCF[iCol][iTime] = itarg[iTime];
815 }
816 }
817 break;
818
819 case 2: // Exponential filter Marian special
820 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
821 FilterSimDeConvExpMI( fADCF[iCol], dtarg, fNTimeBin);
822 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
823 fADCF[iCol][iTime] = (Int_t) TMath::Max(0.0,dtarg[iTime]);
824 }
825 }
826 break;
1d93b218 827
828 //new
829 case 3: // Exponential filter using AliTRDtrapAlu class
830 for (Int_t iCol = 0; iCol < fNADC; iCol++) {
831 FilterSimDeConvExpEl( fADCF[iCol], itarg, fNTimeBin, nexp);
832 for (Int_t iTime = 0; iTime < fNTimeBin; iTime++) {
833 fADCF[iCol][iTime] = itarg[iTime]>>2; // to be used for raw-data
834 fADCT[iCol][iTime] = itarg[iTime]; // 12bits; to be used for tracklet; tracklet will have own container;
835 }
836 }
837 break;
838
dfd03fc3 839
840 default:
841 AliError(Form("Invalid filter type %d ! \n", tftype ));
842 break;
843 }
844
fabf2e09 845 delete [] dtarg;
846 delete [] itarg;
847
dfd03fc3 848}
849
850//_____________________________________________________________________________
851void AliTRDmcmSim::ZSMapping()
852{
0c349049 853 //
dfd03fc3 854 // Zero Suppression Mapping implemented in TRAP chip
855 //
856 // See detail TRAP manual "Data Indication" section:
857 // http://www.kip.uni-heidelberg.de/ti/TRD/doc/trap/TRAP-UserManual.pdf
0c349049 858 //
dfd03fc3 859
0c349049 860 Int_t eBIS = fFeeParam->GetEBsglIndThr(); // TRAP default = 0x4 (Tis=4)
861 Int_t eBIT = fFeeParam->GetEBsumIndThr(); // TRAP default = 0x28 (Tit=40)
862 Int_t eBIL = fFeeParam->GetEBindLUT(); // TRAP default = 0xf0
863 // (lookup table accept (I2,I1,I0)=(111)
864 // or (110) or (101) or (100))
865 Int_t eBIN = fFeeParam->GetEBignoreNeighbour(); // TRAP default = 1 (no neighbor sensitivity)
ecf39416 866 Int_t ep = AliTRDfeeParam::GetPFeffectPedestal();
867
868 if( !CheckInitialized() ) return;
dfd03fc3 869
870 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ ) {
871 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
872
ecf39416 873 // Get ADC data currently in filter buffer
0c349049 874 Int_t ap = fADCF[iadc-1][it] - ep; // previous
875 Int_t ac = fADCF[iadc ][it] - ep; // current
876 Int_t an = fADCF[iadc+1][it] - ep; // next
ecf39416 877
dfd03fc3 878 // evaluate three conditions
0c349049 879 Int_t i0 = ( ac >= ap && ac >= an ) ? 0 : 1; // peak center detection
880 Int_t i1 = ( ap + ac + an > eBIT ) ? 0 : 1; // cluster
881 Int_t i2 = ( ac > eBIS ) ? 0 : 1; // absolute large peak
882
883 Int_t i = i2 * 4 + i1 * 2 + i0; // Bit position in lookup table
884 Int_t d = (eBIL >> i) & 1; // Looking up (here d=0 means true
885 // and d=1 means false according to TRAP manual)
886
887 fZSM[iadc][it] &= d;
888 if( eBIN == 0 ) { // turn on neighboring ADCs
889 fZSM[iadc-1][it] &= d;
890 fZSM[iadc+1][it] &= d;
dfd03fc3 891 }
0c349049 892
dfd03fc3 893 }
894 }
895
896 // do 1 dim projection
897 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
898 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
ecf39416 899 fZSM1Dim[iadc] &= fZSM[iadc][it];
900 }
901 }
0c349049 902
ecf39416 903}
904
905//_____________________________________________________________________________
906void AliTRDmcmSim::DumpData( char *f, char *target )
907{
0c349049 908 //
ecf39416 909 // Dump data stored (for debugging).
910 // target should contain one or multiple of the following characters
911 // R for raw data
912 // F for filtered data
913 // Z for zero suppression map
914 // S Raw dat astream
915 // other characters are simply ignored
0c349049 916 //
917
ecf39416 918 UInt_t tempbuf[1024];
919
920 if( !CheckInitialized() ) return;
921
922 std::ofstream of( f, std::ios::out | std::ios::app );
923 of << Form("AliTRDmcmSim::DumpData det=%03d sm=%02d stack=%d layer=%d rob=%d mcm=%02d\n",
924 fChaId, fSector, fStack, fLayer, fRobPos, fMcmPos );
925
926 for( int t=0 ; target[t] != 0 ; t++ ) {
927 switch( target[t] ) {
928 case 'R' :
929 case 'r' :
930 of << Form("fADCR (raw ADC data)\n");
931 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
932 of << Form(" ADC %02d: ", iadc);
933 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
934 of << Form("% 4d", fADCR[iadc][it]);
935 }
936 of << Form("\n");
937 }
938 break;
939 case 'F' :
940 case 'f' :
941 of << Form("fADCF (filtered ADC data)\n");
942 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
943 of << Form(" ADC %02d: ", iadc);
944 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
945 of << Form("% 4d", fADCF[iadc][it]);
946 }
947 of << Form("\n");
948 }
949 break;
950 case 'Z' :
951 case 'z' :
952 of << Form("fZSM and fZSM1Dim (Zero Suppression Map)\n");
953 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
954 of << Form(" ADC %02d: ", iadc);
955 if( fZSM1Dim[iadc] == 0 ) { of << " R " ; } else { of << " . "; } // R:read .:suppressed
956 for( Int_t it = 0 ; it < fNTimeBin ; it++ ) {
957 if( fZSM[iadc][it] == 0 ) { of << " R"; } else { of << " ."; } // R:read .:suppressed
958 }
959 of << Form("\n");
960 }
961 break;
962 case 'S' :
963 case 's' :
964 Int_t s = ProduceRawStream( tempbuf, 1024 );
965 of << Form("Stream for Raw Simulation size=%d rawver=%d\n", s, fFeeParam->GetRAWversion());
966 of << Form(" address data\n");
967 for( int i = 0 ; i < s ; i++ ) {
968 of << Form(" %04x %08x\n", i, tempbuf[i]);
969 }
dfd03fc3 970 }
971 }
972}
973
974//_____________________________________________________________________________
0c349049 975void AliTRDmcmSim::FilterSimDeConvExpA(Int_t *source, Double_t *target
976 , Int_t n, Int_t nexp)
dfd03fc3 977{
978 //
979 // Exponential filter "analog"
980 // source will not be changed
981 //
982
983 Int_t i = 0;
984 Int_t k = 0;
985 Double_t reminder[2];
986 Double_t correction;
987 Double_t result;
988 Double_t rates[2];
989 Double_t coefficients[2];
990
991 // Initialize (coefficient = alpha, rates = lambda)
992 // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
993
994 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
995 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
996 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
997 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
998
999 coefficients[0] = c1;
1000 coefficients[1] = c2;
1001
1002 Double_t dt = 0.1;
1003 rates[0] = TMath::Exp(-dt/(r1));
1004 rates[1] = TMath::Exp(-dt/(r2));
1005
1006 // Attention: computation order is important
1007 correction = 0.0;
1008 for (k = 0; k < nexp; k++) {
1009 reminder[k] = 0.0;
1010 }
1011
1012 for (i = 0; i < n; i++) {
1013
1014 result = ((Double_t)source[i] - correction); // no rescaling
1015 target[i] = result;
1016
1017 for (k = 0; k < nexp; k++) {
1018 reminder[k] = rates[k] * (reminder[k] + coefficients[k] * result);
1019 }
1020
1021 correction = 0.0;
1022 for (k = 0; k < nexp; k++) {
1023 correction += reminder[k];
1024 }
1025 }
1026}
1027
1028//_____________________________________________________________________________
0c349049 1029void AliTRDmcmSim::FilterSimDeConvExpD(Int_t *source, Int_t *target, Int_t n
1030 , Int_t nexp)
dfd03fc3 1031{
1032 //
1033 // Exponential filter "digital"
1034 // source will not be changed
1035 //
1036
ecf39416 1037 Int_t i = 0;
dfd03fc3 1038 Int_t fAlphaL = 0;
1039 Int_t fAlphaS = 0;
dfd03fc3 1040 Int_t fTailPed = 0;
dfd03fc3 1041 Int_t iAlphaL = 0;
1042 Int_t iAlphaS = 0;
dfd03fc3 1043
1044 // FilterOpt.C (aliroot@pel:/homel/aliroot/root/work/beamt/CERN02)
1045 // initialize (coefficient = alpha, rates = lambda)
1046
1047 Double_t dt = 0.1;
1048 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
1049 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
1050 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
1051 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
1052
ecf39416 1053 Int_t fLambdaL = (Int_t)((TMath::Exp(-dt/r1) - 0.75) * 2048.0);
1054 Int_t fLambdaS = (Int_t)((TMath::Exp(-dt/r2) - 0.25) * 2048.0);
1055 Int_t iLambdaL = fLambdaL & 0x01FF; iLambdaL |= 0x0600; // 9 bit paramter + fixed bits
1056 Int_t iLambdaS = fLambdaS & 0x01FF; iLambdaS |= 0x0200; // 9 bit paramter + fixed bits
dfd03fc3 1057
1058 if (nexp == 1) {
1059 fAlphaL = (Int_t) (c1 * 2048.0);
1060 iAlphaL = fAlphaL & 0x03FF; // 10 bit paramter
1061 }
1062 if (nexp == 2) {
1063 fAlphaL = (Int_t) (c1 * 2048.0);
1064 fAlphaS = (Int_t) ((c2 - 0.5) * 2048.0);
1065 iAlphaL = fAlphaL & 0x03FF; // 10 bit paramter
1066 iAlphaS = fAlphaS & 0x03FF; iAlphaS |= 0x0400; // 10 bit paramter + fixed bits
1067 }
1068
1069 Double_t iAl = iAlphaL / 2048.0; // alpha L: correspondence to floating point numbers
1070 Double_t iAs = iAlphaS / 2048.0; // alpha S: correspondence to floating point numbers
1071 Double_t iLl = iLambdaL / 2048.0; // lambda L: correspondence to floating point numbers
1072 Double_t iLs = iLambdaS / 2048.0; // lambda S: correspondence to floating point numbers
1073
1074 Int_t h1;
1075 Int_t h2;
1076 Int_t rem1;
1077 Int_t rem2;
1078 Int_t correction;
1079 Int_t result;
1080 Int_t iFactor = ((Int_t) fFeeParam->GetPFeffectPedestal() ) << 2;
1081
1082 Double_t xi = 1 - (iLl*iAs + iLs*iAl); // Calculation of equilibrium values of the
1083 rem1 = (Int_t) ((iFactor/xi) * ((1-iLs)*iLl*iAl)); // Internal registers to prevent switch on effects.
1084 rem2 = (Int_t) ((iFactor/xi) * ((1-iLl)*iLs*iAs));
1085
1086 // further initialization
1087 if ((rem1 + rem2) > 0x0FFF) {
1088 correction = 0x0FFF;
1089 }
1090 else {
1091 correction = (rem1 + rem2) & 0x0FFF;
1092 }
1093
1094 fTailPed = iFactor - correction;
1095
1096 for (i = 0; i < n; i++) {
1097
ecf39416 1098 result = (source[i] - correction);
1099 if (result < 0) { // Too much undershoot
dfd03fc3 1100 result = 0;
1101 }
1102
1103 target[i] = result;
1104
1105 h1 = (rem1 + ((iAlphaL * result) >> 11));
1106 if (h1 > 0x0FFF) {
1107 h1 = 0x0FFF;
1108 }
1109 else {
1110 h1 &= 0x0FFF;
1111 }
1112
1113 h2 = (rem2 + ((iAlphaS * result) >> 11));
1114 if (h2 > 0x0FFF) {
1115 h2 = 0x0FFF;
1116 }
1117 else {
1118 h2 &= 0x0FFF;
1119 }
1120
1121 rem1 = (iLambdaL * h1 ) >> 11;
1122 rem2 = (iLambdaS * h2 ) >> 11;
1123
1124 if ((rem1 + rem2) > 0x0FFF) {
1125 correction = 0x0FFF;
1126 }
1127 else {
1128 correction = (rem1 + rem2) & 0x0FFF;
1129 }
1130
1131 }
0c349049 1132
dfd03fc3 1133}
1134
1135//_____________________________________________________________________________
0c349049 1136void AliTRDmcmSim::FilterSimDeConvExpMI(Int_t *source, Double_t *target
1137 , Int_t n)
dfd03fc3 1138{
1139 //
1140 // Exponential filter (M. Ivanov)
1141 // source will not be changed
1142 //
1143
1144 Int_t i = 0;
1145 Double_t sig1[100];
1146 Double_t sig2[100];
1147 Double_t sig3[100];
1148
1149 for (i = 0; i < n; i++) {
1150 sig1[i] = (Double_t)source[i];
1151 }
1152
1153 Float_t dt = 0.1;
1154 Float_t lambda0 = (1.0 / fFeeParam->GetTFr2()) * dt;
1155 Float_t lambda1 = (1.0 / fFeeParam->GetTFr1()) * dt;
1156
1157 FilterSimTailMakerSpline( sig1, sig2, lambda0, n);
1158 FilterSimTailCancelationMI( sig2, sig3, 0.7, lambda1, n);
1159
1160 for (i = 0; i < n; i++) {
1161 target[i] = sig3[i];
1162 }
1163
1164}
1165
1166//______________________________________________________________________________
0c349049 1167void AliTRDmcmSim::FilterSimTailMakerSpline(Double_t *ampin, Double_t *ampout
1168 , Double_t lambda, Int_t n)
dfd03fc3 1169{
1170 //
1171 // Special filter (M. Ivanov)
1172 //
1173
1174 Int_t i = 0;
1175 Double_t l = TMath::Exp(-lambda*0.5);
1176 Double_t in[1000];
1177 Double_t out[1000];
1178
1179 // Initialize in[] and out[] goes 0 ... 2*n+19
1180 for (i = 0; i < n*2+20; i++) {
1181 in[i] = out[i] = 0;
1182 }
1183
1184 // in[] goes 0, 1
1185 in[0] = ampin[0];
1186 in[1] = (ampin[0] + ampin[1]) * 0.5;
1187
1188 // Add charge to the end
1189 for (i = 0; i < 22; i++) {
1190 in[2*(n-1)+i] = ampin[n-1]; // in[] goes 2*n-2, 2*n-1, ... , 2*n+19
1191 }
1192
1193 // Use arithmetic mean
1194 for (i = 1; i < n-1; i++) {
1195 in[2*i] = ampin[i]; // in[] goes 2, 3, ... , 2*n-4, 2*n-3
1196 in[2*i+1] = ((ampin[i]+ampin[i+1]))/2.;
1197 }
1198
1199 Double_t temp;
1200 out[2*n] = in[2*n];
1201 temp = 0;
1202 for (i = 2*n; i >= 0; i--) {
1203 out[i] = in[i] + temp;
1204 temp = l*(temp+in[i]);
1205 }
1206
1207 for (i = 0; i < n; i++){
1208 //ampout[i] = out[2*i+1]; // org
1209 ampout[i] = out[2*i];
1210 }
1211
1212}
1213
1214//______________________________________________________________________________
0c349049 1215void AliTRDmcmSim::FilterSimTailCancelationMI(Double_t *ampin, Double_t *ampout
1216 , Double_t norm, Double_t lambda
1217 , Int_t n)
dfd03fc3 1218{
1219 //
1220 // Special filter (M. Ivanov)
1221 //
1222
1223 Int_t i = 0;
1224
1225 Double_t l = TMath::Exp(-lambda*0.5);
1226 Double_t k = l*(1.0 - norm*lambda*0.5);
1227 Double_t in[1000];
1228 Double_t out[1000];
1229
1230 // Initialize in[] and out[] goes 0 ... 2*n+19
1231 for (i = 0; i < n*2+20; i++) {
1232 in[i] = out[i] = 0;
1233 }
1234
1235 // in[] goes 0, 1
1236 in[0] = ampin[0];
1237 in[1] = (ampin[0]+ampin[1])*0.5;
1238
1239 // Add charge to the end
1240 for (i =-2; i < 22; i++) {
1241 // in[] goes 2*n-4, 2*n-3, ... , 2*n+19
1242 in[2*(n-1)+i] = ampin[n-1];
1243 }
1244
1245 for (i = 1; i < n-2; i++) {
1246 // in[] goes 2, 3, ... , 2*n-6, 2*n-5
1247 in[2*i] = ampin[i];
1248 in[2*i+1] = (9.0 * (ampin[i]+ampin[i+1]) - (ampin[i-1]+ampin[i+2])) / 16.0;
1249 //in[2*i+1] = ((ampin[i]+ampin[i+1]))/2.0;
1250 }
1251
1252 Double_t temp;
1253 out[0] = in[0];
1254 temp = in[0];
1255 for (i = 1; i <= 2*n; i++) {
1256 out[i] = in[i] + (k-l)*temp;
1257 temp = in[i] + k *temp;
1258 }
1259
1260 for (i = 0; i < n; i++) {
1261 //ampout[i] = out[2*i+1]; // org
1262 //ampout[i] = TMath::Max(out[2*i+1],0.0); // org
1263 ampout[i] = TMath::Max(out[2*i],0.0);
1264 }
1265}
1266
1d93b218 1267
1268//_____________________________________________________________________________________
1269//the following filter uses AliTRDtrapAlu-class
1270
1271void AliTRDmcmSim::FilterSimDeConvExpEl(Int_t *source, Int_t *target, Int_t n, Int_t nexp) {
1272 //static Int_t count = 0;
1273
1274 Double_t dt = 0.1;
1275 Double_t r1 = (Double_t)fFeeParam->GetTFr1();
1276 Double_t r2 = (Double_t)fFeeParam->GetTFr2();
1277 Double_t c1 = (Double_t)fFeeParam->GetTFc1();
1278 Double_t c2 = (Double_t)fFeeParam->GetTFc2();
1279
1280 nexp = 1;
1281
1282 //it is assumed that r1,r2,c1,c2 are given such, that the configuration values are in the ranges according to TRAP-manual
1283 //parameters need to be adjusted
1284 AliTRDtrapAlu lambdaL;
1285 AliTRDtrapAlu lambdaS;
1286 AliTRDtrapAlu alphaL;
1287 AliTRDtrapAlu alphaS;
1288
1289 AliTRDtrapAlu correction;
1290 AliTRDtrapAlu result;
1291 AliTRDtrapAlu bufL;
1292 AliTRDtrapAlu bufS;
1293
1294 AliTRDtrapAlu bSource;
1295
1296 lambdaL.Init(1,11);
1297 lambdaS.Init(1,11);
1298 alphaL.Init(1,11);
1299 alphaS.Init(1,11);
1300
1301 //count=count+1;
1302
1303 lambdaL.AssignDouble(TMath::Exp(-dt/r1));
1304 lambdaS.AssignDouble(TMath::Exp(-dt/r2));
1305 alphaL.AssignDouble(c1); // in AliTRDfeeParam the number of exponentials is set and also the according time constants
1306 alphaS.AssignDouble(c2); // later it should be: alphaS=1-alphaL
1307
1308 //data is enlarged to 12 bits, including 2 bits after the comma; class AliTRDtrapAlu is used to handle arithmetics correctly
1309 correction.Init(10,2);
1310 result.Init(10,2);
1311 bufL.Init(10,2);
1312 bufS.Init(10,2);
1313 bSource.Init(10,2);
1314
1315 for(Int_t i = 0; i < n; i++) {
1316 bSource.AssignInt(source[i]);
1317 result = bSource - correction; // subtraction can produce an underflow
1318 if(result.GetSign() == kTRUE) {
1319 result.AssignInt(0);
1320 }
1321
1322 //target[i] = result.GetValuePre(); // later, target and source should become AliTRDtrapAlu,too in order to simulate the 10+2Bits through the filter properly
1323
1324 target[i] = result.GetValue(); // 12 bit-value; to get the corresponding integer value, target must be shifted: target>>2
1325
1326 //printf("target-Wert zur Zeit %d : %d",i,target[i]);
1327 //printf("\n");
1328
1329 bufL = bufL + (result * alphaL);
1330 bufL = bufL * lambdaL;
1331
1332 bufS = bufS + (result * alphaS);
1333 bufS = bufS * lambdaS; // eventually this should look like:
1334 // bufS = (bufS + (result - result * alphaL)) * lambdaS // alphaS=1-alphaL; then alphaS-variable is not needed any more
1335
1336 correction = bufL + bufS; //check for overflow intrinsic; if overflowed, correction is set to 0x03FF
1337 }
1338
1339
1340}
1341
1342
1343
1344
1345
1346
1347
1d93b218 1348//__________________________________________________________________________________
1349
1350
1351// in order to use the Tracklets, please first
1352// -- set AliTRDfeeParam::fgkTracklet to kTRUE, in order to switch on Tracklet-calculation
1353// -- set AliTRDfeeParam::fgkTFtype to 3, in order to use the new tail cancellation filter
96e6312d 1354// currently tracklets from filtered digits are only given when setting fgkTFtype (AliTRDfeeParam) to 3
1355// -- set AliTRDfeeParam::fgkMCTrackletOutput to kTRUE, if you want to use the Tracklet output container with information about the Tracklet position (MCM, channel number)
1d93b218 1356
96e6312d 1357// 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
1d93b218 1358
1359void AliTRDmcmSim::Tracklet(){
1360 // tracklet calculation
96e6312d 1361 // if you use this code after a simulation, please make sure the same filter-settings as in the simulation are set in AliTRDfeeParam
1d93b218 1362
1363 if(!CheckInitialized()){ return; }
1364
1365 Bool_t filtered = kTRUE;
1366
1367
1368
1369 AliTRDtrapAlu data;
1370 data.Init(10,2);
1371 if(fADCT[0][0]==-1){ // check if filter was applied
1372 filtered = kFALSE;
1373 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
1374 for( Int_t iT = 0 ; iT < fNTimeBin ; iT++ ) {
1375 data.AssignInt(fADCR[iadc][iT]);
96e6312d 1376 fADCT[iadc][iT] = data.GetValue(); // all incoming values are positive 10+2 bit values; if el.filter was called, this is done correctly
1d93b218 1377 }
1378 }
1379
1380 }
1381
96e6312d 1382 // the online ordering of mcm's is reverse to the TRAP-manual-ordering! reverse fADCT (to be consistent to TRAP), then do all calculations
1d93b218 1383 // reverse fADCT:
1384 Int_t** rev0 = new Int_t *[fNADC];
1385 Int_t** rev1 = new Int_t *[fNADC];
1386
1387 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
1388 rev0[iadc] = new Int_t[fNTimeBin];
1389 rev1[iadc] = new Int_t[fNTimeBin];
1390 for( Int_t iT = 0; iT < fNTimeBin; iT++) {
1391 if( iadc <= fNADC-iadc-1 ) {
1392 rev0[iadc][iT] = fADCT[fNADC-iadc-1][iT];
1393 rev1[iadc][iT] = fADCT[iadc][iT];
1394 fADCT[iadc][iT] = rev0[iadc][iT];
1395 }
1396 else {
1397 rev0[iadc][iT] = rev1[fNADC-iadc-1][iT];
1398 fADCT[iadc][iT] = rev0[iadc][iT];
1399 }
1400 }
1401 }
1402 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ ) {
1403 delete[] rev0[iadc];
1404 delete[] rev1[iadc];
1405 }
1406
1407 delete[] rev0;
1408 delete[] rev1;
1409
1410 rev0 = NULL;
1411 rev1 = NULL;
1412
1413 // get the filtered pedestal; supports only electronic tail-cancellation filter
1414 AliTRDtrapAlu filPed;
1415 Int_t ep = 0;
1416 Int_t *ieffped = new Int_t[fNTimeBin];
1417 for(Int_t iT = 0; iT < fNTimeBin; iT++){
1418 ieffped[iT] = ep;
1419 }
1420
1421 if( filtered == kTRUE ) {
1422 if( fFeeParam->IsPFon() ){
1423 ep = fFeeParam->GetPFeffectPedestal();
1424 }
1425 Int_t nexp = fFeeParam->GetTFnExp();
1426 Int_t *isource = new Int_t[fNTimeBin];
1427 filPed.Init(10,2);
1428 filPed.AssignInt(ep);
1429 Int_t epf = filPed.GetValue();
1430 for(Int_t iT = 0; iT < fNTimeBin; iT++){
1431 isource[iT] = ep;
1432 ieffped[iT] = epf;
1433 }
1434
1435 if( fFeeParam->IsTFon() ) {
1436 FilterSimDeConvExpEl( isource, ieffped, fNTimeBin, nexp);
1437 }
1438
1439 delete[] isource;
1440 }
1441
96e6312d 1442 //the following values should go to AliTRDfeeParam once they are defined; then they have to be read in properly
1d93b218 1443 //naming follows conventions in TRAP-manual
1444
1445
1446 Bool_t bVBY = kTRUE; // cluster-verification bypass
1447
1448 Double_t cQTParam = 0; // cluster quality threshold; granularity 2^-10; range: 0<=cQT/2^-10<=2^-4 - 2^-10
1449 AliTRDtrapAlu cQTAlu;
1450 cQTAlu.Init(1,10,0,63);
1451 cQTAlu.AssignDouble(cQTParam);
1452 Int_t cQT = cQTAlu.GetValue();
1453
1454 // linear fit
1455 Int_t tFS = fFeeParam->GetLinearFitStart(); // linear fit start
1456 Int_t tFE = fFeeParam->GetLinearFitEnd(); // linear fit stop
1457
1458 // charge accumulators
1459 Int_t tQS0 = fFeeParam->GetQacc0Start(); // start-time for charge-accumulator 0
1460 Int_t tQE0 = fFeeParam->GetQacc0End(); // stop-time for charge-accumulator 0
1461 Int_t tQS1 = fFeeParam->GetQacc1Start(); // start-time for charge-accumulator 1
1462 Int_t tQE1 = fFeeParam->GetQacc1End(); // stop-time for charge-accumulator 1
1463 // values set such that tQS0=tFS; tQE0=tQS1-1; tFE=tQE1; want to do (QS0+QS1)/N
1464
1465 Double_t cTHParam = (Double_t)fFeeParam->GetMinClusterCharge(); // cluster charge threshold
1466 AliTRDtrapAlu cTHAlu;
1467 cTHAlu.Init(12,2);
1468 cTHAlu.AssignDouble(cTHParam);
1469 Int_t cTH = cTHAlu.GetValue(); // cTH used for comparison
1470
1471 struct List_t {
1472 List_t *next;
1473 Int_t iadc;
1474 Int_t value;
1475 };
1476
1477 List_t selection[7]; // list with 7 elements
1478 List_t *list = NULL;
1479 List_t *listLeft = NULL;
1480
1481 Int_t* qsum = new Int_t[fNADC];
1482
1483 // fit sums
1484 AliTRDtrapAlu qsumAlu;
1485 qsumAlu.Init(12,2); // charge sum will be 12+2 bits
1486 AliTRDtrapAlu dCOGAlu;
1487 dCOGAlu.Init(1,7,0,127); // COG will be 1+7 Bits; maximum 1 - 2^-7 for LUT
1488 AliTRDtrapAlu yrawAlu;
1489 yrawAlu.Init(1,8,-1,255);
1490 AliTRDtrapAlu yAlu;
1491 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 -
1492 AliTRDtrapAlu xAlu;
1493 xAlu.Init(5,8); // 8 past-comma bits because value will be added/multiplied to another value with this accuracy
1494 AliTRDtrapAlu xxAlu;
1495 xxAlu.Init(10,0);
1496 AliTRDtrapAlu yyAlu;
1497 yyAlu.Init(1,16,0,0xFFFF); // maximum is 2^16-1; 16Bit for past-commas
1498 AliTRDtrapAlu xyAlu;
1499 xyAlu.Init(6,8);
1500 AliTRDtrapAlu XAlu;
1501 XAlu.Init(9,0);
1502 AliTRDtrapAlu XXAlu;
1503 XXAlu.Init(14,0);
1504 AliTRDtrapAlu YAlu;
1505 YAlu.Init(5,8); // 14 bit, 1 is sign-bit; therefore only 13 bit
1506 AliTRDtrapAlu YYAlu;
1507 YYAlu.Init(5,16);
1508 AliTRDtrapAlu XYAlu;
1509 XYAlu.Init(8,8); // 17 bit, 1 is sign-bit; therefore only 16 bit
1510 AliTRDtrapAlu qtruncAlu;
1511 qtruncAlu.Init(12,0);
1512 AliTRDtrapAlu QT0Alu;
1513 QT0Alu.Init(15,0);
1514 AliTRDtrapAlu QT1Alu;
1515 QT1Alu.Init(16,0);
96e6312d 1516
1517 AliTRDtrapAlu oneAlu;
1518 oneAlu.Init(1,8);
1d93b218 1519
1520
1521 AliTRDtrapAlu inverseNAlu;
96e6312d 1522 inverseNAlu.Init(1,8); // simulates the LUT for 1/N
1d93b218 1523 AliTRDtrapAlu MeanChargeAlu; // mean charge in ADC counts
1524 MeanChargeAlu.Init(8,0);
1525 AliTRDtrapAlu TotalChargeAlu;
1526 TotalChargeAlu.Init(17,8);
1527 //nr of post comma bits should be the same for inverseN and TotalCharge
1528
1529
1530 SetPosLUT(); // initialize the position correction LUT for this MCM;
1531
1532
1533 // fit-sums; remapping!; 0,1,2->0; 1,2,3->1; ... 18,19,20->18
1534 Int_t *X = new Int_t[fNADC-2];
1535 Int_t *XX = new Int_t[fNADC-2];
1536 Int_t *Y = new Int_t[fNADC-2];
1537 Int_t *YY = new Int_t[fNADC-2];
1538 Int_t *XY = new Int_t[fNADC-2];
1539 Int_t *N = new Int_t[fNADC-2];
1540 Int_t *QT0 = new Int_t[fNADC-2]; // accumulated charge
1541 Int_t *QT1 = new Int_t[fNADC-2]; // accumulated charge
1542
1543 for (Int_t iCol = 0; iCol < fNADC-2; iCol++) {
1544
1545 // initialize fit-sums
1546 X[iCol] = 0;
1547 XX[iCol] = 0;
1548 Y[iCol] = 0;
1549 YY[iCol] = 0;
1550 XY[iCol] = 0;
1551 N[iCol] = 0;
1552 QT0[iCol] = 0;
1553 QT1[iCol] = 0;
1554 }
1555
1556
1557 filPed.Init(7,2); // convert filtered pedestal into 7+2Bits
1558
1559 for(Int_t iT = 0; iT < fNTimeBin; iT++){
1560
96e6312d 1561 if(iT<tFS || iT>=tFE) continue; // linear fit yes/no?
1d93b218 1562
1563 // reset
1564 Int_t portChannel[4] = {-1,-1,-1,-1};
1565 Int_t clusterCharge[4] = {0,0,0,0};
1566 Int_t leftCharge[4] = {0,0,0,0};
1567 Int_t centerCharge[4] = {0,0,0,0};
1568 Int_t rightCharge[4] = {0,0,0,0};
1569
1570 Int_t mark = 0;
1571
96e6312d 1572 filPed.AssignFormatted(ieffped[iT]); // no size-checking when using AssignFormatted; ieffped>=0
1d93b218 1573 filPed = filPed; // this checks the size
1574
1575 ieffped[iT] = filPed.GetValue();
1576
1577 for(Int_t i = 0; i<7; i++){
1578 selection[i].next = NULL;
1579 selection[i].iadc = -1; // value of -1: invalid adc
1580 selection[i].value = 0;
1581
1582 }
1583 // selection[0] is starting list-element; just for pointing
1584
1585 // loop over inner adc's
1586 for (Int_t iCol = 1; iCol < fNADC-1; iCol++) {
1587
1588 Int_t left = fADCT[iCol-1][iT];
1589 Int_t center = fADCT[iCol][iT];
1590 Int_t right = fADCT[iCol+1][iT];
1591
1592 Int_t sum = left + center + right; // cluster charge sum
1593 qsumAlu.AssignFormatted(sum);
1594 qsumAlu = qsumAlu; // size-checking; redundant
1595
1596 qsum[iCol] = qsumAlu.GetValue();
1597
1598 //hit detection and masking
1599 if(center>=left){
1600 if(center>right){
1601 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
1602 mark |= 1; // marker
1603 }
1604 }
1605 }
1606 mark = mark<<1;
1607 }
1608 mark = mark>>1;
1609
1610
1611 // get selection of 6 adc's and sort,starting with greatest values
1612
1613 //read three from right side and sort (primitive sorting algorithm)
1614 Int_t i = 0; // adc number
1615 Int_t j = 1; // selection number
1616 while(i<fNADC-2 && j<=3){
1617 i = i + 1;
5a67d089 1618 if( ((mark>>(i-1)) & 1) == 1) {
1d93b218 1619 selection[j].iadc = fNADC-1-i;
1620 selection[j].value = qsum[fNADC-1-i]>>6; // for hit-selection only the first 8 out of the 14 Bits are used for comparison
1621
1622 // insert into sorted list
1623 listLeft = &selection[0];
1624 list = listLeft->next;
1625
1626 if(list!=NULL) {
1627 while((list->next != NULL) && (selection[j].value <= list->value)){
1628 listLeft = list;
1629 list = list->next;
1630 }
1631
1632 if(selection[j].value<=list->value){
1633 selection[j].next = list->next;
1634 list->next = &selection[j];
1635 }
1636 else {
1637 listLeft->next = &selection[j];
1638 selection[j].next = list;
1639 }
1640 }
1641 else{
1642 listLeft->next = &selection[j];
1643 selection[j].next = list;
1644 }
1645
1646 j = j + 1;
1647 }
1648 }
1649
1650
1651 // read three from left side
1652 Int_t k = fNADC-2;
1653 while(k>i && j<=6) {
5a67d089 1654 if( ((mark>>(k-1)) & 1) == 1) {
1d93b218 1655 selection[j].iadc = fNADC-1-k;
1656 selection[j].value = qsum[fNADC-1-k]>>6;
1657
1658 listLeft = &selection[0];
1659 list = listLeft->next;
1660
1661 if(list!=NULL){
1662 while((list->next != NULL) && (selection[j].value <= list->value)){
1663 listLeft = list;
1664 list = list->next;
1665 }
1666
1667 if(selection[j].value<=list->value){
1668 selection[j].next = list->next;
1669 list->next = &selection[j];
1670 }
1671 else {
1672 listLeft->next = &selection[j];
1673 selection[j].next = list;
1674 }
1675 }
1676 else{
1677 listLeft->next = &selection[j];
1678 selection[j].next = list;
1679 }
1680
1681 j = j + 1;
1682 }
1683 k = k - 1;
1684 }
1685
1686 // get the four with greatest charge-sum
1687 list = &selection[0];
1688 for(i = 0; i<4; i++){
1689 if(list->next == NULL) continue;
1690 list = list->next;
1691 if(list->iadc == -1) continue;
1692 Int_t adc = list->iadc; // channel number with selected hit
1693
1694 // the following arrays contain the four chosen channels in 1 time-bin
1695 portChannel[i] = adc;
1696 clusterCharge[i] = qsum[adc];
1697 leftCharge[i] = fADCT[adc-1][iT] - ieffped[iT]; // reduce by filtered pedestal (pedestal is part of the signal)
1698 centerCharge[i] = fADCT[adc][iT] - ieffped[iT];
1699 rightCharge[i] = fADCT[adc+1][iT] - ieffped[iT];
1700 }
1701
1702 // arithmetic unit
1703
1704 // cluster verification
1705 if(!bVBY){
1706 for(i = 0; i<4; i++){
1707 Int_t lr = leftCharge[i]*rightCharge[i]*1024;
1708 Int_t cc = centerCharge[i]*centerCharge[i]*cQT;
1709 if (lr>=cc){
1710 portChannel[i] = -1; // set to invalid address
1711 clusterCharge[i] = 0;
1712 }
1713 }
1714 }
1715
1716 // fit-sums of valid channels
1717 // local hit position
1718 for(i = 0; i<4; i++){
1719 if (centerCharge[i] == 0) {
1720 portChannel[i] = -1;
1721 }// prevent division by 0
1722
1723 if (portChannel[i] == -1) continue;
1724
1725 Double_t dCOG = (Double_t)(rightCharge[i]-leftCharge[i])/centerCharge[i];
1726
1727 Bool_t sign = (dCOG>=0.0) ? kFALSE : kTRUE;
1728 dCOG = (sign == kFALSE) ? dCOG : -dCOG; // AssignDouble doesn't allow for signed doubles
1729 dCOGAlu.AssignDouble(dCOG);
1730 Int_t iLUTpos = dCOGAlu.GetValue(); // steers position in LUT
1731
1732 dCOG = dCOG/2;
1733 yrawAlu.AssignDouble(dCOG);
1734 Int_t iCOG = yrawAlu.GetValue();
1735 Int_t y = iCOG + fPosLUT[iLUTpos % 128]; // local position in pad-units
1736 yrawAlu.AssignFormatted(y); // 0<y<1
1737 yAlu = yrawAlu; // convert to 16 past-comma bits
1738
1739 if(sign == kTRUE) yAlu.SetSign(-1); // buffer width of 9 bits; sign on real (not estimated) position
1740 xAlu.AssignInt(iT); // buffer width of 5 bits
1741
1742
1743 xxAlu = xAlu * xAlu; // buffer width of 10 bits -> fulfilled by x*x
1744
1745 yyAlu = yAlu * yAlu; // buffer width of 16 bits
1746
1747 xyAlu = xAlu * yAlu; // buffer width of 14 bits
1748
1749 Int_t adc = portChannel[i]-1; // remapping! port-channel contains channel-nr. of inner adc's (1..19; mapped to 0..18)
1750
1751 // calculate fit-sums recursively
1752 // interpretation of their bit-length is given as comment
1753
1754 // be aware that the accuracy of the result of a calculation is always determined by the accuracy of the less accurate value
1755
1756 XAlu.AssignFormatted(X[adc]);
1757 XAlu = XAlu + xAlu; // buffer width of 9 bits
1758 X[adc] = XAlu.GetValue();
1759
1760 XXAlu.AssignFormatted(XX[adc]);
1761 XXAlu = XXAlu + xxAlu; // buffer width of 14 bits
1762 XX[adc] = XXAlu.GetValue();
1763
1764 if (Y[adc] < 0) {
1765 YAlu.AssignFormatted(-Y[adc]); // make sure that only positive values are assigned; sign-setting must be done by hand
1766 YAlu.SetSign(-1);
1767 }
1768 else {
1769 YAlu.AssignFormatted(Y[adc]);
1770 YAlu.SetSign(1);
1771 }
1772
1773 YAlu = YAlu + yAlu; // buffer width of 14 bits (8 past-comma);
1774 Y[adc] = YAlu.GetSignedValue();
1775
1776 YYAlu.AssignFormatted(YY[adc]);
1777 YYAlu = YYAlu + yyAlu; // buffer width of 21 bits (16 past-comma)
1778 YY[adc] = YYAlu.GetValue();
1779
1780 if (XY[adc] < 0) {
1781 XYAlu.AssignFormatted(-XY[adc]);
1782 XYAlu.SetSign(-1);
1783 }
1784 else {
1785 XYAlu.AssignFormatted(XY[adc]);
1786 XYAlu.SetSign(1);
1787 }
1788
1789 XYAlu = XYAlu + xyAlu; // buffer allows 17 bits (8 past-comma)
1790 XY[adc] = XYAlu.GetSignedValue();
1791
1792 N[adc] = N[adc] + 1;
1793
1794
1795 // accumulated charge
1796 qsumAlu.AssignFormatted(qsum[adc+1]); // qsum was not remapped!
1797 qtruncAlu = qsumAlu;
1798
1799 if(iT>=tQS0 && iT<=tQE0){
1800 QT0Alu.AssignFormatted(QT0[adc]);
1801 QT0Alu = QT0Alu + qtruncAlu;
1802 QT0[adc] = QT0Alu.GetValue();
1803 //interpretation of QT0 as 12bit-value (all pre-comma); is this as it should be done?; buffer allows 15 Bit
1804 }
1805
1806 if(iT>=tQS1 && iT<=tQE1){
1807 QT1Alu.AssignFormatted(QT1[adc]);
1808 QT1Alu = QT1Alu + qtruncAlu;
1809 QT1[adc] = QT1Alu.GetValue();
1810 //interpretation of QT1 as 12bit-value; buffer allows 16 Bit
1811 }
1812 }// i
1813
1814 // remapping is done!!
1815
1816 }//iT
1817
1818
1819
1820 // tracklet-assembly
1821
1822 // put into AliTRDfeeParam and take care that values are in proper range
1823 const Int_t cTCL = 1; // left adc: number of hits; 8<=TCL<=31 (?? 1<=cTCL<+8 ??)
96e6312d 1824 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%)
1d93b218 1825
1826 Int_t mPair = 0; // marker for possible tracklet pairs
1827 Int_t* hitSum = new Int_t[fNADC-3];
1828 // hitSum[0] means: hit sum of remapped channels 0 and 1; hitSum[17]: 17 and 18;
1829
1830 // check for all possible tracklet-pairs of adjacent channels (two are merged); mark the left channel of the chosen pairs
1831 for (Int_t iCol = 0; iCol < fNADC-3; iCol++) {
1832 hitSum[iCol] = N[iCol] + N[iCol+1];
1833 if ((N[iCol]>=cTCL) && (hitSum[iCol]>=cTCT)) {
1834 mPair |= 1; // mark as possible channel-pair
1835
1836 }
1837 mPair = mPair<<1;
1838 }
1839 mPair = mPair>>1;
1840
1841 List_t* selectPair = new List_t[fNADC-2]; // list with 18 elements (0..18) containing the left channel-nr and hit sums
1842 // selectPair[18] is starting list-element just for pointing
1843 for(Int_t k = 0; k<fNADC-2; k++){
1844 selectPair[k].next = NULL;
1845 selectPair[k].iadc = -1; // invalid adc
1846 selectPair[k].value = 0;
1847
1848 }
1849
1850 list = NULL;
1851 listLeft = NULL;
1852
1853 // read marker and sort according to hit-sum
1854
1855 Int_t adcL = 0; // left adc-channel-number (remapped)
1856 Int_t selNr = 0; // current number in list
1857
1858 // insert marked channels into list and sort according to hit-sum
1859 while(adcL < fNADC-3 && selNr < fNADC-3){
1860
5a67d089 1861 if( ((mPair>>((fNADC-4)-(adcL))) & 1) == 1) {
1d93b218 1862 selectPair[selNr].iadc = adcL;
1863 selectPair[selNr].value = hitSum[adcL];
1864
1865 listLeft = &selectPair[fNADC-3];
1866 list = listLeft->next;
1867
1868 if(list!=NULL) {
1869 while((list->next != NULL) && (selectPair[selNr].value <= list->value)){
1870 listLeft = list;
1871 list = list->next;
1872 }
1873
1874 if(selectPair[selNr].value <= list->value){
1875 selectPair[selNr].next = list->next;
1876 list->next = &selectPair[selNr];
1877 }
1878 else {
1879 listLeft->next = &selectPair[selNr];
1880 selectPair[selNr].next = list;
1881 }
1882
1883 }
1884 else{
1885 listLeft->next = &selectPair[selNr];
1886 selectPair[selNr].next = list;
1887 }
1888
1889 selNr = selNr + 1;
1890 }
1891 adcL = adcL + 1;
1892 }
1893
1894 //select up to 4 channels with maximum number of hits
1895 Int_t lpairChannel[4] = {-1,-1,-1,-1}; // save the left channel-numbers of pairs with most hit-sum
1896 Int_t rpairChannel[4] = {-1,-1,-1,-1}; // save the right channel, too; needed for detecting double tracklets
1897 list = &selectPair[fNADC-3];
1898
1899 for (Int_t i = 0; i<4; i++) {
1900 if(list->next == NULL) continue;
1901 list = list->next;
1902 if(list->iadc == -1) continue;
1903 lpairChannel[i] = list->iadc; // channel number with selected hit
1904 rpairChannel[i] = lpairChannel[i]+1;
1905 }
1906
1907 // avoid submission of double tracklets
1908 for (Int_t i = 3; i>0; i--) {
1909 for (Int_t j = i-1; j>-1; j--) {
1910 if(lpairChannel[i] == rpairChannel[j]) {
1911 lpairChannel[i] = -1;
1912 rpairChannel[i] = -1;
1913 break;
1914 }
96e6312d 1915 /* if(rpairChannel[i] == lpairChannel[j]) {
1d93b218 1916 lpairChannel[i] = -1;
1917 rpairChannel[i] = -1;
1918 break;
96e6312d 1919 }*/
1d93b218 1920 }
1921 }
1922
1923 // merging of the fit-sums of the remainig channels
1924 // assume same data-word-width as for fit-sums for 1 channel
1925 // relative scales!
1926 Int_t mADC[4];
1927 Int_t mN[4];
1928 Int_t mQT0[4];
1929 Int_t mQT1[4];
1930 Int_t mX[4];
1931 Int_t mXX[4];
1932 Int_t mY[4];
1933 Int_t mYY[4];
1934 Int_t mXY[4];
1935 Int_t mOffset[4];
1936 Int_t mSlope[4];
1937 Int_t mMeanCharge[4];
1938 Int_t inverseN = 0;
1939 Double_t invN = 0;
96e6312d 1940 Int_t one = 0;
1941
1d93b218 1942 for (Int_t i = 0; i<4; i++){
1943 mADC[i] = -1; // set to invalid number
1944 mN[i] = 0;
1945 mQT0[i] = 0;
1946 mQT1[i] = 0;
1947 mX[i] = 0;
1948 mXX[i] = 0;
1949 mY[i] = 0;
1950 mYY[i] = 0;
1951 mXY[i] = 0;
1952 mOffset[i] = 0;
1953 mSlope[i] = 0;
1954 mMeanCharge[i] = 0;
1955 }
1956
96e6312d 1957 oneAlu.AssignInt(1);
1958 one = oneAlu.GetValue(); // one with 8 past comma bits
1d93b218 1959
1960 for (Int_t i = 0; i<4; i++){
96e6312d 1961
1962
1d93b218 1963 mADC[i] = lpairChannel[i]; // mapping of merged sums to left channel nr. (0,1->0; 1,2->1; ... 17,18->17)
96e6312d 1964 // the adc and pad-mapping should now be one to one: adc i is linked to pad i; TRAP-numbering
1d93b218 1965 Int_t madc = mADC[i];
1966 if (madc == -1) continue;
96e6312d 1967
1968 YAlu.AssignInt(N[rpairChannel[i]]);
1969 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)
1970
1d93b218 1971 mN[i] = hitSum[madc];
1972
1973 // 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
1974 if (N[madc+1] == 0) {
1975 mQT0[i] = QT0[madc];
1976 mQT1[i] = QT1[madc];
1977
1978 }
1979 else {
1980
1981 // is it ok to do the size-checking for the merged fit-sums with the same format as for single-channel fit-sums?
1982
1983 mQT0[i] = QT0[madc] + QT0[madc+1];
1984 QT0Alu.AssignFormatted(mQT0[i]);
1985 QT0Alu = QT0Alu; // size-check
1986 mQT0[i] = QT0Alu.GetValue(); // write back
1987
1988 mQT1[i] = QT1[madc] + QT1[madc+1];
1989 QT1Alu.AssignFormatted(mQT1[i]);
1990 QT1Alu = QT1Alu;
1991 mQT1[i] = QT1Alu.GetValue();
1992 }
1993
1994 // calculate the mean charge in adc values; later to be replaced by electron likelihood
1995 mMeanCharge[i] = mQT0[i] + mQT1[i]; // total charge
1996 mMeanCharge[i] = mMeanCharge[i]>>2; // losing of accuracy; accounts for high mean charge
1997 // 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
1998 invN = 1.0/(mN[i]);
1999 inverseNAlu.AssignDouble(invN);
2000 inverseN = inverseNAlu.GetValue();
2001 mMeanCharge[i] = mMeanCharge[i] * inverseN; // now to be interpreted with 8 past-comma bits
2002 TotalChargeAlu.AssignFormatted(mMeanCharge[i]);
2003 TotalChargeAlu = TotalChargeAlu;
2004 MeanChargeAlu = TotalChargeAlu;
2005 mMeanCharge[i] = MeanChargeAlu.GetValue();
2006
96e6312d 2007 // this check is not necessary; it is just for efficiency reasons
1d93b218 2008 if (N[madc+1] == 0) {
2009 mX[i] = X[madc];
2010 mXX[i] = XX[madc];
2011 mY[i] = Y[madc];
2012 mXY[i] = XY[madc];
2013 mYY[i] = YY[madc];
2014 }
2015 else {
2016
2017 mX[i] = X[madc] + X[madc+1];
2018 XAlu.AssignFormatted(mX[i]);
96e6312d 2019 XAlu = XAlu;
1d93b218 2020 mX[i] = XAlu.GetValue();
2021
2022 mXX[i] = XX[madc] + XX[madc+1];
2023 XXAlu.AssignFormatted(mXX[i]);
96e6312d 2024 XXAlu = XXAlu;
1d93b218 2025 mXX[i] = XXAlu.GetValue();
2026
2027
2028 mY[i] = Y[madc] + Y[madc+1] + wpad;
2029 if (mY[i] < 0) {
2030 YAlu.AssignFormatted(-mY[i]);
2031 YAlu.SetSign(-1);
2032 }
2033 else {
2034 YAlu.AssignFormatted(mY[i]);
2035 YAlu.SetSign(1);
2036 }
2037 YAlu = YAlu;
2038 mY[i] = YAlu.GetSignedValue();
2039
96e6312d 2040 mXY[i] = XY[madc] + XY[madc+1] + X[madc+1]*one; // multiplication by one to maintain the data format
1d93b218 2041
2042 if (mXY[i] < 0) {
2043 XYAlu.AssignFormatted(-mXY[i]);
2044 XYAlu.SetSign(-1);
2045 }
2046 else {
2047 XYAlu.AssignFormatted(mXY[i]);
2048 XYAlu.SetSign(1);
2049 }
2050 XYAlu = XYAlu;
2051 mXY[i] = XYAlu.GetSignedValue();
2052
96e6312d 2053 mYY[i] = YY[madc] + YY[madc+1] + 2*Y[madc+1]*one+ wpad*one;
1d93b218 2054 if (mYY[i] < 0) {
2055 YYAlu.AssignFormatted(-mYY[i]);
2056 YYAlu.SetSign(-1);
2057 }
2058 else {
2059 YYAlu.AssignFormatted(mYY[i]);
2060 YYAlu.SetSign(1);
2061 }
2062
2063 YYAlu = YYAlu;
2064 mYY[i] = YYAlu.GetSignedValue();
2065 }
2066
2067 }
2068
2069 // calculation of offset and slope from the merged fit-sums;
2070 // YY is needed for some error measure only; still to be done
2071 // be aware that all values are relative values (scale: timebin-width; pad-width) and are integer values on special scale
2072
23200400 2073 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2074 // !!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 !!
2075 // !!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. !!
2076 // !!This has to be taken into account by the GTU. Furthermore a Lorentz correction might have to be applied to the offset (see below). !!
2077 // !!In this implementation it is assumed that no miscalibration containing changing drift velocities in the amplification region is used. !!
2078 // !!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 !!
2079 // !!valid (in approximation) if tFS is close to the beginning of the drift region. !!
2080 // !!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 !!
2081 // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
2082
1d93b218 2083 // which formats should be chosen?
2084 AliTRDtrapAlu denomAlu;
2085 denomAlu.Init(20,8);
2086 AliTRDtrapAlu numAlu;
2087 numAlu.Init(20,8);
2088 // is this enough pre-comma place? covers the range of the 13 bit-word of the transmitted offset
2089 // offset measured in coord. of left channel must be between -0.5 and 1.5; 14 pre-comma bits because numerator can be big
2090
2091 for (Int_t i = 0; i<4; i++) {
2092 if (mADC[i] == -1) continue;
2093
2094 Int_t num0 = (mN[i]*mXX[i]-mX[i]*mX[i]);
2095 if (num0 < 0) {
2096 denomAlu.AssignInt(-num0); // num0 does not have to be interpreted as having past-comma bits -> AssignInt
2097 denomAlu.SetSign(-1);
2098 }
2099 else {
2100 denomAlu.AssignInt(num0);
2101 denomAlu.SetSign(1);
2102 }
2103
2104 Int_t num1 = mN[i]*mXY[i] - mX[i]*mY[i];
2105 if (num1 < 0) {
2106 numAlu.AssignFormatted(-num1); // value of num1 is already formatted to have 8 past-comma bits
2107 numAlu.SetSign(-1);
2108 }
2109 else {
2110 numAlu.AssignFormatted(num1);
2111 numAlu.SetSign(1);
2112 }
2113 numAlu = numAlu/denomAlu;
2114 mSlope[i] = numAlu.GetSignedValue();
2115
2116 Int_t num2 = mXX[i]*mY[i] - mX[i]*mXY[i];
2117
2118 if (num2 < 0) {
2119 numAlu.AssignFormatted(-num2);
2120 numAlu.SetSign(-1);
2121 }
2122 else {
2123 numAlu.AssignFormatted(num2);
2124 numAlu.SetSign(1);
2125 }
2126
2127 numAlu = numAlu/denomAlu;
2128
2129
2130 mOffset[i] = numAlu.GetSignedValue();
2131 numAlu.SetSign(1);
2132 denomAlu.SetSign(1);
2133
2134
2135 //numAlu.AssignInt(mADC[i]+1); // according to TRAP-manual but trafo not to middle of chamber (0.5 channels away)
2136 numAlu.AssignDouble((Double_t)mADC[i] + 1.5); // numAlu has enough pre-comma place for that; correct trafo, best values
2137 mOffset[i] = mOffset[i] + numAlu.GetValue(); // transform offset to a coord.system relative to chip; +1 to avoid neg. values
2138
96e6312d 2139 // up to here: adc-mapping according to TRAP manual and in line with pad-col mapping
1d93b218 2140 // reverse adc-counting to be again in line with the online mapping
2141 mADC[i] = fNADC - 4 - mADC[i]; // fNADC-4-mADC[i]: 0..17; remapping necessary;
2142 mADC[i] = mADC[i] + 2;
2143 // +2: mapping onto original ADC-online-counting: inner adc's corresponding to a chip's pasa: number 2..19
2144 }
2145
2146 // adc-counting is corresponding to online mapping; use AliTRDfeeParam::GetPadColFromADC to get the pad to which adc is connected;
2147 // pad-column mapping is reverse to adc-online mapping; TRAP adc-mapping is in line with pad-mapping (increase in same direction);
2148
2149 // transform parameters to the local coordinate-system of a stack (used by GTU)
2150 AliTRDpadPlane* padPlane = fGeo->CreatePadPlane(fLayer,fStack);
2151
2152 Double_t padWidthI = padPlane->GetWidthIPad()*10.0; // get values in cm; want them in mm
2153 //Double_t padWidthO = padPlane->GetWidthOPad()*10; // difference between outer pad-widths not included; in real TRAP??
2154
2155 // difference between width of inner and outer pads of a row is not accounted for;
2156
96e6312d 2157 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
2158 Double_t eCharge = 0.3; // unit charge in (GeV/c)/m*T
1d93b218 2159 Double_t ptMin = 2.3; // minimum transverse momentum (GeV/c); to be adjusted(?)
2160
2161 Double_t granularityOffset = 0.160; // granularity for offset in mm
2162 Double_t granularitySlope = 0.140; // granularity for slope in mm
2163
2164 // get the coordinates in SM-system; parameters:
2165
2166 Double_t zPos = (padPlane->GetRowPos(fRow))*10.0; // z-position of the MCM; fRow is counted on a chamber; SM consists of 5
2167 // zPos is position of pad-borders;
2168 Double_t zOffset = 0.0;
2169 if ( fRow == 0 || fRow == 15 ) {
2170 zOffset = padPlane->GetLengthOPad();
2171 }
2172 else {
2173 zOffset = padPlane->GetLengthIPad();
2174 }
2175 zOffset = (-1.0) * zOffset/2.0;
2176 // turn zPos to be z-coordinate at middle of pad-row
2177 zPos = zPos + zOffset;
2178
2179
2180 Double_t xPos = 0.0; // x-position of the upper border of the drift-chamber of actual layer
23200400 2181 Int_t icol = 0; // column-number of adc-channel
1d93b218 2182 Double_t yPos[4]; // y-position of the pad to which ADC is connected
23200400 2183 Double_t dx = 30.0; // height of drift-chamber in mm; maybe retrieve from AliTRDGeometry
2184 Double_t freqSample = fFeeParam->GetSamplingFrequency(); // retrieve the sampling frequency (10.019750 MHz)
2185 Double_t vdrift = fCal->GetVdriftAverage(fChaId); // averaged drift velocity for this detector (1.500000 cm/us)
2186 Int_t nrOfDriftTimeBins = Int_t(dx/10.0*freqSample/vdrift); // the number of time bins in the drift region (20)
96e6312d 2187 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))
2188 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
2189 if(nrOfOffsetCorrTimeBins < 0) nrOfOffsetCorrTimeBins = 0;// don't apply offset correction if no drift time bins before tFS can be assumed
1d93b218 2190 Double_t lorTan = fCal->GetOmegaTau(vdrift,magField); // tan of the Lorentz-angle for this detector; could be evaluated and set as a parameter for each mcm
23200400 2191 //Double_t lorAngle = 7.0; // Lorentz-angle in degrees
1d93b218 2192 Double_t tiltAngle = padPlane->GetTiltingAngle(); // sign-respecting tilting angle of pads in actual layer
2193 Double_t tiltTan = TMath::Tan(TMath::Pi()/180.0 * tiltAngle);
2194 //Double_t lorTan = TMath::Tan(TMath::Pi()/180.0 * lorAngle);
2195
2196 Double_t alphaMax[4]; // maximum deflection from the direction to the primary vertex; granularity of hit pads
2197 Double_t slopeMin[4]; // local limits for the deflection
2198 Double_t slopeMax[4];
2199 Int_t mslopeMin[4]; // in granularity units; to be compared to mSlope[i]
2200 Int_t mslopeMax[4];
2201
2202
96e6312d 2203 // x coord. of upper side of drift chambers in local SM-system (in mm)
2204 // obtained by evaluating the x-range of the hits; should be crosschecked; only drift, not amplification region taken into account (30mm);
2205 // the y-deflection is given as difference of y between lower and upper side of drift-chamber, not pad-plane;
1d93b218 2206 switch(fLayer)
2207 {
2208 case 0:
2209 xPos = 3003.0;
2210 break;
2211 case 1:
2212 xPos = 3129.0;
2213 break;
2214 case 2:
2215 xPos = 3255.0;
2216 break;
2217 case 3:
2218 xPos = 3381.0;
2219 break;
2220 case 4:
2221 xPos = 3507.0;
2222 break;
2223 case 5:
2224 xPos = 3633.0;
2225 break;
2226 }
2227
2228 // calculation of offset-correction n:
2229
2230 Int_t nCorrectOffset = (fRobPos % 2 == 0) ? ((fMcmPos % 4)) : ( 4 + (fMcmPos % 4));
2231
2232 nCorrectOffset = (nCorrectOffset - 4)*18 - 1;
2233 if (nCorrectOffset < 0) {
2234 numAlu.AssignInt(-nCorrectOffset);
2235 numAlu.SetSign(-1);
2236 }
2237 else {
2238 numAlu.AssignInt(nCorrectOffset);
2239 numAlu.SetSign(1);
2240 }
96e6312d 2241 nCorrectOffset = numAlu.GetSignedValue();
2242
2243 // the Lorentz correction to the offset
2244 Double_t lorCorrectOffset = lorTan *(Double_t)nrOfOffsetCorrTimeBins*vdrift*10.0/freqSample; // Lorentz offset correction in mm
2245
2246
2247 lorCorrectOffset = lorCorrectOffset/padWidthI; // Lorentz correction in pad width units
2248
2249 if(lorCorrectOffset < 0) {
2250 numAlu.AssignDouble(-lorCorrectOffset);
2251 numAlu.SetSign(-1);
2252 }
2253 else{
2254 numAlu.AssignDouble(lorCorrectOffset);
2255 numAlu.SetSign(1);
2256 }
2257
2258 Int_t mlorCorrectOffset = numAlu.GetSignedValue();
2259
2260
1d93b218 2261 Double_t mCorrectOffset = padWidthI/granularityOffset; // >= 0.0
2262
2263 // calculation of slope-correction
2264
2265 // this is only true for tracks coming (approx.) from primary vertex
23200400 2266 // everything is evaluated for a tracklet covering the whole drift chamber
1d93b218 2267 Double_t cCorrectSlope = (-lorTan*dx + zPos/xPos*dx*tiltTan)/granularitySlope;
2268 // Double_t cCorrectSlope = zPos/xPos*dx*tiltTan/granularitySlope;
2269 // zPos can be negative! for track from primary vertex: zOut-zIn > 0 <=> zPos > 0
2270
2271 if (cCorrectSlope < 0) {
2272 numAlu.AssignDouble(-cCorrectSlope);
2273 numAlu.SetSign(-1);
2274 }
2275 else {
2276 numAlu.AssignDouble(cCorrectSlope);
2277 numAlu.SetSign(1);
2278 }
2279 cCorrectSlope = numAlu.GetSignedValue();
2280
2281 // convert slope to deflection between upper and lower drift-chamber position (slope is given in pad-unit/time-bins)
2282 // different pad-width of outer pads of a pad-plane not taken into account
23200400 2283 // 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)
2284 // 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
2285
1d93b218 2286
23200400 2287 Double_t mCorrectSlope = (Double_t)(nrOfDriftTimeBins)*padWidthI/granularitySlope; // >= 0.0
1d93b218 2288
2289 AliTRDtrapAlu correctAlu;
2290 correctAlu.Init(20,8);
2291
2292 AliTRDtrapAlu offsetAlu;
2293 offsetAlu.Init(13,0,-0x1000,0x0FFF); // 13 bit-word; 2-complement (1 sign-bit); asymmetric range
2294
2295 AliTRDtrapAlu slopeAlu;
2296 slopeAlu.Init(7,0,-0x40,0x3F); // 7 bit-word; 2-complement (1 sign-bit);
2297
2298 for (Int_t i = 0; i<4; i++) {
2299
2300 if (mADC[i] == -1) continue;
2301
2302 icol = fFeeParam->GetPadColFromADC(fRobPos,fMcmPos,mADC[i]); // be aware that mADC[i] contains the ADC-number according to online-mapping
2303 yPos[i] = (padPlane->GetColPos(icol))*10.0;
2304
2305
2306 // offset:
2307
2308 correctAlu.AssignDouble(mCorrectOffset); // done because max. accuracy is 8 bit
2309 mCorrectOffset = correctAlu.GetValueWhole(); // cut offset correction to 8 past-comma bit accuracy
96e6312d 2310 mOffset[i] = (Int_t)((mCorrectOffset)*(Double_t)(mOffset[i] + nCorrectOffset - mlorCorrectOffset));
2311 //mOffset[i] = mOffset[i]*(-1); // adjust to direction of y-axes in online simulation
1d93b218 2312
2313 if (mOffset[i] < 0) {
2314 numAlu.AssignFormatted(-mOffset[i]);
2315 numAlu.SetSign(-1);
2316 }
2317 else {
2318 numAlu.AssignFormatted(mOffset[i]);
2319 numAlu.SetSign(1);
2320 }
2321
2322 offsetAlu = numAlu;
2323 mOffset[i] = offsetAlu.GetSignedValue();
2324
2325
2326 // slope:
2327
2328 correctAlu.AssignDouble(mCorrectSlope);
2329 mCorrectSlope = correctAlu.GetValueWhole();
2330
2331 mSlope[i] = (Int_t)((mCorrectSlope*(Double_t)mSlope[i]) + cCorrectSlope);
2332
2333 if (mSlope[i] < 0) {
2334 numAlu.AssignFormatted(-mSlope[i]);
2335 numAlu.SetSign(-1);
2336 }
2337 else {
2338 numAlu.AssignFormatted(mSlope[i]);
2339 numAlu.SetSign(1);
2340 }
2341
2342 slopeAlu = numAlu; // here all past-comma values are cut, not rounded; alternatively add +0.5 before cutting (means rounding)
2343 mSlope[i] = slopeAlu.GetSignedValue();
2344
2345 // local (LTU) limits for the deflection
2346 // ATan returns angles in radian
2347 alphaMax[i] = TMath::ASin(eCharge*magField/(2.0*ptMin)*(TMath::Sqrt(xPos*xPos + yPos[i]*yPos[i]))/1000.0); // /1000: mm->m
2348 slopeMin[i] = dx*(TMath::Tan(TMath::ATan(yPos[i]/xPos) - alphaMax[i]))/granularitySlope;
2349 slopeMax[i] = dx*(TMath::Tan(TMath::ATan(yPos[i]/xPos) + alphaMax[i]))/granularitySlope;
2350
2351 if (slopeMin[i] < 0) {
2352 slopeAlu.AssignDouble(-slopeMin[i]);
2353 slopeAlu.SetSign(-1);
2354 }
2355 else {
2356 slopeAlu.AssignDouble(slopeMin[i]);
2357 slopeAlu.SetSign(1);
2358 }
2359 mslopeMin[i] = slopeAlu.GetSignedValue(); // the borders should lie inside the range of mSlope -> usage of slopeAlu again
2360
2361 if (slopeMax[i] < 0) {
2362 slopeAlu.AssignDouble(-slopeMax[i]);
2363 slopeAlu.SetSign(-1);
2364 }
2365 else {
2366 slopeAlu.AssignDouble(slopeMax[i]);
2367 slopeAlu.SetSign(1);
2368 }
2369 mslopeMax[i] = slopeAlu.GetSignedValue();
2370 }
2371
2372 // suppress submission of tracks with low stiffness
2373 // put parameters in 32bit-word and submit (write to file as root-file; sort after SM, stack, layer, chamber)
2374
2375 // sort tracklet-words in ascending y-order according to the offset (according to mADC would also be possible)
2376 // up to now they are sorted according to maximum hit sum
2377 // is the sorting really done in the TRAP-chip?
2378
2379 Int_t order[4] = {-1,-1,-1,-1};
2380 Int_t wordnr = 0; // number of tracklet-words
2381
2382 for(Int_t j = 0; j < fMaxTracklets; j++) {
96e6312d 2383 //if( mADC[j] == -1) continue;
2384 if( (mADC[j] == -1) || (mSlope[j] < mslopeMin[j]) || (mSlope[j] > mslopeMax[j])) continue; // this applies a pt-cut
1d93b218 2385 wordnr++;
2386 if( wordnr-1 == 0) {
2387 order[0] = j;
2388 continue;
2389 }
2390 // wordnr-1>0, wordnr-1<4
2391 order[wordnr-1] = j;
2392 for( Int_t k = 0; k < wordnr-1; k++) {
2393 if( mOffset[j] < mOffset[order[k]] ) {
2394 for( Int_t l = wordnr-1; l > k; l-- ) {
2395 order[l] = order[l-1];
2396 }
2397 order[k] = j;
2398 break;
2399 }
2400
2401 }
2402 }
2403
2404 // fill the bit-words in ascending order and without gaps
2405 UInt_t bitWord[4] = {0,0,0,0}; // attention: unsigned int to have real 32 bits (no 2-complement)
2406 for(Int_t j = 0; j < wordnr; j++) { // only "wordnr" tracklet-words
2407 //Bool_t rem1 = kTRUE;
2408
2409 Int_t i = order[j];
23200400 2410 //bit-word is 2-complement and therefore without sign
1d93b218 2411 bitWord[j] = 1; // this is the starting 1 of the bit-word (at 33rd position); the 1 must be ignored
2412 //printf("\n");
23200400 2413 UInt_t shift = 0;
2414 UInt_t shift2 = 0;
2415
2416
1d93b218 2417
2418
2419 /*printf("mean charge: %d\n",mMeanCharge[i]);
2420 printf("row: %d\n",fRow);
2421 printf("slope: %d\n",mSlope[i]);
2422 printf("pad position: %d\n",mOffset[i]);
2423 printf("channel: %d\n",mADC[i]);*/
2424
2425 // electron probability (currently not implemented; the mean charge is just scaled)
23200400 2426 shift = (UInt_t)mMeanCharge[i];
1d93b218 2427 for(Int_t iBit = 0; iBit < 8; iBit++) {
2428 bitWord[j] = bitWord[j]<<1;
23200400 2429 bitWord[j] |= (shift>>(7-iBit))&1;
1d93b218 2430 //printf("0");
2431 }
23200400 2432
1d93b218 2433 // pad row
23200400 2434 shift = (UInt_t)fRow;
1d93b218 2435 for(Int_t iBit = 0; iBit < 4; iBit++) {
2436 bitWord[j] = bitWord[j]<<1;
23200400 2437 bitWord[j] |= (shift>>(3-iBit))&1;
1d93b218 2438 //printf("%d", (fRow>>(3-iBit))&1);
2439 }
2440
2441 // deflection length
1d93b218 2442 if(mSlope[i] < 0) {
23200400 2443 shift = (UInt_t)(-mSlope[i]);
2444 // shift2 is 2-complement of shift
2445 shift2 = 1;
2446 for(Int_t iBit = 1; iBit < 7; iBit++) {
2447 shift2 = shift2<<1;
5a67d089 2448 shift2 |= (1- (((shift)>>(6-iBit))&1) );
23200400 2449 //printf("%d",(1-((-mSlope[i])>>(6-iBit))&1));
2450 }
2451 shift2 = shift2 + 1;
2452 //printf("1");
2453 for(Int_t iBit = 0; iBit < 7; iBit++) {
2454 bitWord[j] = bitWord[j]<<1;
2455 bitWord[j] |= (shift2>>(6-iBit))&1;
2456 //printf("%d",(1-((-mSlope[i])>>(6-iBit))&1));
2457 }
1d93b218 2458 }
2459 else {
23200400 2460 shift = (UInt_t)(mSlope[i]);
1d93b218 2461 bitWord[j] = bitWord[j]<<1;
23200400 2462 bitWord[j] |= 0;
2463 //printf("0");
2464 for(Int_t iBit = 1; iBit < 7; iBit++) {
2465 bitWord[j] = bitWord[j]<<1;
2466 bitWord[j] |= (shift>>(6-iBit))&1;
2467 //printf("%d",(mSlope[i]>>(6-iBit))&1);
2468 }
1d93b218 2469 }
2470
2471 // pad position
1d93b218 2472 if(mOffset[i] < 0) {
23200400 2473 shift = (UInt_t)(-mOffset[i]);
2474 shift2 = 1;
1d93b218 2475 for(Int_t iBit = 1; iBit < 13; iBit++) {
23200400 2476 shift2 = shift2<<1;
5a67d089 2477 shift2 |= (1-(((shift)>>(12-iBit))&1));
1d93b218 2478 //printf("%d",(1-((-mOffset[i])>>(12-iBit))&1));
2479 }
23200400 2480 shift2 = shift2 + 1;
2481 //printf("1");
2482 for(Int_t iBit = 0; iBit < 13; iBit++) {
2483 bitWord[j] = bitWord[j]<<1;
2484 bitWord[j] |= (shift2>>(12-iBit))&1;
2485 //printf("%d",(1-((-mSlope[i])>>(6-iBit))&1));
2486 }
1d93b218 2487 }
2488 else {
23200400 2489 shift = (UInt_t)mOffset[i];
2490 bitWord[j] = bitWord[j]<<1;
2491 bitWord[j] |= 0;
2492 //printf("0");
2493 for(Int_t iBit = 1; iBit < 13; iBit++) {
2494 bitWord[j] = bitWord[j]<<1;
2495 bitWord[j] |= (shift>>(12-iBit))&1;
2496 //printf("%d",(mOffset[i]>>(12-iBit))&1);
2497 }
1d93b218 2498 }
2499
2500
23200400 2501
1d93b218 2502 //printf("bitWord: %u\n",bitWord[j]);
2503 //printf("adc: %d\n",mADC[i]);
2504 fMCMT[j] = bitWord[j];
2505 }
2506
2507 //printf("\n");
2508
2509
2510 delete [] qsum;
2511 delete [] ieffped;
2512
2513 delete [] X;
2514 delete [] XX;
2515 delete [] Y;
2516 delete [] YY;
2517 delete [] XY;
2518 delete [] N;
2519 delete [] QT0;
2520 delete [] QT1;
2521
2522 delete [] hitSum;
2523 delete [] selectPair;
2524
2525 delete padPlane;
2526
96e6312d 2527//if you want to activate the MC tracklet output, set fgkMCTrackletOutput=kTRUE in AliTRDfeeParam
2528
4cc89512 2529 if (!fFeeParam->GetMCTrackletOutput())
2530 return;
1d93b218 2531
1d93b218 2532 AliLog::SetClassDebugLevel("AliTRDmcmSim", 10);
2533 AliLog::SetFileOutput("../log/tracklet.log");
2534
1d93b218 2535 // testing for wordnr in order to speed up the simulation
52c19022 2536 if (wordnr == 0)
1d93b218 2537 return;
1d93b218 2538
4cc89512 2539 UInt_t *trackletWord = new UInt_t[fMaxTracklets];
2540 Int_t *adcChannel = new Int_t[fMaxTracklets];
2541 Int_t *trackRef = new Int_t[fMaxTracklets];
2542
2543 Int_t u = 0;
2544
2545 AliTRDdigitsManager *digman = new AliTRDdigitsManager();
33c3c91a 2546 digman->ReadDigits(AliRunLoader::Instance()->GetLoader("TRDLoader")->TreeD());
4cc89512 2547 digman->SetUseDictionaries(kTRUE);
2548 AliTRDfeeParam *feeParam = AliTRDfeeParam::Instance();
1d93b218 2549
2550 for (Int_t j = 0; j < fMaxTracklets; j++) {
2551 Int_t i = order[j];
2552 trackletWord[j] = 0;
2553 adcChannel[j] = -1;
2554 if (bitWord[j]!=0) {
2555 trackletWord[u] = bitWord[j];
2556 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
4cc89512 2557
2558// Finding label of MC track
2559 TH1F *hTrkRef = new TH1F("trackref", "trackref", 100000, 0, 100000);
2560 Int_t track[3];
2561 Int_t padcol = feeParam->GetPadColFromADC(fRobPos, fMcmPos, adcChannel[u]);
2562 Int_t padcol_ngb = feeParam->GetPadColFromADC(fRobPos, fMcmPos, adcChannel[u] - 1);
2563 Int_t padrow = 4 * (fRobPos / 2) + fMcmPos / 4;
2564 Int_t det = 30 * fSector + 6 * fStack + fLayer;
2565 for(Int_t iTimebin = feeParam->GetLinearFitStart(); iTimebin < feeParam->GetLinearFitEnd(); iTimebin++) {
2566 track[0] = digman->GetTrack(0, padrow, padcol, iTimebin, det);
2567 track[1] = digman->GetTrack(1, padrow, padcol, iTimebin, det);
2568 track[2] = digman->GetTrack(2, padrow, padcol, iTimebin, det);
2569 hTrkRef->Fill(track[0]);
2570 if (track[1] != track[0] && track[1] != -1)
2571 hTrkRef->Fill(track[1]);
2572 if (track[2] != track[0] && track[2] != track[1] && track[2] != -1)
2573 hTrkRef->Fill(track[2]);
2574 if (padcol_ngb >= 0) {
2575 track[0] = digman->GetTrack(0, padrow, padcol, iTimebin, det);
2576 track[1] = digman->GetTrack(1, padrow, padcol, iTimebin, det);
2577 track[2] = digman->GetTrack(2, padrow, padcol, iTimebin, det);
2578 hTrkRef->Fill(track[0]);
2579 if (track[1] != track[0] && track[1] != -1)
2580 hTrkRef->Fill(track[1]);
2581 if (track[2] != track[0] && track[2] != track[1] && track[2] != -1)
2582 hTrkRef->Fill(track[2]);
2583 }
2584 }
2585 trackRef[u] = hTrkRef->GetMaximumBin() - 1;
2586 delete hTrkRef;
1d93b218 2587 u = u + 1;
2588 }
2589 }
1d93b218 2590
33c3c91a 2591 AliDataLoader *dl = AliRunLoader::Instance()->GetLoader("TRDLoader")->GetDataLoader("tracklets");
52c19022 2592 if (!dl) {
2593 AliError("Could not get the tracklets data loader!");
1d93b218 2594 }
52c19022 2595 else {
2596 TTree *trackletTree = dl->Tree();
2597 if (!trackletTree)
2598 dl->MakeTree();
2599 trackletTree = dl->Tree();
1d93b218 2600
52c19022 2601 AliTRDtrackletMCM *trkl = new AliTRDtrackletMCM();
2602 TBranch *trkbranch = trackletTree->GetBranch("mcmtrklbranch");
2603 if (!trkbranch)
2604 trkbranch = trackletTree->Branch("mcmtrklbranch", "AliTRDtrackletMCM", &trkl, 32000);
2605 trkbranch->SetAddress(&trkl);
1d93b218 2606
52c19022 2607 for (Int_t iTracklet = 0; iTracklet < fMaxTracklets; iTracklet++) {
2608 if (trackletWord[iTracklet] == 0)
2609 continue;
2610 trkl->SetTrackletWord(trackletWord[iTracklet]);
2611 trkl->SetDetector(30*fSector + 6*fStack + fLayer);
2612 trkl->SetROB(fRobPos);
2613 trkl->SetMCM(fMcmPos);
4cc89512 2614 trkl->SetLabel(trackRef[iTracklet]);
52c19022 2615 trackletTree->Fill();
52c19022 2616 }
2617 delete trkl;
2618 dl->WriteData("OVERWRITE");
2619 }
23200400 2620
4cc89512 2621 delete [] trackletWord;
2622 delete [] adcChannel;
2623 delete [] trackRef;
2624 delete digman;
1d93b218 2625
2626 // to be done:
2627 // error measure for quality of fit (not necessarily needed for the trigger)
2628 // cluster quality threshold (not yet set)
2629 // electron probability
1d93b218 2630}
b65e5048 2631//_____________________________________________________________________________________
2632void AliTRDmcmSim::GeneratefZSM1Dim()
2633{
2634 //
2635 // Generate the array fZSM1Dim necessary
2636 // for the method ProduceRawStream
2637 //
2638
2639 // Fill the mapping
2640 // Supressed zeros indicated by -1 in digits array
2641 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ )
2642 {
2643 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2644 {
2645
2646 if(fADCF[iadc][it]==-1) // If is a supressed value
2647 {
2648 fZSM[iadc][it]=1;
2649 }
2650 else // Not suppressed
2651 {
2652 fZSM[iadc][it]=0;
2653 }
2654 }
2655 }
2656
2657 // Make the 1 dim projection
2658 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ )
2659 {
2660 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2661 {
2662 fZSM1Dim[iadc] &= fZSM[iadc][it];
2663 }
2664 }
2665}
2666//_______________________________________________________________________________________
2667void AliTRDmcmSim::CopyArrays()
2668{
2669 //
2670 // Initialize filtered data array with raw data
2671 // Method added for internal consistency
2672 //
2673
2674 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ )
2675 {
2676 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2677 {
2678 fADCF[iadc][it] = fADCR[iadc][it];
2679 }
2680 }
2681}
2682//_______________________________________________________________________________________
2683void AliTRDmcmSim::StartfastZS(Int_t pads, Int_t timebins)
2684{
2685 //
2686 // Initialize just the necessary elements to perform
2687 // the zero suppression in the digitizer
2688 //
2689
2690 fFeeParam = AliTRDfeeParam::Instance();
2691 fSimParam = AliTRDSimParam::Instance();
2692 fNADC = pads;
2693 fNTimeBin = timebins;
2694
2695 if( fADCR == NULL )
2696 {
2697 fADCR = new Int_t *[fNADC];
2698 fADCF = new Int_t *[fNADC];
2699 fADCT = new Int_t *[fNADC];
2700 fZSM = new Int_t *[fNADC];
2701 fZSM1Dim = new Int_t [fNADC];
2702 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ )
2703 {
2704 fADCR[iadc] = new Int_t[fNTimeBin];
2705 fADCF[iadc] = new Int_t[fNTimeBin];
2706 fADCT[iadc] = new Int_t[fNTimeBin];
2707 fZSM [iadc] = new Int_t[fNTimeBin];
2708 }
2709 }
2710
2711 for( Int_t iadc = 0 ; iadc < fNADC; iadc++ )
2712 {
2713 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2714 {
2715 fADCR[iadc][it] = 0;
2716 fADCF[iadc][it] = 0;
2717 fADCT[iadc][it] = -1;
2718 fZSM [iadc][it] = 1;
2719 }
2720 fZSM1Dim[iadc] = 1;
2721 }
2722
2723 fInitialized = kTRUE;
2724}
2725//_______________________________________________________________________________________
2726void AliTRDmcmSim::FlagDigitsArray(AliTRDarrayADC *tempdigs, Int_t valrow)
2727{
2728 //
2729 // Modify the digits array to flag suppressed values
2730 //
2731
2732 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ )
2733 {
2734 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2735 {
2736 if(fZSM[iadc][it]==1)
2737 {
2738 tempdigs->SetData(valrow,iadc,it,-1);
2739 }
2740 }
2741 }
2742}
0d64b05f 2743//_______________________________________________________________________________________
2744void AliTRDmcmSim::RestoreZeros()
2745{
2746 //
2747 // Restore the zero-suppressed values (set as -1) to the value 0
2748 //
2749
2750 for( Int_t iadc = 1 ; iadc < fNADC-1; iadc++ )
2751 {
2752 for( Int_t it = 0 ; it < fNTimeBin ; it++ )
2753 {
2754
2755 if(fADCF[iadc][it]==-1) //if is a supressed zero, reset to zero
2756 {
2757 fADCF[iadc][it]=0;
2758 fADCR[iadc][it]=0;
2759 }
2760 }
2761 }
b65e5048 2762
0d64b05f 2763}
1d93b218 2764