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