]>
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 | ||
88cb7938 | 16 | /* $Id$ */ |
4c039060 | 17 | |
030b4415 | 18 | //////////////////////////////////////////////////////////////////////////// |
19 | // // | |
20 | // Transition Radiation Detector version 1 -- slow simulator // | |
21 | // // | |
22 | //////////////////////////////////////////////////////////////////////////// | |
fe4da5cc | 23 | |
1819f4bb | 24 | #include <TLorentzVector.h> |
88cb7938 | 25 | #include <TMath.h> |
26 | #include <TRandom.h> | |
88cb7938 | 27 | #include <TVirtualMC.h> |
f57bb418 | 28 | #include <TGeoManager.h> |
268f57b1 | 29 | #include <TGeoMatrix.h> |
170c35f1 | 30 | #include <TGeoPhysicalNode.h> |
fe4da5cc | 31 | |
e6add757 | 32 | #include "AliTrackReference.h" |
45160b1f | 33 | #include "AliMC.h" |
88cb7938 | 34 | #include "AliRun.h" |
02cb65d6 | 35 | #include "AliGeomManager.h" |
030b4415 | 36 | |
88cb7938 | 37 | #include "AliTRDgeometry.h" |
a076fc2f | 38 | #include "AliTRDCommonParam.h" |
cb2f9e9b | 39 | #include "AliTRDsimTR.h" |
88cb7938 | 40 | #include "AliTRDv1.h" |
851d3db9 | 41 | |
fe4da5cc | 42 | ClassImp(AliTRDv1) |
8230f242 | 43 | |
44 | //_____________________________________________________________________________ | |
030b4415 | 45 | AliTRDv1::AliTRDv1() |
46 | :AliTRD() | |
1315812e | 47 | ,fTRon(kTRUE) |
030b4415 | 48 | ,fTR(NULL) |
030b4415 | 49 | ,fStepSize(0) |
f2979d08 | 50 | ,fWion(0) |
8230f242 | 51 | { |
52 | // | |
53 | // Default constructor | |
54 | // | |
55 | ||
8230f242 | 56 | } |
57 | ||
fe4da5cc | 58 | //_____________________________________________________________________________ |
59 | AliTRDv1::AliTRDv1(const char *name, const char *title) | |
030b4415 | 60 | :AliTRD(name,title) |
61 | ,fTRon(kTRUE) | |
62 | ,fTR(NULL) | |
030b4415 | 63 | ,fStepSize(0.1) |
f2979d08 | 64 | ,fWion(0) |
fe4da5cc | 65 | { |
66 | // | |
851d3db9 | 67 | // Standard constructor for Transition Radiation Detector version 1 |
fe4da5cc | 68 | // |
82bbf98a | 69 | |
5c7f4665 | 70 | SetBufferSize(128000); |
71 | ||
a076fc2f | 72 | if (AliTRDCommonParam::Instance()->IsXenon()) { |
f2979d08 | 73 | fWion = 23.53; // Ionization energy XeCO2 (85/15) |
74 | } | |
a076fc2f | 75 | else if (AliTRDCommonParam::Instance()->IsArgon()) { |
f2979d08 | 76 | fWion = 27.21; // Ionization energy ArCO2 (82/18) |
77 | } | |
78 | else { | |
79 | AliFatal("Wrong gas mixture"); | |
80 | exit(1); | |
81 | } | |
82 | ||
5c7f4665 | 83 | } |
84 | ||
85 | //_____________________________________________________________________________ | |
86 | AliTRDv1::~AliTRDv1() | |
87 | { | |
dd9a6ee3 | 88 | // |
89 | // AliTRDv1 destructor | |
90 | // | |
82bbf98a | 91 | |
030b4415 | 92 | if (fTR) { |
93 | delete fTR; | |
94 | fTR = 0; | |
95 | } | |
82bbf98a | 96 | |
fe4da5cc | 97 | } |
98 | ||
f57bb418 | 99 | //_____________________________________________________________________________ |
100 | void AliTRDv1::AddAlignableVolumes() const | |
101 | { | |
102 | // | |
103 | // Create entries for alignable volumes associating the symbolic volume | |
104 | // name with the corresponding volume path. Needs to be syncronized with | |
105 | // eventual changes in the geometry. | |
106 | // | |
107 | ||
108 | TString volPath; | |
109 | TString symName; | |
110 | ||
92cd97ad | 111 | TString vpStr = "ALIC_1/B077_1/BSEGMO"; |
112 | TString vpApp1 = "_1/BTRD"; | |
113 | TString vpApp2 = "_1"; | |
114 | TString vpApp3a = "/UTR1_1/UTS1_1/UTI1_1/UT"; | |
115 | TString vpApp3b = "/UTR2_1/UTS2_1/UTI2_1/UT"; | |
116 | TString vpApp3c = "/UTR3_1/UTS3_1/UTI3_1/UT"; | |
f57bb418 | 117 | |
92cd97ad | 118 | TString snStr = "TRD/sm"; |
119 | TString snApp1 = "/st"; | |
120 | TString snApp2 = "/pl"; | |
f57bb418 | 121 | |
122 | // | |
123 | // The super modules | |
124 | // The symbolic names are: TRD/sm00 | |
125 | // ... | |
126 | // TRD/sm17 | |
127 | // | |
053767a4 | 128 | for (Int_t isector = 0; isector < AliTRDgeometry::Nsector(); isector++) { |
f57bb418 | 129 | |
130 | volPath = vpStr; | |
053767a4 | 131 | volPath += isector; |
f57bb418 | 132 | volPath += vpApp1; |
053767a4 | 133 | volPath += isector; |
f57bb418 | 134 | volPath += vpApp2; |
135 | ||
136 | symName = snStr; | |
053767a4 | 137 | symName += Form("%02d",isector); |
f57bb418 | 138 | |
139 | gGeoManager->SetAlignableEntry(symName.Data(),volPath.Data()); | |
140 | ||
141 | } | |
142 | ||
143 | // | |
144 | // The readout chambers | |
145 | // The symbolic names are: TRD/sm00/st0/pl0 | |
146 | // ... | |
147 | // TRD/sm17/st4/pl5 | |
148 | // | |
02cb65d6 | 149 | AliGeomManager::ELayerID idTRD1 = AliGeomManager::kTRD1; |
150 | Int_t layer, modUID; | |
151 | ||
053767a4 | 152 | for (Int_t isector = 0; isector < AliTRDgeometry::Nsector(); isector++) { |
8bf0cd64 | 153 | |
053767a4 | 154 | if (fGeometry->GetSMstatus(isector) == 0) continue; |
8bf0cd64 | 155 | |
053767a4 | 156 | for (Int_t istack = 0; istack < AliTRDgeometry::Nstack(); istack++) { |
157 | for (Int_t ilayer = 0; ilayer < AliTRDgeometry::Nlayer(); ilayer++) { | |
f57bb418 | 158 | |
053767a4 | 159 | layer = idTRD1 + ilayer; |
160 | modUID = AliGeomManager::LayerToVolUIDSafe(layer,isector*5+istack); | |
161 | ||
162 | Int_t idet = AliTRDgeometry::GetDetectorSec(ilayer,istack); | |
f57bb418 | 163 | |
164 | volPath = vpStr; | |
053767a4 | 165 | volPath += isector; |
f57bb418 | 166 | volPath += vpApp1; |
053767a4 | 167 | volPath += isector; |
f57bb418 | 168 | volPath += vpApp2; |
053767a4 | 169 | switch (isector) { |
92cd97ad | 170 | case 13: |
171 | case 14: | |
172 | case 15: | |
053767a4 | 173 | if (istack == 2) { |
92cd97ad | 174 | continue; |
175 | } | |
176 | volPath += vpApp3c; | |
177 | break; | |
178 | case 11: | |
179 | case 12: | |
180 | volPath += vpApp3b; | |
181 | break; | |
182 | default: | |
183 | volPath += vpApp3a; | |
184 | }; | |
f57bb418 | 185 | volPath += Form("%02d",idet); |
186 | volPath += vpApp2; | |
187 | ||
188 | symName = snStr; | |
053767a4 | 189 | symName += Form("%02d",isector); |
f57bb418 | 190 | symName += snApp1; |
053767a4 | 191 | symName += istack; |
f57bb418 | 192 | symName += snApp2; |
053767a4 | 193 | symName += ilayer; |
f57bb418 | 194 | |
51a5f1d0 | 195 | TGeoPNEntry *alignableEntry = |
02cb65d6 | 196 | gGeoManager->SetAlignableEntry(symName.Data(),volPath.Data(),modUID); |
f57bb418 | 197 | |
170c35f1 | 198 | // Add the tracking to local matrix following the TPC example |
51a5f1d0 | 199 | if (alignableEntry) { |
02cb65d6 | 200 | TGeoHMatrix *globMatrix = alignableEntry->GetGlobalOrig(); |
053767a4 | 201 | Double_t sectorAngle = 20.0 * (isector % 18) + 10.0; |
51a5f1d0 | 202 | TGeoHMatrix *t2lMatrix = new TGeoHMatrix(); |
203 | t2lMatrix->RotateZ(sectorAngle); | |
204 | t2lMatrix->MultiplyLeft(&(globMatrix->Inverse())); | |
205 | alignableEntry->SetMatrix(t2lMatrix); | |
206 | } | |
207 | else { | |
208 | AliError(Form("Alignable entry %s is not valid!",symName.Data())); | |
209 | } | |
8bf0cd64 | 210 | |
f57bb418 | 211 | } |
212 | } | |
213 | } | |
214 | ||
215 | } | |
216 | ||
fe4da5cc | 217 | //_____________________________________________________________________________ |
218 | void AliTRDv1::CreateGeometry() | |
219 | { | |
220 | // | |
851d3db9 | 221 | // Create the GEANT geometry for the Transition Radiation Detector - Version 1 |
5c7f4665 | 222 | // This version covers the full azimuth. |
d3f347ff | 223 | // |
224 | ||
82bbf98a | 225 | // Check that FRAME is there otherwise we have no place where to put the TRD |
8230f242 | 226 | AliModule* frame = gAlice->GetModule("FRAME"); |
030b4415 | 227 | if (!frame) { |
228 | AliError("TRD needs FRAME to be present\n"); | |
229 | return; | |
230 | } | |
d3f347ff | 231 | |
82bbf98a | 232 | // Define the chambers |
233 | AliTRD::CreateGeometry(); | |
d3f347ff | 234 | |
fe4da5cc | 235 | } |
236 | ||
237 | //_____________________________________________________________________________ | |
238 | void AliTRDv1::CreateMaterials() | |
239 | { | |
240 | // | |
851d3db9 | 241 | // Create materials for the Transition Radiation Detector version 1 |
fe4da5cc | 242 | // |
82bbf98a | 243 | |
d3f347ff | 244 | AliTRD::CreateMaterials(); |
82bbf98a | 245 | |
fe4da5cc | 246 | } |
247 | ||
793ff80c | 248 | //_____________________________________________________________________________ |
249 | void AliTRDv1::CreateTRhit(Int_t det) | |
250 | { | |
251 | // | |
252 | // Creates an electron cluster from a TR photon. | |
253 | // The photon is assumed to be created a the end of the radiator. The | |
254 | // distance after which it deposits its energy takes into account the | |
255 | // absorbtion of the entrance window and of the gas mixture in drift | |
256 | // volume. | |
257 | // | |
258 | ||
793ff80c | 259 | // Maximum number of TR photons per track |
260 | const Int_t kNTR = 50; | |
261 | ||
030b4415 | 262 | TLorentzVector mom; |
263 | TLorentzVector pos; | |
793ff80c | 264 | |
ce0d6231 | 265 | Float_t eTR[kNTR]; |
266 | Int_t nTR; | |
793ff80c | 267 | |
ce0d6231 | 268 | // Create TR photons |
269 | gMC->TrackMomentum(mom); | |
270 | Float_t pTot = mom.Rho(); | |
271 | fTR->CreatePhotons(11,pTot,nTR,eTR); | |
272 | if (nTR > kNTR) { | |
273 | AliFatal(Form("Boundary error: nTR = %d, kNTR = %d",nTR,kNTR)); | |
274 | } | |
f73816f5 | 275 | |
ce0d6231 | 276 | // Loop through the TR photons |
277 | for (Int_t iTR = 0; iTR < nTR; iTR++) { | |
793ff80c | 278 | |
ce0d6231 | 279 | Float_t energyMeV = eTR[iTR] * 0.001; |
280 | Float_t energyeV = eTR[iTR] * 1000.0; | |
281 | Float_t absLength = 0.0; | |
282 | Float_t sigma = 0.0; | |
793ff80c | 283 | |
ce0d6231 | 284 | // Take the absorbtion in the entrance window into account |
285 | Double_t muMy = fTR->GetMuMy(energyMeV); | |
286 | sigma = muMy * fFoilDensity; | |
287 | if (sigma > 0.0) { | |
288 | absLength = gRandom->Exp(1.0/sigma); | |
289 | if (absLength < AliTRDgeometry::MyThick()) { | |
842287f2 | 290 | continue; |
291 | } | |
ce0d6231 | 292 | } |
293 | else { | |
294 | continue; | |
295 | } | |
793ff80c | 296 | |
ce0d6231 | 297 | // The absorbtion cross sections in the drift gas |
298 | // Gas-mixture (Xe/CO2) | |
f2979d08 | 299 | Double_t muNo = 0.0; |
a076fc2f | 300 | if (AliTRDCommonParam::Instance()->IsXenon()) { |
f2979d08 | 301 | muNo = fTR->GetMuXe(energyMeV); |
302 | } | |
a076fc2f | 303 | else if (AliTRDCommonParam::Instance()->IsArgon()) { |
f2979d08 | 304 | muNo = fTR->GetMuAr(energyMeV); |
305 | } | |
ce0d6231 | 306 | Double_t muCO = fTR->GetMuCO(energyMeV); |
f2979d08 | 307 | sigma = (fGasNobleFraction * muNo + (1.0 - fGasNobleFraction) * muCO) |
308 | * fGasDensity | |
309 | * fTR->GetTemp(); | |
ce0d6231 | 310 | |
311 | // The distance after which the energy of the TR photon | |
312 | // is deposited. | |
313 | if (sigma > 0.0) { | |
314 | absLength = gRandom->Exp(1.0/sigma); | |
315 | if (absLength > (AliTRDgeometry::DrThick() | |
316 | + AliTRDgeometry::AmThick())) { | |
842287f2 | 317 | continue; |
318 | } | |
ce0d6231 | 319 | } |
320 | else { | |
321 | continue; | |
322 | } | |
793ff80c | 323 | |
ce0d6231 | 324 | // The position of the absorbtion |
325 | Float_t posHit[3]; | |
326 | gMC->TrackPosition(pos); | |
327 | posHit[0] = pos[0] + mom[0] / pTot * absLength; | |
328 | posHit[1] = pos[1] + mom[1] / pTot * absLength; | |
329 | posHit[2] = pos[2] + mom[2] / pTot * absLength; | |
793ff80c | 330 | |
ce0d6231 | 331 | // Create the charge |
f2979d08 | 332 | Int_t q = ((Int_t) (energyeV / fWion)); |
793ff80c | 333 | |
ce0d6231 | 334 | // Add the hit to the array. TR photon hits are marked |
335 | // by negative charge | |
336 | AddHit(gAlice->GetMCApp()->GetCurrentTrackNumber() | |
337 | ,det | |
338 | ,posHit | |
339 | ,-q | |
25ca55ce | 340 | ,gMC->TrackTime()*1.0e06 |
d4c6453d | 341 | ,kTRUE); |
793ff80c | 342 | |
343 | } | |
344 | ||
345 | } | |
346 | ||
5c7f4665 | 347 | //_____________________________________________________________________________ |
348 | void AliTRDv1::Init() | |
349 | { | |
350 | // | |
351 | // Initialise Transition Radiation Detector after geometry has been built. | |
5c7f4665 | 352 | // |
353 | ||
354 | AliTRD::Init(); | |
355 | ||
45160b1f | 356 | AliDebug(1,"Slow simulator\n"); |
bd0f8685 | 357 | |
358 | // Switch on TR simulation as default | |
359 | if (!fTRon) { | |
45160b1f | 360 | AliInfo("TR simulation off"); |
bd0f8685 | 361 | } |
362 | else { | |
cb2f9e9b | 363 | fTR = new AliTRDsimTR(); |
bd0f8685 | 364 | } |
5c7f4665 | 365 | |
45160b1f | 366 | AliDebug(1,"+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++"); |
5c7f4665 | 367 | |
fe4da5cc | 368 | } |
369 | ||
5c7f4665 | 370 | //_____________________________________________________________________________ |
371 | void AliTRDv1::StepManager() | |
a328fff9 | 372 | { |
373 | // | |
374 | // Slow simulator. Every charged track produces electron cluster as hits | |
375 | // along its path across the drift volume. The step size is fixed in | |
376 | // this version of the step manager. | |
377 | // | |
f2979d08 | 378 | // Works for Xe/CO2 as well as Ar/CO2 |
379 | // | |
a328fff9 | 380 | |
ce0d6231 | 381 | // PDG code electron |
382 | const Int_t kPdgElectron = 11; | |
383 | ||
053767a4 | 384 | Int_t layer = 0; |
385 | Int_t stack = 0; | |
386 | Int_t sector = 0; | |
387 | Int_t det = 0; | |
a328fff9 | 388 | Int_t qTot; |
389 | ||
390 | Float_t hits[3]; | |
391 | Double_t eDep; | |
392 | ||
393 | Bool_t drRegion = kFALSE; | |
394 | Bool_t amRegion = kFALSE; | |
395 | ||
2c8bf4aa | 396 | TString cIdPath; |
397 | Char_t cIdSector[3]; | |
398 | cIdSector[2] = 0; | |
399 | ||
a328fff9 | 400 | TString cIdCurrent; |
401 | TString cIdSensDr = "J"; | |
402 | TString cIdSensAm = "K"; | |
403 | Char_t cIdChamber[3]; | |
2c8bf4aa | 404 | cIdChamber[2] = 0; |
a328fff9 | 405 | |
030b4415 | 406 | TLorentzVector pos; |
407 | TLorentzVector mom; | |
a328fff9 | 408 | |
053767a4 | 409 | const Int_t kNlayer = AliTRDgeometry::Nlayer(); |
410 | const Int_t kNstack = AliTRDgeometry::Nstack(); | |
411 | const Int_t kNdetsec = kNlayer * kNstack; | |
a328fff9 | 412 | |
030b4415 | 413 | const Double_t kBig = 1.0e+12; |
a328fff9 | 414 | const Float_t kEkinMinStep = 1.0e-5; // Minimum energy for the step size adjustment |
415 | ||
416 | // Set the maximum step size to a very large number for all | |
417 | // neutral particles and those outside the driftvolume | |
674812e4 | 418 | if (!fPrimaryIonisation) gMC->SetMaxStep(kBig); |
a328fff9 | 419 | |
420 | // If not charged track or already stopped or disappeared, just return. | |
421 | if ((!gMC->TrackCharge()) || | |
ce0d6231 | 422 | gMC->IsTrackDisappeared()) { |
423 | return; | |
424 | } | |
a328fff9 | 425 | |
426 | // Inside a sensitive volume? | |
427 | cIdCurrent = gMC->CurrentVolName(); | |
428 | ||
ce0d6231 | 429 | if (cIdSensDr == cIdCurrent[1]) { |
430 | drRegion = kTRUE; | |
431 | } | |
432 | if (cIdSensAm == cIdCurrent[1]) { | |
433 | amRegion = kTRUE; | |
434 | } | |
a328fff9 | 435 | |
030b4415 | 436 | if ((!drRegion) && |
437 | (!amRegion)) { | |
438 | return; | |
439 | } | |
a328fff9 | 440 | |
441 | // The hit coordinates and charge | |
442 | gMC->TrackPosition(pos); | |
443 | hits[0] = pos[0]; | |
444 | hits[1] = pos[1]; | |
445 | hits[2] = pos[2]; | |
446 | ||
2c8bf4aa | 447 | // The sector number (0 - 17), according to standard coordinate system |
448 | cIdPath = gGeoManager->GetPath(); | |
449 | cIdSector[0] = cIdPath[21]; | |
450 | cIdSector[1] = cIdPath[22]; | |
053767a4 | 451 | sector = atoi(cIdSector); |
a328fff9 | 452 | |
453 | // The plane and chamber number | |
030b4415 | 454 | cIdChamber[0] = cIdCurrent[2]; |
455 | cIdChamber[1] = cIdCurrent[3]; | |
a328fff9 | 456 | Int_t idChamber = (atoi(cIdChamber) % kNdetsec); |
053767a4 | 457 | stack = ((Int_t) idChamber / kNlayer); |
458 | layer = ((Int_t) idChamber % kNlayer); | |
e0d47c25 | 459 | |
030b4415 | 460 | // The detector number |
053767a4 | 461 | det = fGeometry->GetDetector(layer,stack,sector); |
030b4415 | 462 | |
25ca55ce | 463 | // 0: InFlight 1:Entering 2:Exiting |
030b4415 | 464 | Int_t trkStat = 0; |
a328fff9 | 465 | |
466 | // Special hits only in the drift region | |
ce0d6231 | 467 | if ((drRegion) && |
468 | (gMC->IsTrackEntering())) { | |
a328fff9 | 469 | |
ce0d6231 | 470 | // Create a track reference at the entrance of each |
471 | // chamber that contains the momentum components of the particle | |
472 | gMC->TrackMomentum(mom); | |
e6add757 | 473 | AddTrackReference(gAlice->GetMCApp()->GetCurrentTrackNumber(), AliTrackReference::kTRD); |
ce0d6231 | 474 | trkStat = 1; |
a328fff9 | 475 | |
ce0d6231 | 476 | // Create the hits from TR photons if electron/positron is |
477 | // entering the drift volume | |
1315812e | 478 | if ((fTR) && |
479 | (fTRon) && | |
ce0d6231 | 480 | (TMath::Abs(gMC->TrackPid()) == kPdgElectron)) { |
f2979d08 | 481 | CreateTRhit(det); |
030b4415 | 482 | } |
a328fff9 | 483 | |
ce0d6231 | 484 | } |
485 | else if ((amRegion) && | |
486 | (gMC->IsTrackExiting())) { | |
487 | ||
488 | // Create a track reference at the exit of each | |
489 | // chamber that contains the momentum components of the particle | |
490 | gMC->TrackMomentum(mom); | |
e6add757 | 491 | AddTrackReference(gAlice->GetMCApp()->GetCurrentTrackNumber(), AliTrackReference::kTRD); |
ce0d6231 | 492 | trkStat = 2; |
493 | ||
a328fff9 | 494 | } |
495 | ||
496 | // Calculate the charge according to GEANT Edep | |
497 | // Create a new dEdx hit | |
498 | eDep = TMath::Max(gMC->Edep(),0.0) * 1.0e+09; | |
f2979d08 | 499 | qTot = (Int_t) (eDep / fWion); |
ce0d6231 | 500 | if ((qTot) || |
501 | (trkStat)) { | |
502 | AddHit(gAlice->GetMCApp()->GetCurrentTrackNumber() | |
503 | ,det | |
504 | ,hits | |
505 | ,qTot | |
25ca55ce | 506 | ,gMC->TrackTime()*1.0e06 |
ce0d6231 | 507 | ,drRegion); |
508 | } | |
a328fff9 | 509 | |
510 | // Set Maximum Step Size | |
511 | // Produce only one hit if Ekin is below cutoff | |
030b4415 | 512 | if ((gMC->Etot() - gMC->TrackMass()) < kEkinMinStep) { |
513 | return; | |
514 | } | |
674812e4 | 515 | if (!fPrimaryIonisation) gMC->SetMaxStep(fStepSize); |
a328fff9 | 516 | |
517 | } |