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.12 1999/11/02 16:35:56 fca
19 New version of TRD introduced
21 Revision 1.11 1999/11/01 20:41:51 fca
22 Added protections against using the wrong version of FRAME
24 Revision 1.10 1999/09/29 09:24:35 fca
25 Introduction of the Copyright and cvs Log
29 ///////////////////////////////////////////////////////////////////////////////
31 // Transition Radiation Detector version 0 -- fast simulator //
35 <img src="picts/AliTRDfullClass.gif">
40 ///////////////////////////////////////////////////////////////////////////////
53 //_____________________________________________________________________________
54 AliTRDv0::AliTRDv0(const char *name, const char *title)
58 // Standard constructor for Transition Radiation Detector version 0
73 //_____________________________________________________________________________
74 void AliTRDv0::CreateGeometry()
77 // Create the GEANT geometry for the Transition Radiation Detector - Version 0
78 // This version covers the full azimuth.
81 // Check that FRAME is there otherwise we have no place where to put the TRD
82 AliModule* FRAME = gAlice->GetModule("FRAME");
85 // Define the chambers
86 AliTRD::CreateGeometry();
90 //_____________________________________________________________________________
91 void AliTRDv0::CreateMaterials()
94 // Create materials for the Transition Radiation Detector
97 AliTRD::CreateMaterials();
101 //_____________________________________________________________________________
102 void AliTRDv0::Hits2Clusters()
104 // A simple cluster generator. It takes the hits from the
105 // fast simulator (one hit per plane) and transforms them
106 // into cluster, by applying position smearing and merging
107 // of nearby cluster. The searing is done uniformly in z-direction
108 // over the length of a readout pad. In rphi-direction a Gaussian
109 // smearing is applied with a sigma given by fRphiSigma.
110 // Clusters are considered as overlapping when they are closer in
111 // rphi-direction than the value defined in fRphiDist.
112 // Use the macro fastClusterCreate.C to create the cluster.
114 printf("AliTRDv0::Hits2Clusters -- Start creating cluster\n");
120 // Get the pointer to the hit tree
121 TTree *HitTree = gAlice->TreeH();
122 // Get the pointer to the reconstruction tree
123 TTree *ClusterTree = gAlice->TreeD();
125 TObjArray *Chamber = new TObjArray();
127 // Get the number of entries in the hit tree
128 // (Number of primary particles creating a hit somewhere)
129 Int_t nTrack = (Int_t) HitTree->GetEntries();
131 // Loop through all the chambers
132 for (Int_t icham = 0; icham < kNcham; icham++) {
133 for (Int_t iplan = 0; iplan < kNplan; iplan++) {
134 for (Int_t isect = 0; isect < kNsect; isect++) {
136 // Loop through all entries in the tree
137 for (Int_t iTrack = 0; iTrack < nTrack; iTrack++) {
140 nBytes += HitTree->GetEvent(iTrack);
142 // Get the number of hits in the TRD created by this particle
143 Int_t nHit = fHits->GetEntriesFast();
145 // Loop through the TRD hits
146 for (Int_t iHit = 0; iHit < nHit; iHit++) {
148 if (!(TRDhit = (AliTRDhit *) fHits->UncheckedAt(iHit)))
151 Float_t x = TRDhit->fX;
152 Float_t y = TRDhit->fY;
153 Float_t z = TRDhit->fZ;
154 Int_t track = TRDhit->fTrack;
155 Int_t plane = TRDhit->fPlane;
156 Int_t sector = TRDhit->fSector;
157 Int_t chamber = TRDhit->fChamber;
159 if ((sector != isect+1) ||
160 (plane != iplan+1) ||
161 (chamber != icham+1))
164 // Rotate the sectors on top of each other
165 Float_t phi = 2.0 * kPI / (Float_t) kNsect
166 * ((Float_t) sector - 0.5);
167 Float_t xRot = -x * TMath::Cos(phi) + y * TMath::Sin(phi);
168 Float_t yRot = x * TMath::Sin(phi) + y * TMath::Cos(phi);
171 // Add this cluster to the temporary cluster-array for this chamber
175 clusters[0] = sector;
176 clusters[1] = chamber;
184 AliTRDcluster *Cluster = new AliTRDcluster(tracks,clusters,position);
185 Chamber->Add(Cluster);
191 // Loop through the temporary cluster-array
192 for (Int_t iClus1 = 0; iClus1 < Chamber->GetEntries(); iClus1++) {
194 AliTRDcluster *Cluster1 = (AliTRDcluster *) Chamber->UncheckedAt(iClus1);
195 Float_t x1 = Cluster1->fX;
196 Float_t y1 = Cluster1->fY;
197 Float_t z1 = Cluster1->fZ;
199 if (!(z1)) continue; // Skip marked cluster
201 const Int_t nSave = 2;
202 Int_t idxSave[nSave];
206 tracks[0] = Cluster1->fTracks[0];
208 // Check the other cluster to see, whether there are close ones
209 for (Int_t iClus2 = iClus1 + 1; iClus2 < Chamber->GetEntries(); iClus2++) {
210 AliTRDcluster *Cluster2 = (AliTRDcluster *) Chamber->UncheckedAt(iClus2);
211 Float_t x2 = Cluster2->fX;
212 Float_t y2 = Cluster2->fY;
213 if ((TMath::Abs(x1 - x2) < fRowPadSize) ||
214 (TMath::Abs(y1 - y2) < fRphiDist)) {
215 if (iSave == nSave) {
216 printf("AliTRDv0::Hits2Clusters -- Boundary error: iSave = %d, nSave = %d\n"
220 idxSave[iSave] = iClus2;
221 tracks[iSave+1] = Cluster2->fTracks[0];
227 // Merge close cluster
231 for (Int_t iMerge = 0; iMerge < iSave; iMerge++) {
232 AliTRDcluster *Cluster2 = (AliTRDcluster *) Chamber->UncheckedAt(idxSave[iMerge]);
233 xMerge += Cluster2->fX;
234 yMerge += Cluster2->fY;
235 Cluster2->fZ = 0; // Mark merged cluster
237 xMerge /= (iSave + 1);
238 yMerge /= (iSave + 1);
241 // The position smearing in z-direction (uniform over pad width)
242 Int_t row = (Int_t) ((xMerge - fRow0[iplan][icham][isect]) / fRowPadSize);
243 Float_t xSmear = (row + gRandom->Rndm()) * fRowPadSize
244 + fRow0[iplan][icham][isect];
246 // The position smearing in rphi-direction (Gaussian)
249 ySmear = gRandom->Gaus(yMerge,fRphiSigma);
250 while ((ySmear < fCol0[iplan]) ||
251 (ySmear > fCol0[iplan] + fColMax[iplan] * fColPadSize));
253 // Time direction stays unchanged
257 clusters[0] = Cluster1->fSector;
258 clusters[1] = Cluster1->fChamber;
259 clusters[2] = Cluster1->fPlane;
263 // Rotate the sectors back into their real position
264 Float_t phi = 2*kPI / kNsect * ((Float_t) Cluster1->fSector - 0.5);
265 position[0] = -zSmear * TMath::Cos(phi) + ySmear * TMath::Sin(phi);
266 position[1] = zSmear * TMath::Sin(phi) + ySmear * TMath::Cos(phi);
267 position[2] = xSmear;
269 // Add the smeared cluster to the output array
270 AddCluster(tracks,clusters,position);
274 // Clear the temporary cluster-array and delete the cluster
281 printf("AliTRDv0::Hits2Clusters -- Found %d cluster\n",fClusters->GetEntries());
282 printf("AliTRDv0::Hits2Clusters -- Fill the cluster tree\n");
287 //_____________________________________________________________________________
288 void AliTRDv0::Init()
291 // Initialise Transition Radiation Detector after geometry is built
296 // Identifier of the sensitive volume (amplification region)
297 fIdSens = gMC->VolId("UL06");
299 // Identifier of the TRD-driftchambers
300 fIdChamber1 = gMC->VolId("UCIO");
301 fIdChamber2 = gMC->VolId("UCIM");
302 fIdChamber3 = gMC->VolId("UCII");
304 // Parameter for Hits2Cluster
306 // Position resolution in rphi-direction
308 // Minimum distance of non-overlapping cluster
311 printf(" Fast simulator\n");
312 for (Int_t i = 0; i < 80; i++) printf("*");
317 //_____________________________________________________________________________
318 void AliTRDv0::StepManager()
321 // Procedure called at every step in the TRD
322 // Fast simulator. If switched on, a hit is produced when a track
323 // crosses the border between amplification region and pad plane.
327 Int_t iIdSens, icSens;
328 Int_t iIdChamber, icChamber;
333 TClonesArray &lhits = *fHits;
335 // Writing out hits enabled?
336 if (!(fHitsOn)) return;
338 // Use only charged tracks and count them only once per volume
339 if (gMC->TrackCharge() &&
340 gMC->IsTrackExiting()) {
342 // Check on sensitive volume
343 iIdSens = gMC->CurrentVolID(icSens);
344 if (iIdSens == fIdSens) {
346 gMC->TrackPosition(p);
347 for (Int_t i = 0; i < 3; i++) hits[i] = p[i];
352 Float_t phi = hits[1] != 0 ? kRaddeg*TMath::ATan2(hits[0],hits[1]) : (hits[0] > 0 ? 180. : 0.);
353 vol[0] = ((Int_t) (phi / 20)) + 1;
355 // The chamber number
361 iIdChamber = gMC->CurrentVolOffID(1,icChamber);
362 if (iIdChamber == fIdChamber1)
363 vol[1] = (hits[2] < 0 ? 1 : 5);
364 else if (iIdChamber == fIdChamber2)
365 vol[1] = (hits[2] < 0 ? 2 : 4);
366 else if (iIdChamber == fIdChamber3)
370 vol[2] = icChamber - TMath::Nint((Float_t) (icChamber / 7)) * 6;
372 new(lhits[fNhits++]) AliTRDhit(fIshunt,gAlice->CurrentTrack(),vol,hits);