Project
Loading...
Searching...
No Matches
Detector.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
13
14#include "TRDBase/Geometry.h"
15#include "TRDSimulation/TRsim.h"
18#include "DataFormatsTRD/Hit.h"
19
21#include "DetectorsBase/Stack.h"
22#include "FairVolume.h"
23#include "FairRootManager.h"
24
25#include <TGeoManager.h>
26#include <TVirtualMC.h>
27
28#include <cstdio>
29#include <vector>
30#include <stdexcept>
31#include <string>
32
33using namespace o2::trd;
34using namespace o2::trd::constants;
35
37 : o2::base::DetImpl<Detector>("TRD", active)
38{
39 mHits = o2::utils::createSimVector<Hit>();
40 InitializeParams();
41}
42
44 : o2::base::DetImpl<Detector>(rhs),
45 mHits(o2::utils::createSimVector<Hit>()),
46 mFoilDensity(rhs.mFoilDensity),
47 mGasNobleFraction(rhs.mGasNobleFraction),
48 mGasDensity(rhs.mGasDensity),
49 mGeom(rhs.mGeom)
50{
51 InitializeParams();
52}
53
58
60{
61 // register the sensitive volumes with FairRoot
62 defineSensitiveVolumes();
63 buildVolumeIdTables();
64}
65
66void Detector::buildVolumeIdTables()
67{
68 auto* vmc = TVirtualMC::GetMC();
69 const int nVols = vmc->NofVolumes() + 1;
70 mRegionByVolId.assign(nVols, kNotSensitive);
71 mChamberByVolId.assign(nVols, -1);
72 mSectorByVolId.assign(nVols, -1);
73
74 auto record = [nVols](std::vector<int8_t>& table, int vid, int8_t value, const char* what) {
75 if (vid <= 0 || vid >= nVols) {
76 LOG(fatal) << "TRD volume " << what << " has no usable volume id (" << vid << ")";
77 }
78 table[vid] = value;
79 };
80
81 // The drift and amplification gas volumes, distinguished by the second character of
82 // their name exactly as Geometry::createVolume selects them as sensitive.
83 for (const auto& name : mGeom->getSensitiveTRDVolumes()) {
84 record(mRegionByVolId, vmc->VolId(name.c_str()), name[1] == 'J' ? kDrift : kAmplification, name.c_str());
85 }
86
87 // The readout-chamber assemblies and the supermodule mother volumes. An engine that
88 // collapses assemblies gives the chamber assemblies no volume id at all.
89 char volName[16];
90 mChamberFromName = vmc->VolId("UT00") <= 0;
91 if (mChamberFromName) {
92 LOG(info) << "TRD: chamber assemblies have no volume id, resolving the chamber by name";
93 } else {
94 for (int idet = 0; idet < NLAYER * NSTACK; ++idet) {
95 snprintf(volName, sizeof(volName), "UT%02d", idet);
96 record(mChamberByVolId, vmc->VolId(volName), idet, volName);
97 }
98 }
99 for (int sector = 0; sector < NSECTOR; ++sector) {
100 snprintf(volName, sizeof(volName), "BTRD%d", sector);
101 record(mSectorByVolId, vmc->VolId(volName), sector, volName);
102 }
103}
104
105void Detector::InitializeParams()
106{
108 mWion = 23.53; // Ionization energy XeCO2 (85/15)
110 mWion = 27.21; // Ionization energy ArCO2 (82/18)
111 } else {
112 LOG(fatal) << "Wrong gas mixture";
113 // add hard exit here!
114 }
115 // Switch on TR simulation as default
117 if (!mTRon) {
118 LOG(info) << "TR simulation off";
119 }
120 mTR = new TRsim();
121 mMaxMCStepDef = TRDSimParams::Instance().maxMCStepSize;
122}
123
124bool Detector::ProcessHits(FairVolume* v)
125{
126 // If not charged track or already stopped or disappeared, just return.
127 if ((!fMC->TrackCharge()) || fMC->IsTrackDisappeared()) {
128 return false;
129 }
130 fMC->SetMaxStep(mMaxMCStepDef); // Should we optimize this value?
131
132 // Inside sensitive volume ?
133 int copy = 0;
134 const int vid = fMC->CurrentVolID(copy);
135 const int8_t region = (vid > 0 && vid < (int)mRegionByVolId.size()) ? mRegionByVolId[vid] : kNotSensitive;
136 if (region == kNotSensitive) {
137 return false;
138 }
139 const bool drRegion = (region == kDrift);
140 const bool amRegion = (region == kAmplification);
141
142 // Find how far up the chamber and the supermodule sit, once, by walking up until the
143 // ancestor's volume id is one we know. Hard-coding the depth breaks silently whenever a
144 // level is added, removed, or flattened away by the transport engine's own conversion.
145 if (mSectorOffset < 0) {
146 for (int off = 0; off < 16; ++off) {
147 int chamber = -1;
148 if (mChamberOffset < 0 && mChamberFromName && std::sscanf(fMC->CurrentVolOffName(off), "UT%d", &chamber) == 1) {
149 mChamberOffset = off;
150 }
151 const int oid = fMC->CurrentVolOffID(off, copy);
152 if (oid <= 0 || oid >= (int)mChamberByVolId.size()) {
153 continue;
154 }
155 if (mChamberOffset < 0 && !mChamberFromName && mChamberByVolId[oid] >= 0) {
156 mChamberOffset = off;
157 }
158 if (mSectorByVolId[oid] >= 0) {
159 mSectorOffset = off;
160 break;
161 }
162 }
163 if (mChamberOffset < 0 || mSectorOffset < 0) {
164 LOG(fatal) << "No TRD chamber/supermodule ancestor above sensitive volume " << fMC->CurrentVolName();
165 }
166 LOG(info) << "TRD: chamber at mother offset " << mChamberOffset << ", supermodule at " << mSectorOffset;
167 }
168
169 int idChamber = -1;
170 if (mChamberFromName) {
171 if (std::sscanf(fMC->CurrentVolOffName(mChamberOffset), "UT%d", &idChamber) != 1) {
172 idChamber = -1;
173 }
174 } else {
175 const int chamberVol = fMC->CurrentVolOffID(mChamberOffset, copy);
176 idChamber = (chamberVol > 0 && chamberVol < (int)mChamberByVolId.size()) ? mChamberByVolId[chamberVol] : -1;
177 }
178 const int sectorVol = fMC->CurrentVolOffID(mSectorOffset, copy);
179 const int sector = (sectorVol > 0 && sectorVol < (int)mSectorByVolId.size()) ? mSectorByVolId[sectorVol] : -1;
180 if (idChamber < 0 || sector < 0) {
181 LOG(fatal) << "Cannot resolve TRD chamber/supermodule from volume " << fMC->CurrentVolName();
182 }
183
184 // The detector number (0 - 539)
185 int det = mGeom->getDetector(mGeom->getLayer(idChamber), mGeom->getStack(idChamber), sector);
186 if (det < 0 || det >= MAXCHAMBER) {
187 LOG(fatal) << "Detector number out of bounds";
188 }
189
190 // 0: InFlight 1: Entering 2: Exiting
191 int trkStat = 0;
192
193 o2::data::Stack* stack = (o2::data::Stack*)fMC->GetStack();
194 float xp, yp, zp;
195 float px, py, pz, etot;
196 float trackLength = fMC->TrackLength(); // Return the length of the current track from its origin (in cm)
197 float tof = fMC->TrackTime(); // Return the current time of flight of the track being transported (in s).
198
199 // Special hits if track is entering
200 if (drRegion && fMC->IsTrackEntering()) {
201 // Create a track reference at the entrance of each
202 // chamber that contains the momentum components of the particle
203 fMC->TrackMomentum(px, py, pz, etot);
204 fMC->TrackPosition(xp, yp, zp);
205 stack->addTrackReference(o2::TrackReference(*fMC, GetDetId()));
206 // Update track status
207 trkStat = 1;
208 // Create the hits from TR photons if electron/positron is entering the drift volume
209 const bool ele = (std::fabs(fMC->TrackPid()) == 11); // electron PDG code.
210 if (mTRon && ele) {
211 createTRhit(det);
212 }
213 } else if (amRegion && fMC->IsTrackExiting()) {
214 // Create a track reference at the exit of each
215 // chamber that contains the momentum components of the particle
216 fMC->TrackMomentum(px, py, pz, etot);
217 fMC->TrackPosition(xp, yp, zp);
218 stack->addTrackReference(o2::TrackReference(*fMC, GetDetId()));
219 // Update track status
220 trkStat = 2;
221 }
222
223 // Calculate the charge according to GEANT Edep
224 // Create a new dEdx hit
225 const float enDep = std::max(fMC->Edep(), 0.0) * 1e9; // Energy in eV
226 const int totalChargeDep = (int)(enDep / mWion); // Total charge
227
228 // Store those hits with enDep bigger than the ionization potential of the gas mixture for in-flight tracks
229 // or store hits of tracks that are entering or exiting
230 if (totalChargeDep || trkStat) {
231 fMC->TrackPosition(xp, yp, zp);
232 tof = tof * 1e6; // The time of flight in micro-seconds
233 const int trackID = stack->GetCurrentTrackNumber();
234 double pos[3] = {xp, yp, zp};
235 double loc[3] = {-99, -99, -99};
236 gGeoManager->MasterToLocal(pos, loc); // Go to the local coordinate system (locR, locC, locT)
237 float locC = loc[0], locR = loc[1], locT = loc[2];
238 if (drRegion) {
239 locT = locT - 0.5 * (Geometry::drThick() + Geometry::amThick()); // Relative to middle of amplification region
240 }
241 addHit(xp, yp, zp, locC, locR, locT, tof, totalChargeDep, trackID, det, drRegion);
242 stack->addHit(GetDetId());
243 return true;
244 }
245 return false;
246}
247
248void Detector::createTRhit(int det)
249{
250 //
251 // Creates an electron cluster from a TR photon.
252 // The photon is assumed to be created a the end of the radiator. The
253 // distance after which it deposits its energy takes into account the
254 // absorbtion of the entrance window and of the gas mixture in drift
255 // volume.
256 //
257
258 // Maximum number of TR photons per track
259 constexpr int mMaxNumberOfTRPhotons = 50; // Make this a class member?
260
261 float px, py, pz, etot;
262 fMC->TrackMomentum(px, py, pz, etot);
263 float pTot = std::sqrt(px * px + py * py + pz * pz);
264 std::vector<float> photonEnergyContainer; // energy in keV
265 mTR->createPhotons(11, pTot, photonEnergyContainer); // Create TR photons
266 if (photonEnergyContainer.size() > mMaxNumberOfTRPhotons) {
267 LOG(error) << "Boundary error: nTR = " << photonEnergyContainer.size() << ", mMaxNumberOfTRPhotons = " << mMaxNumberOfTRPhotons;
268 }
269
270 // Loop through the TR photons
271 for (const float& photonEnergy : photonEnergyContainer) {
272 const double energyMeV = photonEnergy * 1e-3;
273 const double energyeV = photonEnergy * 1e3;
274 double absLength = 0.0;
275 double sigma = 0.0;
276 // Take the absorbtion in the entrance window into account
277 double muMy = mTR->getMuMy(energyMeV);
278 sigma = muMy * mFoilDensity;
279 if (sigma > 0.0) {
280 absLength = gRandom->Exp(1.0 / sigma);
281 if (absLength < Geometry::myThick()) {
282 continue;
283 }
284 } else {
285 continue;
286 }
287 // The absorbtion cross sections in the drift gas
288 // Gas-mixture (Xe/CO2)
289 double muNo = 0.0;
291 muNo = mTR->getMuXe(energyMeV);
293 muNo = mTR->getMuAr(energyMeV);
294 }
295 double muCO = mTR->getMuCO(energyMeV);
296 // double fGasNobleFraction = 1;
297 // double fGasDensity = 1;
298 sigma = (mGasNobleFraction * muNo + (1.0 - mGasNobleFraction) * muCO) * mGasDensity * mTR->getTemp();
299
300 // The distance after which the energy of the TR photon
301 // is deposited.
302 if (sigma > 0.0) {
303 absLength = gRandom->Exp(1.0 / sigma);
304 if (absLength > (Geometry::drThick() + Geometry::amThick())) {
305 continue;
306 }
307 } else {
308 continue;
309 }
310
311 // The position of the absorbtion
312 float xp, yp, zp;
313 fMC->TrackPosition(xp, yp, zp);
314 float invpTot = 1. / pTot;
315 float x = xp + px * invpTot * absLength;
316 float y = yp + py * invpTot * absLength;
317 float z = zp + pz * invpTot * absLength;
318
319 // Add the hit to the array. TR photon hits are marked by negative energy (and not by charge)
320 float tof = fMC->TrackTime() * 1e6; // The time of flight in micro-seconds
321 o2::data::Stack* stack = (o2::data::Stack*)fMC->GetStack();
322 const int trackID = stack->GetCurrentTrackNumber();
323 const int totalChargeDep = -1 * (int)(energyeV / mWion); // Negative charge for tagging TR photon hits
324 // prepare local coordinates
325 double pos[3] = {x, y, z};
326 double loc[3] = {-99, -99, -99};
327 gGeoManager->MasterToLocal(pos, loc); // Go to the local coordinate system (locR, locC, locT)
328 float locC = loc[0], locR = loc[1], locT = loc[2];
329 locT = locT - 0.5 * (Geometry::drThick() + Geometry::amThick()); // Relative to middle of amplification region
330 addHit(x, y, z, locC, locR, locT, tof, totalChargeDep, trackID, det, true); // All TR hits are in drift region
331 stack->addHit(GetDetId());
332 }
333}
334
336{
337 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, true);
338}
339
341{
342 // Sort hit vector by detector number before the End of the Event
343 std::sort(mHits->begin(), mHits->end(),
344 [](const Hit& a, const Hit& b) {
345 return a.GetDetectorID() < b.GetDetectorID();
346 });
347}
348
349// this is very problematic; we should do round robin or the clear needs
350// to be done by the HitMerger
352{
353 if (!o2::utils::ShmManager::Instance().isOperational()) {
354 mHits->clear();
355 }
356}
357
359
360//_____________________________________________________________________________
362{
363 //
364 // Create the materials for the TRD
365 //
366 int isxfld = 2;
367 float sxmgmx = 10.;
369
371 // Define Materials
373
374 // Aluminum
375 Material(1, "Al", 26.98, 13.0, 2.7, 8.9, 37.2);
376 // Copper
377 Material(2, "Cu", 63.54, 29.0, 8.96, 1.43, 14.8);
378 // Carbon
379 Material(3, "C", 12.01, 6.0, 2.265, 18.8, 74.4);
380 // Carbon for fiber mats
381 Material(4, "C2", 12.01, 6.0, 1.75, 18.8, 74.4);
382 // Zinc
383 Material(5, "Sn", 118.71, 50.0, 7.31, 1.21, 14.8);
384 // Silicon
385 Material(6, "Si", 28.09, 14.0, 2.33, 9.36, 37.2);
386 // Iron
387 Material(7, "Fe", 55.85, 26.0, 7.87, 1.76, 14.8);
388
389 // Air
390 float aAir[4] = {12.011, 14.0, 15.9994, 36.0};
391 float zAir[4] = {6.0, 7.0, 8.0, 18.0};
392 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
393 float dAir = 1.20479e-03;
394 Mixture(51, "Air", aAir, zAir, dAir, 4, wAir);
395 // Polyethilene (CH2)
396 float ape[2] = {12.011, 1.0079};
397 float zpe[2] = {6.0, 1.0};
398 float wpe[2] = {1.0, 2.0};
399 float dpe = 0.95;
400 Mixture(52, "Polyethilene", ape, zpe, dpe, -2, wpe);
401 // Gas mixtures
402 // Xe/CO2-gas-mixture (85% / 15%)
403 float aXeCO2[3] = {131.29, 12.0107, 15.9994};
404 float zXeCO2[3] = {54.0, 6.0, 8.0};
405 float wXeCO2[3] = {8.5, 1.5, 3.0};
406 float fxc = 0.85;
407 float dxe = 0.00549; // at 20C
408 float dco = 0.00186; // at 20C
409 float dgmXe = fxc * dxe + (1.0 - fxc) * dco;
410 // Ar/CO2-gas-mixture
411 float aArCO2[3] = {39.948, 12.0107, 15.9994};
412 float zArCO2[3] = {18.0, 6.0, 8.0};
413 float wArCO2[3] = {8.2, 1.8, 3.6};
414 float fac = 0.82;
415 float dar = 0.00166; // at 20C
416 float dgmAr = fac * dar + (1.0 - fac) * dco;
418 Mixture(53, "XeCO2", aXeCO2, zXeCO2, dgmXe, -3, wXeCO2);
420 LOG(info) << "Gas mixture: Ar C02 (80/20)";
421 Mixture(53, "ArCO2", aArCO2, zArCO2, dgmAr, -3, wArCO2);
422 } else {
423 LOG(fatal) << "Wrong gas mixture";
424 exit(1);
425 }
426 // G10
427 float aG10[4] = {1.0079, 12.011, 15.9994, 28.086};
428 float zG10[4] = {1.0, 6.0, 8.0, 14.0};
429 float wG10[4] = {0.023, 0.194, 0.443, 0.340};
430 float dG10 = 2.0;
431 Mixture(54, "G10", aG10, zG10, dG10, 4, wG10);
432 // Water
433 float awa[2] = {1.0079, 15.9994};
434 float zwa[2] = {1.0, 8.0};
435 float wwa[2] = {2.0, 1.0};
436 float dwa = 1.0;
437 Mixture(55, "Water", awa, zwa, dwa, -2, wwa);
438 // Rohacell (C5H8O2), X0 = 535.005cm
439 float arh[3] = {12.011, 1.0079, 15.9994};
440 float zrh[3] = {6.0, 1.0, 8.0};
441 float wrh[3] = {5.0, 8.0, 2.0};
442 float drh = 0.075;
443 Mixture(56, "Rohacell", arh, zrh, drh, -3, wrh);
444 // Epoxy (C18H19O3)
445 float aEpoxy[3] = {15.9994, 1.0079, 12.011};
446 float zEpoxy[3] = {8.0, 1.0, 6.0};
447 float wEpoxy[3] = {3.0, 19.0, 18.0};
448 float dEpoxy = 1.8;
449 Mixture(57, "Epoxy", aEpoxy, zEpoxy, dEpoxy, -3, wEpoxy);
450 // Araldite, low density epoxy (C18H19O3)
451 float aAral[3] = {15.9994, 1.0079, 12.011};
452 float zAral[3] = {8.0, 1.0, 6.0};
453 float wAral[3] = {3.0, 19.0, 18.0};
454 float dAral = 1.12; // Hardener: 1.15, epoxy: 1.1, mixture: 1/2
455 Mixture(58, "Araldite", aAral, zAral, dAral, -3, wAral);
456 // Mylar
457 float aMy[3] = {12.011, 1.0, 15.9994};
458 float zMy[3] = {6.0, 1.0, 8.0};
459 float wMy[3] = {5.0, 4.0, 2.0};
460 float dMy = 1.39;
461 Mixture(59, "Mylar", aMy, zMy, dMy, -3, wMy);
462 // Polypropylene (C3H6) for radiator fibers
463 float app[2] = {12.011, 1.0079};
464 float zpp[2] = {6.0, 1.0};
465 float wpp[2] = {3.0, 6.0};
466 float dpp = 0.068;
467 Mixture(60, "Polypropylene", app, zpp, dpp, -2, wpp);
468 // Aramide for honeycomb
469 float aAra[4] = {1.0079, 12.011, 15.9994, 14.0067};
470 float zAra[4] = {1.0, 6.0, 8.0, 7.0};
471 float wAra[4] = {3.0, 1.0, 1.0, 1.0};
472 float dAra = 0.032;
473 Mixture(61, "Aramide", aAra, zAra, dAra, -4, wAra);
474 // GFK for Wacosit (Epoxy + Si)
475 float aGFK[4] = {1.0079, 12.011, 15.9994, 28.086};
476 float zGFK[4] = {1.0, 6.0, 8.0, 14.0};
477 float wGFK[4] = {0.0445, 0.5031, 0.1118, 0.340};
478 float dGFK = 2.0;
479 Mixture(62, "GFK", aGFK, zGFK, dGFK, 4, wGFK);
480
482 // Tracking Media Parameters
484
485 // General tracking parameter
486 float tmaxfd = -10.0;
487 float stemax = -1.0e10;
488 float deemax = -0.1;
489 float epsil = 1.0e-4;
490 float stmin = -0.001;
491
492 // Al Frame
493 Medium(1, "Al Frame", 1, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
494 // Air
495 Medium(2, "Air", 51, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
496 // Wires
497 Medium(3, "Wires", 2, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
498 // All other ROB materials (caps, etc.)
499 Medium(4, "ROB Other", 2, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
500 // Cu pads
501 Medium(5, "Padplane", 2, 1, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
502 // Fee + cables
503 Medium(6, "Readout", 2, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
504 // C frame (Wacosit)
505 Medium(7, "Wacosit", 62, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
506 // INOX of cooling bus bars
507 Medium(8, "Cooling bus", 7, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
508 // Gas-mixture (Xe/CO2)
509 Medium(9, "Gas-mix", 53, 1, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
510 // Honeycomb
511 Medium(10, "Honeycomb", 61, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
512 // Araldite glue
513 Medium(11, "Glue", 58, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
514 // G10-plates
515 Medium(13, "G10-plates", 54, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
516 // Cooling water
517 Medium(14, "Water", 55, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
518 // Rohacell for the radiator
519 Medium(15, "Rohacell", 56, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
520 // Al layer in MCMs
521 Medium(16, "MCM-Al", 1, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
522 // Sn layer in MCMs
523 Medium(17, "MCM-Sn", 5, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
524 // Cu layer in MCMs
525 Medium(18, "MCM-Cu", 2, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
526 // G10 layer in MCMs
527 Medium(19, "MCM-G10", 54, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
528 // Si in readout chips
529 Medium(20, "Chip-Si", 6, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
530 // Epoxy in readout chips
531 Medium(21, "Chip-Ep", 57, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
532 // PE in connectors
533 Medium(22, "Conn-PE", 52, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
534 // Cu in connectors
535 Medium(23, "Chip-Cu", 2, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
536 // Al of cooling pipes
537 Medium(24, "Cooling", 1, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
538 // Cu in services
539 Medium(25, "Serv-Cu", 2, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
540 // Carbon fiber mat
541 Medium(26, "Carbon", 4, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
542 // Mylar foil
543 Medium(27, "Mylar", 59, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
544 // Polypropylene fibers
545 Medium(28, "Fiber", 60, 0, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
546
547 // Save the density values for the TRD absorbtion
548 float dmy = 1.39;
549 mFoilDensity = dmy;
551 mGasDensity = dgmXe;
552 mGasNobleFraction = fxc;
554 mGasDensity = dgmAr;
555 mGasNobleFraction = fac;
556 }
557}
558
559// setting up the geometry
561{
563
564 std::vector<int> medmapping;
565 // now query the medium mapping and fill a vector to be passed along
566 // to the geometry creation
567 getMediumIDMappingAsVector(medmapping);
568
569 mGeom = Geometry::instance();
570 mGeom->createGeometry(medmapping);
571}
572
573void Detector::defineSensitiveVolumes()
574{
575 auto vols = mGeom->getSensitiveTRDVolumes();
576 for (auto& name : vols) {
577 auto tgeovol = gGeoManager->GetVolume(name.c_str());
578 if (tgeovol != nullptr) {
579 AddSensitiveVolume(tgeovol);
580 } else {
581 LOG(error) << "No TGeo volume for TRD vol name " << name << " found\n";
582 }
583 }
584}
585
587{
588 mGeom->addAlignableVolumes();
589}
590
Global TRD definitions and constants.
Definition of the Stack class.
ClassImp(IdPath)
uint16_t pos
Definition RawData.h:3
uint32_t stack
Definition RawData.h:1
void getMediumIDMappingAsVector(std::vector< int > &mapping)
Definition Detector.h:144
Detector()
Default Constructor.
Definition Detector.cxx:36
void Mixture(Int_t imat, const char *name, Float_t *a, Float_t *z, Float_t dens, Int_t nlmat, Float_t *wmat)
Definition Detector.cxx:66
void Medium(Int_t numed, const char *name, Int_t nmat, Int_t isvol, Int_t ifield, Float_t fieldm, Float_t tmaxfd, Float_t stemax, Float_t deemax, Float_t epsil, Float_t stmin, Float_t *ubuf=nullptr, Int_t nbuf=0)
Definition Detector.cxx:72
static void initFieldTrackingParams(int &mode, float &maxfield)
Definition Detector.cxx:143
void Material(Int_t imat, const char *name, Float_t a, Float_t z, Float_t dens, Float_t radl, Float_t absl, Float_t *buf=nullptr, Int_t nwbuf=0)
Definition Detector.cxx:59
std::string addNameTo(const char *ext) const
Definition Detector.h:151
Int_t GetCurrentTrackNumber() const override
Definition Stack.h:133
void addTrackReference(const o2::TrackReference &p)
Definition Stack.h:335
~Detector() override
Definition Detector.cxx:54
void InitializeO2Detector() override
Definition Detector.cxx:59
void EndOfEvent() override
Definition Detector.cxx:358
void Register() override
Definition Detector.cxx:335
Detector(Bool_t active=true)
Definition Detector.cxx:36
void ConstructGeometry() override
Definition Detector.cxx:560
void addAlignableVolumes() const override
Add alignable top volumes.
Definition Detector.cxx:586
bool ProcessHits(FairVolume *v=nullptr) override
Definition Detector.cxx:124
void Reset() override
Definition Detector.cxx:351
void FinishEvent() override
Definition Detector.cxx:340
void addAlignableVolumes() const
static Geometry * instance()
Definition Geometry.h:33
void createGeometry(std::vector< int > const &idtmed)
Definition Geometry.cxx:258
std::vector< std::string > const & getSensitiveTRDVolumes() const
Definition Geometry.h:46
int createPhotons(int pdg, float p, std::vector< float > &ePhoton)
Definition TRsim.cxx:122
double getMuAr(double energyMeV)
Definition TRsim.cxx:418
double getMuXe(double energyMeV)
Definition TRsim.cxx:375
float getTemp() const
Definition TRsim.h:114
double getMuCO(double energyMeV)
Definition TRsim.cxx:340
double getMuMy(double energyMeV)
Definition TRsim.cxx:455
static ShmManager & Instance()
Definition ShmManager.h:61
GLint GLenum GLint x
Definition glcorearb.h:403
const GLdouble * v
Definition glcorearb.h:832
GLuint const GLchar * name
Definition glcorearb.h:781
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint y
Definition glcorearb.h:270
GLsizei const GLfloat * value
Definition glcorearb.h:819
GLboolean * data
Definition glcorearb.h:298
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
uint8_t int statusCode int
void freeSimVector(std::vector< T > *ptr)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...
Common utility functions.
bool doTR
switch for transition radiation
SimParam::GasMixture gas
the gas mixture in the TRD
float maxMCStepSize
maximum size of MC steps
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"