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.5 2000/05/09 16:38:57 cblume
19 Removed PadResponse(). Merge problem
21 Revision 1.4 2000/05/08 15:53:45 cblume
22 Resolved merge conflict
24 Revision 1.3 2000/04/28 14:49:27 cblume
25 Only one declaration of iDict in MakeDigits()
27 Revision 1.1.4.1 2000/05/08 14:42:04 cblume
28 Introduced AliTRDdigitsManager
30 Revision 1.1 2000/02/28 19:00:13 cblume
35 ///////////////////////////////////////////////////////////////////////////////
37 // Creates and handles digits from TRD hits //
39 // The following effects are included: //
42 // - Gas gain including fluctuations //
43 // - Pad-response (simple Gaussian approximation) //
44 // - Electronics noise //
45 // - Electronics gain //
48 // The corresponding parameter can be adjusted via the various //
49 // Set-functions. If these parameters are not explicitly set, default //
50 // values are used (see Init-function). //
51 // To produce digits from a root-file with TRD-hits use the //
52 // slowDigitsCreate.C macro. //
54 ///////////////////////////////////////////////////////////////////////////////
61 #include "AliTRDdigitizer.h"
62 #include "AliTRDdataArrayI.h"
63 #include "AliTRDdataArrayF.h"
64 #include "AliTRDdigitsManager.h"
66 ClassImp(AliTRDdigitizer)
68 //_____________________________________________________________________________
69 AliTRDdigitizer::AliTRDdigitizer():TNamed()
72 // AliTRDdigitizer default constructor
98 //_____________________________________________________________________________
99 AliTRDdigitizer::AliTRDdigitizer(const Text_t *name, const Text_t *title)
103 // AliTRDdigitizer default constructor
117 //_____________________________________________________________________________
118 AliTRDdigitizer::~AliTRDdigitizer()
130 if (fPRF) delete fPRF;
134 //_____________________________________________________________________________
135 Int_t AliTRDdigitizer::Diffusion(Float_t driftlength, Float_t *xyz)
138 // Applies the diffusion smearing to the position of a single electron
141 Float_t driftSqrt = TMath::Sqrt(driftlength);
142 Float_t sigmaT = driftSqrt * fDiffusionT;
143 Float_t sigmaL = driftSqrt * fDiffusionL;
144 xyz[0] = gRandom->Gaus(xyz[0], sigmaL * fLorentzFactor);
145 xyz[1] = gRandom->Gaus(xyz[1], sigmaT * fLorentzFactor);
146 xyz[2] = gRandom->Gaus(xyz[2], sigmaT);
151 //_____________________________________________________________________________
152 Int_t AliTRDdigitizer::ExB(Float_t driftlength, Float_t *xyz)
155 // Applies E x B effects to the position of a single electron
159 xyz[1] = xyz[1] + fLorentzAngle * driftlength;
166 //_____________________________________________________________________________
167 void AliTRDdigitizer::Init()
170 // Initializes the digitization procedure with standard values
173 // The default parameter for the digitization
181 // Transverse and longitudinal diffusion coefficients (Xe/Isobutane)
186 // Propability for electron attachment
192 // omega * tau. (tau ~ 12 * 10^-12, B = 0.2T)
193 fLorentzAngle = 17.6 * 12.0 * 0.2 * 0.01;
195 // The pad response function
196 fPRF = new TF1("PRF","[0]*([1]+exp(-x*x/(2.0*[2])))",-2,2);
197 fPRF->SetParameter(0, 0.8872);
198 fPRF->SetParameter(1,-0.00573);
199 fPRF->SetParameter(2, 0.454 * 0.454);
203 //_____________________________________________________________________________
204 Bool_t AliTRDdigitizer::Open(const Char_t *name, Int_t nEvent)
207 // Opens a ROOT-file with TRD-hits and reads in the hit-tree
210 // Connect the AliRoot file containing Geometry, Kine, and Hits
211 fInputFile = (TFile*) gROOT->GetListOfFiles()->FindObject(name);
213 printf("AliTRDdigitizer::Open -- ");
214 printf("Open the ALIROOT-file %s.\n",name);
215 fInputFile = new TFile(name,"UPDATE");
218 printf("AliTRDdigitizer::Open -- ");
219 printf("%s is already open.\n",name);
222 gAlice = (AliRun*) fInputFile->Get("gAlice");
224 printf("AliTRDdigitizer::Open -- ");
225 printf("AliRun object found on file.\n");
228 printf("AliTRDdigitizer::Open -- ");
229 printf("Could not find AliRun object.\n");
235 // Import the Trees for the event nEvent in the file
236 Int_t nparticles = gAlice->GetEvent(fEvent);
237 if (nparticles <= 0) {
238 printf("AliTRDdigitizer::Open -- ");
239 printf("No entries in the trees for event %d.\n",fEvent);
247 //_____________________________________________________________________________
248 Bool_t AliTRDdigitizer::MakeDigits()
251 // Loops through the TRD-hits and creates the digits.
254 ///////////////////////////////////////////////////////////////
256 ///////////////////////////////////////////////////////////////
258 // Converts number of electrons to fC
259 const Float_t el2fC = 1.602E-19 * 1.0E15;
261 ///////////////////////////////////////////////////////////////
263 Int_t iRow, iCol, iTime;
267 Int_t totalSizeDigits = 0;
268 Int_t totalSizeDict0 = 0;
269 Int_t totalSizeDict1 = 0;
270 Int_t totalSizeDict2 = 0;
272 AliTRDdataArrayI *Digits;
273 AliTRDdataArrayI *Dictionary[kNDict];
276 printf("AliTRDdigitizer::MakeDigits -- ");
277 printf("No geometry defined\n");
281 // Create a digits manager
282 fDigits = new AliTRDdigitsManager();
284 // Create detector arrays to keep the signal and track numbers
285 AliTRDdataArrayF *Signal = new AliTRDdataArrayF();
286 AliTRDdataArrayI *Tracks[kNDict];
287 for (iDict = 0; iDict < kNDict; iDict++) {
288 Tracks[iDict] = new AliTRDdataArrayI();
291 // Get the pointer to the hit tree
292 TTree *HitTree = gAlice->TreeH();
294 // Get the number of entries in the hit tree
295 // (Number of primary particles creating a hit somewhere)
296 Int_t nTrack = (Int_t) HitTree->GetEntries();
298 printf("AliTRDdigitizer::MakeDigits -- ");
299 printf("Start creating digits.\n");
301 // The Lorentz factor
303 fLorentzFactor = 1.0 / (1.0 + fLorentzAngle*fLorentzAngle);
306 fLorentzFactor = 1.0;
310 Int_t chamEnd = kNcham;
311 if (fTRD->GetSensChamber() >= 0) {
312 chamBeg = fTRD->GetSensChamber();
313 chamEnd = chamBeg + 1;
316 Int_t planEnd = kNplan;
317 if (fTRD->GetSensPlane() >= 0) {
318 planBeg = fTRD->GetSensPlane();
319 planEnd = planBeg + 1;
322 Int_t sectEnd = kNsect;
324 Int_t count_hits = 0;
326 // Loop through all the chambers
327 for (Int_t iCham = chamBeg; iCham < chamEnd; iCham++) {
328 for (Int_t iPlan = planBeg; iPlan < planEnd; iPlan++) {
329 for (Int_t iSect = sectBeg; iSect < sectEnd; iSect++) {
331 if (fTRD->GetSensSector() >= 0) {
332 Int_t sens1 = fTRD->GetSensSector();
333 Int_t sens2 = sens1 + fTRD->GetSensSectorRange();
334 sens2 -= ((Int_t) (sens2 / kNsect)) * kNsect;
336 if ((iSect < sens1) || (iSect >= sens2)) continue;
338 if ((iSect < sens1) && (iSect >= sens2)) continue;
343 printf("AliTRDdigitizer::MakeDigits -- ");
344 printf("Digitizing chamber %d, plane %d, sector %d.\n"
347 Int_t iDet = fGeo->GetDetector(iPlan,iCham,iSect);
348 Int_t nRowMax = fGeo->GetRowMax(iPlan,iCham,iSect);
349 Int_t nColMax = fGeo->GetColMax(iPlan);
350 Int_t nTimeMax = fGeo->GetTimeMax();
351 Float_t row0 = fGeo->GetRow0(iPlan,iCham,iSect);
352 Float_t col0 = fGeo->GetCol0(iPlan);
353 Float_t time0 = fGeo->GetTime0(iPlan);
354 Float_t rowPadSize = fGeo->GetRowPadSize();
355 Float_t colPadSize = fGeo->GetColPadSize();
356 Float_t timeBinSize = fGeo->GetTimeBinSize();
358 // Adjust the size of the detector arrays
359 Signal->Allocate(nRowMax,nColMax,nTimeMax);
360 for (iDict = 0; iDict < kNDict; iDict++) {
361 Tracks[iDict]->Allocate(nRowMax,nColMax,nTimeMax);
364 // Loop through all entries in the tree
365 for (Int_t iTrack = 0; iTrack < nTrack; iTrack++) {
368 nBytes += HitTree->GetEvent(iTrack);
370 // Get the number of hits in the TRD created by this particle
371 Int_t nHit = fTRD->Hits()->GetEntriesFast();
373 // Loop through the TRD hits
374 for (Int_t iHit = 0; iHit < nHit; iHit++) {
378 AliTRDhit *Hit = (AliTRDhit *) fTRD->Hits()->UncheckedAt(iHit);
384 Int_t track = Hit->fTrack;
385 Int_t detector = Hit->fDetector;
386 Int_t plane = fGeo->GetPlane(detector);
387 Int_t sector = fGeo->GetSector(detector);
388 Int_t chamber = fGeo->GetChamber(detector);
390 if ((sector != iSect) ||
395 // Rotate the sectors on top of each other
397 fGeo->Rotate(detector,pos,rot);
399 // The hit position in pad coordinates (center pad)
400 // The pad row (z-direction)
401 Int_t rowH = (Int_t) ((rot[2] - row0) / rowPadSize);
402 // The pad column (rphi-direction)
403 Int_t colH = (Int_t) ((rot[1] - col0) / colPadSize);
405 Int_t timeH = (Int_t) ((rot[0] - time0) / timeBinSize);
407 // Array to sum up the signal in a box surrounding the
409 const Int_t timeBox = 7;
410 const Int_t colBox = 9;
411 const Int_t rowBox = 7;
412 Float_t signalSum[rowBox][colBox][timeBox];
413 for (iRow = 0; iRow < rowBox; iRow++ ) {
414 for (iCol = 0; iCol < colBox; iCol++ ) {
415 for (iTime = 0; iTime < timeBox; iTime++) {
416 signalSum[iRow][iCol][iTime] = 0;
421 // Loop over all electrons of this hit
422 Int_t nEl = (Int_t) q;
423 for (Int_t iEl = 0; iEl < nEl; iEl++) {
426 Float_t driftlength = rot[0] - time0;
427 if ((driftlength < 0) ||
428 (driftlength > kDrThick)) break;
429 Float_t driftlengthL = driftlength;
430 if (fExBOn) driftlengthL /= TMath::Sqrt(fLorentzFactor);
436 // Electron attachment
438 if (gRandom->Rndm() < (driftlengthL * fElAttachProp / 100.)) continue;
441 // Apply the diffusion smearing
443 if (!(Diffusion(driftlengthL,xyz))) continue;
446 // Apply E x B effects
448 if (!(ExB(driftlength,xyz))) continue;
451 // The electron position and the distance to the hit position
453 // The pad row (z-direction)
454 Int_t rowE = (Int_t) ((xyz[2] - row0) / rowPadSize);
455 Int_t rowD = rowH - rowE;
456 // The pad column (rphi-direction)
457 Int_t colE = (Int_t) ((xyz[1] - col0) / colPadSize);
458 Int_t colD = colH - colE;
460 Int_t timeE = (Int_t) ((xyz[0] - time0) / timeBinSize);
461 Int_t timeD = timeH - timeE;
463 // Apply the gas gain including fluctuations
464 Int_t signal = (Int_t) (-fGasGain * TMath::Log(gRandom->Rndm()));
466 // The distance of the electron to the center of the pad
467 // in units of pad width
468 Float_t dist = (xyz[1] - col0 - (colE + 0.5) * colPadSize)
471 // Sum up the signal in the different pixels
472 // and apply the pad response
473 Int_t rowIdx = rowD + (Int_t) ( rowBox / 2);
474 Int_t colIdx = colD + (Int_t) ( colBox / 2);
475 Int_t timeIdx = timeD + (Int_t) (timeBox / 2);
477 if (( rowIdx < 0) || ( rowIdx > rowBox)) {
478 printf("AliTRDdigitizer::MakeDigits -- ");
479 printf("Boundary error. rowIdx = %d (%d)\n", rowIdx, rowBox);
482 if (( colIdx < 0) || ( colIdx > colBox)) {
483 printf("AliTRDdigitizer::MakeDigits -- ");
484 printf("Boundary error. colIdx = %d (%d)\n", colIdx, colBox);
487 if ((timeIdx < 0) || (timeIdx > timeBox)) {
488 printf("AliTRDdigitizer::MakeDigits -- ");
489 printf("Boundary error. timeIdx = %d (%d)\n",timeIdx,timeBox);
492 signalSum[rowIdx][colIdx-1][timeIdx] += fPRF->Eval(dist-1.0,0,0) * signal;
493 signalSum[rowIdx][colIdx ][timeIdx] += fPRF->Eval(dist ,0,0) * signal;
494 signalSum[rowIdx][colIdx+1][timeIdx] += fPRF->Eval(dist+1.0,0,0) * signal;
498 // Add the padcluster to the detector matrix
499 for (iRow = 0; iRow < rowBox; iRow++ ) {
500 for (iCol = 0; iCol < colBox; iCol++ ) {
501 for (iTime = 0; iTime < timeBox; iTime++) {
503 Int_t rowB = rowH + iRow - (Int_t) ( rowBox / 2);
504 Int_t colB = colH + iCol - (Int_t) ( colBox / 2);
505 Int_t timeB = timeH + iTime - (Int_t) (timeBox / 2);
506 Float_t signalB = signalSum[iRow][iCol][iTime];
507 if (( rowB < 0) || ( rowB >= nRowMax)) continue;
508 if (( colB < 0) || ( colB >= nColMax)) continue;
509 if ((timeB < 0) || (timeB >= nTimeMax)) continue;
512 // Add the signal sum
513 signalB += Signal->GetData(rowB,colB,timeB);
514 Signal->SetData(rowB,colB,timeB,signalB);
515 // Store the track index in the dictionary
516 // Note: We store index+1 in order to allow the array to be compressed
517 for (iDict = 0; iDict < kNDict; iDict++) {
518 Int_t oldTrack = Tracks[iDict]->GetData(rowB,colB,timeB);
519 if (oldTrack == track+1) break;
520 if (oldTrack == -1) break;
522 Tracks[iDict]->SetData(rowB,colB,timeB,track+1);
526 if (iDict == kNDict) {
527 printf("AliTRDdigitizer::MakeDigits -- ");
528 printf("More than three tracks for one digit!\n");
540 // Add a container for the digits of this detector
541 Digits = fDigits->GetDigits(iDet);
542 // Allocate memory space for the digits buffer
543 Digits->Allocate(nRowMax,nColMax,nTimeMax);
545 // Do the same for the dictionary arrays
546 for (iDict = 0; iDict < kNDict; iDict++) {
547 Dictionary[iDict] = fDigits->GetDictionary(iDet,iDict);
548 Dictionary[iDict]->Allocate(nRowMax,nColMax,nTimeMax);
551 // Create the digits for this chamber
552 for (iRow = 0; iRow < nRowMax; iRow++ ) {
553 for (iCol = 0; iCol < nColMax; iCol++ ) {
554 for (iTime = 0; iTime < nTimeMax; iTime++) {
556 Float_t signalAmp = Signal->GetData(iRow,iCol,iTime);
559 signalAmp = TMath::Max((Float_t) gRandom->Gaus(signalAmp,fNoise)
564 signalAmp *= fChipGain;
565 // Convert to ADC counts
566 Int_t adc = (Int_t) (signalAmp * (fADCoutRange / fADCinRange));
568 if (adc > fADCthreshold) {
572 // Store the amplitude of the digit
573 Digits->SetData(iRow,iCol,iTime,adc);
575 // Store the track index in the dictionary
576 // Note: We store index+1 in order to allow the array to be compressed
577 for (iDict = 0; iDict < kNDict; iDict++) {
578 Dictionary[iDict]->SetData(iRow,iCol,iTime
579 ,Tracks[iDict]->GetData(iRow,iCol,iTime));
588 // Compress the arrays
589 Digits->Compress(1,0);
590 for (iDict = 0; iDict < kNDict; iDict++) {
591 Dictionary[iDict]->Compress(1,0);
594 totalSizeDigits += Digits->GetSize();
595 totalSizeDict0 += Dictionary[0]->GetSize();
596 totalSizeDict1 += Dictionary[1]->GetSize();
597 totalSizeDict2 += Dictionary[2]->GetSize();
599 printf("AliTRDdigitizer::MakeDigits -- ");
600 printf("Number of digits found: %d.\n",nDigits);
604 for (iDict = 0; iDict < kNDict; iDict++) {
605 Tracks[iDict]->Reset();
612 printf("AliTRDdigitizer::MakeDigits -- ");
613 printf("Total number of analyzed hits = %d\n",count_hits);
615 printf("AliTRDdigitizer::MakeDigits -- ");
616 printf("Total digits data size = %d, %d, %d, %d\n",totalSizeDigits
625 //_____________________________________________________________________________
626 Bool_t AliTRDdigitizer::WriteDigits()
629 // Writes out the TRD-digits and the dictionaries
632 // Create the branches
633 if (!(gAlice->TreeD()->GetBranch("TRDdigits"))) {
634 if (!fDigits->MakeBranch()) return kFALSE;
637 // Store the digits and the dictionary in the tree
638 fDigits->WriteDigits();
640 // Write the new tree into the input file (use overwrite option)
642 sprintf(treeName,"TreeD%d",fEvent);
643 printf("AliTRDdigitizer::WriteDigits -- ");
644 printf("Write the digits tree %s for event %d.\n"
646 gAlice->TreeD()->Write(treeName,2);