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
16
19
20#include "MFTBase/Geometry.h"
21#include "MFTBase/GeometryTGeo.h"
23
25
26#include "Field/MagneticField.h"
27#include "DetectorsBase/Stack.h"
28
29#include <fairlogger/Logger.h>
30#include "FairRootManager.h"
31#include "FairVolume.h"
32#include "TGeoManager.h"
33#include "TLorentzVector.h"
34#include "TVector3.h"
35#include "TVirtualMC.h"
36
37using o2::itsmft::Hit;
38using namespace o2::mft;
39
41
42//_____________________________________________________________________________
44 : o2::base::DetImpl<Detector>("MFT", kTRUE), mVersion(1), mDensitySupportOverSi(0.036), mHits(o2::utils::createSimVector<o2::itsmft::Hit>()), mTrackData() {}
45
46//_____________________________________________________________________________
48 : o2::base::DetImpl<Detector>("MFT", active), mVersion(1), mDensitySupportOverSi(0.036), mHits(o2::utils::createSimVector<o2::itsmft::Hit>()), mTrackData() {}
49
50//_____________________________________________________________________________
52 : o2::base::DetImpl<Detector>(src), mVersion(src.mVersion), mDensitySupportOverSi(src.mDensitySupportOverSi), mHits(o2::utils::createSimVector<o2::itsmft::Hit>()), mTrackData() {}
53
54//_____________________________________________________________________________
55Detector& Detector::operator=(const Detector& src)
56{
57
58 if (this == &src) {
59 return *this;
60 }
61
62 // base class assignment
64
65 mVersion = src.mVersion;
66 mDensitySupportOverSi = src.mDensitySupportOverSi;
67 mHits = nullptr;
68 mTrackData.mHitStarted = src.mTrackData.mHitStarted;
69 mTrackData.mTrkStatusStart = src.mTrackData.mTrkStatusStart;
70 mTrackData.mPositionStart = src.mTrackData.mPositionStart;
71 mTrackData.mMomentumStart = src.mTrackData.mMomentumStart;
72 mTrackData.mEnergyLoss = src.mTrackData.mEnergyLoss;
73 return *this;
74}
75
76//_____________________________________________________________________________
78{
79
80 if (mHits) {
81 // delete mHits;
83 }
84}
85
86//_____________________________________________________________________________
93
94//_____________________________________________________________________________
95Bool_t Detector::ProcessHits(FairVolume* vol)
96{
97 // This method is called from the MC stepping
98
99 if (fMC->IsTrackEntering() && !fMC->IsNewTrack() && fMC->TrackCharge() != 0) { // one reference per charged particle, first entry from outside
100 auto o2stack = static_cast<o2::data::Stack*>(fMC->GetStack());
101 if (o2stack->GetCurrentTrackNumber() != mTrackRefLastTrackID) {
102 mTrackRefLastTrackID = o2stack->GetCurrentTrackNumber();
103 o2stack->addTrackReference(o2::TrackReference(*fMC, GetDetId()));
104 }
105 }
106 // do not track neutral particles
107 if (!(fMC->TrackCharge())) {
108 return kFALSE;
109 }
110
111 Geometry* mftGeo = Geometry::instance();
112
113 Int_t copy;
114 // Check if hit is into a MFT sensor volume
115 if (fMC->CurrentVolID(copy) != mftGeo->getSensorVolumeID()) {
116 return kFALSE;
117 }
118
119 // Get The Sensor Unique ID
120 Int_t sensorID = -1, ladderID = -1, diskID = -1, halfID = -1, level = 0;
121 fMC->CurrentVolOffID(++level, sensorID);
122 fMC->CurrentVolOffID(++level, ladderID);
123 fMC->CurrentVolOffID(++level, diskID);
124 fMC->CurrentVolOffID(++level, halfID);
125
126 Int_t sensorIndex =
127 mGeometryTGeo->getSensorIndex(halfID, diskID, ladderID, sensorID);
128
129 // LOG(info) << "Found hit into half = " << halfID << "; disk = " << diskID <<
130 // "; ladder = " << ladderID << "; sensor = " << sensorID ;
131
132 bool startHit = false, stopHit = false;
133 unsigned char status = 0;
134 if (fMC->IsTrackEntering()) {
135 status |= Hit::kTrackEntering;
136 }
137 if (fMC->IsTrackInside()) {
138 status |= Hit::kTrackInside;
139 }
140 if (fMC->IsTrackExiting()) {
141 status |= Hit::kTrackExiting;
142 }
143 if (fMC->IsTrackOut()) {
144 status |= Hit::kTrackOut;
145 }
146 if (fMC->IsTrackStop()) {
147 status |= Hit::kTrackStopped;
148 }
149 if (fMC->IsTrackAlive()) {
150 status |= Hit::kTrackAlive;
151 }
152
153 // track is entering or created in the volume
154 if ((status & Hit::kTrackEntering) ||
155 (status & Hit::kTrackInside && !mTrackData.mHitStarted)) {
156 startHit = true;
157 } else if ((status &
158 (Hit::kTrackExiting | Hit::kTrackOut | Hit::kTrackStopped))) {
159 stopHit = true;
160 }
161
162 // increment energy loss at all steps except entrance
163 if (!startHit) {
164 mTrackData.mEnergyLoss += fMC->Edep();
165 }
166 if (!(startHit | stopHit)) {
167 return kFALSE; // do noting
168 }
169
170 if (startHit) {
171
172 mTrackData.mEnergyLoss = 0.;
173 fMC->TrackMomentum(mTrackData.mMomentumStart);
174 fMC->TrackPosition(mTrackData.mPositionStart);
175 mTrackData.mTrkStatusStart = status;
176 mTrackData.mHitStarted = true;
177 }
178
179 if (stopHit) {
180
181 TLorentzVector positionStop;
182 fMC->TrackPosition(positionStop);
183
184 Int_t trackID = fMC->GetStack()->GetCurrentTrackNumber();
185 // Int_t detID = vol->getMCid();
186
187 Hit* p = addHit(trackID, sensorIndex, mTrackData.mPositionStart.Vect(),
188 positionStop.Vect(), mTrackData.mMomentumStart.Vect(),
189 mTrackData.mMomentumStart.E(), positionStop.T(),
190 mTrackData.mEnergyLoss, mTrackData.mTrkStatusStart, status);
191
192 o2::data::Stack* stack = (o2::data::Stack*)fMC->GetStack();
193 stack->addHit(GetDetId());
194 }
195
196 return kTRUE;
197}
198
199//_____________________________________________________________________________
200Hit* Detector::addHit(Int_t trackID, Int_t detID, TVector3 startPos,
201 TVector3 endPos, TVector3 startMom, Double_t startE,
202 Double_t endTime, Double_t eLoss,
203 unsigned char startStatus, unsigned char endStatus)
204{
205
206 mHits->emplace_back(trackID, detID, startPos, endPos, startMom, startE,
207 endTime, eLoss, startStatus, endStatus);
208
209 return &(mHits->back());
210}
211
212//_____________________________________________________________________________
214{
215 auto& mftBaseParam = MFTBaseParam::Instance();
216
217 // data from PDG booklet 2002 density [gr/cm^3] rad len
218 // [cm] abs len [cm]
219 Float_t aSi = 28.085, zSi = 14., dSi = 2.329, radSi = 21.82 / dSi,
220 absSi = 108.4 / dSi; // Silicon
221 Float_t aCarb = 12.01, zCarb = 6., dCarb = 2.265, radCarb = 18.8,
222 absCarb = 49.9; // Carbon
223 Float_t aAlu = 26.98, zAlu = 13., dAlu = 2.70, radAlu = 8.897,
224 absAlu = 39.70; // Aluminum
225 Float_t aBe = 9.012182, zBe = 4., dBe = 1.85, radBe = 65.19 / dBe,
226 absBe = 77.8 / dBe; // Beryllium
227 Float_t aCu = 63.546, zCu = 29., dCu = 8.96, radCu = 1.436,
228 absCu = 15.32; // Copper
229
230 // Air mixture
231 const Int_t nAir = 4;
232 Float_t aAir[nAir] = {12, 14, 16, 36}, zAir[nAir] = {6, 7, 8, 18},
233 wAir[nAir] = {0.000124, 0.755267, 0.231781, 0.012827},
234 dAir = 0.00120479, dAirVacuum = 0.00120479e-4;
235
236 // Water mixture
237 const Int_t nWater = 2;
238 Float_t aWater[nWater] = {1.00794, 15.9994}, zWater[nWater] = {1, 8},
239 wWater[nWater] = {0.111894, 0.888106}, dWater = 1.;
240
241 // SiO2 mixture
242 const Int_t nSiO2 = 2;
243 Float_t aSiO2[nSiO2] = {15.9994, 28.0855}, zSiO2[nSiO2] = {8., 14.},
244 wSiO2[nSiO2] = {0.532565, 0.467435}, dSiO2 = 2.20;
245
246 // Inox mixture
247 const Int_t nInox = 9;
248 Float_t aInox[nInox] = {12.0107, 54.9380, 28.0855, 30.9738, 32.0660,
249 58.6928, 51.9961, 95.9400, 55.8450};
250 Float_t zInox[nInox] = {6, 25, 14, 15, 16, 28, 24, 42, 26};
251 Float_t wInox[nInox] = {0.0003, 0.02, 0.01, 0.00045, 0.0003,
252 0.12, 0.17, 0.025, 0.65395};
253 Float_t dInox = 8.03;
254
255 // Kapton polyimide film (from SPD AliITSv11.cxx) and
256 // http://physics.nist.gov/cgi-bin/Star/compos.pl?matno=179
257 Float_t aKapton[4] = {1.00794, 12.0107, 14.010, 15.9994};
258 Float_t zKapton[4] = {1., 6., 7., 8.};
259 Float_t wKapton[4] = {0.026362, 0.69113, 0.07327, 0.209235};
260 Float_t dKapton = 1.42;
261
262 //--- EPOXY --- C18 H19 O3 from ITS AliITSv11.cxx
263 Float_t aEpoxy[3] = {15.9994, 1.00794, 12.0107};
264 Float_t zEpoxy[3] = {8., 1., 6.};
265 Float_t wEpoxy[3] = {3., 19., 18.};
266 Float_t dEpoxy = 1.23; // 1.8 very high value from ITS! ou 1.23 from eccobond
267 // 45 lv datasheet
268
269 //--- Silicone SE4445 Dow Corning
270 // Si, Al, O, C, H
271 Float_t aSE4445[5] = {28.0855, 26.981538, 15.9994, 12.0107, 1.00794};
272 Float_t zSE4445[5] = {14., 13., 8., 6., 1.};
273 Float_t wSE4445[5] = {5.531, 45.222, 43.351, 4.717, 1.172};
274 Float_t dSE4445 = 2.36; // from LBNL file, priv. comm.
275
276 //--- CARBON FIBER CM55J --- from ITS AliITSv11.cxx
277 Float_t aCM55J[4] = {12.0107, 14.0067, 15.9994, 1.00794};
278 Float_t zCM55J[4] = {6., 7., 8., 1.};
279 Float_t wCM55J[4] = {0.908508078, 0.010387573, 0.055957585, 0.025146765};
280 Float_t dCM55J = 1.33; // from J.M. Buhour infos
281
282 // Rohacell mixture
283 const Int_t nRohacell = 3;
284 Float_t aRohacell[nRohacell] = {1.00794, 12.0107, 15.9994};
285 Float_t zRohacell[nRohacell] = {1., 6., 8.};
286 Float_t wRohacell[nRohacell] = {0.0858, 0.5964, 0.3178};
287 Float_t dRohacell;
288 if (Geometry::sGrooves == 0) {
289 // No grooves, water pipes outside rohacell ==>
290 // smaller rohacell thickness, greater density by 15% (from 1.327cm to 1.117cm)
291 dRohacell = 0.032 / (1 - 0.158);
292 // to perform chips aligment
293 if (mftBaseParam.buildAlignment) {
294 dRohacell = dRohacell / (1 - 0.358); // decrase by 4mm of the rohacell thickness
295 }
296 }
297 if (Geometry::sGrooves == 1) {
298 // With grooves, usual rohacell density: 0.032 g/cm3 rohacell 31
299 dRohacell = 0.032;
300 // to perform chips aligment
301 if (mftBaseParam.buildAlignment) {
302 dRohacell = dRohacell / (1 - 0.301); // decrase by 4mm of the rohacell thickness
303 }
304 }
305
306 // Polyimide pipe mixture
307 const Int_t nPolyimide = 4;
308 Float_t aPolyimide[nPolyimide] = {1.00794, 12.0107, 14.0067, 15.9994};
309 Float_t zPolyimide[nPolyimide] = {1, 6, 7, 8};
310 Float_t wPolyimide[nPolyimide] = {0.00942, 0.56089, 0.13082, 0.29887};
311 Float_t dPolyimide = 1.4;
312
313 // PEEK mixture (Polyether Ether Ketone)
314 const Int_t nPEEK = 3;
315 Float_t aPEEK[nPEEK] = {1.00794, 12.0107, 15.9994};
316 Float_t zPEEK[nPEEK] = {1, 6, 8};
317 Float_t wPEEK[nPEEK] = {0.06713, 0.40001, 0.53285};
318 Float_t dPEEK = 1.32;
319
320 // (Printed Circuit Board), material type FR4
321 const Int_t nFR4 = 5;
322 Float_t aFR4[nFR4] = {1.00794, 12.0107, 15.9994, 28.0855, 79.904};
323 Float_t zFR4[nFR4] = {1, 6, 8, 14, 35};
324 Float_t wFR4[nFR4] = {0.0684428, 0.278042, 0.405633, 0.180774, 0.0671091};
325 Float_t dFR4 = 1.7; // Density FR4= 1.7 Cu=8.96
326
327 //======================== From ITS code ===================================
328 // X7R capacitors - updated from F.Tosello's web page - M.S. 18 Oct 10
329 // 58.6928 --> innner electrodes (mainly Ni)
330 // 63.5460 --> terminaisons (Cu)
331 // 118.710 --> terminaisons (Sn)
332 // 137.327 Ba, 47.867 Ti, 15.9994 O (mainly BaTiO3)
333 Float_t aX7R[6] = {137.327, 47.867, 15.9994, 58.6928, 63.5460, 118.710};
334 Float_t zX7R[6] = {56., 22., 8., 28., 29., 50.};
335 Float_t wX7R[6] = {0.524732, 0.176736, 0.179282,
336 0.079750, 0.019750, 0.019750};
337 Float_t dX7R = 6.07914;
338
339 // X7R weld, i.e. Sn 60% Pb 40% (from F.Tosello's web page - M.S. 15 Oct 10)
340
341 Float_t aX7Rweld[2] = {118.71, 207.20};
342 Float_t zX7Rweld[2] = {50., 82.};
343 Float_t wX7Rweld[2] = {0.60, 0.40};
344 Float_t dX7Rweld = 8.52358;
345 //==========================================================================
346
347 // Barrel CarbonFiber M46J
348 const Int_t nCM46J = 4;
349 Float_t aCM46J[4] = {12.0107, 14.0067, 15.9994, 1.00794};
350 Float_t zCM46J[4] = {6., 7., 8., 1.};
351 Float_t wCM46J[4] = {0.908508078, 0.010387573, 0.055957585, 0.025146765};
352 Float_t dCM46J = 1.48; // only changes density
353
354 // Polypropylene[C3H6]n
355 const Int_t nPolyppln = 2;
356 Float_t aPolyppln[2] = {12.0107, 1.00794};
357 Float_t zPolyppln[2] = {6.0, 1.0};
358 Float_t wPolyppln[2] = {0.856307, 0.143693};
359 Float_t dPolyppln = 1.19;
360
361 // Polyurethane [HN-CO-O]
362 const Int_t nPolyurthn = 4;
363 Float_t aPolyurthn[4] = {1.00794, 14.010, 12.0107, 15.9994};
364 Float_t zPolyurthn[4] = {1.0, 7.0, 6.0, 8.0};
365 Float_t wPolyurthn[4] = {0.017077588, 0.237314387, 0.203327619, 0.542280405};
366 Float_t dPolyurthn = 1.25;
367
368 Int_t matId = 0; // tmp material id number
369 Int_t unsens = 0, sens = 1; // sensitive or unsensitive medium
370 Int_t itgfld = 3; // type of field intergration 0 no field -1 user in guswim 1
371 // Runge Kutta 2 helix 3 const field along z
372 Float_t maxfld = 5.; // max field value
373
374 Float_t tmaxfd =
375 0.1; // -10.0; // max deflection angle due to magnetic field in one step
376 Float_t stemax = 1.0; // 0.001; // max step allowed [cm]
377 Float_t deemax =
378 0.1; // -0.2; // maximum fractional energy loss in one step 0<deemax<=1
379 Float_t epsil = 1.0e-4; // 0.001; // tracking precision [cm]
380 Float_t stmin = 0.0; // -0.001; // minimum step due to continuous processes
381 // [cm] (negative value: choose it automatically)
382
383 Float_t tmaxfdSi =
384 0.1; // max deflection angle due to magnetic field in one step
385 Float_t stemaxSi = 0.075; // 5.0e-4; // maximum step allowed [cm]
386 Float_t deemaxSi =
387 0.1; // maximum fractional energy loss in one step 0<deemax<=1
388 Float_t epsilSi = 1.0e-4; // 0.5e-4; // tracking precision [cm]
389 Float_t stminSi = 0.0; // -0.001; // minimum step due to continuous processes
390 // [cm] (negative value: choose it automatically)
391
392 Int_t fieldType;
393 Float_t maxField;
395
396 LOG(debug) << "Detector::createMaterials >>>>> fieldType " << fieldType
397 << " maxField " << maxField;
398
399 matId = 0; // starting value
400
401 o2::base::Detector::Mixture(matId, "Air$", aAir, zAir, dAir, nAir, wAir);
402 o2::base::Detector::Medium(matId, "Air$", matId, unsens, fieldType, maxField,
403 tmaxfd, stemax, deemax, epsil, stmin);
404 matId++;
405
406 o2::base::Detector::Mixture(matId, "Vacuum$", aAir, zAir, dAirVacuum, nAir,
407 wAir);
408 o2::base::Detector::Medium(matId, "Vacuum$", matId, unsens, itgfld, maxfld,
409 tmaxfd, stemax, deemax, epsil, stmin);
410 matId++;
411
412 o2::base::Detector::Material(matId, "Si$", aSi, zSi, dSi, radSi, absSi);
413 o2::base::Detector::Medium(matId, "Si$", matId, sens, fieldType, maxField,
414 tmaxfdSi, stemaxSi, deemaxSi, epsilSi, stminSi);
415 matId++;
416
417 o2::base::Detector::Material(matId, "Readout$", aSi, zSi, dSi, radSi, absSi);
418 o2::base::Detector::Medium(matId, "Readout$", matId, unsens, fieldType,
419 maxField, tmaxfdSi, stemaxSi, deemaxSi, epsilSi,
420 stminSi);
421 matId++;
422
424 matId, "Support$", aSi, zSi, dSi * mDensitySupportOverSi,
426 o2::base::Detector::Medium(matId, "Support$", matId, unsens, fieldType,
427 maxField, tmaxfdSi, stemaxSi, deemaxSi, epsilSi,
428 stminSi);
429 matId++;
430
431 Double_t maxBending = 0; // Max Angle
432 Double_t maxStepSize = 0.001; // Max step size
433 Double_t maxEnergyLoss = 1; // Max Delta E
434 Double_t precision = 0.001; // Precision
435 Double_t minStepSize = 0.001; // Minimum step size
436
437 // Carbon
438 aCarb = 12.011;
439 zCarb = 6.;
440 dCarb = 2.265;
441 radCarb = 18.8;
442 absCarb = 999;
443 maxBending = 10;
444 maxStepSize = .01;
445 precision = .003;
446 minStepSize = .003;
447 o2::base::Detector::Material(matId, "Carbon$", aCarb, zCarb, dCarb, radCarb,
448 absCarb);
449 o2::base::Detector::Medium(matId, "Carbon$", matId, 0, fieldType, maxField,
450 maxBending, maxStepSize, maxEnergyLoss, precision,
451 minStepSize);
452 matId++;
453
454 o2::base::Detector::Material(matId, "Be$", aBe, zBe, dBe, radBe, absBe);
455 o2::base::Detector::Medium(matId, "Be$", matId, unsens, fieldType, maxField,
456 tmaxfd, stemax, deemax, epsil, stmin);
457 matId++;
458
459 o2::base::Detector::Material(matId, "Alu$", aAlu, zAlu, dAlu, radAlu, absAlu);
460 o2::base::Detector::Medium(matId, "Alu$", matId, unsens, fieldType, maxField,
461 tmaxfd, stemax, deemax, epsil, stmin);
462 matId++;
463
464 o2::base::Detector::Mixture(matId, "Water$", aWater, zWater, dWater, nWater,
465 wWater);
466 o2::base::Detector::Medium(matId, "Water$", matId, unsens, itgfld, maxfld,
467 tmaxfd, stemax, deemax, epsil, stmin);
468 matId++;
469
470 o2::base::Detector::Mixture(matId, "SiO2$", aSiO2, zSiO2, dSiO2, nSiO2,
471 wSiO2);
472 o2::base::Detector::Medium(matId, "SiO2$", matId, unsens, itgfld, maxfld,
473 tmaxfd, stemax, deemax, epsil, stmin);
474 matId++;
475
476 o2::base::Detector::Mixture(matId, "Inox$", aInox, zInox, dInox, nInox,
477 wInox);
478 o2::base::Detector::Medium(matId, "Inox$", matId, unsens, itgfld, maxfld,
479 tmaxfd, stemax, deemax, epsil, stmin);
480 matId++;
481
482 o2::base::Detector::Mixture(matId, "Kapton$", aKapton, zKapton, dKapton, 4,
483 wKapton);
484 o2::base::Detector::Medium(matId, "Kapton$", matId, unsens, itgfld, maxfld,
485 tmaxfd, stemax, deemax, epsil, stmin);
486 matId++;
487
488 o2::base::Detector::Mixture(matId, "Epoxy$", aEpoxy, zEpoxy, dEpoxy, -3,
489 wEpoxy);
490 o2::base::Detector::Medium(matId, "Epoxy$", matId, unsens, itgfld, maxfld,
491 tmaxfd, stemax, deemax, epsil, stmin);
492 matId++;
493
494 o2::base::Detector::Mixture(matId, "SE4445$", aSE4445, zSE4445, dSE4445, -5,
495 wSE4445);
496 o2::base::Detector::Medium(matId, "SE4445$", matId, unsens, itgfld, maxfld,
497 tmaxfd, stemax, deemax, epsil, stmin);
498 matId++;
499
500 o2::base::Detector::Mixture(matId, "CarbonFiber$", aCM55J, zCM55J, dCM55J, 4,
501 wCM55J);
502 o2::base::Detector::Medium(matId, "CarbonFiber$", matId, unsens, itgfld,
503 maxfld, tmaxfd, stemax, deemax, epsil, stmin);
504 matId++;
505
506 o2::base::Detector::Mixture(matId, "Rohacell$", aRohacell, zRohacell,
507 dRohacell, nRohacell, wRohacell);
508 o2::base::Detector::Medium(matId, "Rohacell$", matId, unsens, itgfld, maxfld,
509 tmaxfd, stemax, deemax, epsil, stmin);
510 matId++;
511
512 o2::base::Detector::Mixture(matId, "Polyimide$", aPolyimide, zPolyimide,
513 dPolyimide, nPolyimide, wPolyimide);
514 o2::base::Detector::Medium(matId, "Polyimide$", matId, unsens, itgfld, maxfld,
515 tmaxfd, stemax, deemax, epsil, stmin);
516 matId++;
517
518 o2::base::Detector::Mixture(matId, "PEEK$", aPEEK, zPEEK, dPEEK, nPEEK,
519 wPEEK);
520 o2::base::Detector::Medium(matId, "PEEK$", matId, unsens, itgfld, maxfld,
521 tmaxfd, stemax, deemax, epsil, stmin);
522 matId++;
523
524 o2::base::Detector::Mixture(matId, "FR4$", aFR4, zFR4, dFR4, nFR4, wFR4);
525 o2::base::Detector::Medium(matId, "FR4$", matId, unsens, itgfld, maxfld,
526 tmaxfd, stemax, deemax, epsil, stmin);
527 matId++;
528
529 o2::base::Detector::Material(matId, "Cu$", aCu, zCu, dCu, radCu, absCu);
530 o2::base::Detector::Medium(matId, "Cu$", matId, unsens, itgfld, maxfld,
531 tmaxfd, stemax, deemax, epsil, stmin);
532 matId++;
533
534 o2::base::Detector::Mixture(matId, "X7Rcapacitors$", aX7R, zX7R, dX7R, 6,
535 wX7R);
536 o2::base::Detector::Medium(matId, "X7Rcapacitors$", matId, unsens, itgfld,
537 maxfld, tmaxfd, stemax, deemax, epsil, stmin);
538 matId++;
539
540 o2::base::Detector::Mixture(matId, "X7Rweld$", aX7Rweld, zX7Rweld, dX7Rweld,
541 2, wX7Rweld);
542 o2::base::Detector::Medium(matId, "X7Rweld$", matId, unsens, itgfld, maxfld,
543 tmaxfd, stemax, deemax, epsil, stmin);
544 matId++;
545
546 // Carbon fleece from AliITSSUv2.cxx
547 o2::base::Detector::Material(matId, "CarbonFleece$", 12.0107, 6, 0.4, radCarb,
548 absCarb); // 999,999); why 999???
549 o2::base::Detector::Medium(matId, "CarbonFleece$", matId, unsens, itgfld,
550 maxfld, tmaxfd, stemax, deemax, epsil, stmin);
551 matId++;
552
553 // Barrel Materials
554
555 o2::base::Detector::Mixture(matId, "CarbonFiberM46J$", aCM46J, zCM46J, dCM46J,
556 nCM46J, wCM46J);
557 o2::base::Detector::Medium(matId, "CarbonFiberM46J$", matId, unsens, itgfld,
558 maxfld, tmaxfd, stemax, deemax, epsil, stmin);
559 matId++;
560
561 o2::base::Detector::Mixture(matId, "Polypropylene$", aPolyppln, zPolyppln,
562 dPolyppln, nPolyppln, wPolyppln);
563 o2::base::Detector::Medium(matId, "Polypropylene$", matId, unsens, itgfld,
564 maxfld, tmaxfd, stemax, deemax, epsil, stmin);
565 matId++;
566
567 o2::base::Detector::Mixture(matId, "Polyurethane$", aPolyurthn, zPolyurthn,
568 dPolyurthn, nPolyurthn, wPolyurthn);
569 o2::base::Detector::Medium(matId, "Polyurethane$", matId, unsens, itgfld,
570 maxfld, tmaxfd, stemax, deemax, epsil, stmin);
571 matId++;
572
573 // Halfcone Materials
574 // Alu5083 mixture
575 const Int_t nAlu5083 = 9; // iron, silicon, copper, Manganese, Magnesium,
576 // Zinc, Titanium, Chromium, Aluminium
577 Float_t aAlu5083[nAlu5083] = {55.845, 28.0855, 63.546, 54.938049, 24.3050,
578 65.39, 47.867, 51.9961, 26.981538};
579 Float_t zAlu5083[nAlu5083] = {26., 14., 29., 25., 12., 30., 22., 24., 13.};
580 Float_t wAlu5083[nAlu5083] = {0.004, 0.004, 0.001, 0.002, 0.0025,
581 0.0025, 0.0015, 0.0010, 0.9815};
582 Float_t dAlu5083 = 2.65;
583
584 o2::base::Detector::Mixture(matId, "Alu5083$", aAlu5083, zAlu5083, dAlu5083,
585 nAlu5083, wAlu5083);
586 o2::base::Detector::Medium(matId, "Alu5083$", matId, unsens, itgfld, maxfld,
587 tmaxfd, stemax, deemax, epsil, stmin);
588 matId++;
589
590 LOG(debug) << "Detector::createMaterials -----> matId = " << matId;
591}
592
593//_____________________________________________________________________________
595{
596
597 Geometry* mftGeom = Geometry::instance();
598 mftGeom->build();
599}
600
601//_____________________________________________________________________________
608
609//_____________________________________________________________________________
611{
612 Geometry* mftGeom = Geometry::instance();
613
614 auto id = registerSensitiveVolumeAndGetVolID("MFTSensor");
615 if (id <= 0) {
616 LOG(fatal) << "Can't register volume MFTSensor";
617 }
618 if (!mftGeom->getSensorVolumeID()) {
619 mftGeom->setSensorVolumeID(id);
620 }
621}
622
623//_____________________________________________________________________________
625{
626 // Creates entries for MFT alignable volumes associating the symbolic volume
627 // name with the corresponding volume path.
628 // Created: 06 Mar 2018 Mario Sitta First version (mainly ported from AliRoot)
629 // Modified: 21 Apr 2021 Robin Caron
630
631 if (!gGeoManager) {
632 LOG(fatal) << "TGeoManager doesn't exist !";
633 return;
634 }
635
636 TString path = Form("/cave_1/barrel_1/%s_0", GeometryTGeo::getMFTVolPattern());
637 TString sname = GeometryTGeo::composeSymNameMFT();
638
639 if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) {
640 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
641 }
642
643 Int_t lastUID = 0;
644 Int_t nHalf = mGeometryTGeo->getNumberOfHalfs();
645
646 for (Int_t hf = 0; hf < nHalf; hf++) {
647 addAlignableVolumesHalf(hf, path, lastUID);
648 }
649}
650
651//_____________________________________________________________________________
652void Detector::addAlignableVolumesHalf(int hf, TString& parent, Int_t& lastUID) const
653{
654 // Add alignable volumes for half-MFT and its daughters
655
656 TString path = Form("%s/%s_%d_%d", parent.Data(), GeometryTGeo::getMFTHalfPattern(), hf, hf);
657 TString sname = mGeometryTGeo->composeSymNameHalf(hf);
658
659 if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) {
660 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
661 }
662
663 Int_t nDisks = mGeometryTGeo->getNumberOfDisksPerHalf(hf);
664
665 for (int dk = 0; dk < nDisks; dk++) {
666 addAlignableVolumesDisk(hf, dk, path, lastUID);
667 }
668}
669
670//_____________________________________________________________________________
671void Detector::addAlignableVolumesDisk(Int_t hf, Int_t dk,
672 TString& parent, Int_t& lastUID) const
673{
674 // Add alignable volumes for disk and its daughters
675
676 TString path = Form("%s/%s_%d_%d_%d", parent.Data(), GeometryTGeo::getMFTDiskPattern(), hf, dk, dk);
677 TString sname = mGeometryTGeo->composeSymNameDisk(hf, dk);
678
679 if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) {
680 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
681 }
682
683 Int_t nLadders = 0;
684
685 for (Int_t sensor = mGeometryTGeo->getMinSensorsPerLadder(); sensor < mGeometryTGeo->getMaxSensorsPerLadder() + 1; sensor++) {
686 nLadders += mGeometryTGeo->getNumberOfLaddersPerDisk(hf, dk, sensor);
687 }
688
689 for (Int_t lr = 0; lr < nLadders; lr++) {
690 addAlignableVolumesLadder(hf, dk, lr, path, lastUID);
691 }
692}
693
694//_____________________________________________________________________________
695void Detector::addAlignableVolumesLadder(Int_t hf, Int_t dk, Int_t lr,
696 TString& parent, Int_t& lastUID) const
697{
698 // Add alignable volumes for ladder and its daughters
699
700 TString path = parent;
701 path = Form("%s/%s_%d_%d_%d_%d", parent.Data(), GeometryTGeo::getMFTLadderPattern(), hf, dk, lr, lr);
702 TString sname = mGeometryTGeo->composeSymNameLadder(hf, dk, lr);
703
704 if (!gGeoManager->SetAlignableEntry(sname.Data(), path.Data())) {
705 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
706 }
707
708 Int_t nSensors = mGeometryTGeo->getNumberOfSensorsPerLadder(hf, dk, lr);
709
710 for (Int_t ms = 0; ms < nSensors; ms++) {
711 addAlignableVolumesChip(hf, dk, lr, ms, path, lastUID);
712 }
713}
714
715//_____________________________________________________________________________
716void Detector::addAlignableVolumesChip(Int_t hf, Int_t dk, Int_t lr, Int_t ms,
717 TString& parent, Int_t& lastUID) const
718{
719 // Add alignable volumes for a Chip
720
721 TString path = Form("%s/%s_%d_%d_%d_%d", parent.Data(), GeometryTGeo::getMFTChipPattern(), hf, dk, lr, ms);
722 TString sname = mGeometryTGeo->composeSymNameChip(hf, dk, lr, ms);
723
724 Int_t chipID = itsmft::ChipMappingMFT::mChipIDGeoToRO[lastUID++];
725 Int_t uid = o2::base::GeometryManager::getSensID(o2::detectors::DetID::MFT, chipID);
726
727 if (!gGeoManager->SetAlignableEntry(sname, path.Data(), uid)) {
728 LOG(fatal) << "Unable to set alignable entry ! " << sname << " : " << path;
729 }
730}
731
732//_____________________________________________________________________________
734
735//_____________________________________________________________________________
737{
738 // This will create a branch in the output tree called Hit, setting the last
739 // parameter to kFALSE means that this collection will not be written to the
740 // file, it will exist only during the simulation
741
742 if (FairRootManager::Instance()) {
743 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits,
744 kTRUE);
745 }
746}
747
748//_____________________________________________________________________________
750{
751 if (!o2::utils::ShmManager::Instance().isOperational()) {
752 mHits->clear();
753 }
754 mTrackRefLastTrackID = -1;
755}
Definition of the Stack class.
Definition of the ITSMFT Hit class.
std::ostringstream debug
Class handling both virtual segmentation and real volumes.
Definition of the Detector class.
ClassImp(o2::mft::Detector)
Definition of the MagF class.
uint32_t stack
Definition RawData.h:1
int registerSensitiveVolumeAndGetVolID(std::string const &name)
Definition Detector.cxx:190
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
static int getSensID(o2::detectors::DetID detid, int sensid)
void addHit(int iDet)
Definition Stack.cxx:639
static constexpr std::array< int, NChips > mChipIDGeoToRO
~Detector() override
Default destructor.
Definition Detector.cxx:77
void InitializeO2Detector() override
Initialization of the detector is done here.
Definition Detector.cxx:87
void createMaterials()
Creating materials for the detector.
Definition Detector.cxx:213
GeometryTGeo * mGeometryTGeo
Definition Detector.h:142
void addAlignableVolumesLadder(Int_t hf, Int_t dk, Int_t lr, TString &parent, Int_t &lastUID) const
Definition Detector.cxx:695
void EndOfEvent() override
Definition Detector.cxx:733
void Register() override
Registers the produced collections in FAIRRootManager.
Definition Detector.cxx:736
Bool_t ProcessHits(FairVolume *v=nullptr) override
This method is called for each step during simulation (see FairMCApplication::Stepping())
Definition Detector.cxx:95
void ConstructGeometry() override
Definition Detector.cxx:602
void addAlignableVolumes() const override
Add alignable top volumes.
Definition Detector.cxx:624
Detector()
Default constructor.
Definition Detector.cxx:43
void defineSensitiveVolumes()
Definition Detector.cxx:610
void addAlignableVolumesChip(Int_t hf, Int_t dk, Int_t lr, Int_t ms, TString &parent, Int_t &lastUID) const
Definition Detector.cxx:716
Double_t mDensitySupportOverSi
Definition Detector.h:146
Int_t mVersion
access to geometry details
Definition Detector.h:145
void addAlignableVolumesDisk(Int_t hf, Int_t dk, TString &parent, Int_t &lastUID) const
Definition Detector.cxx:671
void Reset() override
Has to be called after each event to reset the containers.
Definition Detector.cxx:749
void addAlignableVolumesHalf(Int_t hf, TString &parent, Int_t &lastUID) const
Definition Detector.cxx:652
static const char * composeSymNameHalf(int hf)
sym name of the half
static const Char_t * getMFTHalfPattern()
Int_t getMaxSensorsPerLadder()
Returns the max number of sensors per ladder.
static const char * composeSymNameChip(int hf, int dk, int lr, int chip)
Sym name of the chip in the given half/disk/ladder.
Int_t getNumberOfLaddersPerDisk(Int_t half, Int_t disk, Int_t sensors) const
Returns the number of ladders in each disk of each half.
static const Char_t * getMFTChipPattern()
Int_t getMinSensorsPerLadder()
Returns the min number of sensors per ladder.
Int_t getNumberOfHalfs()
Returns the number of halves MFT.
Int_t getNumberOfDisksPerHalf(Int_t half) const
Returns the number of disks in each half.
static const char * composeSymNameLadder(int hf, int dk, int lr)
Sym name of the ladder at given half/disk.
Int_t getSensorIndex(Int_t half, Int_t disk, Int_t ladder, Int_t sensor) const
static const Char_t * getMFTLadderPattern()
static const Char_t * getMFTVolPattern()
static GeometryTGeo * Instance()
static const Char_t * getMFTDiskPattern()
Int_t getNumberOfSensorsPerLadder(Int_t half, Int_t disk, Int_t ladder) const
static const char * composeSymNameMFT()
sym name of the MFT
static const char * composeSymNameDisk(int hf, int dk)
Sym name of the disk at given half.
void setSensorVolumeID(Int_t val)
Set the TGeo ID of the volume describing the sensors.
Definition Geometry.h:124
Int_t getSensorVolumeID() const
Returns TGeo ID of the volume describing the sensors.
Definition Geometry.h:121
static const Int_t sGrooves
Definition Geometry.h:83
static Geometry * instance()
Singleton access.
Definition Geometry.cxx:99
static ShmManager & Instance()
Definition ShmManager.h:61
GLenum src
Definition glcorearb.h:1767
GLboolean * data
Definition glcorearb.h:298
GLsizei const GLchar *const * path
Definition glcorearb.h:3591
GLint level
Definition glcorearb.h:275
GLenum GLint GLint * precision
Definition glcorearb.h:1899
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.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"