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 **************************************************************************/
18 Revision 1.8 2000/06/09 11:10:07 cblume
19 Compiler warnings and coding conventions, next round
21 Revision 1.7 2000/06/08 18:32:58 cblume
22 Make code compliant to coding conventions
24 Revision 1.6 2000/06/07 16:27:32 cblume
25 Try to remove compiler warnings on Sun and HP
27 Revision 1.5 2000/05/09 16:38:57 cblume
28 Removed PadResponse(). Merge problem
30 Revision 1.4 2000/05/08 15:53:45 cblume
31 Resolved merge conflict
33 Revision 1.3 2000/04/28 14:49:27 cblume
34 Only one declaration of iDict in MakeDigits()
36 Revision 1.1.4.1 2000/05/08 14:42:04 cblume
37 Introduced AliTRDdigitsManager
39 Revision 1.1 2000/02/28 19:00:13 cblume
44 ///////////////////////////////////////////////////////////////////////////////
46 // Creates and handles digits from TRD hits //
48 // The following effects are included: //
51 // - Gas gain including fluctuations //
52 // - Pad-response (simple Gaussian approximation) //
53 // - Electronics noise //
54 // - Electronics gain //
57 // The corresponding parameter can be adjusted via the various //
58 // Set-functions. If these parameters are not explicitly set, default //
59 // values are used (see Init-function). //
60 // To produce digits from a root-file with TRD-hits use the //
61 // slowDigitsCreate.C macro. //
63 ///////////////////////////////////////////////////////////////////////////////
72 #include "AliTRDdigitizer.h"
73 #include "AliTRDdataArrayI.h"
74 #include "AliTRDdataArrayF.h"
75 #include "AliTRDdigitsManager.h"
77 ClassImp(AliTRDdigitizer)
79 //_____________________________________________________________________________
80 AliTRDdigitizer::AliTRDdigitizer():TNamed()
83 // AliTRDdigitizer default constructor
109 //_____________________________________________________________________________
110 AliTRDdigitizer::AliTRDdigitizer(const Text_t *name, const Text_t *title)
114 // AliTRDdigitizer default constructor
128 //_____________________________________________________________________________
129 AliTRDdigitizer::AliTRDdigitizer(const AliTRDdigitizer &d)
132 // AliTRDdigitizer copy constructor
135 ((AliTRDdigitizer &) d).Copy(*this);
139 //_____________________________________________________________________________
140 AliTRDdigitizer::~AliTRDdigitizer()
143 // AliTRDdigitizer destructor
155 if (fPRF) delete fPRF;
159 //_____________________________________________________________________________
160 AliTRDdigitizer &AliTRDdigitizer::operator=(const AliTRDdigitizer &d)
163 // Assignment operator
166 if (this != &d) ((AliTRDdigitizer &) d).Copy(*this);
171 //_____________________________________________________________________________
172 void AliTRDdigitizer::Copy(TObject &d)
178 ((AliTRDdigitizer &) d).fInputFile = NULL;
179 ((AliTRDdigitizer &) d).fDigits = NULL;
180 ((AliTRDdigitizer &) d).fTRD = NULL;
181 ((AliTRDdigitizer &) d).fGeo = NULL;
183 ((AliTRDdigitizer &) d).fEvent = 0;
185 ((AliTRDdigitizer &) d).fGasGain = fGasGain;
186 ((AliTRDdigitizer &) d).fNoise = fNoise;
187 ((AliTRDdigitizer &) d).fChipGain = fChipGain;
188 ((AliTRDdigitizer &) d).fADCoutRange = fADCoutRange;
189 ((AliTRDdigitizer &) d).fADCinRange = fADCinRange;
190 ((AliTRDdigitizer &) d).fADCthreshold = fADCthreshold;
191 ((AliTRDdigitizer &) d).fDiffusionOn = fDiffusionOn;
192 ((AliTRDdigitizer &) d).fDiffusionT = fDiffusionT;
193 ((AliTRDdigitizer &) d).fDiffusionL = fDiffusionL;
194 ((AliTRDdigitizer &) d).fElAttachOn = fElAttachOn;
195 ((AliTRDdigitizer &) d).fElAttachProp = fElAttachProp;
196 ((AliTRDdigitizer &) d).fExBOn = fExBOn;
197 ((AliTRDdigitizer &) d).fLorentzAngle = fLorentzAngle;
198 ((AliTRDdigitizer &) d).fLorentzFactor = fLorentzFactor;
200 fPRF->Copy(*((AliTRDdigitizer &) d).fPRF);
204 //_____________________________________________________________________________
205 Int_t AliTRDdigitizer::Diffusion(Float_t driftlength, Float_t *xyz)
208 // Applies the diffusion smearing to the position of a single electron
211 Float_t driftSqrt = TMath::Sqrt(driftlength);
212 Float_t sigmaT = driftSqrt * fDiffusionT;
213 Float_t sigmaL = driftSqrt * fDiffusionL;
214 xyz[0] = gRandom->Gaus(xyz[0], sigmaL * fLorentzFactor);
215 xyz[1] = gRandom->Gaus(xyz[1], sigmaT * fLorentzFactor);
216 xyz[2] = gRandom->Gaus(xyz[2], sigmaT);
221 //_____________________________________________________________________________
222 Int_t AliTRDdigitizer::ExB(Float_t driftlength, Float_t *xyz)
225 // Applies E x B effects to the position of a single electron
229 xyz[1] = xyz[1] + fLorentzAngle * driftlength;
236 //_____________________________________________________________________________
237 void AliTRDdigitizer::Init()
240 // Initializes the digitization procedure with standard values
243 // The default parameter for the digitization
251 // Transverse and longitudinal diffusion coefficients (Xe/Isobutane)
256 // Propability for electron attachment
262 // omega * tau. (tau ~ 12 * 10^-12, B = 0.2T)
263 fLorentzAngle = 17.6 * 12.0 * 0.2 * 0.01;
265 // The pad response function
266 fPRF = new TF1("PRF","[0]*([1]+exp(-x*x/(2.0*[2])))",-2,2);
267 fPRF->SetParameter(0, 0.8872);
268 fPRF->SetParameter(1,-0.00573);
269 fPRF->SetParameter(2, 0.454 * 0.454);
273 //_____________________________________________________________________________
274 Bool_t AliTRDdigitizer::Open(const Char_t *name, Int_t nEvent)
277 // Opens a ROOT-file with TRD-hits and reads in the hit-tree
280 // Connect the AliRoot file containing Geometry, Kine, and Hits
281 fInputFile = (TFile*) gROOT->GetListOfFiles()->FindObject(name);
283 printf("AliTRDdigitizer::Open -- ");
284 printf("Open the ALIROOT-file %s.\n",name);
285 fInputFile = new TFile(name,"UPDATE");
288 printf("AliTRDdigitizer::Open -- ");
289 printf("%s is already open.\n",name);
292 gAlice = (AliRun*) fInputFile->Get("gAlice");
294 printf("AliTRDdigitizer::Open -- ");
295 printf("AliRun object found on file.\n");
298 printf("AliTRDdigitizer::Open -- ");
299 printf("Could not find AliRun object.\n");
305 // Import the Trees for the event nEvent in the file
306 Int_t nparticles = gAlice->GetEvent(fEvent);
307 if (nparticles <= 0) {
308 printf("AliTRDdigitizer::Open -- ");
309 printf("No entries in the trees for event %d.\n",fEvent);
313 // Get the pointer to the detector class and check for version 1
314 fTRD = (AliTRD*) gAlice->GetDetector("TRD");
315 if (fTRD->IsVersion() != 1) {
316 printf("AliTRDdigitizer::Open -- ");
317 printf("TRD must be version 1 (slow simulator).\n");
322 fGeo = fTRD->GetGeometry();
323 printf("AliTRDdigitizer::Open -- ");
324 printf("Geometry version %d\n",fGeo->IsVersion());
330 //_____________________________________________________________________________
331 Bool_t AliTRDdigitizer::MakeDigits()
334 // Loops through the TRD-hits and creates the digits.
337 ///////////////////////////////////////////////////////////////
339 ///////////////////////////////////////////////////////////////
341 // Converts number of electrons to fC
342 const Float_t kEl2fC = 1.602E-19 * 1.0E15;
344 ///////////////////////////////////////////////////////////////
346 Int_t iRow, iCol, iTime;
350 Int_t totalSizeDigits = 0;
351 Int_t totalSizeDict0 = 0;
352 Int_t totalSizeDict1 = 0;
353 Int_t totalSizeDict2 = 0;
355 AliTRDdataArrayI *digits;
356 AliTRDdataArrayI *dictionary[kNDict];
359 printf("AliTRDdigitizer::MakeDigits -- ");
360 printf("No geometry defined\n");
364 // Create a digits manager
365 fDigits = new AliTRDdigitsManager();
367 // Create detector arrays to keep the signal and track numbers
368 AliTRDdataArrayF *signal = new AliTRDdataArrayF();
369 AliTRDdataArrayI *tracks[kNDict];
370 for (iDict = 0; iDict < kNDict; iDict++) {
371 tracks[iDict] = new AliTRDdataArrayI();
374 // Get the pointer to the hit tree
375 TTree *hitTree = gAlice->TreeH();
377 // Get the number of entries in the hit tree
378 // (Number of primary particles creating a hit somewhere)
379 Int_t nTrack = (Int_t) hitTree->GetEntries();
381 printf("AliTRDdigitizer::MakeDigits -- ");
382 printf("Start creating digits.\n");
384 // The Lorentz factor
386 fLorentzFactor = 1.0 / (1.0 + fLorentzAngle*fLorentzAngle);
389 fLorentzFactor = 1.0;
393 Int_t chamEnd = kNcham;
394 if (fTRD->GetSensChamber() >= 0) {
395 chamBeg = fTRD->GetSensChamber();
396 chamEnd = chamBeg + 1;
399 Int_t planEnd = kNplan;
400 if (fTRD->GetSensPlane() >= 0) {
401 planBeg = fTRD->GetSensPlane();
402 planEnd = planBeg + 1;
405 Int_t sectEnd = kNsect;
409 // Loop through all the chambers
410 for (Int_t iCham = chamBeg; iCham < chamEnd; iCham++) {
411 for (Int_t iPlan = planBeg; iPlan < planEnd; iPlan++) {
412 for (Int_t iSect = sectBeg; iSect < sectEnd; iSect++) {
414 if (fTRD->GetSensSector() >= 0) {
415 Int_t sens1 = fTRD->GetSensSector();
416 Int_t sens2 = sens1 + fTRD->GetSensSectorRange();
417 sens2 -= ((Int_t) (sens2 / kNsect)) * kNsect;
419 if ((iSect < sens1) || (iSect >= sens2)) continue;
422 if ((iSect < sens1) && (iSect >= sens2)) continue;
428 printf("AliTRDdigitizer::MakeDigits -- ");
429 printf("Digitizing chamber %d, plane %d, sector %d.\n"
432 Int_t iDet = fGeo->GetDetector(iPlan,iCham,iSect);
433 Int_t nRowMax = fGeo->GetRowMax(iPlan,iCham,iSect);
434 Int_t nColMax = fGeo->GetColMax(iPlan);
435 Int_t nTimeMax = fGeo->GetTimeMax();
436 Float_t row0 = fGeo->GetRow0(iPlan,iCham,iSect);
437 Float_t col0 = fGeo->GetCol0(iPlan);
438 Float_t time0 = fGeo->GetTime0(iPlan);
439 Float_t rowPadSize = fGeo->GetRowPadSize();
440 Float_t colPadSize = fGeo->GetColPadSize();
441 Float_t timeBinSize = fGeo->GetTimeBinSize();
443 // Adjust the size of the detector arrays
444 signal->Allocate(nRowMax,nColMax,nTimeMax);
445 for (iDict = 0; iDict < kNDict; iDict++) {
446 tracks[iDict]->Allocate(nRowMax,nColMax,nTimeMax);
449 // Loop through all entries in the tree
450 for (Int_t iTrack = 0; iTrack < nTrack; iTrack++) {
453 nBytes += hitTree->GetEvent(iTrack);
455 // Get the number of hits in the TRD created by this particle
456 Int_t nHit = fTRD->Hits()->GetEntriesFast();
458 // Loop through the TRD hits
459 for (Int_t iHit = 0; iHit < nHit; iHit++) {
463 AliTRDhit *hit = (AliTRDhit *) fTRD->Hits()->UncheckedAt(iHit);
468 Float_t q = hit->GetCharge();
469 Int_t track = hit->Track();
470 Int_t detector = hit->GetDetector();
471 Int_t plane = fGeo->GetPlane(detector);
472 Int_t sector = fGeo->GetSector(detector);
473 Int_t chamber = fGeo->GetChamber(detector);
475 if ((sector != iSect) ||
480 // Rotate the sectors on top of each other
482 fGeo->Rotate(detector,pos,rot);
484 // The hit position in pad coordinates (center pad)
485 // The pad row (z-direction)
486 Int_t rowH = (Int_t) ((rot[2] - row0) / rowPadSize);
487 // The pad column (rphi-direction)
488 Int_t colH = (Int_t) ((rot[1] - col0) / colPadSize);
490 Int_t timeH = (Int_t) ((rot[0] - time0) / timeBinSize);
492 // Array to sum up the signal in a box surrounding the
494 const Int_t kTimeBox = 7;
495 const Int_t kColBox = 9;
496 const Int_t kRowBox = 7;
497 Float_t signalSum[kRowBox][kColBox][kTimeBox];
498 for (iRow = 0; iRow < kRowBox; iRow++ ) {
499 for (iCol = 0; iCol < kColBox; iCol++ ) {
500 for (iTime = 0; iTime < kTimeBox; iTime++) {
501 signalSum[iRow][iCol][iTime] = 0;
506 // Loop over all electrons of this hit
507 Int_t nEl = (Int_t) q;
508 for (Int_t iEl = 0; iEl < nEl; iEl++) {
511 Float_t driftlength = rot[0] - time0;
512 if ((driftlength < 0) ||
513 (driftlength > kDrThick)) break;
514 Float_t driftlengthL = driftlength;
515 if (fExBOn) driftlengthL /= TMath::Sqrt(fLorentzFactor);
521 // Electron attachment
523 if (gRandom->Rndm() < (driftlengthL * fElAttachProp / 100.)) continue;
526 // Apply the diffusion smearing
528 if (!(Diffusion(driftlengthL,xyz))) continue;
531 // Apply E x B effects
533 if (!(ExB(driftlength,xyz))) continue;
536 // The electron position and the distance to the hit position
538 // The pad row (z-direction)
539 Int_t rowE = (Int_t) ((xyz[2] - row0) / rowPadSize);
540 Int_t rowD = rowH - rowE;
541 // The pad column (rphi-direction)
542 Int_t colE = (Int_t) ((xyz[1] - col0) / colPadSize);
543 Int_t colD = colH - colE;
545 Int_t timeE = (Int_t) ((xyz[0] - time0) / timeBinSize);
546 Int_t timeD = timeH - timeE;
548 // Apply the gas gain including fluctuations
549 Int_t signal = (Int_t) (-fGasGain * TMath::Log(gRandom->Rndm()));
551 // The distance of the electron to the center of the pad
552 // in units of pad width
553 Float_t dist = (xyz[1] - col0 - (colE + 0.5) * colPadSize)
556 // Sum up the signal in the different pixels
557 // and apply the pad response
558 Int_t rowIdx = rowD + (Int_t) ( kRowBox / 2);
559 Int_t colIdx = colD + (Int_t) ( kColBox / 2);
560 Int_t timeIdx = timeD + (Int_t) (kTimeBox / 2);
562 if (( rowIdx < 0) || ( rowIdx > kRowBox)) {
563 printf("AliTRDdigitizer::MakeDigits -- ");
564 printf("Boundary error. rowIdx = %d (%d)\n", rowIdx, kRowBox);
567 if (( colIdx < 0) || ( colIdx > kColBox)) {
568 printf("AliTRDdigitizer::MakeDigits -- ");
569 printf("Boundary error. colIdx = %d (%d)\n", colIdx, kColBox);
572 if ((timeIdx < 0) || (timeIdx > kTimeBox)) {
573 printf("AliTRDdigitizer::MakeDigits -- ");
574 printf("Boundary error. timeIdx = %d (%d)\n",timeIdx,kTimeBox);
577 signalSum[rowIdx][colIdx-1][timeIdx] += fPRF->Eval(dist-1.0,0,0) * signal;
578 signalSum[rowIdx][colIdx ][timeIdx] += fPRF->Eval(dist ,0,0) * signal;
579 signalSum[rowIdx][colIdx+1][timeIdx] += fPRF->Eval(dist+1.0,0,0) * signal;
583 // Add the padcluster to the detector matrix
584 for (iRow = 0; iRow < kRowBox; iRow++ ) {
585 for (iCol = 0; iCol < kColBox; iCol++ ) {
586 for (iTime = 0; iTime < kTimeBox; iTime++) {
588 Int_t rowB = rowH + iRow - (Int_t) ( kRowBox / 2);
589 Int_t colB = colH + iCol - (Int_t) ( kColBox / 2);
590 Int_t timeB = timeH + iTime - (Int_t) (kTimeBox / 2);
591 Float_t signalB = signalSum[iRow][iCol][iTime];
592 if (( rowB < 0) || ( rowB >= nRowMax)) continue;
593 if (( colB < 0) || ( colB >= nColMax)) continue;
594 if ((timeB < 0) || (timeB >= nTimeMax)) continue;
597 // Add the signal sum
598 signalB += signal->GetData(rowB,colB,timeB);
599 signal->SetData(rowB,colB,timeB,signalB);
600 // Store the track index in the dictionary
601 // Note: We store index+1 in order to allow the array to be compressed
602 for (iDict = 0; iDict < kNDict; iDict++) {
603 Int_t oldTrack = tracks[iDict]->GetData(rowB,colB,timeB);
604 if (oldTrack == track+1) break;
605 if (oldTrack == -1) break;
607 tracks[iDict]->SetData(rowB,colB,timeB,track+1);
611 if (iDict == kNDict) {
612 printf("AliTRDdigitizer::MakeDigits -- ");
613 printf("More than three tracks for one digit!\n");
625 // Add a container for the digits of this detector
626 digits = fDigits->GetDigits(iDet);
627 // Allocate memory space for the digits buffer
628 digits->Allocate(nRowMax,nColMax,nTimeMax);
630 // Do the same for the dictionary arrays
631 for (iDict = 0; iDict < kNDict; iDict++) {
632 dictionary[iDict] = fDigits->GetDictionary(iDet,iDict);
633 dictionary[iDict]->Allocate(nRowMax,nColMax,nTimeMax);
636 // Create the digits for this chamber
637 for (iRow = 0; iRow < nRowMax; iRow++ ) {
638 for (iCol = 0; iCol < nColMax; iCol++ ) {
639 for (iTime = 0; iTime < nTimeMax; iTime++) {
641 Float_t signalAmp = signal->GetData(iRow,iCol,iTime);
644 signalAmp = TMath::Max((Float_t) gRandom->Gaus(signalAmp,fNoise)
649 signalAmp *= fChipGain;
650 // Convert to ADC counts
651 Int_t adc = (Int_t) (signalAmp * (fADCoutRange / fADCinRange));
653 if (adc > fADCthreshold) {
657 // Store the amplitude of the digit
658 digits->SetData(iRow,iCol,iTime,adc);
660 // Store the track index in the dictionary
661 // Note: We store index+1 in order to allow the array to be compressed
662 for (iDict = 0; iDict < kNDict; iDict++) {
663 dictionary[iDict]->SetData(iRow,iCol,iTime
664 ,tracks[iDict]->GetData(iRow,iCol,iTime));
673 // Compress the arrays
674 digits->Compress(1,0);
675 for (iDict = 0; iDict < kNDict; iDict++) {
676 dictionary[iDict]->Compress(1,0);
679 totalSizeDigits += digits->GetSize();
680 totalSizeDict0 += dictionary[0]->GetSize();
681 totalSizeDict1 += dictionary[1]->GetSize();
682 totalSizeDict2 += dictionary[2]->GetSize();
684 printf("AliTRDdigitizer::MakeDigits -- ");
685 printf("Number of digits found: %d.\n",nDigits);
689 for (iDict = 0; iDict < kNDict; iDict++) {
690 tracks[iDict]->Reset();
697 printf("AliTRDdigitizer::MakeDigits -- ");
698 printf("Total number of analyzed hits = %d\n",countHits);
700 printf("AliTRDdigitizer::MakeDigits -- ");
701 printf("Total digits data size = %d, %d, %d, %d\n",totalSizeDigits
710 //_____________________________________________________________________________
711 Bool_t AliTRDdigitizer::WriteDigits()
714 // Writes out the TRD-digits and the dictionaries
717 // Create the branches
718 if (!(gAlice->TreeD()->GetBranch("TRDdigits"))) {
719 if (!fDigits->MakeBranch()) return kFALSE;
722 // Store the digits and the dictionary in the tree
723 fDigits->WriteDigits();
725 // Write the new tree into the input file (use overwrite option)
727 sprintf(treeName,"TreeD%d",fEvent);
728 printf("AliTRDdigitizer::WriteDigits -- ");
729 printf("Write the digits tree %s for event %d.\n"
731 gAlice->TreeD()->Write(treeName,2);