1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
20 ///////////////////////////////////////////////////////////////////////////////
22 // Creates and handles digits from TRD hits //
24 // The following effects are included: //
27 // - Gas gain including fluctuations //
28 // - Pad-response (simple Gaussian approximation) //
29 // - Electronics noise //
30 // - Electronics gain //
33 // The corresponding parameter can be adjusted via the various //
34 // Set-functions. If these parameters are not explicitly set, default //
35 // values are used (see Init-function). //
36 // To produce digits from a root-file with TRD-hits use the //
37 // slowDigitsCreate.C macro. //
39 ///////////////////////////////////////////////////////////////////////////////
46 #include "AliTRDdigitizer.h"
47 #include "AliTRDmatrix.h"
49 ClassImp(AliTRDdigitizer)
51 //_____________________________________________________________________________
52 AliTRDdigitizer::AliTRDdigitizer():TNamed()
55 // AliTRDdigitizer default constructor
63 //_____________________________________________________________________________
64 AliTRDdigitizer::AliTRDdigitizer(const Text_t *name, const Text_t *title)
68 // AliTRDdigitizer default constructor
74 fDigitsArray = new AliTRDsegmentArray(kNsect*kNplan*kNcham);
75 for (Int_t iDict = 0; iDict < kNDict; iDict++) {
76 fDictionary[iDict] = new AliTRDsegmentArray(kNsect*kNplan*kNcham);
83 //_____________________________________________________________________________
84 AliTRDdigitizer::~AliTRDdigitizer()
93 fDigitsArray->Delete();
97 for (Int_t iDict = 0; iDict < kNDict; iDict++) {
98 fDictionary[iDict]->Delete();
99 delete fDictionary[iDict];
104 //_____________________________________________________________________________
105 Int_t AliTRDdigitizer::Diffusion(Float_t driftlength, Float_t *xyz)
108 // Applies the diffusion smearing to the position of a single electron
111 Float_t driftSqrt = TMath::Sqrt(driftlength);
112 Float_t sigmaT = driftSqrt * fDiffusionT;
113 Float_t sigmaL = driftSqrt * fDiffusionL;
114 xyz[0] = gRandom->Gaus(xyz[0], sigmaL * fLorentzFactor);
115 xyz[1] = gRandom->Gaus(xyz[1], sigmaT * fLorentzFactor);
116 xyz[2] = gRandom->Gaus(xyz[2], sigmaT);
121 //_____________________________________________________________________________
122 Int_t AliTRDdigitizer::ExB(Float_t driftlength, Float_t *xyz)
125 // Applies E x B effects to the position of a single electron
129 xyz[1] = xyz[1] + fLorentzAngle * driftlength;
136 //_____________________________________________________________________________
137 void AliTRDdigitizer::Init()
140 // Initializes the digitization procedure with standard values
143 // The default parameter for the digitization
151 // Transverse and longitudinal diffusion coefficients (Xe/Isobutane)
156 // Propability for electron attachment
162 // omega * tau. (tau ~ 12 * 10^-12, B = 0.2T)
163 fLorentzAngle = 17.6 * 12.0 * 0.2 * 0.01;
167 //_____________________________________________________________________________
168 Bool_t AliTRDdigitizer::Open(const Char_t *name, Int_t nEvent)
171 // Opens a ROOT-file with TRD-hits and reads in the hit-tree
174 // Connect the AliRoot file containing Geometry, Kine, and Hits
175 fInputFile = (TFile*) gROOT->GetListOfFiles()->FindObject(name);
177 printf("AliTRDdigitizer::Open -- ");
178 printf("Open the ALIROOT-file %s.\n",name);
179 fInputFile = new TFile(name,"UPDATE");
182 printf("AliTRDdigitizer::Open -- ");
183 printf("%s is already open.\n",name);
186 // Get AliRun object from file or create it if not on file
188 gAlice = (AliRun*) fInputFile->Get("gAlice");
190 printf("AliTRDdigitizer::Open -- ");
191 printf("AliRun object found on file.\n");
194 printf("AliTRDdigitizer::Open -- ");
195 printf("Could not find AliRun object.\n");
202 // Import the Trees for the event nEvent in the file
203 Int_t nparticles = gAlice->GetEvent(fEvent);
204 if (nparticles <= 0) {
205 printf("AliTRDdigitizer::Open -- ");
206 printf("No entries in the trees for event %d.\n",fEvent);
214 //_____________________________________________________________________________
215 Float_t AliTRDdigitizer::PadResponse(Float_t x)
218 // The pad response for the chevron pads.
219 // We use a simple Gaussian approximation which should be good
220 // enough for our purpose.
223 // The parameters for the response function
224 const Float_t aa = 0.8872;
225 const Float_t bb = -0.00573;
226 const Float_t cc = 0.454;
227 const Float_t cc2 = cc*cc;
229 Float_t pr = aa * (bb + TMath::Exp(-x*x / (2. * cc2)));
235 //_____________________________________________________________________________
236 Bool_t AliTRDdigitizer::MakeDigits()
239 // Loops through the TRD-hits and creates the digits.
242 // Get the pointer to the detector class and check for version 1
243 AliTRD *TRD = (AliTRD*) gAlice->GetDetector("TRD");
244 if (TRD->IsVersion() != 1) {
245 printf("AliTRDdigitizer::MakeDigits -- ");
246 printf("TRD must be version 1 (slow simulator).\n");
251 AliTRDgeometry *Geo = TRD->GetGeometry();
252 printf("AliTRDdigitizer::MakeDigits -- ");
253 printf("Geometry version %d\n",Geo->IsVersion());
255 printf("AliTRDdigitizer::MakeDigits -- ");
256 printf("Start creating digits.\n");
258 ///////////////////////////////////////////////////////////////
260 ///////////////////////////////////////////////////////////////
262 // Converts number of electrons to fC
263 const Float_t el2fC = 1.602E-19 * 1.0E15;
265 ///////////////////////////////////////////////////////////////
267 Int_t iRow, iCol, iTime;
270 Int_t totalSizeDigits = 0;
271 Int_t totalSizeDict0 = 0;
272 Int_t totalSizeDict1 = 0;
273 Int_t totalSizeDict2 = 0;
276 AliTRDdataArray *Digits;
277 AliTRDdataArray *Dictionary[kNDict];
279 // Get the pointer to the hit tree
280 TTree *HitTree = gAlice->TreeH();
282 // The Lorentz factor
284 fLorentzFactor = 1.0 / (1.0 + fLorentzAngle*fLorentzAngle);
287 fLorentzFactor = 1.0;
290 // Get the number of entries in the hit tree
291 // (Number of primary particles creating a hit somewhere)
292 Int_t nTrack = (Int_t) HitTree->GetEntries();
295 Int_t chamEnd = kNcham;
296 if (TRD->GetSensChamber() >= 0) {
297 chamBeg = TRD->GetSensChamber();
298 chamEnd = chamEnd + 1;
301 Int_t planEnd = kNplan;
302 if (TRD->GetSensPlane() >= 0) {
303 planBeg = TRD->GetSensPlane();
304 planEnd = planBeg + 1;
307 Int_t sectEnd = kNsect;
308 if (TRD->GetSensSector() >= 0) {
309 sectBeg = TRD->GetSensSector();
310 sectEnd = sectBeg + 1;
313 // Loop through all the chambers
314 for (Int_t iCham = chamBeg; iCham < chamEnd; iCham++) {
315 for (Int_t iPlan = planBeg; iPlan < planEnd; iPlan++) {
316 for (Int_t iSect = sectBeg; iSect < sectEnd; iSect++) {
320 Int_t iDet = Geo->GetDetector(iPlan,iCham,iSect);
322 printf("AliTRDdigitizer::MakeDigits -- ");
323 printf("Digitizing chamber %d, plane %d, sector %d.\n"
326 Int_t nRowMax = Geo->GetRowMax(iPlan,iCham,iSect);
327 Int_t nColMax = Geo->GetColMax(iPlan);
328 Int_t nTimeMax = Geo->GetTimeMax();
329 Float_t row0 = Geo->GetRow0(iPlan,iCham,iSect);
330 Float_t col0 = Geo->GetCol0(iPlan);
331 Float_t time0 = Geo->GetTime0(iPlan);
332 Float_t rowPadSize = Geo->GetRowPadSize();
333 Float_t colPadSize = Geo->GetColPadSize();
334 Float_t timeBinSize = Geo->GetTimeBinSize();
336 // Create a detector matrix to keep the signal and track numbers
337 AliTRDmatrix *Matrix = new AliTRDmatrix(nRowMax,nColMax,nTimeMax
340 // Loop through all entries in the tree
341 for (Int_t iTrack = 0; iTrack < nTrack; iTrack++) {
344 nBytes += HitTree->GetEvent(iTrack);
346 // Get the number of hits in the TRD created by this particle
347 Int_t nHit = TRD->Hits()->GetEntriesFast();
349 // Loop through the TRD hits
350 for (Int_t iHit = 0; iHit < nHit; iHit++) {
352 if (!(Hit = (AliTRDhit *) TRD->Hits()->UncheckedAt(iHit)))
360 Int_t track = Hit->fTrack;
361 Int_t detector = Hit->fDetector;
362 Int_t plane = Geo->GetPlane(detector);
363 Int_t sector = Geo->GetSector(detector);
364 Int_t chamber = Geo->GetChamber(detector);
366 if ((sector != iSect) ||
371 // Rotate the sectors on top of each other
373 Geo->Rotate(detector,pos,rot);
375 // The hit position in pad coordinates (center pad)
376 // The pad row (z-direction)
377 Int_t rowH = (Int_t) ((rot[2] - row0) / rowPadSize);
378 // The pad column (rphi-direction)
379 Int_t colH = (Int_t) ((rot[1] - col0) / colPadSize);
381 Int_t timeH = (Int_t) ((rot[0] - time0) / timeBinSize);
383 // Array to sum up the signal in a box surrounding the
385 const Int_t timeBox = 7;
386 const Int_t colBox = 9;
387 const Int_t rowBox = 7;
388 Float_t signalSum[rowBox][colBox][timeBox];
389 for (iRow = 0; iRow < rowBox; iRow++ ) {
390 for (iCol = 0; iCol < colBox; iCol++ ) {
391 for (iTime = 0; iTime < timeBox; iTime++) {
392 signalSum[iRow][iCol][iTime] = 0;
397 // Loop over all electrons of this hit
398 Int_t nEl = (Int_t) q;
399 for (Int_t iEl = 0; iEl < nEl; iEl++) {
402 Float_t driftlength = rot[0] - time0;
403 if ((driftlength < 0) ||
404 (driftlength > kDrThick)) break;
405 Float_t driftlengthL = driftlength;
406 if (fExBOn) driftlengthL /= TMath::Sqrt(fLorentzFactor);
412 // Electron attachment
414 if (gRandom->Rndm() < (driftlengthL * fElAttachProp / 100.)) continue;
417 // Apply the diffusion smearing
419 if (!(Diffusion(driftlengthL,xyz))) continue;
422 // Apply E x B effects
424 if (!(ExB(driftlength,xyz))) continue;
427 // The electron position and the distance to the hit position
429 // The pad row (z-direction)
430 Int_t rowE = (Int_t) ((xyz[2] - row0) / rowPadSize);
431 Int_t rowD = rowH - rowE;
432 // The pad column (rphi-direction)
433 Int_t colE = (Int_t) ((xyz[1] - col0) / colPadSize);
434 Int_t colD = colH - colE;
436 Int_t timeE = (Int_t) ((xyz[0] - time0) / timeBinSize);
437 Int_t timeD = timeH - timeE;
439 // Apply the gas gain including fluctuations
440 Int_t signal = (Int_t) (-fGasGain * TMath::Log(gRandom->Rndm()));
442 // The distance of the electron to the center of the pad
443 // in units of pad width
444 Float_t dist = (xyz[1] - col0 - (colE + 0.5) * colPadSize)
447 // Sum up the signal in the different pixels
448 // and apply the pad response
449 Int_t rowIdx = rowD + (Int_t) ( rowBox / 2);
450 Int_t colIdx = colD + (Int_t) ( colBox / 2);
451 Int_t timeIdx = timeD + (Int_t) (timeBox / 2);
453 if (( rowIdx < 0) || ( rowIdx > rowBox)) {
454 printf("AliTRDdigitizer::MakeDigits -- ");
455 printf("Boundary error. rowIdx = %d (%d)\n", rowIdx, rowBox);
458 if (( colIdx < 0) || ( colIdx > colBox)) {
459 printf("AliTRDdigitizer::MakeDigits -- ");
460 printf("Boundary error. colIdx = %d (%d)\n", colIdx, colBox);
463 if ((timeIdx < 0) || (timeIdx > timeBox)) {
464 printf("AliTRDdigitizer::MakeDigits -- ");
465 printf("Boundary error. timeIdx = %d (%d)\n",timeIdx,timeBox);
468 signalSum[rowIdx][colIdx-1][timeIdx] += PadResponse(dist-1.) * signal;
469 signalSum[rowIdx][colIdx ][timeIdx] += PadResponse(dist ) * signal;
470 signalSum[rowIdx][colIdx+1][timeIdx] += PadResponse(dist+1.) * signal;
474 // Add the padcluster to the detector matrix
475 for (iRow = 0; iRow < rowBox; iRow++ ) {
476 for (iCol = 0; iCol < colBox; iCol++ ) {
477 for (iTime = 0; iTime < timeBox; iTime++) {
479 Int_t rowB = rowH + iRow - (Int_t) ( rowBox / 2);
480 Int_t colB = colH + iCol - (Int_t) ( colBox / 2);
481 Int_t timeB = timeH + iTime - (Int_t) (timeBox / 2);
483 Float_t signalB = signalSum[iRow][iCol][iTime];
485 Matrix->AddSignal(rowB,colB,timeB,signalB);
486 if (!(Matrix->AddTrack(rowB,colB,timeB,track))) {
487 printf("AliTRDdigitizer::MakeDigits -- ");
488 printf("More than three tracks in a pixel!\n");
500 // Add a container for the digits of this detector
501 Digits = (AliTRDdataArray *) fDigitsArray->At(iDet);
502 // Allocate memory space for the digits buffer
503 Digits->Allocate(nRowMax,nColMax,nTimeMax);
505 for (Int_t iDict = 0; iDict < kNDict; iDict++) {
506 Dictionary[iDict] = (AliTRDdataArray *) fDictionary[iDict]->At(iDet);
507 Dictionary[iDict]->Allocate(nRowMax,nColMax,nTimeMax);
510 // Create the hits for this chamber
511 for (iRow = 0; iRow < nRowMax; iRow++ ) {
512 for (iCol = 0; iCol < nColMax; iCol++ ) {
513 for (iTime = 0; iTime < nTimeMax; iTime++) {
515 Float_t signalAmp = Matrix->GetSignal(iRow,iCol,iTime);
518 signalAmp = TMath::Max(gRandom->Gaus(signalAmp,fNoise),(Float_t) 0.0);
522 signalAmp *= fChipGain;
523 // Convert to ADC counts
524 Int_t adc = (Int_t) (signalAmp * (fADCoutRange / fADCinRange));
526 // Store the amplitude of the digit
527 Digits->SetData(iRow,iCol,iTime,adc);
529 // Store the track index in the dictionary
530 // Note: We store index+1 in order to allow the array to be compressed
531 for (Int_t iDict = 0; iDict < kNDict; iDict++) {
532 Dictionary[iDict]->SetData(iRow,iCol,iTime
533 ,Matrix->GetTrack(iRow,iCol,iTime,iDict)+1);
536 if (adc > fADCthreshold) nDigits++;
542 // Compress the arrays
543 Digits->Compress(1,fADCthreshold);
544 for (Int_t iDict = 0; iDict < kNDict; iDict++) {
545 Dictionary[iDict]->Compress(1,0);
548 totalSizeDigits += Digits->GetSize();
549 totalSizeDict0 += Dictionary[0]->GetSize();
550 totalSizeDict1 += Dictionary[1]->GetSize();
551 totalSizeDict2 += Dictionary[2]->GetSize();
553 printf("AliTRDdigitizer::MakeDigits -- ");
554 printf("Number of digits found: %d.\n",nDigits);
557 if (Matrix) delete Matrix;
563 printf("AliTRDdigitizer::MakeDigits -- ");
564 printf("Total digits data size = %d, %d, %d, %d\n",totalSizeDigits
573 //_____________________________________________________________________________
574 Bool_t AliTRDdigitizer::MakeBranch()
577 // Creates the branches for the digits and the dictionary
580 Int_t buffersize = 64000;
582 Bool_t status = kTRUE;
584 if (gAlice->TreeD()) {
586 // Make the branch for the digits
588 const AliTRDdataArray *Digits =
589 (AliTRDdataArray *) fDigitsArray->At(0);
591 gAlice->TreeD()->Branch("TRDdigits",Digits->IsA()->GetName()
592 ,&Digits,buffersize,1);
593 printf("AliTRDdigitizer::MakeBranch -- ");
594 printf("Making branch TRDdigits\n");
604 // Make the branches for the dictionaries
605 for (Int_t iDict = 0; iDict < kNDict; iDict++) {
607 Char_t branchname[15];
608 sprintf(branchname,"TRDdictionary%d",iDict);
609 if (fDictionary[iDict]) {
610 const AliTRDdataArray *Dictionary =
611 (AliTRDdataArray *) fDictionary[iDict]->At(0);
613 gAlice->TreeD()->Branch(branchname,Dictionary->IsA()->GetName()
614 ,&Dictionary,buffersize,1);
615 printf("AliTRDdigitizer::MakeBranch -- ");
616 printf("Making branch %s\n",branchname);
636 //_____________________________________________________________________________
637 Bool_t AliTRDdigitizer::WriteDigits()
640 // Writes out the TRD-digits and the dictionaries
643 // Create the branches
644 if (!(gAlice->TreeD()->GetBranch("TRDdigits"))) {
645 if (!MakeBranch()) return kFALSE;
648 // Store the contents of the segment array in the tree
649 if (!fDigitsArray->StoreArray("TRDdigits")) {
650 printf("AliTRDdigitizer::WriteDigits -- ");
651 printf("Error while storing digits in branch TRDdigits\n");
654 for (Int_t iDict = 0; iDict < kNDict; iDict++) {
655 Char_t branchname[15];
656 sprintf(branchname,"TRDdictionary%d",iDict);
657 if (!fDictionary[iDict]->StoreArray(branchname)) {
658 printf("AliTRDdigitizer::WriteDigits -- ");
659 printf("Error while storing dictionary in branch %s\n",branchname);
664 // Write the new tree into the input file (use overwrite option)
666 sprintf(treeName,"TreeD%d",fEvent);
667 printf("AliTRDdigitizer::WriteDigits -- ");
668 printf("Write the digits tree %s for event %d.\n"
670 gAlice->TreeD()->Write(treeName,2);
676 ClassImp(AliTRDdigit)
678 //_____________________________________________________________________________
679 AliTRDdigit::AliTRDdigit(Int_t *digits):AliDigitNew()
682 // Create a TRD digit
685 // Store the volume hierarchy
686 fDetector = digits[0];
688 // Store the row, pad, and time bucket number
693 // Store the signal amplitude
694 fAmplitude = digits[4];