]>
Commit | Line | Data |
---|---|---|
4c039060 | 1 | /************************************************************************** |
2 | * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. * | |
3 | * * | |
4 | * Author: The ALICE Off-line Project. * | |
5 | * Contributors are mentioned in the code where appropriate. * | |
6 | * * | |
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 | **************************************************************************/ | |
15 | ||
16 | /* | |
17 | $Log$ | |
90f8d287 | 18 | Revision 1.12 1999/11/02 16:35:56 fca |
19 | New version of TRD introduced | |
20 | ||
5c7f4665 | 21 | Revision 1.11 1999/11/01 20:41:51 fca |
22 | Added protections against using the wrong version of FRAME | |
23 | ||
ab76897d | 24 | Revision 1.10 1999/09/29 09:24:35 fca |
25 | Introduction of the Copyright and cvs Log | |
26 | ||
4c039060 | 27 | */ |
28 | ||
fe4da5cc | 29 | /////////////////////////////////////////////////////////////////////////////// |
30 | // // | |
5c7f4665 | 31 | // Transition Radiation Detector version 0 -- fast simulator // |
fe4da5cc | 32 | // // |
33 | //Begin_Html | |
34 | /* | |
5c7f4665 | 35 | <img src="picts/AliTRDfullClass.gif"> |
fe4da5cc | 36 | */ |
37 | //End_Html | |
38 | // // | |
39 | // // | |
40 | /////////////////////////////////////////////////////////////////////////////// | |
41 | ||
42 | #include <TMath.h> | |
43 | #include <TRandom.h> | |
44 | #include <TVector.h> | |
fe4da5cc | 45 | |
fe4da5cc | 46 | #include "AliTRDv0.h" |
47 | #include "AliRun.h" | |
48 | #include "AliMC.h" | |
49 | #include "AliConst.h" | |
50 | ||
51 | ClassImp(AliTRDv0) | |
52 | ||
53 | //_____________________________________________________________________________ | |
54 | AliTRDv0::AliTRDv0(const char *name, const char *title) | |
55 | :AliTRD(name, title) | |
56 | { | |
57 | // | |
58 | // Standard constructor for Transition Radiation Detector version 0 | |
59 | // | |
82bbf98a | 60 | |
61 | fIdSens = 0; | |
62 | fHitsOn = 0; | |
63 | ||
82bbf98a | 64 | fIdChamber1 = 0; |
65 | fIdChamber2 = 0; | |
66 | fIdChamber3 = 0; | |
67 | ||
5c7f4665 | 68 | fRphiSigma = 0; |
69 | fRphiDist = 0; | |
70 | ||
fe4da5cc | 71 | } |
72 | ||
73 | //_____________________________________________________________________________ | |
74 | void AliTRDv0::CreateGeometry() | |
75 | { | |
76 | // | |
82bbf98a | 77 | // Create the GEANT geometry for the Transition Radiation Detector - Version 0 |
78 | // This version covers the full azimuth. | |
d3f347ff | 79 | // |
d3f347ff | 80 | |
82bbf98a | 81 | // Check that FRAME is there otherwise we have no place where to put the TRD |
82 | AliModule* FRAME = gAlice->GetModule("FRAME"); | |
83 | if (!FRAME) return; | |
fe4da5cc | 84 | |
82bbf98a | 85 | // Define the chambers |
86 | AliTRD::CreateGeometry(); | |
fe4da5cc | 87 | |
fe4da5cc | 88 | } |
89 | ||
90 | //_____________________________________________________________________________ | |
91 | void AliTRDv0::CreateMaterials() | |
92 | { | |
93 | // | |
94 | // Create materials for the Transition Radiation Detector | |
95 | // | |
82bbf98a | 96 | |
fe4da5cc | 97 | AliTRD::CreateMaterials(); |
82bbf98a | 98 | |
fe4da5cc | 99 | } |
100 | ||
5c7f4665 | 101 | //_____________________________________________________________________________ |
102 | void AliTRDv0::Hits2Clusters() | |
103 | { | |
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. | |
113 | ||
114 | printf("AliTRDv0::Hits2Clusters -- Start creating cluster\n"); | |
115 | ||
116 | Int_t nBytes = 0; | |
117 | ||
118 | AliTRDhit *TRDhit; | |
119 | ||
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(); | |
124 | ||
125 | TObjArray *Chamber = new TObjArray(); | |
126 | ||
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(); | |
130 | ||
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++) { | |
135 | ||
136 | // Loop through all entries in the tree | |
137 | for (Int_t iTrack = 0; iTrack < nTrack; iTrack++) { | |
138 | ||
139 | gAlice->ResetHits(); | |
140 | nBytes += HitTree->GetEvent(iTrack); | |
141 | ||
142 | // Get the number of hits in the TRD created by this particle | |
143 | Int_t nHit = fHits->GetEntriesFast(); | |
144 | ||
145 | // Loop through the TRD hits | |
146 | for (Int_t iHit = 0; iHit < nHit; iHit++) { | |
147 | ||
148 | if (!(TRDhit = (AliTRDhit *) fHits->UncheckedAt(iHit))) | |
149 | continue; | |
150 | ||
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; | |
158 | ||
159 | if ((sector != isect+1) || | |
160 | (plane != iplan+1) || | |
161 | (chamber != icham+1)) | |
162 | continue; | |
163 | ||
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); | |
169 | Float_t zRot = z; | |
170 | ||
171 | // Add this cluster to the temporary cluster-array for this chamber | |
172 | Int_t tracks[3]; | |
173 | tracks[0] = track; | |
174 | Int_t clusters[5]; | |
175 | clusters[0] = sector; | |
176 | clusters[1] = chamber; | |
177 | clusters[2] = plane; | |
178 | clusters[3] = 0; | |
179 | clusters[4] = 0; | |
180 | Float_t position[3]; | |
181 | position[0] = zRot; | |
182 | position[1] = yRot; | |
183 | position[2] = xRot; | |
184 | AliTRDcluster *Cluster = new AliTRDcluster(tracks,clusters,position); | |
185 | Chamber->Add(Cluster); | |
186 | ||
187 | } | |
188 | ||
189 | } | |
190 | ||
191 | // Loop through the temporary cluster-array | |
192 | for (Int_t iClus1 = 0; iClus1 < Chamber->GetEntries(); iClus1++) { | |
193 | ||
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; | |
198 | ||
199 | if (!(z1)) continue; // Skip marked cluster | |
200 | ||
201 | const Int_t nSave = 2; | |
202 | Int_t idxSave[nSave]; | |
203 | Int_t iSave = 0; | |
204 | ||
205 | Int_t tracks[3]; | |
206 | tracks[0] = Cluster1->fTracks[0]; | |
207 | ||
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" | |
217 | ,iSave,nSave); | |
218 | } | |
219 | else { | |
220 | idxSave[iSave] = iClus2; | |
221 | tracks[iSave+1] = Cluster2->fTracks[0]; | |
222 | } | |
223 | iSave++; | |
224 | } | |
225 | } | |
226 | ||
227 | // Merge close cluster | |
228 | Float_t yMerge = y1; | |
229 | Float_t xMerge = x1; | |
230 | if (iSave) { | |
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 | |
236 | } | |
237 | xMerge /= (iSave + 1); | |
238 | yMerge /= (iSave + 1); | |
239 | } | |
240 | ||
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]; | |
245 | ||
246 | // The position smearing in rphi-direction (Gaussian) | |
247 | Float_t ySmear = 0; | |
248 | do | |
249 | ySmear = gRandom->Gaus(yMerge,fRphiSigma); | |
250 | while ((ySmear < fCol0[iplan]) || | |
251 | (ySmear > fCol0[iplan] + fColMax[iplan] * fColPadSize)); | |
252 | ||
253 | // Time direction stays unchanged | |
254 | Float_t zSmear = z1; | |
255 | ||
256 | Int_t clusters[5]; | |
257 | clusters[0] = Cluster1->fSector; | |
258 | clusters[1] = Cluster1->fChamber; | |
259 | clusters[2] = Cluster1->fPlane; | |
260 | clusters[3] = 0; | |
261 | clusters[4] = 0; | |
262 | Float_t position[3]; | |
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; | |
268 | ||
269 | // Add the smeared cluster to the output array | |
270 | AddCluster(tracks,clusters,position); | |
271 | ||
272 | } | |
273 | ||
274 | // Clear the temporary cluster-array and delete the cluster | |
275 | Chamber->Delete(); | |
276 | ||
277 | } | |
278 | } | |
279 | } | |
280 | ||
281 | printf("AliTRDv0::Hits2Clusters -- Found %d cluster\n",fClusters->GetEntries()); | |
282 | printf("AliTRDv0::Hits2Clusters -- Fill the cluster tree\n"); | |
283 | ClusterTree->Fill(); | |
284 | ||
285 | } | |
286 | ||
fe4da5cc | 287 | //_____________________________________________________________________________ |
288 | void AliTRDv0::Init() | |
289 | { | |
290 | // | |
291 | // Initialise Transition Radiation Detector after geometry is built | |
292 | // | |
82bbf98a | 293 | |
fe4da5cc | 294 | AliTRD::Init(); |
82bbf98a | 295 | |
82bbf98a | 296 | // Identifier of the sensitive volume (amplification region) |
297 | fIdSens = gMC->VolId("UL06"); | |
298 | ||
82bbf98a | 299 | // Identifier of the TRD-driftchambers |
300 | fIdChamber1 = gMC->VolId("UCIO"); | |
301 | fIdChamber2 = gMC->VolId("UCIM"); | |
302 | fIdChamber3 = gMC->VolId("UCII"); | |
303 | ||
5c7f4665 | 304 | // Parameter for Hits2Cluster |
305 | ||
306 | // Position resolution in rphi-direction | |
307 | fRphiSigma = 0.02; | |
308 | // Minimum distance of non-overlapping cluster | |
309 | fRphiDist = 1.0; | |
310 | ||
311 | printf(" Fast simulator\n"); | |
312 | for (Int_t i = 0; i < 80; i++) printf("*"); | |
313 | printf("\n"); | |
314 | ||
fe4da5cc | 315 | } |
316 | ||
317 | //_____________________________________________________________________________ | |
318 | void AliTRDv0::StepManager() | |
319 | { | |
320 | // | |
321 | // Procedure called at every step in the TRD | |
82bbf98a | 322 | // Fast simulator. If switched on, a hit is produced when a track |
323 | // crosses the border between amplification region and pad plane. | |
fe4da5cc | 324 | // |
325 | ||
82bbf98a | 326 | Int_t vol[3]; |
327 | Int_t iIdSens, icSens; | |
82bbf98a | 328 | Int_t iIdChamber, icChamber; |
329 | ||
82bbf98a | 330 | Float_t hits[4]; |
fe4da5cc | 331 | |
0a6d8768 | 332 | TLorentzVector p; |
82bbf98a | 333 | TClonesArray &lhits = *fHits; |
fe4da5cc | 334 | |
82bbf98a | 335 | // Writing out hits enabled? |
336 | if (!(fHitsOn)) return; | |
fe4da5cc | 337 | |
fe4da5cc | 338 | // Use only charged tracks and count them only once per volume |
82bbf98a | 339 | if (gMC->TrackCharge() && |
340 | gMC->IsTrackExiting()) { | |
fe4da5cc | 341 | |
342 | // Check on sensitive volume | |
82bbf98a | 343 | iIdSens = gMC->CurrentVolID(icSens); |
344 | if (iIdSens == fIdSens) { | |
345 | ||
346 | gMC->TrackPosition(p); | |
347 | for (Int_t i = 0; i < 3; i++) hits[i] = p[i]; | |
348 | // No charge created | |
349 | hits[3] = 0; | |
350 | ||
fe4da5cc | 351 | // The sector number |
90f8d287 | 352 | Float_t phi = hits[1] != 0 ? kRaddeg*TMath::ATan2(hits[0],hits[1]) : (hits[0] > 0 ? 180. : 0.); |
5c7f4665 | 353 | vol[0] = ((Int_t) (phi / 20)) + 1; |
82bbf98a | 354 | |
d3f347ff | 355 | // The chamber number |
356 | // 1: outer left | |
82bbf98a | 357 | // 2: middle left |
d3f347ff | 358 | // 3: inner |
82bbf98a | 359 | // 4: middle right |
d3f347ff | 360 | // 5: outer right |
5c7f4665 | 361 | iIdChamber = gMC->CurrentVolOffID(1,icChamber); |
82bbf98a | 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) | |
d3f347ff | 367 | vol[1] = 3; |
82bbf98a | 368 | |
fe4da5cc | 369 | // The plane number |
82bbf98a | 370 | vol[2] = icChamber - TMath::Nint((Float_t) (icChamber / 7)) * 6; |
371 | ||
372 | new(lhits[fNhits++]) AliTRDhit(fIshunt,gAlice->CurrentTrack(),vol,hits); | |
d3f347ff | 373 | |
fe4da5cc | 374 | } |
d3f347ff | 375 | |
fe4da5cc | 376 | } |
d3f347ff | 377 | |
fe4da5cc | 378 | } |