/*
$Log$
+Revision 1.1.4.9 2000/10/26 17:00:22 cblume
+Fixed bug in CheckDetector()
+
+Revision 1.1.4.8 2000/10/23 13:41:35 cblume
+Added protection against Log(0) in the gas gain calulation
+
+Revision 1.1.4.7 2000/10/17 02:27:34 cblume
+Get rid of global constants
+
+Revision 1.1.4.6 2000/10/16 01:16:53 cblume
+Changed timebin 0 to be the one closest to the readout
+
+Revision 1.1.4.5 2000/10/15 23:34:29 cblume
+Faster version of the digitizer
+
+Revision 1.1.4.4 2000/10/06 16:49:46 cblume
+Made Getters const
+
+Revision 1.1.4.3 2000/10/04 16:34:58 cblume
+Replace include files by forward declarations
+
+Revision 1.1.4.2 2000/09/22 14:41:10 cblume
+Bug fix in PRF. Included time response. New structure
+
+Revision 1.10 2000/10/05 07:27:53 cblume
+Changes in the header-files by FCA
+
+Revision 1.9 2000/10/02 21:28:19 fca
+Removal of useless dependecies via forward declarations
+
+Revision 1.8 2000/06/09 11:10:07 cblume
+Compiler warnings and coding conventions, next round
+
+Revision 1.7 2000/06/08 18:32:58 cblume
+Make code compliant to coding conventions
+
+Revision 1.6 2000/06/07 16:27:32 cblume
+Try to remove compiler warnings on Sun and HP
+
+Revision 1.5 2000/05/09 16:38:57 cblume
+Removed PadResponse(). Merge problem
+
+Revision 1.4 2000/05/08 15:53:45 cblume
+Resolved merge conflict
+
+Revision 1.3 2000/04/28 14:49:27 cblume
+Only one declaration of iDict in MakeDigits()
+
+Revision 1.1.4.1 2000/05/08 14:42:04 cblume
+Introduced AliTRDdigitsManager
+
+Revision 1.1 2000/02/28 19:00:13 cblume
+Add new TRD classes
+
*/
///////////////////////////////////////////////////////////////////////////////
// //
///////////////////////////////////////////////////////////////////////////////
+#include <stdlib.h>
+
#include <TMath.h>
#include <TVector.h>
#include <TRandom.h>
+#include <TROOT.h>
+#include <TTree.h>
+#include <TFile.h>
+#include <TF1.h>
+
+#include "AliRun.h"
#include "AliTRD.h"
+#include "AliTRDhit.h"
#include "AliTRDdigitizer.h"
-#include "AliTRDmatrix.h"
+#include "AliTRDdataArrayI.h"
+#include "AliTRDdataArrayF.h"
+#include "AliTRDsegmentArray.h"
+#include "AliTRDdigitsManager.h"
+#include "AliTRDgeometry.h"
ClassImp(AliTRDdigitizer)
// AliTRDdigitizer default constructor
//
- fInputFile = NULL;
- fEvent = 0;
+ fInputFile = NULL;
+ fDigits = NULL;
+ fTRD = NULL;
+ fGeo = NULL;
+ fPRF = NULL;
+ fTRF = NULL;
+ fTRFint = NULL;
+
+ fEvent = 0;
+ fGasGain = 0.0;
+ fNoise = 0.0;
+ fChipGain = 0.0;
+ fADCoutRange = 0.0;
+ fADCinRange = 0.0;
+ fADCthreshold = 0;
+ fDiffusionOn = 0;
+ fDiffusionT = 0.0;
+ fDiffusionL = 0.0;
+ fElAttachOn = 0;
+ fElAttachProp = 0.0;
+ fExBOn = 0;
+ fOmegaTau = 0.0;
+ fPRFOn = 0;
+ fTRFOn = 0;
+ fDriftVelocity = 0.0;
+
+ fTRFbin = 0;
+ fTRFlo = 0.0;
+ fTRFhi = 0.0;
+ fTRFwid = 0.0;
+ fCompress = kFALSE;
+ fVerbose = 1;
}
// AliTRDdigitizer default constructor
//
- fInputFile = NULL;
- fEvent = 0;
+ fInputFile = NULL;
+ fDigits = NULL;
+ fTRD = NULL;
+ fGeo = NULL;
- fDigitsArray = new AliTRDsegmentArray(kNsect*kNplan*kNcham);
- for (Int_t iDict = 0; iDict < kNDict; iDict++) {
- fDictionary[iDict] = new AliTRDsegmentArray(kNsect*kNplan*kNcham);
- }
+ fEvent = 0;
+
+ fCompress = kTRUE;
+ fVerbose = 1;
Init();
}
+//_____________________________________________________________________________
+AliTRDdigitizer::AliTRDdigitizer(const AliTRDdigitizer &d)
+{
+ //
+ // AliTRDdigitizer copy constructor
+ //
+
+ ((AliTRDdigitizer &) d).Copy(*this);
+
+}
+
//_____________________________________________________________________________
AliTRDdigitizer::~AliTRDdigitizer()
{
+ //
+ // AliTRDdigitizer destructor
+ //
if (fInputFile) {
fInputFile->Close();
delete fInputFile;
}
- if (fDigitsArray) {
- fDigitsArray->Delete();
- delete fDigitsArray;
+ if (fDigits) {
+ delete fDigits;
}
- for (Int_t iDict = 0; iDict < kNDict; iDict++) {
- fDictionary[iDict]->Delete();
- delete fDictionary[iDict];
- }
+ if (fPRF) delete fPRF;
+ if (fTRF) delete fTRF;
+
+}
+
+//_____________________________________________________________________________
+AliTRDdigitizer &AliTRDdigitizer::operator=(const AliTRDdigitizer &d)
+{
+ //
+ // Assignment operator
+ //
+
+ if (this != &d) ((AliTRDdigitizer &) d).Copy(*this);
+ return *this;
+
+}
+
+//_____________________________________________________________________________
+void AliTRDdigitizer::Copy(TObject &d)
+{
+ //
+ // Copy function
+ //
+
+ ((AliTRDdigitizer &) d).fInputFile = NULL;
+ ((AliTRDdigitizer &) d).fDigits = NULL;
+ ((AliTRDdigitizer &) d).fTRD = NULL;
+ ((AliTRDdigitizer &) d).fGeo = NULL;
+
+ ((AliTRDdigitizer &) d).fEvent = 0;
+
+ ((AliTRDdigitizer &) d).fGasGain = fGasGain;
+ ((AliTRDdigitizer &) d).fNoise = fNoise;
+ ((AliTRDdigitizer &) d).fChipGain = fChipGain;
+ ((AliTRDdigitizer &) d).fADCoutRange = fADCoutRange;
+ ((AliTRDdigitizer &) d).fADCinRange = fADCinRange;
+ ((AliTRDdigitizer &) d).fADCthreshold = fADCthreshold;
+ ((AliTRDdigitizer &) d).fDiffusionOn = fDiffusionOn;
+ ((AliTRDdigitizer &) d).fDiffusionT = fDiffusionT;
+ ((AliTRDdigitizer &) d).fDiffusionL = fDiffusionL;
+ ((AliTRDdigitizer &) d).fElAttachOn = fElAttachOn;
+ ((AliTRDdigitizer &) d).fElAttachProp = fElAttachProp;
+ ((AliTRDdigitizer &) d).fExBOn = fExBOn;
+ ((AliTRDdigitizer &) d).fOmegaTau = fOmegaTau;
+ ((AliTRDdigitizer &) d).fLorentzFactor = fLorentzFactor;
+ ((AliTRDdigitizer &) d).fPRFOn = fPRFOn;
+ ((AliTRDdigitizer &) d).fTRFOn = fTRFOn;
+
+ ((AliTRDdigitizer &) d).fCompress = fCompress;
+ ((AliTRDdigitizer &) d).fVerbose = fVerbose;
+
+ fPRF->Copy(*((AliTRDdigitizer &) d).fPRF);
+ fTRF->Copy(*((AliTRDdigitizer &) d).fTRF);
+
+ ((AliTRDdigitizer &) d).fTRFbin = fTRFbin;
+ ((AliTRDdigitizer &) d).fTRFlo = fTRFlo;
+ ((AliTRDdigitizer &) d).fTRFhi = fTRFhi;
+ ((AliTRDdigitizer &) d).fTRFwid = fTRFwid;
+ if (((AliTRDdigitizer &) d).fTRFint) delete ((AliTRDdigitizer &) d).fTRFint;
+ ((AliTRDdigitizer &) d).fTRFint = new Float_t[fTRFbin];
+ for (Int_t iBin = 0; iBin < fTRFbin; iBin++) {
+ ((AliTRDdigitizer &) d).fTRFint[iBin] = fTRFint[iBin];
+ }
}
xyz[0] = gRandom->Gaus(xyz[0], sigmaL * fLorentzFactor);
xyz[1] = gRandom->Gaus(xyz[1], sigmaT * fLorentzFactor);
xyz[2] = gRandom->Gaus(xyz[2], sigmaT);
+
return 1;
}
//
xyz[0] = xyz[0];
- xyz[1] = xyz[1] + fLorentzAngle * driftlength;
+ xyz[1] = xyz[1] + fOmegaTau * driftlength;
xyz[2] = xyz[2];
return 1;
}
+//_____________________________________________________________________________
+Int_t AliTRDdigitizer::PadResponse(Float_t signal, Float_t dist, Float_t *pad)
+{
+ //
+ // Applies the pad response
+ //
+
+ if (fPRF) {
+ pad[0] = TMath::Max(fPRF->Eval(-1.0 - dist,0,0) * signal,0.0);
+ pad[1] = TMath::Max(fPRF->Eval( - dist,0,0) * signal,0.0);
+ pad[2] = TMath::Max(fPRF->Eval( 1.0 - dist,0,0) * signal,0.0);
+ return 1;
+ }
+ else {
+ return 0;
+ }
+
+}
+
+//_____________________________________________________________________________
+Float_t AliTRDdigitizer::TimeResponse(Float_t time)
+{
+ //
+ // Applies the preamp shaper time response
+ //
+
+ Int_t iBin = ((Int_t) ((time - fTRFlo) / fTRFwid));
+ if ((iBin >= 0) && (iBin < fTRFbin)) {
+ return fTRFint[iBin];
+ }
+ else {
+ return 0.0;
+ }
+
+}
+
//_____________________________________________________________________________
void AliTRDdigitizer::Init()
{
//
// The default parameter for the digitization
- fGasGain = 2.0E3;
+ fGasGain = 8.0E3;
fNoise = 3000.;
fChipGain = 10.;
fADCoutRange = 255.;
// E x B effects
fExBOn = 0;
// omega * tau. (tau ~ 12 * 10^-12, B = 0.2T)
- fLorentzAngle = 17.6 * 12.0 * 0.2 * 0.01;
+ fOmegaTau = 17.6 * 12.0 * 0.2 * 0.01;
+
+ // The pad response function
+ fPRFOn = 1;
+ fPRF = new TF1("PRF","[0]*([1]+exp(-x*x/(2.0*[2])))",-3,3);
+ fPRF->SetParameter(0, 0.8872);
+ fPRF->SetParameter(1,-0.00573);
+ fPRF->SetParameter(2, 0.454 * 0.454);
+
+ // The drift velocity (cm / mus)
+ fDriftVelocity = 1.0;
+
+ // The time response function
+ fTRFOn = 1;
+ Float_t loTRF = -200.0;
+ Float_t hiTRF = 1000.0;
+ fTRF = new TF1("TRF",TRFlandau,loTRF,hiTRF,3);
+ fTRF->SetParameter(0, 1.0 / 24.24249);
+ fTRF->SetParameter(1, 0.0);
+ fTRF->SetParameter(2, 25.0);
+ fTRFbin = 1200;
+ fTRFlo = loTRF * fDriftVelocity / 1000.0;
+ fTRFhi = hiTRF * fDriftVelocity / 1000.0;
+ fTRFwid = (fTRFhi - fTRFlo) / ((Float_t) fTRFbin);
+
+}
+
+//_____________________________________________________________________________
+void AliTRDdigitizer::IntegrateTRF()
+{
+ //
+ // Integrates the time response function over the time bin size
+ //
+
+ if (fTRFint) delete fTRFint;
+ fTRFint = new Float_t[fTRFbin];
+ Float_t hiTRF = fTRFhi / fDriftVelocity * 1000.0;
+ Float_t loTRF = fTRFlo / fDriftVelocity * 1000.0;
+ Float_t timeBin = fGeo->GetTimeBinSize() / fDriftVelocity * 1000.0;
+ Float_t binWidth = (hiTRF - loTRF) / ((Float_t) fTRFbin);
+ for (Int_t iBin = 0; iBin < fTRFbin; iBin++) {
+ Float_t bin = iBin * binWidth + loTRF - 0.5 * timeBin;
+ fTRFint[iBin] = fTRF->Integral(bin,bin + timeBin);
+ }
}
printf("%s is already open.\n",name);
}
- // Get AliRun object from file or create it if not on file
- //if (!gAlice) {
- gAlice = (AliRun*) fInputFile->Get("gAlice");
- if (gAlice) {
- printf("AliTRDdigitizer::Open -- ");
- printf("AliRun object found on file.\n");
- }
- else {
- printf("AliTRDdigitizer::Open -- ");
- printf("Could not find AliRun object.\n");
- return kFALSE;
- }
- //}
+ gAlice = (AliRun*) fInputFile->Get("gAlice");
+ if (gAlice) {
+ printf("AliTRDdigitizer::Open -- ");
+ printf("AliRun object found on file.\n");
+ }
+ else {
+ printf("AliTRDdigitizer::Open -- ");
+ printf("Could not find AliRun object.\n");
+ return kFALSE;
+ }
fEvent = nEvent;
return kFALSE;
}
- return kTRUE;
+ return InitDetector();
}
//_____________________________________________________________________________
-Float_t AliTRDdigitizer::PadResponse(Float_t x)
+Bool_t AliTRDdigitizer::InitDetector()
{
//
- // The pad response for the chevron pads.
- // We use a simple Gaussian approximation which should be good
- // enough for our purpose.
+ // Sets the pointer to the TRD detector and the geometry
//
- // The parameters for the response function
- const Float_t aa = 0.8872;
- const Float_t bb = -0.00573;
- const Float_t cc = 0.454;
- const Float_t cc2 = cc*cc;
+ // Get the pointer to the detector class and check for version 1
+ fTRD = (AliTRD*) gAlice->GetDetector("TRD");
+ if (fTRD->IsVersion() != 1) {
+ printf("AliTRDdigitizer::Open -- ");
+ printf("TRD must be version 1 (slow simulator).\n");
+ exit(1);
+ }
- Float_t pr = aa * (bb + TMath::Exp(-x*x / (2. * cc2)));
+ // Get the geometry
+ fGeo = fTRD->GetGeometry();
+ printf("AliTRDdigitizer::Open -- ");
+ printf("Geometry version %d\n",fGeo->IsVersion());
- return (pr);
+ return kTRUE;
}
// Loops through the TRD-hits and creates the digits.
//
- // Get the pointer to the detector class and check for version 1
- AliTRD *TRD = (AliTRD*) gAlice->GetDetector("TRD");
- if (TRD->IsVersion() != 1) {
- printf("AliTRDdigitizer::MakeDigits -- ");
- printf("TRD must be version 1 (slow simulator).\n");
- return kFALSE;
- }
-
- // Get the geometry
- AliTRDgeometry *Geo = TRD->GetGeometry();
- printf("AliTRDdigitizer::MakeDigits -- ");
- printf("Geometry version %d\n",Geo->IsVersion());
-
- printf("AliTRDdigitizer::MakeDigits -- ");
- printf("Start creating digits.\n");
-
///////////////////////////////////////////////////////////////
// Parameter
///////////////////////////////////////////////////////////////
// Converts number of electrons to fC
- const Float_t el2fC = 1.602E-19 * 1.0E15;
+ const Float_t kEl2fC = 1.602E-19 * 1.0E15;
///////////////////////////////////////////////////////////////
+ // Number of pads included in the pad response
+ const Int_t kNpad = 3;
+
+ // Number of track dictionary arrays
+ const Int_t kNDict = AliTRDdigitsManager::NDict();
+
Int_t iRow, iCol, iTime;
+ Int_t iDict;
Int_t nBytes = 0;
Int_t totalSizeDigits = 0;
Int_t totalSizeDict1 = 0;
Int_t totalSizeDict2 = 0;
- AliTRDhit *Hit;
- AliTRDdataArray *Digits;
- AliTRDdataArray *Dictionary[kNDict];
+ AliTRDdataArrayF *signals = 0;
+ AliTRDdataArrayI *digits = 0;
+ AliTRDdataArrayI *dictionary[kNDict];
- // Get the pointer to the hit tree
- TTree *HitTree = gAlice->TreeH();
+ // Create a digits manager
+ fDigits = new AliTRDdigitsManager();
+
+ // Create a container for the amplitudes
+ AliTRDsegmentArray *signalsArray
+ = new AliTRDsegmentArray("AliTRDdataArrayF",AliTRDgeometry::Ndet());
+
+ if (!fGeo) {
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("No geometry defined\n");
+ return kFALSE;
+ }
+
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Start creating digits.\n");
+ if (fVerbose > 0) this->Dump();
// The Lorentz factor
if (fExBOn) {
- fLorentzFactor = 1.0 / (1.0 + fLorentzAngle*fLorentzAngle);
+ fLorentzFactor = 1.0 / (1.0 + fOmegaTau*fOmegaTau);
}
else {
fLorentzFactor = 1.0;
}
+ // Create the integrated TRF
+ IntegrateTRF();
+
+ // Get the pointer to the hit tree
+ TTree *HitTree = gAlice->TreeH();
+
// Get the number of entries in the hit tree
// (Number of primary particles creating a hit somewhere)
Int_t nTrack = (Int_t) HitTree->GetEntries();
+ if (fVerbose > 0) {
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Found %d primary particles\n",nTrack);
+ }
- Int_t chamBeg = 0;
- Int_t chamEnd = kNcham;
- if (TRD->GetSensChamber() >= 0) {
- chamBeg = TRD->GetSensChamber();
- chamEnd = chamEnd + 1;
- }
- Int_t planBeg = 0;
- Int_t planEnd = kNplan;
- if (TRD->GetSensPlane() >= 0) {
- planBeg = TRD->GetSensPlane();
- planEnd = planBeg + 1;
- }
- Int_t sectBeg = 0;
- Int_t sectEnd = kNsect;
- if (TRD->GetSensSector() >= 0) {
- sectBeg = TRD->GetSensSector();
- sectEnd = sectBeg + 1;
- }
+ Int_t detectorOld = -1;
+ Int_t countHits = 0;
- // Loop through all the chambers
- for (Int_t iCham = chamBeg; iCham < chamEnd; iCham++) {
- for (Int_t iPlan = planBeg; iPlan < planEnd; iPlan++) {
- for (Int_t iSect = sectBeg; iSect < sectEnd; iSect++) {
-
- Int_t nDigits = 0;
-
- Int_t iDet = Geo->GetDetector(iPlan,iCham,iSect);
-
- printf("AliTRDdigitizer::MakeDigits -- ");
- printf("Digitizing chamber %d, plane %d, sector %d.\n"
- ,iCham,iPlan,iSect);
-
- Int_t nRowMax = Geo->GetRowMax(iPlan,iCham,iSect);
- Int_t nColMax = Geo->GetColMax(iPlan);
- Int_t nTimeMax = Geo->GetTimeMax();
- Float_t row0 = Geo->GetRow0(iPlan,iCham,iSect);
- Float_t col0 = Geo->GetCol0(iPlan);
- Float_t time0 = Geo->GetTime0(iPlan);
- Float_t rowPadSize = Geo->GetRowPadSize();
- Float_t colPadSize = Geo->GetColPadSize();
- Float_t timeBinSize = Geo->GetTimeBinSize();
-
- // Create a detector matrix to keep the signal and track numbers
- AliTRDmatrix *Matrix = new AliTRDmatrix(nRowMax,nColMax,nTimeMax
- ,iSect,iCham,iPlan);
-
- // Loop through all entries in the tree
- for (Int_t iTrack = 0; iTrack < nTrack; iTrack++) {
-
- gAlice->ResetHits();
- nBytes += HitTree->GetEvent(iTrack);
-
- // Get the number of hits in the TRD created by this particle
- Int_t nHit = TRD->Hits()->GetEntriesFast();
-
- // Loop through the TRD hits
- for (Int_t iHit = 0; iHit < nHit; iHit++) {
-
- if (!(Hit = (AliTRDhit *) TRD->Hits()->UncheckedAt(iHit)))
- continue;
-
- Float_t pos[3];
- pos[0] = Hit->fX;
- pos[1] = Hit->fY;
- pos[2] = Hit->fZ;
- Float_t q = Hit->fQ;
- Int_t track = Hit->fTrack;
- Int_t detector = Hit->fDetector;
- Int_t plane = Geo->GetPlane(detector);
- Int_t sector = Geo->GetSector(detector);
- Int_t chamber = Geo->GetChamber(detector);
-
- if ((sector != iSect) ||
- (plane != iPlan) ||
- (chamber != iCham))
- continue;
-
- // Rotate the sectors on top of each other
- Float_t rot[3];
- Geo->Rotate(detector,pos,rot);
-
- // The hit position in pad coordinates (center pad)
- // The pad row (z-direction)
- Int_t rowH = (Int_t) ((rot[2] - row0) / rowPadSize);
- // The pad column (rphi-direction)
- Int_t colH = (Int_t) ((rot[1] - col0) / colPadSize);
- // The time bucket
- Int_t timeH = (Int_t) ((rot[0] - time0) / timeBinSize);
-
- // Array to sum up the signal in a box surrounding the
- // hit postition
- const Int_t timeBox = 7;
- const Int_t colBox = 9;
- const Int_t rowBox = 7;
- Float_t signalSum[rowBox][colBox][timeBox];
- for (iRow = 0; iRow < rowBox; iRow++ ) {
- for (iCol = 0; iCol < colBox; iCol++ ) {
- for (iTime = 0; iTime < timeBox; iTime++) {
- signalSum[iRow][iCol][iTime] = 0;
- }
- }
- }
-
- // Loop over all electrons of this hit
- Int_t nEl = (Int_t) q;
- for (Int_t iEl = 0; iEl < nEl; iEl++) {
-
- // The driftlength
- Float_t driftlength = rot[0] - time0;
- if ((driftlength < 0) ||
- (driftlength > kDrThick)) break;
- Float_t driftlengthL = driftlength;
- if (fExBOn) driftlengthL /= TMath::Sqrt(fLorentzFactor);
- Float_t xyz[3];
- xyz[0] = rot[0];
- xyz[1] = rot[1];
- xyz[2] = rot[2];
-
- // Electron attachment
- if (fElAttachOn) {
- if (gRandom->Rndm() < (driftlengthL * fElAttachProp / 100.)) continue;
- }
+ // Loop through all entries in the tree
+ for (Int_t iTrack = 0; iTrack < nTrack; iTrack++) {
- // Apply the diffusion smearing
- if (fDiffusionOn) {
- if (!(Diffusion(driftlengthL,xyz))) continue;
- }
+ gAlice->ResetHits();
+ nBytes += HitTree->GetEvent(iTrack);
- // Apply E x B effects
- if (fExBOn) {
- if (!(ExB(driftlength,xyz))) continue;
- }
+ // Get the number of hits in the TRD created by this particle
+ Int_t nHit = fTRD->Hits()->GetEntriesFast();
+ if (fVerbose > 0) {
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Found %d hits for primary particle %d\n",nHit,iTrack);
+ }
- // The electron position and the distance to the hit position
- // in pad units
- // The pad row (z-direction)
- Int_t rowE = (Int_t) ((xyz[2] - row0) / rowPadSize);
- Int_t rowD = rowH - rowE;
- // The pad column (rphi-direction)
- Int_t colE = (Int_t) ((xyz[1] - col0) / colPadSize);
- Int_t colD = colH - colE;
- // The time bucket
- Int_t timeE = (Int_t) ((xyz[0] - time0) / timeBinSize);
- Int_t timeD = timeH - timeE;
-
- // Apply the gas gain including fluctuations
- Int_t signal = (Int_t) (-fGasGain * TMath::Log(gRandom->Rndm()));
-
- // The distance of the electron to the center of the pad
- // in units of pad width
- Float_t dist = (xyz[1] - col0 - (colE + 0.5) * colPadSize)
- / colPadSize;
-
- // Sum up the signal in the different pixels
- // and apply the pad response
- Int_t rowIdx = rowD + (Int_t) ( rowBox / 2);
- Int_t colIdx = colD + (Int_t) ( colBox / 2);
- Int_t timeIdx = timeD + (Int_t) (timeBox / 2);
-
- if (( rowIdx < 0) || ( rowIdx > rowBox)) {
- printf("AliTRDdigitizer::MakeDigits -- ");
- printf("Boundary error. rowIdx = %d (%d)\n", rowIdx, rowBox);
- continue;
- }
- if (( colIdx < 0) || ( colIdx > colBox)) {
- printf("AliTRDdigitizer::MakeDigits -- ");
- printf("Boundary error. colIdx = %d (%d)\n", colIdx, colBox);
- continue;
- }
- if ((timeIdx < 0) || (timeIdx > timeBox)) {
- printf("AliTRDdigitizer::MakeDigits -- ");
- printf("Boundary error. timeIdx = %d (%d)\n",timeIdx,timeBox);
- continue;
- }
- signalSum[rowIdx][colIdx-1][timeIdx] += PadResponse(dist-1.) * signal;
- signalSum[rowIdx][colIdx ][timeIdx] += PadResponse(dist ) * signal;
- signalSum[rowIdx][colIdx+1][timeIdx] += PadResponse(dist+1.) * signal;
+ // Loop through the TRD hits
+ for (Int_t iHit = 0; iHit < nHit; iHit++) {
+
+ countHits++;
+
+ AliTRDhit *hit = (AliTRDhit *) fTRD->Hits()->UncheckedAt(iHit);
+ Float_t pos[3];
+ pos[0] = hit->X();
+ pos[1] = hit->Y();
+ pos[2] = hit->Z();
+ Float_t q = hit->GetCharge();
+ Int_t track = hit->Track();
+ Int_t detector = hit->GetDetector();
+ Int_t plane = fGeo->GetPlane(detector);
+ Int_t sector = fGeo->GetSector(detector);
+ Int_t chamber = fGeo->GetChamber(detector);
+
+ if (!(CheckDetector(plane,chamber,sector))) continue;
+
+ Int_t nRowMax = fGeo->GetRowMax(plane,chamber,sector);
+ Int_t nColMax = fGeo->GetColMax(plane);
+ Int_t nTimeMax = fGeo->GetTimeMax();
+ Float_t row0 = fGeo->GetRow0(plane,chamber,sector);
+ Float_t col0 = fGeo->GetCol0(plane);
+ Float_t time0 = fGeo->GetTime0(plane);
+ Float_t rowPadSize = fGeo->GetRowPadSize();
+ Float_t colPadSize = fGeo->GetColPadSize();
+ Float_t timeBinSize = fGeo->GetTimeBinSize();
+
+ if (fVerbose > 1) {
+ printf("Analyze hit no. %d ",iHit);
+ printf("-----------------------------------------------------------\n");
+ hit->Dump();
+ printf("plane = %d, sector = %d, chamber = %d\n"
+ ,plane,sector,chamber);
+ printf("nRowMax = %d, nColMax = %d, nTimeMax = %d\n"
+ ,nRowMax,nColMax,nTimeMax);
+ printf("row0 = %f, col0 = %f, time0 = %f\n"
+ ,row0,col0,time0);
+ }
+
+ // Get different container if the detector has changed
+ if (detector != detectorOld) {
+ if (fVerbose > 1) {
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Get new container. New det = %d, Old det = %d\n"
+ ,detector,detectorOld);
+ }
+ // Compress the old one if enabled
+ if ((fCompress) && (detectorOld > -1)) {
+ if (fVerbose > 1) {
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Compress the old container ... ");
+ }
+ signals->Compress(1,0);
+ for (iDict = 0; iDict < kNDict; iDict++) {
+ dictionary[iDict]->Compress(1,0);
+ }
+ if (fVerbose > 1) printf("done\n");
+ }
+ // Get the new container
+ signals = (AliTRDdataArrayF *) signalsArray->At(detector);
+ if (signals->GetNtime() == 0) {
+ // Allocate a new one if not yet existing
+ if (fVerbose > 1) {
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Allocate a new container ... ");
+ }
+ signals->Allocate(nRowMax,nColMax,nTimeMax);
+ }
+ else {
+ // Expand an existing one
+ if (fVerbose > 1) {
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Expand an existing container ... ");
+ }
+ if (fCompress) signals->Expand();
+ }
+ // The same for the dictionary
+ for (iDict = 0; iDict < kNDict; iDict++) {
+ dictionary[iDict] = fDigits->GetDictionary(detector,iDict);
+ if (dictionary[iDict]->GetNtime() == 0) {
+ dictionary[iDict]->Allocate(nRowMax,nColMax,nTimeMax);
+ }
+ else {
+ if (fCompress) dictionary[iDict]->Expand();
+ }
+ }
+ if (fVerbose > 1) printf("done\n");
+ detectorOld = detector;
+ }
- }
+ // Rotate the sectors on top of each other
+ Float_t rot[3];
+ fGeo->Rotate(detector,pos,rot);
+
+ // The driftlength
+ Float_t driftlength = time0 - rot[0];
+ if ((driftlength < 0) ||
+ (driftlength > AliTRDgeometry::DrThick())) break;
+ Float_t driftlengthL = driftlength;
+ if (fExBOn) driftlengthL /= TMath::Sqrt(fLorentzFactor);
+
+ // The hit position in pad coordinates (center pad)
+ // The pad row (z-direction)
+ Int_t rowH = (Int_t) ((rot[2] - row0) / rowPadSize);
+ // The pad column (rphi-direction)
+ Int_t colH = (Int_t) ((rot[1] - col0) / colPadSize);
+ // The time bucket
+ Int_t timeH = (Int_t) (driftlength / timeBinSize);
+ if (fVerbose > 1) {
+ printf("rowH = %d, colH = %d, timeH = %d\n"
+ ,rowH,colH,timeH);
+ }
- // Add the padcluster to the detector matrix
- for (iRow = 0; iRow < rowBox; iRow++ ) {
- for (iCol = 0; iCol < colBox; iCol++ ) {
- for (iTime = 0; iTime < timeBox; iTime++) {
-
- Int_t rowB = rowH + iRow - (Int_t) ( rowBox / 2);
- Int_t colB = colH + iCol - (Int_t) ( colBox / 2);
- Int_t timeB = timeH + iTime - (Int_t) (timeBox / 2);
-
- Float_t signalB = signalSum[iRow][iCol][iTime];
- if (signalB > 0.0) {
- Matrix->AddSignal(rowB,colB,timeB,signalB);
- if (!(Matrix->AddTrack(rowB,colB,timeB,track))) {
- printf("AliTRDdigitizer::MakeDigits -- ");
- printf("More than three tracks in a pixel!\n");
- }
- }
-
- }
- }
- }
+ // Loop over all electrons of this hit
+ // TR photons produce hits with negative charge
+ Int_t nEl = ((Int_t) TMath::Abs(q));
+ for (Int_t iEl = 0; iEl < nEl; iEl++) {
+
+ Float_t xyz[3];
+ xyz[0] = rot[0];
+ xyz[1] = rot[1];
+ xyz[2] = rot[2];
+
+ // Electron attachment
+ if (fElAttachOn) {
+ if (gRandom->Rndm() < (driftlengthL * fElAttachProp / 100.))
+ continue;
+ }
+
+ // Apply the diffusion smearing
+ if (fDiffusionOn) {
+ if (!(Diffusion(driftlengthL,xyz))) continue;
+ }
- }
+ // Apply E x B effects
+ if (fExBOn) {
+ if (!(ExB(driftlength,xyz))) continue;
+ }
- }
+ // The electron position
+ // The pad row (z-direction)
+ Int_t rowE = (Int_t) ((xyz[2] - row0) / rowPadSize);
+ // The pad column (rphi-direction)
+ Int_t colE = (Int_t) ((xyz[1] - col0) / colPadSize);
+ // The time bucket
+ Int_t timeE = (Int_t) ((time0 - xyz[0]) / timeBinSize);
+
+ if (( rowE < 0) || ( rowE >= nRowMax)) continue;
+ if (( colE < 0) || ( colE >= nColMax)) continue;
+ if ((timeE < 0) || (timeE >= nTimeMax)) continue;
+
+ // Apply the gas gain including fluctuations
+ Float_t ggRndm = 0.0;
+ do {
+ ggRndm = gRandom->Rndm();
+ } while (ggRndm <= 0);
+ Int_t signal = (Int_t) (-fGasGain * TMath::Log(ggRndm));
+
+ if (fVerbose > 2) {
+ printf(" electron no. %d, signal = %d\n",iEl,signal);
+ printf(" rowE = %d, colE = %d, timeE = %d\n"
+ ,rowE,colE,timeE);
+ }
- // Add a container for the digits of this detector
- Digits = (AliTRDdataArray *) fDigitsArray->At(iDet);
- // Allocate memory space for the digits buffer
- Digits->Allocate(nRowMax,nColMax,nTimeMax);
+ // Apply the pad response
+ Float_t padSignal[kNpad];
+ if (fPRFOn) {
+ // The distance of the electron to the center of the pad
+ // in units of pad width
+ Float_t dist = (xyz[1] - col0 - (colE + 0.5) * colPadSize)
+ / colPadSize;
+ if (!(PadResponse(signal,dist,padSignal))) continue;
+ }
+ else {
+ padSignal[0] = 0.0;
+ padSignal[1] = signal;
+ padSignal[2] = 0.0;
+ }
- for (Int_t iDict = 0; iDict < kNDict; iDict++) {
- Dictionary[iDict] = (AliTRDdataArray *) fDictionary[iDict]->At(iDet);
- Dictionary[iDict]->Allocate(nRowMax,nColMax,nTimeMax);
+ // The distance of the position to the beginning of the timebin
+ Float_t timeOffset = (time0 - timeE * timeBinSize) - xyz[0];
+ Int_t timeTRDbeg = 0;
+ Int_t timeTRDend = 1;
+ if (fTRFOn) {
+ timeTRDbeg = 2;
+ timeTRDend = 11;
}
+ for (Int_t iTimeBin = TMath::Max(timeE - timeTRDbeg, 0)
+ ; iTimeBin < TMath::Min(timeE + timeTRDend,nTimeMax)
+ ; iTimeBin++) {
+
+ // Apply the time response
+ Float_t timeResponse = 1.0;
+ if (fTRFOn) {
+ Float_t time = (iTimeBin - timeE) * timeBinSize + timeOffset;
+ timeResponse = TimeResponse(time);
+ }
- // Create the hits for this chamber
- for (iRow = 0; iRow < nRowMax; iRow++ ) {
- for (iCol = 0; iCol < nColMax; iCol++ ) {
- for (iTime = 0; iTime < nTimeMax; iTime++) {
-
- Float_t signalAmp = Matrix->GetSignal(iRow,iCol,iTime);
-
- // Add the noise
- signalAmp = TMath::Max(gRandom->Gaus(signalAmp,fNoise),(Float_t) 0.0);
- // Convert to fC
- signalAmp *= el2fC;
- // Convert to mV
- signalAmp *= fChipGain;
- // Convert to ADC counts
- Int_t adc = (Int_t) (signalAmp * (fADCoutRange / fADCinRange));
-
- // Store the amplitude of the digit
- Digits->SetData(iRow,iCol,iTime,adc);
-
- // Store the track index in the dictionary
- // Note: We store index+1 in order to allow the array to be compressed
- for (Int_t iDict = 0; iDict < kNDict; iDict++) {
- Dictionary[iDict]->SetData(iRow,iCol,iTime
- ,Matrix->GetTrack(iRow,iCol,iTime,iDict)+1);
- }
+ // Add the signals
+ Float_t signalOld[kNpad] = { 0.0, 0.0, 0.0 };
+ for (Int_t iPad = 0; iPad < kNpad; iPad++) {
+ Int_t colPos = colE + iPad - 1;
+ if (colPos < 0) continue;
+ if (colPos >= nColMax) break;
+ signalOld[iPad] = signals->GetData(rowE,colPos,iTimeBin);
+ signalOld[iPad] += padSignal[iPad] * timeResponse;
+ signals->SetData(rowE,colPos,iTimeBin,signalOld[iPad]);
+ }
+ if (fVerbose > 3) {
+ printf(" iTimeBin = %d, timeResponse = %f\n"
+ ,iTimeBin,timeResponse);
+ printf(" pad-signal = %f, %f, %f\n"
+ ,signalOld[0],signalOld[1],signalOld[2]);
+ }
- if (adc > fADCthreshold) nDigits++;
+ // Store the track index in the dictionary
+ // Note: We store index+1 in order to allow the array to be compressed
+ for (iDict = 0; iDict < kNDict; iDict++) {
+ Int_t oldTrack = dictionary[iDict]->GetData(rowE,colE,timeE);
+ if (oldTrack == track+1) break;
+ //if (oldTrack == -1) break;
+ if (oldTrack == 0) {
+ dictionary[iDict]->SetData(rowE,colE,timeE,track+1);
+ if (fVerbose > 3) {
+ printf(" track index = %d\n",track);
+ }
+ break;
+ }
+ }
+ if ((fVerbose > 1) && (iDict == kNDict)) {
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("More than three tracks for one digit!\n");
+ }
- }
- }
}
- // Compress the arrays
- Digits->Compress(1,fADCthreshold);
- for (Int_t iDict = 0; iDict < kNDict; iDict++) {
- Dictionary[iDict]->Compress(1,0);
- }
+ }
- totalSizeDigits += Digits->GetSize();
- totalSizeDict0 += Dictionary[0]->GetSize();
- totalSizeDict1 += Dictionary[1]->GetSize();
- totalSizeDict2 += Dictionary[2]->GetSize();
+ }
- printf("AliTRDdigitizer::MakeDigits -- ");
- printf("Number of digits found: %d.\n",nDigits);
+ } // All hits finished
- // Clean up
- if (Matrix) delete Matrix;
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Finished analyzing %d hits\n",countHits);
+
+ // Loop through all chambers to finalize the digits
+ for (Int_t iDet = 0; iDet < AliTRDgeometry::Ndet(); iDet++) {
+
+ Int_t plane = fGeo->GetPlane(iDet);
+ Int_t sector = fGeo->GetSector(iDet);
+ Int_t chamber = fGeo->GetChamber(iDet);
+ Int_t nRowMax = fGeo->GetRowMax(plane,chamber,sector);
+ Int_t nColMax = fGeo->GetColMax(plane);
+ Int_t nTimeMax = fGeo->GetTimeMax();
+
+ if (!(CheckDetector(plane,chamber,sector))) continue;
+ if (fVerbose > 0) {
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Digitization for chamber %d\n",iDet);
+ }
+
+ // Add a container for the digits of this detector
+ digits = fDigits->GetDigits(iDet);
+ // Allocate memory space for the digits buffer
+ digits->Allocate(nRowMax,nColMax,nTimeMax);
+
+ // Get the signal container
+ signals = (AliTRDdataArrayF *) signalsArray->At(iDet);
+ if (signals->GetNtime() == 0) {
+ // Create missing containers
+ signals->Allocate(nRowMax,nColMax,nTimeMax);
+ }
+ else {
+ // Expand the container if neccessary
+ if (fCompress) signals->Expand();
+ }
+ // Create the missing dictionary containers
+ for (iDict = 0; iDict < kNDict; iDict++) {
+ dictionary[iDict] = fDigits->GetDictionary(iDet,iDict);
+ if (dictionary[iDict]->GetNtime() == 0) {
+ dictionary[iDict]->Allocate(nRowMax,nColMax,nTimeMax);
+ }
+ }
+
+ Int_t nDigits = 0;
+
+ // Create the digits for this chamber
+ for (iRow = 0; iRow < nRowMax; iRow++ ) {
+ for (iCol = 0; iCol < nColMax; iCol++ ) {
+ for (iTime = 0; iTime < nTimeMax; iTime++) {
+
+ Float_t signalAmp = signals->GetData(iRow,iCol,iTime);
+
+ // Add the noise
+ signalAmp = TMath::Max((Float_t) gRandom->Gaus(signalAmp,fNoise),0.0);
+ // Convert to fC
+ signalAmp *= kEl2fC;
+ // Convert to mV
+ signalAmp *= fChipGain;
+ // Convert to ADC counts. Set the overflow-bit fADCoutRange if the
+ // signal is larger than fADCinRange
+ Int_t adc = 0;
+ if (signalAmp >= fADCinRange) {
+ adc = ((Int_t) fADCoutRange);
+ }
+ else {
+ adc = ((Int_t) (signalAmp * (fADCoutRange / fADCinRange)));
+ }
+ if (fVerbose > 2) {
+ printf(" iRow = %d, iCol = %d, iTime = %d\n"
+ ,iRow,iCol,iTime);
+ printf(" signal = %f, adc = %d\n",signalAmp,adc);
+ }
+
+ // Store the amplitude of the digit if above threshold
+ if (adc > fADCthreshold) {
+ nDigits++;
+ digits->SetData(iRow,iCol,iTime,adc);
+ }
+ }
}
}
+
+ // Compress the arrays
+ digits->Compress(1,0);
+ for (iDict = 0; iDict < kNDict; iDict++) {
+ dictionary[iDict]->Compress(1,0);
+ }
+
+ totalSizeDigits += digits->GetSize();
+ totalSizeDict0 += dictionary[0]->GetSize();
+ totalSizeDict1 += dictionary[1]->GetSize();
+ totalSizeDict2 += dictionary[2]->GetSize();
+
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Found %d digits in detector %d.\n",nDigits,iDet);
+
+ if (fCompress) signals->Compress(1,0);
+
}
+ printf("AliTRDdigitizer::MakeDigits -- ");
+ printf("Total number of analyzed hits = %d\n",countHits);
+
printf("AliTRDdigitizer::MakeDigits -- ");
printf("Total digits data size = %d, %d, %d, %d\n",totalSizeDigits
,totalSizeDict0
}
//_____________________________________________________________________________
-Bool_t AliTRDdigitizer::MakeBranch()
+Bool_t AliTRDdigitizer::CheckDetector(Int_t plane, Int_t chamber, Int_t sector)
{
//
- // Creates the branches for the digits and the dictionary
+ // Checks whether a detector is enabled
//
- Int_t buffersize = 64000;
-
- Bool_t status = kTRUE;
-
- if (gAlice->TreeD()) {
-
- // Make the branch for the digits
- if (fDigitsArray) {
- const AliTRDdataArray *Digits =
- (AliTRDdataArray *) fDigitsArray->At(0);
- if (Digits) {
- gAlice->TreeD()->Branch("TRDdigits",Digits->IsA()->GetName()
- ,&Digits,buffersize,1);
- printf("AliTRDdigitizer::MakeBranch -- ");
- printf("Making branch TRDdigits\n");
- }
- else {
- status = kFALSE;
- }
+ if ((fTRD->GetSensChamber() >= 0) &&
+ (fTRD->GetSensChamber() != chamber)) return kFALSE;
+ if ((fTRD->GetSensPlane() >= 0) &&
+ (fTRD->GetSensPlane() != sector)) return kFALSE;
+ if ( fTRD->GetSensSector() >= 0) {
+ Int_t sens1 = fTRD->GetSensSector();
+ Int_t sens2 = sens1 + fTRD->GetSensSectorRange();
+ sens2 -= ((Int_t) (sens2 / AliTRDgeometry::Nsect()))
+ * AliTRDgeometry::Nsect();
+ if (sens1 < sens2) {
+ if ((sector < sens1) || (sector >= sens2)) return kFALSE;
}
else {
- status = kFALSE;
- }
-
- // Make the branches for the dictionaries
- for (Int_t iDict = 0; iDict < kNDict; iDict++) {
-
- Char_t branchname[15];
- sprintf(branchname,"TRDdictionary%d",iDict);
- if (fDictionary[iDict]) {
- const AliTRDdataArray *Dictionary =
- (AliTRDdataArray *) fDictionary[iDict]->At(0);
- if (Dictionary) {
- gAlice->TreeD()->Branch(branchname,Dictionary->IsA()->GetName()
- ,&Dictionary,buffersize,1);
- printf("AliTRDdigitizer::MakeBranch -- ");
- printf("Making branch %s\n",branchname);
- }
- else {
- status = kFALSE;
- }
- }
- else {
- status = kFALSE;
- }
+ if ((sector < sens1) && (sector >= sens2)) return kFALSE;
}
-
- }
- else {
- status = kFALSE;
}
- return status;
+ return kTRUE;
}
// Create the branches
if (!(gAlice->TreeD()->GetBranch("TRDdigits"))) {
- if (!MakeBranch()) return kFALSE;
+ if (!fDigits->MakeBranch()) return kFALSE;
}
- // Store the contents of the segment array in the tree
- if (!fDigitsArray->StoreArray("TRDdigits")) {
- printf("AliTRDdigitizer::WriteDigits -- ");
- printf("Error while storing digits in branch TRDdigits\n");
- return kFALSE;
- }
- for (Int_t iDict = 0; iDict < kNDict; iDict++) {
- Char_t branchname[15];
- sprintf(branchname,"TRDdictionary%d",iDict);
- if (!fDictionary[iDict]->StoreArray(branchname)) {
- printf("AliTRDdigitizer::WriteDigits -- ");
- printf("Error while storing dictionary in branch %s\n",branchname);
- return kFALSE;
- }
- }
+ // Store the digits and the dictionary in the tree
+ fDigits->WriteDigits();
// Write the new tree into the input file (use overwrite option)
Char_t treeName[7];
}
-ClassImp(AliTRDdigit)
+//_____________________________________________________________________________
+void AliTRDdigitizer::SetPRF(TF1 *prf)
+{
+ //
+ // Defines a new pad response function
+ //
+
+ if (fPRF) delete fPRF;
+ fPRF = prf;
+
+}
//_____________________________________________________________________________
-AliTRDdigit::AliTRDdigit(Int_t *digits):AliDigitNew()
+void AliTRDdigitizer::SetTRF(TF1 *trf)
{
//
- // Create a TRD digit
+ // Defines a new time response function
//
- // Store the volume hierarchy
- fDetector = digits[0];
+ if (fTRF) delete fTRF;
+ fTRF = trf;
+
+}
+
+//_____________________________________________________________________________
+Double_t TRFlandau(Double_t *x, Double_t *par)
+{
- // Store the row, pad, and time bucket number
- fRow = digits[1];
- fCol = digits[2];
- fTime = digits[3];
+ Double_t xx = x[0];
+ Double_t landau = par[0] * TMath::Landau(xx,par[1],par[2]);
- // Store the signal amplitude
- fAmplitude = digits[4];
+ return landau;
}