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
14
24
25#include "DetectorsBase/Stack.h"
28#include "SimConfig/G4Params.h"
29#include "fairlogger/Logger.h" // for LOG, LOG_IF
30
31// FairRoot includes
32#include "FairDetector.h" // for FairDetector
33#include "FairRootManager.h" // for FairRootManager
34#include "FairRun.h" // for FairRun
35#include "FairVolume.h" // for FairVolume
36#include "FairRootManager.h"
37
38#include "TGeoManager.h" // for TGeoManager, gGeoManager
39#include "TGeoTube.h" // for TGeoTube
40#include "TGeoPcon.h" // for TGeoPcon
41#include "TGeoVolume.h" // for TGeoVolume, TGeoVolumeAssembly
42#include "TString.h" // for TString, operator+
43#include "TVirtualMC.h" // for gMC, TVirtualMC
44#include "TVirtualMCStack.h" // for TVirtualMCStack
45#include "TFile.h" // for TVirtualMCStack
46#include "TGeoParallelWorld.h"
47
48#include <cstdio> // for NULL, snprintf
49#include <cmath>
50
51class FairModule;
52
53class TGeoMedium;
54
55class TParticle;
56
57using std::cout;
58using std::endl;
59
60using o2::itsmft::Hit;
62using namespace o2::its;
63
64#ifdef ENABLE_UPGRADES
66using namespace o2::its3;
67#endif
68
70 : o2::base::DetImpl<Detector>("ITS", kTRUE),
71 mTrackData(),
72 /*
73 mHitStarted(false),
74 mTrkStatusStart(),
75 mPositionStart(),
76 mMomentumStart(),
77 mEnergyLoss(),
78 */
79 mNumberOfDetectors(-1),
80 mModifyGeometry(kFALSE),
81 mNumberInnerLayers(3),
82 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
83{
84 mDescriptorIB = nullptr;
86}
87
88void Detector::configOuterBarrelITS(int nInnerBarrelLayers, int buildLevel)
89{
90 // build ITS outer barrel detector
91 const int kNLr = 4;
92 const int kSensTypeID = 0; // dummy id for Alpide sensor
93
94 const double ChipThicknessOB = 100.e-4;
95
96 const int kRmd = 1;
97 const int kNModPerStave = 3;
98 const int kPhi0 = 4;
99 const int kNStave = 5;
100 const int kNPar = 6;
101
102 // Radii are from last TDR (ALICE-TDR-017.pdf Tab. 1.1, rMid is mean value)
103
104 const double tdr5dat[kNLr][kNPar] = {
105 {-1, 19.40, -1, 4., 7.5, 24}, // for others: -, rMid, -, NMod/HStave, phi0, nStaves // 24 was 49
106 {-1, 24.35, -1, 4., 6., 30}, // 30 was 61
107 {-1, 34.19, -1, 7., 4.29, 42}, // 42 was 88
108 {-1, 39.15, -1, 7., 3.75, 48} // 48 was 100
109 };
110
111 double rLr, phi0, turbo;
112 int nStaveLr, nModPerStaveLr;
113
114 const int kNWrapVol = 2;
115 const double wrpRMin[kNWrapVol] = {19.2, 33.32};
116 const double wrpRMax[kNWrapVol] = {29.14, 44.9};
117 const double wrpZSpan[kNWrapVol] = {93., 163.0};
118
119 for (int iw = 0; iw < kNWrapVol; iw++) {
120 defineWrapperVolume(iw + 1, wrpRMin[iw], wrpRMax[iw], wrpZSpan[iw]); // first wrapper volume managed by DescriptorInnerBarrel
121 }
122
123 for (int idLr = 0; idLr < kNLr; idLr++) {
124 rLr = tdr5dat[idLr][kRmd];
125 phi0 = tdr5dat[idLr][kPhi0];
126
127 nStaveLr = TMath::Nint(tdr5dat[idLr][kNStave]);
128 nModPerStaveLr = TMath::Nint(tdr5dat[idLr][kNModPerStave]);
129 defineLayer(idLr + nInnerBarrelLayers, phi0, rLr, nStaveLr, nModPerStaveLr, ChipThicknessOB, Segmentation::SensorLayerThickness,
130 kSensTypeID, buildLevel);
131 }
132}
133
135 : o2::base::DetImpl<Detector>(name, active),
136 mTrackData(),
137 /*
138 mHitStarted(false),
139 mTrkStatusStart(),
140 mPositionStart(),
141 mMomentumStart(),
142 mEnergyLoss(),
143 */
144 mNumberOfDetectors(-1),
145 mModifyGeometry(kFALSE),
146 mNumberLayers(sNumberOuterLayers),
147 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
148{
149 if (name == "ITS") {
150 mDescriptorIB = std::make_shared<DescriptorInnerBarrelITS2>(3);
151 } else if (name == "IT3") {
152#ifdef ENABLE_UPGRADES
153 mDescriptorIB = std::make_shared<DescriptorInnerBarrelITS3>();
154#endif
155 } else {
156 LOG(fatal) << "Detector name not supported (options ITS and ITS3)";
157 }
158
160 int buildLevelITS = param.buildLevel;
161
162 TString detName = GetName();
163 if (detName == "ITS") {
164 dynamic_cast<DescriptorInnerBarrelITS2*>(mDescriptorIB.get())->configure(buildLevelITS);
165 } else if (detName == "IT3") {
166#ifdef ENABLE_UPGRADES
167 dynamic_cast<DescriptorInnerBarrelITS3*>(mDescriptorIB.get())->configure();
168#endif
169 }
170
173
186 mGeometry.resize(mNumberLayers);
188
189 for (int j{0}; j < mNumberLayers; j++) {
190 if (detName == "IT3" && j < mNumberInnerLayers) {
192 } else {
193 mLayerName[j].Form("%s%d", GeometryTGeo::getITSSensorPattern(), j); // See V3Layer
194 }
195 LOGP(debug, "{}: mLayerName={}", j, mLayerName[j].Data());
196 }
197
198 if (mNumberLayers > 0) { // if not, we'll Fatal-ize in CreateGeometry
199 for (Int_t j = 0; j < mNumberLayers; j++) {
200 mLayerPhi0[j] = 0;
201 mLayerRadii[j] = 0.;
202 mStavePerLayer[j] = 0;
203 mUnitPerStave[j] = 0;
204 mChipThickness[j] = 0.;
205 mStaveWidth[j] = 0.;
206 mStaveTilt[j] = 0.;
207 mDetectorThickness[j] = 0.;
208 mChipTypeID[j] = 0;
209 mBuildLevel[j] = 0;
210 mGeometry[j] = nullptr;
211 }
212 }
213 mServicesGeometry = nullptr;
214
215 for (int i = sNumberOfWrapperVolumes; i--;) {
217 }
218
220}
221
223 : o2::base::DetImpl<Detector>(rhs),
224 mTrackData(),
225 /*
226 mHitStarted(false),
227 mTrkStatusStart(),
228 mPositionStart(),
229 mMomentumStart(),
230 mEnergyLoss(),
231 */
232 mNumberOfDetectors(rhs.mNumberOfDetectors),
233 mModifyGeometry(rhs.mModifyGeometry),
234
236 mHits(o2::utils::createSimVector<o2::itsmft::Hit>())
237{
238 mDescriptorIB = rhs.mDescriptorIB;
239 mNumberInnerLayers = rhs.mNumberInnerLayers;
240 mNumberLayers = rhs.mNumberLayers;
242
243 TString detName = rhs.GetName();
244 for (int j{0}; j < mNumberLayers; j++) {
245 if (detName == "IT3" && j < mNumberInnerLayers) {
246 mLayerName[j].Form("%s%d", GeometryTGeo::getITS3SensorPattern(), j); // See V3Layer
247 } else {
248 mLayerName[j].Form("%s%d", GeometryTGeo::getITSSensorPattern(), j); // See V3Layer
249 }
250 }
251}
252
254{
255
256 if (mHits) {
257 // delete mHits;
259 }
260}
261
263{
264 // The standard = operator
265 // Inputs:
266 // Detector &h the sourse of this copy
267 // Outputs:
268 // none.
269 // Return:
270 // A copy of the sourse hit h
271
272 if (this == &rhs) {
273 return *this;
274 }
275
276 // base class assignment
278
279 mNumberOfDetectors = rhs.mNumberOfDetectors;
280
281 mModifyGeometry = rhs.mModifyGeometry;
282
284 mHits = nullptr;
285
286 mDescriptorIB = rhs.mDescriptorIB;
287
288 mNumberInnerLayers = rhs.mNumberInnerLayers;
289 mNumberLayers = rhs.mNumberLayers;
291
292 TString detName = rhs.GetName();
293 for (Int_t j = 0; j < mNumberLayers; j++) {
294 if (detName == "IT3" && j < mNumberInnerLayers) {
295 mLayerName[j].Form("%s%d", GeometryTGeo::getITS3SensorPattern(), j); // See V3Layer
296 } else {
297 mLayerName[j].Form("%s%d", GeometryTGeo::getITSSensorPattern(), j); // See V3Layer
298 }
299 }
300
301 return *this;
302}
303
305{
306 // Define the list of sensitive volumes
308
309 mLayerID.resize(mNumberLayers);
310 for (int i = 0; i < mNumberLayers; i++) {
311 mLayerID[i] = gMC ? TVirtualMC::GetMC()->VolId(mLayerName[i]) : 0;
312 }
313
315}
316
318{
319 // This method is called from the MC stepping
320 // Electrically neutral magnetic monopoles deposit energy in the
321 // silicon through G4mplIonisation (Ahlen stopping power), so they must not be
322 // rejected by the electric-charge gate. The PDG lookup only runs for neutral
323 // particles in runs with monopole physics enabled.
324 // To-do: handle dyons.
325 static const bool sMonopoleIonisation = o2::conf::G4Params::Instance().monopole;
326 const bool isNeutral = (fMC->TrackCharge() == 0);
327 const bool isMonopole = isNeutral && sMonopoleIonisation && o2::sim::isMonopole(fMC->TrackPid());
328 if (isNeutral && !isMonopole) {
329 return kFALSE;
330 }
331
332 Int_t lay = 0, volID = vol->getMCid();
333
334 // FIXME: Determine the layer number. Is this information available directly from the FairVolume?
335 bool notSens = false;
336 while ((lay < mNumberLayers) && (notSens = (volID != mLayerID[lay]))) {
337 ++lay;
338 }
339 if (notSens) {
340 return kFALSE; // RS: can this happen? This method must be called for sensors only?
341 }
342
343 // Is it needed to keep a track reference when the outer ITS volume is encountered?
344 auto stack = (o2::data::Stack*)fMC->GetStack();
345 if (fMC->IsTrackExiting()) {
346 // Keep the track refs for the innermost and outermost layers only
348 tr.setTrackID(stack->GetCurrentTrackNumber());
349 tr.setUserId(lay);
350 stack->addTrackReference(tr);
351 }
352 bool startHit = false, stopHit = false;
353 unsigned char status = 0;
354 if (fMC->IsTrackEntering()) {
355 status |= Hit::kTrackEntering;
356 }
357 if (fMC->IsTrackInside()) {
358 status |= Hit::kTrackInside;
359 }
360 if (fMC->IsTrackExiting()) {
361 status |= Hit::kTrackExiting;
362 }
363 if (fMC->IsTrackOut()) {
364 status |= Hit::kTrackOut;
365 }
366 if (fMC->IsTrackStop()) {
367 status |= Hit::kTrackStopped;
368 }
369 if (fMC->IsTrackAlive()) {
370 status |= Hit::kTrackAlive;
371 }
372
373 // track is entering or created in the volume
374 if ((status & Hit::kTrackEntering) || (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
375 startHit = true;
376 } else if ((status & (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
377 stopHit = true;
378 }
379
380 // increment energy loss at all steps except entrance
381 if (!startHit) {
382 mTrackData.mEnergyLoss += fMC->Edep();
383 }
384 if (!(startHit | stopHit)) {
385 return kFALSE; // do noting
386 }
387
388 if (startHit) {
390 fMC->TrackMomentum(mTrackData.mMomentumStart);
391 fMC->TrackPosition(mTrackData.mPositionStart);
393 mTrackData.mHitStarted = true;
394 }
395 if (stopHit) {
396 // A monopole that deposited nothing in the sensor leaves no hit
397 if (isMonopole && mTrackData.mEnergyLoss <= 0.) {
398 return kFALSE;
399 }
400 TLorentzVector positionStop;
401 fMC->TrackPosition(positionStop);
402 // Retrieve the indices with the volume path
403 int halfbarrel(0), stave(0), halfstave(0), chipinmodule(0), module(0);
404 fMC->CurrentVolOffID(1, chipinmodule);
405 fMC->CurrentVolOffID(2, module);
406 fMC->CurrentVolOffID(3, halfstave);
407 fMC->CurrentVolOffID(4, stave);
408 fMC->CurrentVolOffID(5, halfbarrel);
409 int chipindex = mGeometryTGeo->getChipIndex(lay, halfbarrel, stave, halfstave, module, chipinmodule);
410
411 Hit* p = addHit(stack->GetCurrentTrackNumber(), chipindex, mTrackData.mPositionStart.Vect(), positionStop.Vect(),
412 mTrackData.mMomentumStart.Vect(), mTrackData.mMomentumStart.E(), positionStop.T(),
414 // p->SetTotalEnergy(vmc->Etot());
415
416 // RS: not sure this is needed
417 // Increment number of Detector det points in TParticle
418 stack->addHit(GetDetId());
419 }
420
421 return kTRUE;
422}
423
425{
426 Int_t ifield = 2;
427 Float_t fieldm = 10.0;
430
431 Float_t tmaxfd = 0.1; // 1.0; // Degree
432 Float_t stemax = 1.0; // cm
433 Float_t deemax = 0.1; // 30.0; // Fraction of particle's energy 0<deemax<=1
434 Float_t epsil = 1.0E-4; // 1.0; // cm
435 Float_t stmin = 0.0; // cm "Default value used"
436
437 Float_t tmaxfdSi = 0.1; // .10000E+01; // Degree
438 Float_t stemaxSi = 0.0075; // .10000E+01; // cm
439 Float_t deemaxSi = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
440 Float_t epsilSi = 1.0E-4; // .10000E+01;
441 Float_t stminSi = 0.0; // cm "Default value used"
442
443 Float_t tmaxfdAir = 0.1; // .10000E+01; // Degree
444 Float_t stemaxAir = .10000E+01; // cm
445 Float_t deemaxAir = 0.1; // 0.30000E-02; // Fraction of particle's energy 0<deemax<=1
446 Float_t epsilAir = 1.0E-4; // .10000E+01;
447 Float_t stminAir = 0.0; // cm "Default value used"
448
449 // AIR
450 Float_t aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
451 Float_t zAir[4] = {6., 7., 8., 18.};
452 Float_t wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
453 Float_t dAir = 1.20479E-3;
454
455 // Water
456 Float_t aWater[2] = {1.00794, 15.9994};
457 Float_t zWater[2] = {1., 8.};
458 Float_t wWater[2] = {0.111894, 0.888106};
459 Float_t dWater = 1.0;
460
461 // PEEK CF30
462 Float_t aPEEK[3] = {12.0107, 1.00794, 15.9994};
463 Float_t zPEEK[3] = {6., 1., 8.};
464 Float_t wPEEK[3] = {19., 12., 3};
465 Float_t dPEEK = 1.32;
466
467 // Kapton
468 Float_t aKapton[4] = {1.00794, 12.0107, 14.010, 15.9994};
469 Float_t zKapton[4] = {1., 6., 7., 8.};
470 Float_t wKapton[4] = {0.026362, 0.69113, 0.07327, 0.209235};
471 Float_t dKapton = 1.42;
472
473 // Tungsten Carbide
474 Float_t aWC[2] = {183.84, 12.0107};
475 Float_t zWC[2] = {74, 6};
476 Float_t wWC[2] = {0.5, 0.5};
477 Float_t dWC = 15.63;
478
479 // BEOL (Metal interconnection stack in Si sensors)
480 Float_t aBEOL[3] = {26.982, 28.086, 15.999};
481 Float_t zBEOL[3] = {13, 14, 8}; // Al, Si, O
482 Float_t wBEOL[3] = {0.170, 0.388, 0.442};
483 Float_t dBEOL = 2.28;
484
485 // Inox 304
486 Float_t aInox304[4] = {12.0107, 51.9961, 58.6928, 55.845};
487 Float_t zInox304[4] = {6., 24., 28, 26}; // C, Cr, Ni, Fe
488 Float_t wInox304[4] = {0.0003, 0.18, 0.10, 0}; // [3] will be computed
489 Float_t dInox304 = 7.85;
490
491 // Ceramic (for IB capacitors) (BaTiO3)
492 // Density includes soldering
493 Float_t aCeramic[3] = {137.327, 47.867, 15.999};
494 Float_t zCeramic[3] = {56, 22, 8}; // Ba, Ti, O
495 Float_t wCeramic[3] = {1, 1, 3}; // Molecular composition
496 Float_t dCeramic = 8.28;
497
498 // Rohacell (C9 H13 N1 O2)
499 Float_t aRohac[4] = {12.01, 1.01, 14.010, 16.};
500 Float_t zRohac[4] = {6., 1., 7., 8.};
501 Float_t wRohac[4] = {9., 13., 1., 2.};
502 Float_t dRohac = 0.05;
503
504 // Rohacell RIST 110
505 Float_t dRist = 0.11;
506
507 // EN AW 7075 (Al alloy with Cu Mg Zn)
508 Float_t aENAW7075[4] = {26.98, 63.55, 24.31, 65.41};
509 Float_t zENAW7075[4] = {13., 29., 12., 30.};
510 Float_t wENAW7075[4] = {0., 0.015, 0.025, 0.055}; // [0] will be computed
511 Float_t dENAW7075 = 2.85;
512
513 // Brass CuZn39Pb3 (Cu Zn Pb)
514 Float_t aBrass[3] = {63.55, 65.41, 207.2};
515 Float_t zBrass[3] = {29., 30., 82.};
516 Float_t wBrass[3] = {0.58, 0.39, 0.03};
517 Float_t dBrass = 8.46;
518
519 // Polymer for ITS services
520 Float_t aPoly[2] = {12.01, 1.};
521 Float_t zPoly[2] = {6., 1.};
522 Float_t wPoly[2] = {0.857, .143};
523 Float_t dPoly = 0.9;
524
525 // Vespel for Beam Pipe Support (same definition of Polyimide in Pipe.cxx)
526 Float_t aVesp[4] = {16., 14., 12., 1.};
527 Float_t zVesp[4] = {8., 7., 6., 1.};
528 Float_t wVesp[4] = {5., 2., 22., 10.};
529 Float_t dVesp = 1.42;
530
531 o2::base::Detector::Mixture(1, "AIR$", aAir, zAir, dAir, 4, wAir);
532 o2::base::Detector::Medium(1, "AIR$", 1, 0, ifield, fieldm, tmaxfdAir, stemaxAir, deemaxAir, epsilAir, stminAir);
533
534 o2::base::Detector::Mixture(2, "WATER$", aWater, zWater, dWater, 2, wWater);
535 o2::base::Detector::Medium(2, "WATER$", 2, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
536
537 o2::base::Detector::Material(3, "SI$", 0.28086E+02, 0.14000E+02, 0.23300E+01, 0.93600E+01, 0.99900E+03);
538 o2::base::Detector::Medium(3, "SI$", 3, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
539
540 o2::base::Detector::Material(4, "BERILLIUM$", 9.01, 4., 1.848, 35.3, 36.7); // From AliPIPEv3
541 o2::base::Detector::Medium(4, "BERILLIUM$", 4, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
542
543 o2::base::Detector::Material(5, "COPPER$", 0.63546E+02, 0.29000E+02, 0.89600E+01, 0.14300E+01, 0.99900E+03);
544 o2::base::Detector::Medium(5, "COPPER$", 5, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
545
546 // needed for STAVE , Carbon, kapton, Epoxy, flexcable
547
548 // AliceO2::Base::Detector::Material(6,"CARBON$",12.0107,6,2.210,999,999);
549 o2::base::Detector::Material(6, "CARBON$", 12.0107, 6, 2.210 / 1.3, 999, 999);
550 o2::base::Detector::Medium(6, "CARBON$", 6, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
551
552 o2::base::Detector::Mixture(7, "KAPTON(POLYCH2)$", aKapton, zKapton, dKapton, 4, wKapton);
553 o2::base::Detector::Medium(7, "KAPTON(POLYCH2)$", 7, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
554
555 // values below modified as compared to source AliITSv11 !
556
557 // BEOL (Metal interconnection stack in Si sensors)
558 o2::base::Detector::Mixture(29, "METALSTACK$", aBEOL, zBEOL, dBEOL, 3, wBEOL);
559 o2::base::Detector::Medium(29, "METALSTACK$", 29, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
560
561 // Glue between IB chip and FPC: density reduced to take into account
562 // empty spaces (160 glue spots/chip , diam. 1 spot = 1 mm)
563 o2::base::Detector::Material(30, "GLUE_IBFPC$", 12.011, 6, 1.05 * 0.3, 999, 999);
564 o2::base::Detector::Medium(30, "GLUE_IBFPC$", 30, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
565
566 // Ceramic for IB capacitors (nmat < 0 => wmat contains number of atoms)
567 o2::base::Detector::Mixture(31, "CERAMIC$", aCeramic, zCeramic, dCeramic, -3, wCeramic);
568 o2::base::Detector::Medium(31, "CERAMIC$", 31, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
569
570 // All types of carbon
571 // Unidirectional prepreg
572 o2::base::Detector::Material(8, "K13D2U2k$", 12.0107, 6, 1.643, 999, 999);
573 o2::base::Detector::Medium(8, "K13D2U2k$", 8, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
574 o2::base::Detector::Material(17, "K13D2U120$", 12.0107, 6, 1.583, 999, 999);
575 o2::base::Detector::Medium(17, "K13D2U120$", 17, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
576 // Carbon prepreg woven
577 o2::base::Detector::Material(18, "F6151B05M$", 12.0107, 6, 2.133, 999, 999);
578 o2::base::Detector::Medium(18, "F6151B05M$", 18, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
579 // Impregnated thread
580 o2::base::Detector::Material(9, "M60J3K$", 12.0107, 6, 2.21, 999, 999);
581 o2::base::Detector::Medium(9, "M60J3K$", 9, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
582 // Impregnated thread
583 o2::base::Detector::Material(10, "M55J6K$", 12.0107, 6, 1.63, 999, 999);
584 o2::base::Detector::Medium(10, "M55J6K$", 10, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
585 // Fabric(0/90)
586 o2::base::Detector::Material(11, "T300$", 12.0107, 6, 1.725, 999, 999);
587 o2::base::Detector::Medium(11, "T300$", 11, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
588 // AMEC Thermasol
589 o2::base::Detector::Material(12, "FGS003$", 12.0107, 6, 1.6, 999, 999);
590 o2::base::Detector::Medium(12, "FGS003$", 12, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
591 // Carbon fleece
592 o2::base::Detector::Material(13, "CarbonFleece$", 12.0107, 6, 0.4, 999, 999);
593 o2::base::Detector::Medium(13, "CarbonFleece$", 13, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
594 // AS4C 200 gsm EX1515
595 o2::base::Detector::Material(37, "AS4C200$", 12.0107, 6, 1.48, 999, 999);
596 o2::base::Detector::Medium(37, "AS4C200$", 37, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
597
598 // Rohacell (various types)
599 o2::base::Detector::Mixture(32, "ROHACELL$", aRohac, zRohac, dRohac, -4, wRohac);
600 o2::base::Detector::Medium(32, "ROHACELL$", 32, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
601
602 o2::base::Detector::Mixture(38, "RIST110$", aRohac, zRohac, dRist, -4, wRohac);
603 o2::base::Detector::Medium(38, "RIST110$", 38, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
604
605 // Carbon prepreg (Cage)
606 o2::base::Detector::Material(33, "M46J6K$", 12.0107, 6, 1.48, 999, 999);
607 o2::base::Detector::Medium(33, "M46J6K$", 33, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
608
609 // PEEK CF30
610 o2::base::Detector::Mixture(19, "PEEKCF30$", aPEEK, zPEEK, dPEEK, -3, wPEEK);
611 o2::base::Detector::Medium(19, "PEEKCF30$", 19, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
612
613 // Flex cable
614 Float_t aFCm[5] = {12.0107, 1.00794, 14.0067, 15.9994, 26.981538};
615 Float_t zFCm[5] = {6., 1., 7., 8., 13.};
616 Float_t wFCm[5] = {0.520088819984, 0.01983871336, 0.0551367996, 0.157399667056, 0.247536};
617 // Float_t dFCm = 1.6087; // original
618 // Float_t dFCm = 2.55; // conform with STAR
619 Float_t dFCm = 2.595; // conform with Corrado
620
621 o2::base::Detector::Mixture(14, "FLEXCABLE$", aFCm, zFCm, dFCm, 5, wFCm);
622 o2::base::Detector::Medium(14, "FLEXCABLE$", 14, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
623
624 // AliceO2::Base::Detector::Material(7,"GLUE$",0.12011E+02,0.60000E+01,0.1930E+01/2.015,999,999);
625 // // original
626 o2::base::Detector::Material(15, "GLUE$", 12.011, 6, 1.93 / 2.015, 999, 999); // conform with ATLAS, Corrado, Stefan
627 o2::base::Detector::Medium(15, "GLUE$", 15, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
628
629 o2::base::Detector::Material(16, "ALUMINUM$", 0.26982E+02, 0.13000E+02, 0.26989E+01, 0.89000E+01, 0.99900E+03);
630 o2::base::Detector::Medium(16, "ALUMINUM$", 16, 0, ifield, fieldm, tmaxfd, stemax, deemax, epsil, stmin);
631
632 o2::base::Detector::Mixture(20, "TUNGCARB$", aWC, zWC, dWC, 2, wWC);
633 o2::base::Detector::Medium(20, "TUNGCARB$", 20, 0, ifield, fieldm, tmaxfd, stemax, deemaxSi, epsilSi, stminSi);
634
635 wInox304[3] = 1. - wInox304[0] - wInox304[1] - wInox304[2];
636 o2::base::Detector::Mixture(21, "INOX304$", aInox304, zInox304, dInox304, 4, wInox304);
637 o2::base::Detector::Medium(21, "INOX304$", 21, 0, ifield, fieldm, tmaxfd, stemax, deemaxSi, epsilSi, stminSi);
638
639 // Tungsten (for gamma converter rods)
640 o2::base::Detector::Material(28, "TUNGSTEN$", 183.84, 74, 19.25, 999, 999);
641 o2::base::Detector::Medium(28, "TUNGSTEN$", 28, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
642
643 // EN AW 7075 (Al alloy with Cu Mg Zn) (for Cage rails)
644 wENAW7075[0] = 1. - wENAW7075[1] - wENAW7075[2] - wENAW7075[3];
645 o2::base::Detector::Mixture(36, "ENAW7075$", aENAW7075, zENAW7075, dENAW7075, 4, wENAW7075);
646 o2::base::Detector::Medium(36, "ENAW7075$", 36, 0, ifield, fieldm, tmaxfd, stemax, deemaxSi, epsilSi, stminSi);
647
648 // Brass CuZn39Pb3
649 o2::base::Detector::Mixture(34, "BRASS$", aBrass, zBrass, dBrass, 3, wBrass);
650 o2::base::Detector::Medium(34, "BRASS$", 34, 0, ifield, fieldm, tmaxfd, stemax, deemaxSi, epsilSi, stminSi);
651
652 // Titanium
653 o2::base::Detector::Material(35, "TITANIUM$", 47.867, 22, 4.506, 999, 999);
654 o2::base::Detector::Medium(35, "TITANIUM$", 35, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
655
656 // Carbon-Fiber-Reinforced Polymer
657 o2::base::Detector::Material(43, "CFRP$", 12.01, 6, 1.55, 999, 999);
658 o2::base::Detector::Medium(43, "CFRP$", 43, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
659
660 // Vespel for Beam Pipe Support
661 o2::base::Detector::Mixture(44, "VESPEL$", aVesp, zVesp, dVesp, -4, wVesp);
662 o2::base::Detector::Medium(44, "VESPEL$", 44, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
663
664 // Carbon for ITS services
665 o2::base::Detector::Material(41, "C4SERVICES$", 12.01, 6, 1.75, 999, 999);
666 o2::base::Detector::Medium(41, "C4SERVICES$", 41, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
667
668 // Polymer for ITS services
669 o2::base::Detector::Mixture(42, "POLY4SERVICES$", aPoly, zPoly, dPoly, 2, wPoly);
670 o2::base::Detector::Medium(42, "POLY4SERVICES$", 42, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
671
672 // For ITS3
673
674 // Araldite 2011
675 Float_t dAraldite = 1.05;
676
677 // ERG Duocel
678 o2::base::Detector::Material(39, "ERGDUOCEL$", 12.0107, 6, 0.06, 999, 999);
679 o2::base::Detector::Medium(39, "ERGDUOCEL$", 39, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
680
681 // Impregnated carbon fleece
682 // (as educated guess we assume 50% carbon fleece 50% Araldite glue)
683 o2::base::Detector::Material(40, "IMPREG_FLEECE$", 12.0107, 6, 0.5 * (dAraldite + 0.4), 999, 999);
684 o2::base::Detector::Medium(40, "IMPREG_FLEECE$", 40, 0, ifield, fieldm, tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
685}
686
688
690{
691 // This will create a branch in the output tree called Hit, setting the last
692 // parameter to kFALSE means that this collection will not be written to the file,
693 // it will exist only during the simulation
694
697 }
698}
699
701{
702 if (!o2::utils::ShmManager::Instance().isOperational()) {
703 mHits->clear();
704 }
705}
706
707void Detector::defineWrapperVolume(Int_t id, Double_t rmin, Double_t rmax, Double_t zspan)
708{
709 // set parameters of id-th wrapper volume
710 if (id >= sNumberOfWrapperVolumes || id < 0) {
711 LOG(fatal) << "id " << id << " of wrapper volume is not in 0-" << sNumberOfWrapperVolumes - 1 << " range";
712 }
713
714 mWrapperMinRadius[id] = rmin;
715 mWrapperMaxRadius[id] = rmax;
716 mWrapperZSpan[id] = zspan;
717}
718
719void Detector::defineLayer(Int_t nlay, Double_t phi0, Double_t r, Int_t nstav, Int_t nunit, Double_t lthick,
720 Double_t dthick, UInt_t dettypeID, Int_t buildLevel)
721{
722 // Sets the layer parameters
723 // Inputs:
724 // nlay layer number
725 // phi0 layer phi0
726 // r layer radius
727 // nstav number of staves
728 // nunit IB: number of chips per stave
729 // OB: number of modules per half stave
730 // lthick stave thickness (if omitted, defaults to 0)
731 // dthick detector thickness (if omitted, defaults to 0)
732 // dettypeID ??
733 // buildLevel (if 0, all geometry is build, used for material budget studies)
734 // Outputs:
735 // none.
736 // Return:
737 // none.
738
739 LOG(debug) << "L# " << nlay << " Phi:" << phi0 << " R:" << r << " Nst:" << nstav << " Nunit:" << nunit
740 << " Lthick:" << lthick << " Dthick:" << dthick << " DetID:" << dettypeID << " B:" << buildLevel;
741
742 if (nlay >= mNumberLayers || nlay < 0) {
743 LOG(error) << "Wrong layer number " << nlay;
744 return;
745 }
746
747 mTurboLayer[nlay] = kFALSE;
748 mLayerPhi0[nlay] = phi0;
749 mLayerRadii[nlay] = r;
750 mStavePerLayer[nlay] = nstav;
751 mUnitPerStave[nlay] = nunit;
752 mChipThickness[nlay] = lthick;
753 mDetectorThickness[nlay] = dthick;
754 mChipTypeID[nlay] = dettypeID;
755 mBuildLevel[nlay] = buildLevel;
756}
757
758void Detector::getLayerParameters(Int_t nlay, Double_t& phi0, Double_t& r, Int_t& nstav, Int_t& nmod, Double_t& width,
759 Double_t& tilt, Double_t& lthick, Double_t& dthick, UInt_t& dettype) const
760{
761 // Gets the layer parameters
762 // Inputs:
763 // nlay layer number
764 // Outputs:
765 // phi0 phi of 1st stave
766 // r layer radius
767 // nstav number of staves
768 // nmod IB: number of chips per stave
769 // OB: number of modules per half stave
770 // width stave width
771 // tilt stave tilt angle
772 // lthick stave thickness
773 // dthick detector thickness
774 // dettype detector type
775 // Return:
776 // none.
777
778 if (nlay >= mNumberLayers || nlay < 0) {
779 LOG(error) << "Wrong layer number " << nlay;
780 return;
781 }
782
783 phi0 = mLayerPhi0[nlay];
784 r = mLayerRadii[nlay];
785 nstav = mStavePerLayer[nlay];
786 nmod = mUnitPerStave[nlay];
787 width = mStaveWidth[nlay];
788 tilt = mStaveTilt[nlay];
789 lthick = mChipThickness[nlay];
790 dthick = mDetectorThickness[nlay];
791 dettype = mChipTypeID[nlay];
792}
793
794TGeoVolume* Detector::createWrapperVolume(Int_t id)
795{
796 // Creates an air-filled wrapper cylindrical volume
797 // For OB a Pcon is needed to host the support rings
798 // while avoiding overlaps with MFT structures and OB cones
799
800 const Double_t suppRingAZlen = 4.;
801 const Double_t coneRingARmax = 33.96;
802 const Double_t coneRingAZlen[2] = {5.6, 0.3};
803 const Double_t suppRingCZlen[3] = {4.8, 4.0, 2.1};
804 const Double_t suppRingsRmin[3] = {23.35, 20.05, 35.4};
805
806 if (id > 0 && (mWrapperMinRadius[id] < 0 || mWrapperMaxRadius[id] < 0 || mWrapperZSpan[id] < 0)) { // check only for OB, IB managed in DescriptorInnerBarrel
807 LOG(fatal) << "Wrapper volume " << id << " was requested but not defined";
808 }
809
810 // Now create the actual shape and volume
811 TGeoShape* tube = nullptr;
812 Double_t zlen;
813 switch (id) {
814 case 0: // IB Layer 0,1,2: simple cylinder
815 {
816 tube = (TGeoShape*)mDescriptorIB->defineWrapperVolume();
817 } break;
818 case 1: // MB Layer 3,4: complex Pcon to avoid MFT overlaps
819 {
820 TGeoPcon* wrap = new TGeoPcon(0, 360, 6);
821 zlen = mWrapperZSpan[id] / 2 + suppRingCZlen[0];
822 wrap->DefineSection(0, -zlen, suppRingsRmin[0], mWrapperMaxRadius[id]);
823 zlen = mWrapperZSpan[id] / 2 + suppRingCZlen[1];
824 wrap->DefineSection(1, -zlen, suppRingsRmin[0], mWrapperMaxRadius[id]);
825 wrap->DefineSection(2, -zlen, suppRingsRmin[1], mWrapperMaxRadius[id]);
826 wrap->DefineSection(3, -mWrapperZSpan[id] / 2., suppRingsRmin[1], mWrapperMaxRadius[id]);
827 wrap->DefineSection(4, -mWrapperZSpan[id] / 2., mWrapperMinRadius[id], mWrapperMaxRadius[id]);
828 zlen = mWrapperZSpan[id] / 2 + suppRingAZlen;
829 wrap->DefineSection(5, zlen, mWrapperMinRadius[id], mWrapperMaxRadius[id]);
830 tube = (TGeoShape*)wrap;
831 } break;
832 case 2: // OB Layer 5,6: simpler Pcon to avoid OB cones overlaps
833 {
834 TGeoPcon* wrap = new TGeoPcon(0, 360, 6);
835 zlen = mWrapperZSpan[id] / 2;
836 wrap->DefineSection(0, -zlen, suppRingsRmin[2], mWrapperMaxRadius[id]);
837 zlen -= suppRingCZlen[2];
838 wrap->DefineSection(1, -zlen, suppRingsRmin[2], mWrapperMaxRadius[id]);
839 wrap->DefineSection(2, -zlen, mWrapperMinRadius[id], mWrapperMaxRadius[id]);
840 zlen = mWrapperZSpan[id] / 2 - coneRingAZlen[0];
841 wrap->DefineSection(3, zlen, mWrapperMinRadius[id], mWrapperMaxRadius[id]);
842 wrap->DefineSection(4, zlen, coneRingARmax, mWrapperMaxRadius[id]);
843 zlen = mWrapperZSpan[id] / 2 + coneRingAZlen[1];
844 wrap->DefineSection(5, zlen, coneRingARmax, mWrapperMaxRadius[id]);
845 tube = (TGeoShape*)wrap;
846 } break;
847 default: // Can never happen, keeps gcc quiet
848 break;
849 }
850
851 TGeoMedium* medAir = gGeoManager->GetMedium(Form("%s_AIR$", GetName()));
852
853 char volnam[30];
854 snprintf(volnam, 29, "%s%d", GeometryTGeo::getITSWrapVolPattern(), id);
855
856 auto* wrapper = new TGeoVolume(volnam, tube, medAir);
857
858 return wrapper;
859}
860
862{
863 // Create the detector materials
865
866 // Construct the detector geometry
868}
869
871{
872 // Create the geometry and insert it in the mother volume ITSV
873 TGeoManager* geoManager = gGeoManager;
874
875 TGeoVolume* vALIC = geoManager->GetVolume("barrel");
876
877 if (!vALIC) {
878 LOG(fatal) << "Could not find the top volume";
879 }
880
881 new TGeoVolumeAssembly(GeometryTGeo::getITSVolPattern());
882 TGeoVolume* vITSV = geoManager->GetVolume(GeometryTGeo::getITSVolPattern());
883 vALIC->AddNode(vITSV, 2, new TGeoTranslation(0, 30., 0)); // Copy number is 2 to cheat AliGeoManager::CheckSymNamesLUT
884
885 const Int_t kLength = 100;
886 Char_t vstrng[kLength] = "xxxRS"; //?
887 vITSV->SetTitle(vstrng);
888
889 // Check that we have all needed parameters for OB (no need IB, which is managed by the DescriptorInnerBarrel)
890 for (Int_t j = mNumberInnerLayers; j < mNumberLayers; j++) {
891 if (mLayerRadii[j] <= 0) {
892 LOG(fatal) << "Wrong layer radius for layer " << j << "(" << mLayerRadii[j] << ")";
893 }
894 if (mStavePerLayer[j] <= 0) {
895 LOG(fatal) << "Wrong number of staves for layer " << j << "(" << mStavePerLayer[j] << ")";
896 }
897 if (mUnitPerStave[j] <= 0) {
898 LOG(fatal) << "Wrong number of chips for layer " << j << "(" << mUnitPerStave[j] << ")";
899 }
900 if (mChipThickness[j] < 0) {
901 LOG(fatal) << "Wrong chip thickness for layer " << j << "(" << mChipThickness[j] << ")";
902 }
903 if (mTurboLayer[j] && mStaveWidth[j] <= 0) {
904 LOG(fatal) << "Wrong stave width for layer " << j << "(" << mStaveWidth[j] << ")";
905 }
906 if (mDetectorThickness[j] < 0) {
907 LOG(fatal) << "Wrong Sensor thickness for layer " << j << "(" << mDetectorThickness[j] << ")";
908 }
909
910 if (j > 0) {
911 if (mLayerRadii[j] <= mLayerRadii[j - 1]) {
912 LOG(fatal) << "Layer " << j << " radius (" << mLayerRadii[j] << ") is smaller than layer " << j - 1
913 << " radius (" << mLayerRadii[j - 1] << ")";
914 }
915 }
916
917 if (mChipThickness[j] == 0) {
918 LOG(info) << "Chip thickness for layer " << j << " not set, using default";
919 }
920 }
921
922 // Create the wrapper volumes
923 TGeoVolume** wrapVols = nullptr;
924
926 wrapVols = new TGeoVolume*[sNumberOfWrapperVolumes];
927 for (int id = 0; id < sNumberOfWrapperVolumes; id++) {
928 wrapVols[id] = createWrapperVolume(id);
929 vITSV->AddNode(wrapVols[id], 1, nullptr);
930 }
931 }
932
933 // Now create the actual geometry
934 for (Int_t j = 0; j < mNumberLayers; j++) {
935
936 if (j < mNumberInnerLayers) {
937 TString detName = GetName();
938 if (detName == "ITS") {
939 mGeometry[j] = ((DescriptorInnerBarrelITS2*)mDescriptorIB.get())->createLayer(j, wrapVols[0]); // define IB layers on first wrapper volume always
940 } else if (detName == "IT3") {
941#ifdef ENABLE_UPGRADES
942 ((DescriptorInnerBarrelITS3*)mDescriptorIB.get())->createLayer(j, wrapVols[0]); // define IB layers on first wrapper volume always
943#endif
944 }
945 mWrapperLayerId[j] = 0;
946 } else {
947 TGeoVolume* dest = vITSV;
948 mWrapperLayerId[j] = -1;
949
950 if (mTurboLayer[j]) {
951 mGeometry[j] = new V3Layer(j, kTRUE, kFALSE, GetName());
952 mGeometry[j]->setStaveWidth(mStaveWidth[j]);
953 mGeometry[j]->setStaveTilt(mStaveTilt[j]);
954 } else {
955 mGeometry[j] = new V3Layer(j, kFALSE, kFALSE, GetName());
956 }
957
958 mGeometry[j]->setPhi0(mLayerPhi0[j]);
959 mGeometry[j]->setRadius(mLayerRadii[j]);
960 mGeometry[j]->setNumberOfStaves(mStavePerLayer[j]);
961 mGeometry[j]->setNumberOfUnits(mUnitPerStave[j]);
962 mGeometry[j]->setChipType(mChipTypeID[j]);
963 mGeometry[j]->setBuildLevel(mBuildLevel[j]);
964
965 mGeometry[j]->setStaveModel(V3Layer::kOBModel2);
966
967 LOG(debug1) << "mBuildLevel: " << mBuildLevel[j];
968
969 if (mChipThickness[j] != 0) {
970 mGeometry[j]->setChipThick(mChipThickness[j]);
971 }
972 if (mDetectorThickness[j] != 0) {
973 mGeometry[j]->setSensorThick(mDetectorThickness[j]);
974 }
975
976 for (int iw = 0; iw < sNumberOfWrapperVolumes; iw++) {
978 LOG(debug) << "Will embed layer " << j << " in wrapper volume " << iw;
979
980 dest = wrapVols[iw];
981 mWrapperLayerId[j] = iw;
982 break;
983 }
984 }
985 mGeometry[j]->createLayer(dest);
986 }
987 }
988
989 // Now create the services
990 TString detName = GetName();
991 if (detName == "ITS") {
992 ((DescriptorInnerBarrelITS2*)mDescriptorIB.get())->createServices(wrapVols[0]);
993 } else if (detName == "IT3") {
994#ifdef ENABLE_UPGRADES
995 ((DescriptorInnerBarrelITS3*)mDescriptorIB.get())->createServices(wrapVols[0]);
996#endif
997 }
998
999 mServicesGeometry = new V3Services(detName);
1000 createMiddlBarrelServices(wrapVols[1]);
1001 createOuterBarrelServices(wrapVols[2]);
1003
1004 createITSServices(vALIC);
1005
1007
1008 // Finally create and place the cage
1009 V3Cage* cagePtr = new V3Cage(GetName());
1010 cagePtr->createAndPlaceCage(vALIC); // vALIC = barrel
1011
1012 delete[] wrapVols; // delete pointer only, not the volumes
1013}
1014
1015void Detector::createMiddlBarrelServices(TGeoVolume* motherVolume)
1016{
1017 //
1018 // Creates the Middle Barrel Service structures
1019 //
1020 // Input:
1021 // motherVolume : the volume hosting the services
1022 //
1023 // Output:
1024 //
1025 // Return:
1026 //
1027 // Created: 24 Sep 2019 Mario Sitta
1028 //
1029
1030 // Create the End Wheels on Side A
1032
1033 // Create the End Wheels on Side C
1035}
1036
1037void Detector::createOuterBarrelServices(TGeoVolume* motherVolume)
1038{
1039 //
1040 // Creates the Outer Barrel Service structures
1041 //
1042 // Input:
1043 // motherVolume : the volume hosting the services
1044 //
1045 // Output:
1046 //
1047 // Return:
1048 //
1049 // Created: 27 Sep 2019 Mario Sitta
1050 //
1051
1052 // Create the End Wheels on Side A
1054
1055 // Create the End Wheels on Side C
1057}
1058
1059void Detector::createOuterBarrelSupports(TGeoVolume* motherVolume)
1060{
1061 //
1062 // Creates the Outer Barrel Service structures
1063 //
1064 // Input:
1065 // motherVolume : the volume hosting the supports
1066 //
1067 // Output:
1068 //
1069 // Return:
1070 //
1071 // Created: 26 Jan 2020 Mario Sitta
1072 // Updated: 02 Mar 2020 Mario Sitta
1073 //
1074
1075 // Create the Cone on Side A
1076 mServicesGeometry->createOBConeSideA(motherVolume);
1077
1078 // Create the Cone on Side C
1079 mServicesGeometry->createOBConeSideC(motherVolume);
1080
1081 // Create the CYSS Cylinder
1083}
1084
1085void Detector::createITSServices(TGeoVolume* motherVolume)
1086{
1087 //
1088 // Creates the ITS services: tubes, cables and the like
1089 //
1090 // Input:
1091 // motherVolume : the volume hosting the supports
1092 //
1093 // Output:
1094 //
1095 // Return:
1096 //
1097 // Created: 12 Apr 2023 Mario Sitta
1098 //
1099
1101}
1102
1104{
1105 //
1106 // Creates entries for alignable volumes associating the symbolic volume
1107 // name with the corresponding volume path.
1108 //
1109 // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot)
1110 //
1111
1112 LOG(info) << "Add ITS alignable volumes";
1113
1114 if (!gGeoManager) {
1115 LOG(fatal) << "TGeoManager doesn't exist !";
1116 return;
1117 }
1118
1119 TString detName = GetName();
1120 TString path = Form("/cave_1/barrel_1/%s_2", GeometryTGeo::getITSVolPattern());
1121 TString sname = GeometryTGeo::composeSymNameITS();
1122
1123 LOG(debug) << sname << " <-> " << path;
1124
1125 if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) {
1126 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
1127 }
1128
1129 Int_t lastUID = 0;
1130 for (Int_t lr = 0; lr < mNumberLayers; lr++) {
1131 if (lr < mNumberInnerLayers) {
1132#ifdef ENABLE_UPGRADES
1133 if (detName == "ITS") {
1135 } else {
1137 }
1138#else
1140#endif
1141 } else {
1142 addAlignableVolumesLayer(lr, path, lastUID);
1143 }
1144 }
1145}
1146
1147void Detector::addAlignableVolumesLayer(int lr, TString& parent, Int_t& lastUID) const
1148{
1149 //
1150 // Add alignable volumes for a Layer and its daughters
1151 //
1152 // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot)
1153 // Updated: 06 Jul 2021 Mario Sitta Do not set Layer as alignable volume
1154 //
1155
1156 TString wrpV =
1157 mWrapperLayerId[lr] != -1 ? Form("%s%d_1", GeometryTGeo::getITSWrapVolPattern(), mWrapperLayerId[lr]) : "";
1158 TString path = Form("%s/%s/%s%d_1", parent.Data(), wrpV.Data(), GeometryTGeo::getITSLayerPattern(), lr);
1159 TString sname = GeometryTGeo::composeSymNameLayer(lr);
1160
1161 const V3Layer* lrobj = mGeometry[lr];
1162 Int_t nhbarrel = lrobj->getNumberOfHalfBarrelsPerParent();
1163 Int_t start = nhbarrel > 0 ? 0 : -1;
1164 for (Int_t hb = start; hb < nhbarrel; hb++) {
1165 addAlignableVolumesHalfBarrel(lr, hb, path, lastUID);
1166 }
1167}
1168
1169void Detector::addAlignableVolumesHalfBarrel(Int_t lr, Int_t hb, TString& parent, Int_t& lastUID) const
1170{
1171 //
1172 // Add alignable volumes for a Half barrel and its daughters
1173 //
1174 // Created: 28 Jun 2021 Mario Sitta First version (based on similar methods)
1175 //
1176
1177 TString path = parent;
1178 if (hb >= 0) {
1179 path = Form("%s/%s%d_%d", parent.Data(), GeometryTGeo::getITSHalfBarrelPattern(), lr, hb);
1180 TString sname = GeometryTGeo::composeSymNameHalfBarrel(lr, hb);
1181
1182 LOG(debug) << "Add " << sname << " <-> " << path;
1183
1184 if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) {
1185 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
1186 }
1187 }
1188
1189 const V3Layer* lrobj = mGeometry[lr];
1190 Int_t nstaves = lrobj->getNumberOfStavesPerParent();
1191 for (int st = 0; st < nstaves; st++) {
1192 addAlignableVolumesStave(lr, hb, st, path, lastUID);
1193 }
1194}
1195
1196void Detector::addAlignableVolumesStave(Int_t lr, Int_t hb, Int_t st, TString& parent, Int_t& lastUID) const
1197{
1198 //
1199 // Add alignable volumes for a Stave and its daughters
1200 //
1201 // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot)
1202 // Updated: 29 Jun 2021 Mario Sitta Hal Barrel index added
1203 //
1204
1205 TString path = Form("%s/%s%d_%d", parent.Data(), GeometryTGeo::getITSStavePattern(), lr, st);
1206 TString sname = GeometryTGeo::composeSymNameStave(lr, hb, st);
1207
1208 LOG(debug) << "Add " << sname << " <-> " << path;
1209
1210 if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) {
1211 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
1212 }
1213
1214 const V3Layer* lrobj = mGeometry[lr];
1215 Int_t nhstave = lrobj->getNumberOfHalfStavesPerParent();
1216 Int_t start = nhstave > 0 ? 0 : -1;
1217 for (Int_t sst = start; sst < nhstave; sst++) {
1218 addAlignableVolumesHalfStave(lr, hb, st, sst, path, lastUID);
1219 }
1220}
1221
1222void Detector::addAlignableVolumesHalfStave(Int_t lr, Int_t hb, Int_t st, Int_t hst, TString& parent, Int_t& lastUID) const
1223{
1224 //
1225 // Add alignable volumes for a HalfStave (if any) and its daughters
1226 //
1227 // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot)
1228 // Updated: 29 Jun 2021 Mario Sitta Hal Barrel index added
1229 //
1230
1231 TString path = parent;
1232 if (hst >= 0) {
1233 path = Form("%s/%s%d_%d", parent.Data(), GeometryTGeo::getITSHalfStavePattern(), lr, hst);
1234 TString sname = GeometryTGeo::composeSymNameHalfStave(lr, hb, st, hst);
1235
1236 LOG(debug) << "Add " << sname << " <-> " << path;
1237
1238 if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) {
1239 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
1240 }
1241 }
1242
1243 const V3Layer* lrobj = mGeometry[lr];
1244 Int_t nmodules = lrobj->getNumberOfModulesPerParent();
1245 Int_t start = nmodules > 0 ? 0 : -1;
1246 for (Int_t md = start; md < nmodules; md++) {
1247 addAlignableVolumesModule(lr, hb, st, hst, md, path, lastUID);
1248 }
1249}
1250
1251void Detector::addAlignableVolumesModule(Int_t lr, Int_t hb, Int_t st, Int_t hst, Int_t md, TString& parent, Int_t& lastUID) const
1252{
1253 //
1254 // Add alignable volumes for a Module (if any) and its daughters
1255 //
1256 // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot)
1257 // Updated: 29 Jun 2021 Mario Sitta Hal Barrel index added
1258 //
1259
1260 TString path = parent;
1261 if (md >= 0) {
1262 path = Form("%s/%s%d_%d", parent.Data(), GeometryTGeo::getITSModulePattern(), lr, md);
1263 TString sname = GeometryTGeo::composeSymNameModule(lr, hb, st, hst, md);
1264
1265 LOG(debug) << "Add " << sname << " <-> " << path;
1266
1267 if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) {
1268 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
1269 }
1270 }
1271
1272 const V3Layer* lrobj = mGeometry[lr];
1273 Int_t nchips = lrobj->getNumberOfChipsPerParent();
1274 for (Int_t ic = 0; ic < nchips; ic++) {
1275 addAlignableVolumesChip(lr, hb, st, hst, md, ic, path, lastUID);
1276 }
1277}
1278
1279void Detector::addAlignableVolumesChip(Int_t lr, Int_t hb, Int_t st, Int_t hst, Int_t md, Int_t ch, TString& parent,
1280 Int_t& lastUID) const
1281{
1282 //
1283 // Add alignable volumes for a Chip
1284 //
1285 // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot)
1286 // Updated: 29 Jun 2021 Mario Sitta Hal Barrel index added
1287 //
1288
1289 TString path = Form("%s/%s%d_%d", parent.Data(), GeometryTGeo::getITSChipPattern(), lr, ch);
1290 TString sname = GeometryTGeo::composeSymNameChip(lr, hb, st, hst, md, ch);
1291 Int_t modUID = chipVolUID(lastUID++);
1292
1293 LOG(debug) << "Add " << sname << " <-> " << path;
1294
1295 if (gGeoManager->SetAlignableEntry(sname, path.Data(), modUID) == nullptr) {
1296 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
1297 }
1298}
1299
1301{
1302 TGeoManager* geoManager = gGeoManager;
1303 TGeoVolume* v = nullptr;
1304
1305 TString volumeName;
1306
1307 // The names of the ITS sensitive volumes have the format: ITSUSensor(0...mNumberLayers-1)
1308 for (Int_t j = 0; j < mNumberLayers; j++) {
1309 TString detName = GetName();
1310 if (j < mNumberInnerLayers && detName == "IT3") {
1311 volumeName = GeometryTGeo::getITS3SensorPattern() + TString::Itoa(j, 10);
1312 } else {
1313 volumeName = GeometryTGeo::getITSSensorPattern() + TString::Itoa(j, 10);
1314 }
1315 v = geoManager->GetVolume(volumeName.Data());
1317 }
1318}
1319
1321{
1322 TGeoParallelWorld* pw = gGeoManager->GetParallelWorld();
1323 if (pw == nullptr) {
1324 LOG(error) << "Parallel world was not created";
1325 return;
1326 }
1327 auto& param = ITSSimParam::Instance();
1328
1329 for (int iL{0}; iL < mNumberLayers; ++iL) {
1330 auto const layer = mGeometry[iL];
1331 int nhbarrels = layer->getNumberOfHalfBarrelsPerParent();
1332 int nstaves = layer->getNumberOfStavesPerParent();
1333 int nhstaves = layer->getNumberOfHalfStavesPerParent();
1334 int nmodules = layer->getNumberOfModulesPerParent();
1335 int nchips = layer->getNumberOfChipsPerParent();
1336
1337 for (int iHB{0}; iHB < nhbarrels; ++iHB) {
1338 for (int iS{0}; iS < nstaves; ++iS) {
1339 for (int iHS{nhstaves > 0 ? 0 : -1}; iHS < nhstaves; ++iHS) {
1340 for (int iM{nmodules > 0 ? 0 : -1}; iM < nmodules; ++iM) {
1341 for (int iC{0}; iC < nchips; ++iC) {
1342 TString sname = GeometryTGeo::composeSymNameChip(iL, iHB, iS, iHS, iM, iC);
1343 TGeoPNEntry* pne = gGeoManager->GetAlignableEntry(sname);
1344 auto path = pne->GetTitle();
1345
1346 if (param.addMetalToPW) {
1347 TString metalPath = Form("%s/MetalStack_1", path);
1348 gGeoManager->MakePhysicalNode(metalPath);
1349 pw->AddNode(metalPath);
1350 }
1351 if (param.addSensorToPW) {
1352 TString sensorPath = Form("%s/ITSUSensor%d_1", path, iL);
1353 gGeoManager->MakePhysicalNode(sensorPath);
1354 pw->AddNode(sensorPath);
1355 }
1356 if (param.addChipToPW) {
1357 pw->AddNode(path);
1358 }
1359 }
1360 }
1361 }
1362 }
1363 }
1364 }
1365}
1366
1367Hit* Detector::addHit(int trackID, int detID, const TVector3& startPos, const TVector3& endPos,
1368 const TVector3& startMom, double startE, double endTime, double eLoss, unsigned char startStatus,
1369 unsigned char endStatus)
1370{
1371 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE, endTime, eLoss, startStatus, endStatus);
1372 return &(mHits->back());
1373}
1374
1376
1377// Define Factory method for calling from the outside
1378extern "C" {
1383}
Definition of the DescriptorInnerBarrelITS3 class.
Definition of the Stack class.
Definition of the ITSMFT Hit class.
std::ostringstream debug
int32_t i
char error[CURL_ERROR_SIZE]
Definition of the GeometryTGeo class.
Definition of the Detector class.
o2::base::Detector * create_detector_its(const char *name, bool active)
ClassImp(IdPath)
Identification of the BSM magnetic monopoles across the simulation.
uint32_t j
Definition RawData.h:0
uint32_t stack
Definition RawData.h:1
Definition of the SegmentationAlpide class.
Definition of the V3Cage class.
Definition of the V3Layer class.
Definition of the V3Services class.
benchmark::State & st
Int_t GetDetId()
void AddSensitiveVolume(TGeoVolume *v)
TVirtualMC * fMC
flag for initialisation
Definition FairModule.h:160
void RegisterAny(const char *name, T *&obj, Bool_t toFile)
static FairRootManager * Instance()
Int_t getMCid()
Definition FairVolume.h:57
void setUserId(Int_t userId)
void setTrackID(Int_t track)
Detector & operator=(const Detector &)
Definition Detector.cxx:46
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
void createOuterBarrelSupports(TGeoVolume *motherVolume)
Double_t mWrapperZSpan[sNumberOfWrapperVolumes]
Max radius of wrapper volume.
Definition Detector.h:256
void addAlignableVolumesModule(Int_t lr, Int_t hb, Int_t st, Int_t hst, Int_t md, TString &parent, Int_t &lastUID) const
struct o2::its::Detector::TrackData mTrackData
~Detector() override
Default destructor.
Definition Detector.cxx:253
Detector & operator=(const Detector &)
Definition Detector.cxx:262
std::vector< int > mStavePerLayer
Vector of layer radii.
Definition Detector.h:262
virtual void getLayerParameters(Int_t nlay, Double_t &phi0, Double_t &r, Int_t &nladd, Int_t &nmod, Double_t &width, Double_t &tilt, Double_t &lthick, Double_t &mthick, UInt_t &dettype) const
Definition Detector.cxx:758
void InitializeO2Detector() override
Initialization of the detector is done here.
Definition Detector.cxx:304
std::vector< V3Layer * > mGeometry
Definition Detector.h:306
Int_t chipVolUID(Int_t id) const
Definition Detector.h:219
virtual void createMaterials()
Create the detector materials.
Definition Detector.cxx:424
std::vector< double > mStaveWidth
Vector of chip thicknesses.
Definition Detector.h:265
Bool_t mModifyGeometry
Definition Detector.h:252
void defineLayer(Int_t nlay, Double_t phi0, Double_t r, Int_t nladd, Int_t nmod, Double_t lthick=0., Double_t dthick=0., UInt_t detType=0, Int_t buildFlag=0) override
Definition Detector.cxx:719
void addAlignableVolumesLayer(Int_t lr, TString &parent, Int_t &lastUID) const
std::vector< double > mChipThickness
Vector of number of "units" per stave.
Definition Detector.h:264
void createITSServices(TGeoVolume *motherVolume)
void addAlignableVolumesHalfStave(Int_t lr, Int_t hb, Int_t st, Int_t hst, TString &parent, Int_t &lastUID) const
std::vector< int > mWrapperLayerId
Z span of wrapper volume.
Definition Detector.h:257
void EndOfEvent() override
Definition Detector.cxx:687
std::vector< double > mStaveTilt
Vector of stave width (only used for turbo)
Definition Detector.h:266
std::vector< int > mBuildLevel
Vector of detector type id.
Definition Detector.h:269
o2::itsmft::Hit * addHit(int trackID, int detID, const TVector3 &startPos, const TVector3 &endPos, const TVector3 &startMom, double startE, double endTime, double eLoss, unsigned char startStatus, unsigned char endStatus)
This method is an example of how to add your own point of type Hit to the clones array.
std::vector< bool > mTurboLayer
Id of wrapper layer to which layer belongs (-1 if not wrapped)
Definition Detector.h:259
void constructDetectorGeometry()
Construct the detector geometry.
Definition Detector.cxx:870
void Register() override
Registers the produced collections in FAIRRootManager.
Definition Detector.cxx:689
std::vector< uint > mChipTypeID
Vector of detector thicknesses.
Definition Detector.h:268
Double_t mWrapperMinRadius[sNumberOfWrapperVolumes]
Definition Detector.h:254
Bool_t ProcessHits(FairVolume *v=nullptr) override
This method is called for each step during simulation (see FairMCApplication::Stepping())
Definition Detector.cxx:317
std::vector< int > mUnitPerStave
Vector of number of staves per layer.
Definition Detector.h:263
void ConstructGeometry() override
Base class to create the detector geometry.
Definition Detector.cxx:861
void addAlignableVolumesHalfBarrel(Int_t lr, Int_t hb, TString &parent, Int_t &lastUID) const
static constexpr Int_t sNumberOfWrapperVolumes
Number of wrapper volumes.
Definition Detector.h:75
static constexpr Int_t sNumberOuterLayers
Number of outer layers in ITSU (fixed)
Definition Detector.h:74
void addAlignableVolumes() const override
Add alignable top volumes.
void addAlignableVolumesChip(Int_t lr, Int_t hb, Int_t st, Int_t hst, Int_t md, Int_t ch, TString &parent, Int_t &lastUID) const
Detector()
Default constructor.
Definition Detector.cxx:69
void defineSensitiveVolumes()
Define the sensitive volumes of the geometry.
void createOuterBarrelServices(TGeoVolume *motherVolume)
static o2::base::Detector * create(const char *name, bool active)
Definition Detector.h:83
std::vector< double > mLayerPhi0
True for "turbo" layers.
Definition Detector.h:260
void fillParallelWorld() const override
Add ITS chip volumes to parallel world geometry.
int mNumberLayers
Number of inner layers (depends on ITS version)
Definition Detector.h:245
V3Services * mServicesGeometry
Geometry.
Definition Detector.h:307
std::vector< o2::itsmft::Hit > * mHits
Vector of Material Budget Studies.
Definition Detector.h:272
void createMiddlBarrelServices(TGeoVolume *motherVolume)
std::vector< double > mLayerRadii
Vector of layer's 1st stave phi in lab.
Definition Detector.h:261
std::vector< int > mLayerID
Number of layers (depends on inner layer version)
Definition Detector.h:247
Double_t mWrapperMaxRadius[sNumberOfWrapperVolumes]
Min radius of wrapper volume.
Definition Detector.h:255
Int_t mNumberOfDetectors
layer names
Definition Detector.h:250
std::shared_ptr< DescriptorInnerBarrel > mDescriptorIB
Services Geometry.
Definition Detector.h:309
std::vector< double > mDetectorThickness
Vector of stave tilt (only used for turbo)
Definition Detector.h:267
void addAlignableVolumesStave(Int_t lr, Int_t hb, Int_t st, TString &parent, Int_t &lastUID) const
std::vector< TString > mLayerName
layer identifiers
Definition Detector.h:248
TGeoVolume * createWrapperVolume(const Int_t nLay)
Creates an air-filled wrapper cylindrical volume.
Definition Detector.cxx:794
void Reset() override
Has to be called after each event to reset the containers.
Definition Detector.cxx:700
GeometryTGeo * mGeometryTGeo
Definition Detector.h:232
void defineWrapperVolume(Int_t id, Double_t rmin, Double_t rmax, Double_t zspan) override
Set per wrapper volume parameters.
Definition Detector.cxx:707
void configOuterBarrelITS(int nInnerBarrelLayers, int buildLevel=0)
We need this as a method to access members.
Definition Detector.cxx:88
static const char * getITSLayerPattern()
static const char * composeSymNameLayer(int lr, bool isITS3=false)
sym name of the layer
static const char * getITS3SensorPattern()
static const char * getITSSensorPattern()
static const char * getITSHalfBarrelPattern()
static const char * composeSymNameHalfBarrel(int lr, int hba, bool isITS3=false)
Sym name of the half barrel at given layer.
static const char * composeSymNameITS()
sym name of the layer
static const char * composeSymNameHalfStave(int lr, int hba, int sta, int ssta, bool isITS3=false)
Sym name of the stave at given layer/halfbarrel.
static GeometryTGeo * Instance()
static const char * composeSymNameChip(int lr, int hba, int sta, int ssta, int mod, int chip, bool isITS3=false)
Sym name of the chip in the given layer/halfbarrel/stave/substave/module.
static const char * getITSChipPattern()
static const char * composeSymNameModule(int lr, int hba, int sta, int ssta, int mod, bool isITS3=false)
Sym name of the substave at given layer/halfbarrel/stave.
static const char * getITSVolPattern()
static const char * getITSModulePattern()
int getChipIndex(int lay, int detInLay) const
static const char * composeSymNameStave(int lr, int hba, int sta, bool isITS3=false)
Sym name of the stave at given layer.
static const char * getITSHalfStavePattern()
static const char * getITSStavePattern()
static const char * getITSWrapVolPattern()
This class defines the Geometry for the Cage of the ITS Upgrade using TGeo.
Definition V3Cage.h:38
void createAndPlaceCage(TGeoVolume *mother, const TGeoManager *mgr=gGeoManager)
Definition V3Cage.cxx:206
Int_t getNumberOfChipsPerParent() const
Definition V3Layer.h:110
Int_t getNumberOfHalfStavesPerParent() const
Definition V3Layer.h:106
Int_t getNumberOfHalfBarrelsPerParent() const
Definition V3Layer.h:102
Int_t getNumberOfStavesPerParent() const
Definition V3Layer.h:104
Int_t getNumberOfModulesPerParent() const
Definition V3Layer.h:108
This class defines the Geometry for the Services of the ITS Upgrade using TGeo.
Definition V3Services.h:39
void createMBEndWheelsSideC(TGeoVolume *mother, const TGeoManager *mgr=gGeoManager)
void createOBConeSideA(TGeoVolume *mother, const TGeoManager *mgr=gGeoManager)
void createMBEndWheelsSideA(TGeoVolume *mother, const TGeoManager *mgr=gGeoManager)
void createOBCYSSCylinder(TGeoVolume *mother, const TGeoManager *mgr=gGeoManager)
void createOBConeSideC(TGeoVolume *mother, const TGeoManager *mgr=gGeoManager)
void createOBEndWheelsSideC(TGeoVolume *mother, const TGeoManager *mgr=gGeoManager)
void createOBEndWheelsSideA(TGeoVolume *mother, const TGeoManager *mgr=gGeoManager)
void createAllITSServices(TGeoVolume *motherVolume, const TGeoManager *mgr=gGeoManager)
void createOBGammaConvWire(TGeoVolume *mother, const TGeoManager *mgr=gGeoManager)
static constexpr float SensorLayerThickness
static ShmManager & Instance()
Definition ShmManager.h:61
const GLdouble * v
Definition glcorearb.h:832
GLuint const GLchar * name
Definition glcorearb.h:781
GLint GLsizei width
Definition glcorearb.h:270
GLboolean * data
Definition glcorearb.h:298
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLenum GLuint GLint GLint layer
Definition glcorearb.h:1310
GLboolean r
Definition glcorearb.h:1233
GLenum GLfloat param
Definition glcorearb.h:271
GLuint id
Definition glcorearb.h:650
constexpr bool isMonopole(int pdg) noexcept
true for the monopole and antimonopole of both species
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.
double mEnergyLoss
momentum
Definition Detector.h:241
TLorentzVector mMomentumStart
position at entrance
Definition Detector.h:240
TLorentzVector mPositionStart
track status flag
Definition Detector.h:239
unsigned char mTrkStatusStart
hit creation started
Definition Detector.h:238
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"