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.11 1999/11/01 20:41:51 fca
19 Added protections against using the wrong version of FRAME
21 Revision 1.10 1999/09/29 09:24:35 fca
22 Introduction of the Copyright and cvs Log
26 ///////////////////////////////////////////////////////////////////////////////
28 // Transition Radiation Detector version 0 -- fast simulator //
32 <img src="picts/AliTRDfullClass.gif">
37 ///////////////////////////////////////////////////////////////////////////////
50 //_____________________________________________________________________________
51 AliTRDv0::AliTRDv0(const char *name, const char *title)
55 // Standard constructor for Transition Radiation Detector version 0
70 //_____________________________________________________________________________
71 void AliTRDv0::CreateGeometry()
74 // Create the GEANT geometry for the Transition Radiation Detector - Version 0
75 // This version covers the full azimuth.
78 // Check that FRAME is there otherwise we have no place where to put the TRD
79 AliModule* FRAME = gAlice->GetModule("FRAME");
82 // Define the chambers
83 AliTRD::CreateGeometry();
87 //_____________________________________________________________________________
88 void AliTRDv0::CreateMaterials()
91 // Create materials for the Transition Radiation Detector
94 AliTRD::CreateMaterials();
98 //_____________________________________________________________________________
99 void AliTRDv0::Hits2Clusters()
101 // A simple cluster generator. It takes the hits from the
102 // fast simulator (one hit per plane) and transforms them
103 // into cluster, by applying position smearing and merging
104 // of nearby cluster. The searing is done uniformly in z-direction
105 // over the length of a readout pad. In rphi-direction a Gaussian
106 // smearing is applied with a sigma given by fRphiSigma.
107 // Clusters are considered as overlapping when they are closer in
108 // rphi-direction than the value defined in fRphiDist.
109 // Use the macro fastClusterCreate.C to create the cluster.
111 printf("AliTRDv0::Hits2Clusters -- Start creating cluster\n");
117 // Get the pointer to the hit tree
118 TTree *HitTree = gAlice->TreeH();
119 // Get the pointer to the reconstruction tree
120 TTree *ClusterTree = gAlice->TreeD();
122 TObjArray *Chamber = new TObjArray();
124 // Get the number of entries in the hit tree
125 // (Number of primary particles creating a hit somewhere)
126 Int_t nTrack = (Int_t) HitTree->GetEntries();
128 // Loop through all the chambers
129 for (Int_t icham = 0; icham < kNcham; icham++) {
130 for (Int_t iplan = 0; iplan < kNplan; iplan++) {
131 for (Int_t isect = 0; isect < kNsect; isect++) {
133 // Loop through all entries in the tree
134 for (Int_t iTrack = 0; iTrack < nTrack; iTrack++) {
137 nBytes += HitTree->GetEvent(iTrack);
139 // Get the number of hits in the TRD created by this particle
140 Int_t nHit = fHits->GetEntriesFast();
142 // Loop through the TRD hits
143 for (Int_t iHit = 0; iHit < nHit; iHit++) {
145 if (!(TRDhit = (AliTRDhit *) fHits->UncheckedAt(iHit)))
148 Float_t x = TRDhit->fX;
149 Float_t y = TRDhit->fY;
150 Float_t z = TRDhit->fZ;
151 Int_t track = TRDhit->fTrack;
152 Int_t plane = TRDhit->fPlane;
153 Int_t sector = TRDhit->fSector;
154 Int_t chamber = TRDhit->fChamber;
156 if ((sector != isect+1) ||
157 (plane != iplan+1) ||
158 (chamber != icham+1))
161 // Rotate the sectors on top of each other
162 Float_t phi = 2.0 * kPI / (Float_t) kNsect
163 * ((Float_t) sector - 0.5);
164 Float_t xRot = -x * TMath::Cos(phi) + y * TMath::Sin(phi);
165 Float_t yRot = x * TMath::Sin(phi) + y * TMath::Cos(phi);
168 // Add this cluster to the temporary cluster-array for this chamber
172 clusters[0] = sector;
173 clusters[1] = chamber;
181 AliTRDcluster *Cluster = new AliTRDcluster(tracks,clusters,position);
182 Chamber->Add(Cluster);
188 // Loop through the temporary cluster-array
189 for (Int_t iClus1 = 0; iClus1 < Chamber->GetEntries(); iClus1++) {
191 AliTRDcluster *Cluster1 = (AliTRDcluster *) Chamber->UncheckedAt(iClus1);
192 Float_t x1 = Cluster1->fX;
193 Float_t y1 = Cluster1->fY;
194 Float_t z1 = Cluster1->fZ;
196 if (!(z1)) continue; // Skip marked cluster
198 const Int_t nSave = 2;
199 Int_t idxSave[nSave];
203 tracks[0] = Cluster1->fTracks[0];
205 // Check the other cluster to see, whether there are close ones
206 for (Int_t iClus2 = iClus1 + 1; iClus2 < Chamber->GetEntries(); iClus2++) {
207 AliTRDcluster *Cluster2 = (AliTRDcluster *) Chamber->UncheckedAt(iClus2);
208 Float_t x2 = Cluster2->fX;
209 Float_t y2 = Cluster2->fY;
210 if ((TMath::Abs(x1 - x2) < fRowPadSize) ||
211 (TMath::Abs(y1 - y2) < fRphiDist)) {
212 if (iSave == nSave) {
213 printf("AliTRDv0::Hits2Clusters -- Boundary error: iSave = %d, nSave = %d\n"
217 idxSave[iSave] = iClus2;
218 tracks[iSave+1] = Cluster2->fTracks[0];
224 // Merge close cluster
228 for (Int_t iMerge = 0; iMerge < iSave; iMerge++) {
229 AliTRDcluster *Cluster2 = (AliTRDcluster *) Chamber->UncheckedAt(idxSave[iMerge]);
230 xMerge += Cluster2->fX;
231 yMerge += Cluster2->fY;
232 Cluster2->fZ = 0; // Mark merged cluster
234 xMerge /= (iSave + 1);
235 yMerge /= (iSave + 1);
238 // The position smearing in z-direction (uniform over pad width)
239 Int_t row = (Int_t) ((xMerge - fRow0[iplan][icham][isect]) / fRowPadSize);
240 Float_t xSmear = (row + gRandom->Rndm()) * fRowPadSize
241 + fRow0[iplan][icham][isect];
243 // The position smearing in rphi-direction (Gaussian)
246 ySmear = gRandom->Gaus(yMerge,fRphiSigma);
247 while ((ySmear < fCol0[iplan]) ||
248 (ySmear > fCol0[iplan] + fColMax[iplan] * fColPadSize));
250 // Time direction stays unchanged
254 clusters[0] = Cluster1->fSector;
255 clusters[1] = Cluster1->fChamber;
256 clusters[2] = Cluster1->fPlane;
260 // Rotate the sectors back into their real position
261 Float_t phi = 2*kPI / kNsect * ((Float_t) Cluster1->fSector - 0.5);
262 position[0] = -zSmear * TMath::Cos(phi) + ySmear * TMath::Sin(phi);
263 position[1] = zSmear * TMath::Sin(phi) + ySmear * TMath::Cos(phi);
264 position[2] = xSmear;
266 // Add the smeared cluster to the output array
267 AddCluster(tracks,clusters,position);
271 // Clear the temporary cluster-array and delete the cluster
278 printf("AliTRDv0::Hits2Clusters -- Found %d cluster\n",fClusters->GetEntries());
279 printf("AliTRDv0::Hits2Clusters -- Fill the cluster tree\n");
284 //_____________________________________________________________________________
285 void AliTRDv0::Init()
288 // Initialise Transition Radiation Detector after geometry is built
293 // Identifier of the sensitive volume (amplification region)
294 fIdSens = gMC->VolId("UL06");
296 // Identifier of the TRD-driftchambers
297 fIdChamber1 = gMC->VolId("UCIO");
298 fIdChamber2 = gMC->VolId("UCIM");
299 fIdChamber3 = gMC->VolId("UCII");
301 // Parameter for Hits2Cluster
303 // Position resolution in rphi-direction
305 // Minimum distance of non-overlapping cluster
308 printf(" Fast simulator\n");
309 for (Int_t i = 0; i < 80; i++) printf("*");
314 //_____________________________________________________________________________
315 void AliTRDv0::StepManager()
318 // Procedure called at every step in the TRD
319 // Fast simulator. If switched on, a hit is produced when a track
320 // crosses the border between amplification region and pad plane.
324 Int_t iIdSens, icSens;
325 Int_t iIdChamber, icChamber;
330 TClonesArray &lhits = *fHits;
332 // Writing out hits enabled?
333 if (!(fHitsOn)) return;
335 // Use only charged tracks and count them only once per volume
336 if (gMC->TrackCharge() &&
337 gMC->IsTrackExiting()) {
339 // Check on sensitive volume
340 iIdSens = gMC->CurrentVolID(icSens);
341 if (iIdSens == fIdSens) {
343 gMC->TrackPosition(p);
344 for (Int_t i = 0; i < 3; i++) hits[i] = p[i];
349 Float_t phi = hits[1] != 0 ? TMath::Atan2(hits[0],hits[1]) : (hits[0] > 0 ? 180. : 0.);
350 vol[0] = ((Int_t) (phi / 20)) + 1;
352 // The chamber number
358 iIdChamber = gMC->CurrentVolOffID(1,icChamber);
359 if (iIdChamber == fIdChamber1)
360 vol[1] = (hits[2] < 0 ? 1 : 5);
361 else if (iIdChamber == fIdChamber2)
362 vol[1] = (hits[2] < 0 ? 2 : 4);
363 else if (iIdChamber == fIdChamber3)
367 vol[2] = icChamber - TMath::Nint((Float_t) (icChamber / 7)) * 6;
369 new(lhits[fNhits++]) AliTRDhit(fIshunt,gAlice->CurrentTrack(),vol,hits);