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
12#include <algorithm>
13#include <iomanip>
14
15#include "TFile.h"
16#include "TGeoManager.h"
17#include "TGeoVolume.h"
18#include "TH2.h"
19#include "TVirtualMC.h"
20#include "TVector2.h"
21#include "TVector3.h"
22
23#include "FairRootManager.h"
24#include "FairVolume.h"
25
26#include "EMCALBase/Geometry.h"
27#include "EMCALBase/Hit.h"
31
32#include "DetectorsBase/Stack.h"
33
34#include <boost/algorithm/string/predicate.hpp>
35#include <boost/range/irange.hpp>
36
37using namespace o2::emcal;
38
40
42 : o2::base::DetImpl<Detector>("EMC", active),
43 mBirkC0(0),
44 mBirkC1(0.),
45 mBirkC2(0.),
46 mSensitive(),
47 mSMVolumeID(),
48 mSMVolNames(),
49 mVolumeIDScintillator(-1),
50 mHits(o2::utils::createSimVector<Hit>()),
51 mGeometry(nullptr),
52 mSuperParentsIndices(),
53 mSuperParents(),
54 mCurrentSuperparent(nullptr),
55 mCurrentTrack(-1),
56 mCurrentPrimaryID(-1),
57 mCurrentParentID(-1),
58 mSampleWidth(0.),
59 mSmodPar0(0.),
60 mSmodPar1(0.),
61 mSmodPar2(0.),
62 mInnerEdge(0.),
63 mDCALInnerGap(7)
64{
65 using boost::algorithm::contains;
66 memset(mParEMOD, 0, sizeof(Double_t) * 5);
67
68 Geometry* geo = GetGeometry();
69 if (!geo) {
70 LOG(fatal) << "Geometry is nullptr";
71 }
72 std::string gn = geo->GetName();
73 std::transform(gn.begin(), gn.end(), gn.begin(), ::toupper);
74
75 mSampleWidth = Double_t(geo->GetECPbRadThick() + geo->GetECScintThick());
76
77 if (contains(gn, "V1")) {
78 mSampleWidth += 2. * geo->GetTrd1BondPaperThick();
79 }
80}
81
83 : o2::base::DetImpl<Detector>(rhs),
84 mBirkC0(rhs.mBirkC0),
85 mBirkC1(rhs.mBirkC1),
86 mBirkC2(rhs.mBirkC2),
87 mSensitive(rhs.mSensitive),
88 mSMVolumeID(),
89 mSMVolNames(rhs.mSMVolNames),
90 mVolumeIDScintillator(-1),
91 mHits(o2::utils::createSimVector<Hit>()),
92 mGeometry(rhs.mGeometry),
93 mSuperParentsIndices(),
94 mSuperParents(),
95 mCurrentSuperparent(nullptr),
96 mCurrentTrack(-1),
97 mCurrentPrimaryID(-1),
98 mCurrentParentID(-1),
99 mSampleWidth(rhs.mSampleWidth),
100 mSmodPar0(rhs.mSmodPar0),
101 mSmodPar1(rhs.mSmodPar1),
102 mSmodPar2(rhs.mSmodPar2),
103 mInnerEdge(rhs.mInnerEdge),
104 mDCALInnerGap(rhs.mDCALInnerGap)
105{
106 for (int i = 0; i < 5; ++i) {
107 mParEMOD[i] = rhs.mParEMOD[i];
108 }
109}
110
115
117{
118 // All EMCAL volumes must be declared as sensitive, otherwise
119 // the decay chains are broken by volumes not processed in ProceeHits
120 for (const auto& child : mSensitive) {
121 LOG(debug1) << "Adding sensitive volume " << child;
122 auto svolID = registerSensitiveVolumeAndGetVolID(child);
123 if (child == "SCMX") {
124 LOG(debug1) << "Adding SCMX volume as sensitive volume with ID " << svolID;
125 mVolumeIDScintillator = svolID;
126 }
127 auto smtype = mSMVolNames.find(child);
128 if (smtype != mSMVolNames.end()) {
129 std::cout << "Adding supermodule type " << smtype->second << " for SM " << smtype->first << " with volume ID " << svolID << std::endl;
130 mSMVolumeID[svolID] = smtype->second;
131 }
132 }
133
134 LOG(debug1) << "Supermodule volume map: ";
135 for (auto [volID, volType] : mSMVolumeID) {
136 LOG(debug1) << "Volume " << volID << ", type " << int(volType);
137 }
138}
139
141
143{
144 using boost::algorithm::contains;
145 LOG(debug) << "Creating EMCAL geometry";
146
147 Geometry* geom = GetGeometry();
148 if (!(geom->IsInitialized())) {
149 LOG(error) << "ConstructGeometry: EMCAL Geometry class has not been set up.";
150 }
151
153
154 SpaceFrame emcalframe;
155 emcalframe.CreateGeometry();
156
157 // CreateEmcalEnvelope();
158
159 // COMPACT, TRD1
160 LOG(debug2) << "Shish-Kebab geometry : " << GetTitle();
162
163 geom->DefineSamplingFraction(TVirtualMC::GetMC()->GetName(), TVirtualMC::GetMC()->GetTitle());
164 LOG(info) << "Using EMCAL sampling fraction " << geom->GetSampling() << " for " << TVirtualMC::GetMC()->GetName() << " / " << TVirtualMC::GetMC()->GetTitle();
165
166 gGeoManager->CheckGeometry();
167}
168
170{
171 int track = fMC->GetStack()->GetCurrentTrackNumber(),
172 directparent = fMC->GetStack()->GetCurrentParentTrackNumber();
173 if (track != mCurrentTrack) {
174 LOG(debug4) << "Doing new track " << track << " current (" << mCurrentTrack << "), direct parent (" << directparent << ")" << std::endl;
175 // new current track - check parentage
176 auto hasSuperParent = mSuperParentsIndices.find(directparent);
177 if (hasSuperParent != mSuperParentsIndices.end()) {
178 // same superparent as direct parent
179 mCurrentParentID = hasSuperParent->second;
180 mSuperParentsIndices[track] = hasSuperParent->second;
181 auto superparent = mSuperParents.find(mCurrentParentID);
182 if (superparent != mSuperParents.end()) {
183 mCurrentSuperparent = &(superparent->second);
184 } else {
185 LOG(error) << "Attention: No superparent object found (parent " << mCurrentParentID << ")";
186 mCurrentSuperparent = nullptr;
187 }
188 LOG(debug4) << "Found superparent " << mCurrentParentID << std::endl;
189 } else {
190 // start of new chain
191 // for new incoming tracks the super parent index is equal to the track ID (for recursion)
192 mSuperParentsIndices[track] = track;
193 mCurrentSuperparent = AddSuperparent(track, fMC->TrackPid(), fMC->Etot());
194 mCurrentParentID = track;
195 }
196 mCurrentTrack = track;
197 }
198 if (v->getVolumeId() == mVolumeIDScintillator) {
199 LOG(debug4) << "We are in sensitive volume " << v->GetName() << ": " << fMC->CurrentVolPath() << std::endl;
200 // TODO Implement handling of parents and primary particle
201 Double_t eloss = fMC->Edep();
202 if (eloss < DBL_EPSILON) {
203 return false; // only process hits which actually deposit some energy in the EMCAL
204 }
205 Geometry* geom = GetGeometry();
206 // Obtain detector ID
207 // This is not equal to the volume ID of the fair volume
208 // EMCAL geometry implementation in VMC works with a copy of the volume and placing it n-times into the mother volume
209 // via translation / rotation, so the copy index is the index of a tower / module / supermodule node within a mother
210 // volume Additional care needs to be taken for the supermodule index: The copy is connected to a certain supermodule
211 // type, which differs for various parts of the detector
212 Int_t copyEta, copyPhi, copyMod, copySmod;
213 fMC->CurrentVolID(copyEta); // Tower in module - x-direction
214 fMC->CurrentVolOffID(1, copyPhi); // Tower in module - y-direction
215 fMC->CurrentVolOffID(3, copyMod); // Module in supermodule
216 auto smvolID = fMC->CurrentVolOffID(
217 4, copySmod); // Supermodule in EMCAL - attention, with respect to a given supermodule type (offsets needed)
218 int offset(0);
219 auto typeFromVolID = mSMVolumeID.find(smvolID);
220 if (typeFromVolID == mSMVolumeID.end()) {
221 LOG(error) << "No supermodule with volume ID " << smvolID << " found";
222 return false;
223 }
224 auto supermoduletype = typeFromVolID->second;
225 switch (supermoduletype) {
226 case EMCAL_STANDARD:
227 break;
228 case EMCAL_THIRD:
229 offset = 10;
230 break;
231 case DCAL_STANDARD:
232 offset = 12;
233 break;
234 case DCAL_EXT:
235 offset = 18;
236 break;
237 default:
238 break;
239 }
240
241 LOG(debug3) << "Supermodule copy " << copySmod << ", module copy " << copyMod << ", y-dir " << copyPhi << ", x-dir "
242 << copyEta << ", supermodule ID " << copySmod + offset - 1;
243 LOG(debug3) << "path " << fMC->CurrentVolPath();
244 LOG(debug3) << "Name of the supermodule type " << fMC->CurrentVolOffName(4) << ", Module name "
245 << fMC->CurrentVolOffName(3);
246
247 // porting from aliroot: circumvention of the index problem. GetAbsCellID cannot be used
248 // Int_t detID = geom->GetAbsCellId(offset + copySmod - 1, copyMod - 1, copyPhi - 1, copyEta - 1);
249 //
250 // Swap A side in Phi and C side in Eta due to wrong indexing.
251 //
252 Int_t smNumber = offset + copySmod - 1, smTypeID = 1;
253 auto [iphi, ieta] = geom->GetCellPhiEtaIndexInSModule(smNumber, copyMod - 1, copyPhi - 1, copyEta - 1);
254 // iphi = std::get<0>(posetaphi);
255 // ieta = std::get<1>(posetaphi);
256 if (smNumber % 2 == 0) {
257 if (supermoduletype == DCAL_STANDARD) {
258 smTypeID = 3; // DCal supermodule. previous design/idea
259 } else {
260 smTypeID = 2;
261 }
262 ieta = ((geom->GetCentersOfCellsEtaDir()).size() * 2 / smTypeID - 1) - ieta; // 47/31-ieta, revert the ordering on A side in order to keep convention.
263 } else {
264 if (supermoduletype == EMCAL_HALF) {
265 smTypeID = 2; // half supermodule. previous design/idea
266 }
267 if (supermoduletype == EMCAL_THIRD) {
268 smTypeID = 3; // one third (installed in 2012) supermodule
269 }
270 if (supermoduletype == DCAL_EXT) {
271 smTypeID = 3; // one third (installed in 2012) supermodule
272 }
273 iphi = ((geom->GetCentersOfCellsPhiDir()).size() / smTypeID - 1) - iphi; // 23/7-iphi, revert the ordering on C side in order to keep convention.
274 }
275
276 // Once we know the indexes, calculate the absolute ID
277 Int_t detID = geom->GetAbsCellIdFromCellIndexes(smNumber, iphi, ieta);
278
279 // In case of new parent track create new track reference
280 auto o2stack = static_cast<o2::data::Stack*>(fMC->GetStack());
281 if (!mCurrentSuperparent->mHasTrackReference) {
282 float x, y, z, px, py, pz, e;
283 fMC->TrackPosition(x, y, z);
284 fMC->TrackMomentum(px, py, pz, e);
285 o2::TrackReference trackref(x, y, z, px, py, pz, fMC->TrackLength(), fMC->TrackTime(), mCurrentParentID, GetDetId());
286 o2stack->addTrackReference(trackref);
287 mCurrentSuperparent->mHasTrackReference = true;
288 }
289
290 Double_t lightyield(eloss);
291 if (fMC->TrackCharge()) {
292 lightyield = CalculateLightYield(eloss, fMC->TrackStep(), fMC->TrackCharge());
293 }
294 lightyield *= geom->GetSampling();
295
296 auto currenthit = FindHit(detID, mCurrentParentID);
297 if (!currenthit) {
298 // Condition for new hit:
299 // - Processing different partent track (parent track must be produced outside EMCAL)
300 // - Inside different cell
301 // - First track of the event
302 Float_t posX, posY, posZ, momX, momY, momZ, energy;
303 fMC->TrackPosition(posX, posY, posZ);
304 fMC->TrackMomentum(momX, momY, momZ, energy);
305 Double_t time = fMC->TrackTime() * 1e9; // time in ns
306 LOG(debug3) << "Adding new hit for parent " << mCurrentParentID << " and cell " << detID << std::endl;
307
309 AddHit(mCurrentParentID, mCurrentPrimaryID, mCurrentSuperparent->mEnergy, detID, math_utils::Point3D<float>(posX, posY, posZ),
310 math_utils::Vector3D<float>(momX, momY, momZ), time, lightyield);
311 o2stack->addHit(GetDetId());
312 } else {
313 LOG(debug3) << "Adding energy to the current hit" << std::endl;
314 currenthit->SetEnergyLoss(currenthit->GetEnergyLoss() + lightyield);
315 o2stack->modifiesHit(GetDetId());
316 }
317 }
318
319 return true;
320}
321
322Hit* Detector::AddHit(Int_t trackID, Int_t primary, Double_t initialEnergy, Int_t detID,
323 const math_utils::Point3D<float>& pos, const math_utils::Vector3D<float>& mom, Double_t time, Double_t eLoss)
324{
325 LOG(debug3) << "Adding hit for track " << trackID << " with position (" << pos.X() << ", "
326 << pos.Y() << ", " << pos.Z() << ") and momentum (" << mom.X() << ", " << mom.Y() << ", " << mom.Z()
327 << ") with energy " << initialEnergy << " loosing " << eLoss;
328 mHits->emplace_back(primary, trackID, detID, initialEnergy, pos, mom, time, eLoss);
329 return &(mHits->back());
330}
331
332Parent* Detector::AddSuperparent(Int_t trackID, Int_t pdg, Double_t energy)
333{
334 LOG(debug3) << "Adding superparent for track " << trackID << " with PID " << pdg << " and energy " << energy;
335 auto entry = mSuperParents.insert({trackID, {pdg, energy, false}});
336 return &(entry.first->second);
337}
338
339Double_t Detector::CalculateLightYield(Double_t energydeposit, Double_t tracklength, Int_t charge) const
340{
341 if (charge == 0) {
342 return energydeposit; // full energy deposit for neutral particles (photons)
343 }
344 // Apply Birk's law (copied from G3BIRK)
345
346 Float_t birkC1Mod = 0;
347 if (mBirkC0 == 1) { // Apply correction for higher charge states
348 if (std::abs(charge) >= 2) {
349 birkC1Mod = mBirkC1 * 7.2 / 12.6;
350 } else {
351 birkC1Mod = mBirkC1;
352 }
353 }
354
355 Float_t dedxcm = 0.;
356 if (tracklength > 0) {
357 dedxcm = 1000. * energydeposit / tracklength;
358 } else {
359 dedxcm = 0;
360 }
361
362 return energydeposit / (1. + birkC1Mod * dedxcm + mBirkC2 * dedxcm * dedxcm);
363}
364
365Hit* Detector::FindHit(int cellID, int parentID)
366{
367 auto result = std::find_if(mHits->begin(), mHits->end(), [cellID, parentID](const Hit& hit) { return hit.GetTrackID() == parentID && hit.GetDetectorID() == cellID; });
368 if (result == mHits->end()) {
369 return nullptr;
370 }
371 return &(*result);
372}
373
375{
376 FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, kTRUE);
377}
378
380{
381 LOG(debug) << "Cleaning EMCAL hits ...";
382 if (!o2::utils::ShmManager::Instance().isOperational()) {
383 mHits->clear();
384 }
385 mSuperParentsIndices.clear();
386 mSuperParents.clear();
387 mCurrentTrack = -1;
388 mCurrentParentID = -1;
389}
390
392{
393 if (!mGeometry) {
394 mGeometry = Geometry::GetInstanceFromRunNumber(223409);
395 }
396 if (!mGeometry) {
397 LOG(error) << "Failure accessing geometry";
398 }
399 return mGeometry;
400}
401
403{
404 using boost::algorithm::contains;
405
406 Geometry* geom = GetGeometry();
407 std::string gn = geom->GetName();
408 std::transform(gn.begin(), gn.end(), gn.begin(), ::toupper);
409
410 Int_t rotMatrixID(-1); // Will be assigned by the simulation engine
411 // TVirtualMC::GetMC()->Matrix(nmat, theta1, phi1, theta2, phi2, theta3, phi3) - see AliModule
412 Matrix(rotMatrixID, 90.0, 0., 90.0, 90.0, 0.0, 0.0);
413
414 // Create the EMCAL Mother Volume (a polygone) within which to place the Detector and named XEN1
415 if (contains(gn, "WSUC")) { // TRD1 for WSUC facility
416 // Nov 25,2010
417 Double_t envelopA[3];
418 envelopA[0] = 30.;
419 envelopA[1] = 30;
420 envelopA[2] = 20;
421
422 CreateEMCALVolume(geom->GetNameOfEMCALEnvelope(), "BOX", ID_SC, envelopA, 3);
423 for (Int_t i = 0; i < 3; i++) {
424 // Position the EMCAL Mother Volume (XEN1) in WSUC.
425 // Look to AliEMCALWsuCosmicRaySetUp.
426 TVirtualMC::GetMC()->Gspos(geom->GetNameOfEMCALEnvelope(), 1, "WSUC", 0.0, 0.0, +265., rotMatrixID, "ONLY");
427 }
428 } else {
429 Double_t envelopA[10];
430 envelopA[0] = geom->GetArm1PhiMin(); // minimum phi angle
431 envelopA[1] = geom->GetArm1PhiMax() - geom->GetArm1PhiMin(); // angular range in phi
432 envelopA[2] = envelopA[1] / geom->GetPhiSuperModule(); // Section of that
433 envelopA[3] = 2; // 2: z coordinates
434 envelopA[4] = -geom->GetEnvelop(2) / 2.; // zmin - includes padding
435 envelopA[5] = geom->GetEnvelop(0); // rmin at z1 - includes padding
436 envelopA[6] = geom->GetEnvelop(1); // rmax at z1 - includes padding
437 envelopA[7] = geom->GetEnvelop(2) / 2.; // zmax includes padding
438
439 envelopA[8] = envelopA[5]; // radii are the same.
440 envelopA[9] = envelopA[6];
441 // radii are the same.
442 CreateEMCALVolume(geom->GetNameOfEMCALEnvelope(), "PGON", ID_AIR, envelopA,
443 10); // Polygone filled with air
444
445 LOG(debug2) << "ConstructGeometry: " << geom->GetNameOfEMCALEnvelope() << " = " << envelopA[5] << ", "
446 << envelopA[6];
447 LOG(debug2) << "ConstructGeometry: XU0 = " << envelopA[5] << ", " << envelopA[6];
448
449 // Position the EMCAL Mother Volume (XEN1) in ALICE (cave)
450 TVirtualMC::GetMC()->Gspos(geom->GetNameOfEMCALEnvelope(), 1, "barrel", 0.0, 0.0, 0.0, rotMatrixID, "ONLY");
451 }
452}
453
455{
456 // TRD1
457 using boost::algorithm::contains;
459 std::string gn = g->GetName();
460 std::transform(gn.begin(), gn.end(), gn.begin(), ::toupper);
461
462 Double_t trd1Angle = g->GetTrd1Angle() * TMath::DegToRad(), tanTrd1 = TMath::Tan(trd1Angle / 2.);
463 // see AliModule::fFIdTmedArr
464 // fIdTmedArr = fIdtmed->GetArray() - 1599 ; // see AliEMCAL::::CreateMaterials()
465 // Int_t kIdAIR=1599, kIdPB = 1600, kIdSC = 1601, kIdSTEEL = 1603;
466 // idAL = 1602;
467 Double_t par[10], xpos = 0., ypos = 0., zpos = 0.;
468
469 std::string mothervolume;
470 if (contains(g->GetName(), "WSUC")) {
471 mothervolume = "WSUC";
472 } else {
473 mothervolume = "barrel";
474 }
475 LOG(debug2) << "Name of mother volume: " << mothervolume;
476 CreateSupermoduleGeometry(mothervolume);
477
478 auto SMTypeList = g->GetEMCSystem();
479 auto tmpType = NOT_EXISTENT;
480 std::string namesmtype;
481 for (auto i : boost::irange(0, g->GetNumberOfSuperModules())) {
482 if (SMTypeList[i] == tmpType) {
483 continue;
484 } else {
485 tmpType = SMTypeList[i];
486 }
487
488 switch (tmpType) {
489 case EMCAL_STANDARD:
490 namesmtype = "SMOD";
491 break;
492 case EMCAL_HALF:
493 namesmtype = "SM10";
494 break;
495 case EMCAL_THIRD:
496 namesmtype = "SM3rd";
497 break;
498 case DCAL_STANDARD:
499 namesmtype = "DCSM";
500 break;
501 case DCAL_EXT:
502 namesmtype = "DCEXT";
503 break;
504 default:
505 LOG(error) << "Unkown SM Type!!";
506 };
507 LOG(debug2) << "Creating EMCAL module for SM " << namesmtype << std::endl;
508 if (namesmtype.length()) {
509 CreateEmcalModuleGeometry(namesmtype, "EMOD");
510 }
511 }
512
513 // Sensitive SC (2x2 tiles)
514 Double_t parSCM0[5] = {0, 0, 0, 0}, *dummy = nullptr, parTRAP[11];
515 if (!contains(gn, "V1")) {
516 Double_t wallThickness = g->GetPhiModuleSize() / g->GetNPHIdiv() - g->GetPhiTileSize();
517 for (Int_t i = 0; i < 3; i++) {
518 parSCM0[i] = mParEMOD[i] - wallThickness;
519 }
520 parSCM0[3] = mParEMOD[3];
521 CreateEMCALVolume("SCM0", "TRD1", ID_AIR, parSCM0, 4);
522 TVirtualMC::GetMC()->Gspos("SCM0", 1, "EMOD", 0., 0., 0., 0, "ONLY");
523 } else {
524 Double_t wTh = g->GetLateralSteelStrip();
525 parSCM0[0] = mParEMOD[0] - wTh + tanTrd1 * g->GetTrd1AlFrontThick();
526 parSCM0[1] = mParEMOD[1] - wTh;
527 parSCM0[2] = mParEMOD[2] - wTh;
528 parSCM0[3] = mParEMOD[3] - g->GetTrd1AlFrontThick() / 2.;
529 CreateEMCALVolume("SCM0", "TRD1", ID_AIR, parSCM0, 4);
530 Double_t zshift = g->GetTrd1AlFrontThick() / 2.;
531 TVirtualMC::GetMC()->Gspos("SCM0", 1, "EMOD", 0., 0., zshift, 0, "ONLY");
532 //
533 CreateAlFrontPlate("EMOD", "ALFP");
534 }
535
536 if (g->GetNPHIdiv() == 2 && g->GetNETAdiv() == 2) {
537 // Division to tile size - 1-oct-04
538 LOG(debug2) << " Divide SCM0 on y-axis " << g->GetNETAdiv();
539 TVirtualMC::GetMC()->Gsdvn("SCMY", "SCM0", g->GetNETAdiv(), 2); // y-axis
540 mSensitive.emplace_back("SCMY");
541
542 // Trapesoid 2x2
543 parTRAP[0] = parSCM0[3]; // dz
544 parTRAP[1] = TMath::ATan2((parSCM0[1] - parSCM0[0]) / 2., 2. * parSCM0[3]) * 180. / TMath::Pi(); // theta
545 parTRAP[2] = 0.; // phi
546
547 // bottom
548 parTRAP[3] = parSCM0[2] / 2.; // H1
549 parTRAP[4] = parSCM0[0] / 2.; // BL1
550 parTRAP[5] = parTRAP[4]; // TL1
551 parTRAP[6] = 0.0; // ALP1
552
553 // top
554 parTRAP[7] = parSCM0[2] / 2.; // H2
555 parTRAP[8] = parSCM0[1] / 2.; // BL2
556 parTRAP[9] = parTRAP[8]; // TL2
557 parTRAP[10] = 0.0; // ALP2
558
559 LOG(debug2) << " ** TRAP ** ";
560 for (Int_t i = 0; i < 11; i++) {
561 LOG(debug3) << " par[" << std::setw(2) << std::setprecision(2) << i << "] " << std::setw(9)
562 << std::setprecision(4) << parTRAP[i];
563 }
564
565 mVolumeIDScintillator = CreateEMCALVolume("SCMX", "TRAP", ID_SC, parTRAP, 11);
566 xpos = +(parSCM0[1] + parSCM0[0]) / 4.;
567 TVirtualMC::GetMC()->Gspos("SCMX", 1, "SCMY", xpos, 0.0, 0.0, 0, "ONLY");
568
569 // Using rotation because SCMX should be the same due to Pb tiles
570 xpos = -xpos;
571 Int_t rotMatrixID(-1);
572 Matrix(rotMatrixID, 90.0, 180., 90.0, 270.0, 0.0, 0.0);
573 TVirtualMC::GetMC()->Gspos("SCMX", 2, "SCMY", xpos, 0.0, 0.0, rotMatrixID, "ONLY");
574
575 // put LED to the SCM0
576 const ShishKebabTrd1Module& mod = g->GetShishKebabTrd1Modules()[0];
577 Double_t tanBetta = mod.GetTanBetta();
578
579 Int_t nr = 0;
580 ypos = 0.0;
581 Double_t xCenterSCMX = (parTRAP[4] + parTRAP[8]) / 2.;
582 if (!contains(gn, "V1")) {
583 par[1] = parSCM0[2] / 2; // y
584 par[2] = g->GetECPbRadThick() / 2.; // z
585 CreateEMCALVolume("PBTI", "BOX", ID_PB, dummy, 0);
586
587 zpos = -mSampleWidth * g->GetNECLayers() / 2. + g->GetECPbRadThick() / 2.;
588 LOG(debug2) << " Pb tiles ";
589
590 for (Int_t iz = 0; iz < g->GetNECLayers(); iz++) {
591 par[0] = (parSCM0[0] + tanBetta * mSampleWidth * iz) / 2.;
592 xpos = par[0] - xCenterSCMX;
593 TVirtualMC::GetMC()->Gsposp("PBTI", ++nr, "SCMX", xpos, ypos, zpos, 0, "ONLY", par, 3);
594 LOG(debug3) << iz + 1 << " xpos " << xpos << " zpos " << zpos << " par[0] " << par[0];
595 zpos += mSampleWidth;
596 }
597
598 LOG(debug2) << " Number of Pb tiles in SCMX " << nr;
599 } else {
600 // Oct 26, 2010
601 // First sheet of paper
602 par[1] = parSCM0[2] / 2.; // y
603 par[2] = g->GetTrd1BondPaperThick() / 2.; // z
604 par[0] = parSCM0[0] / 2.; // x
605 CreateEMCALVolume("PAP1", "BOX", ID_PAPER, par, 3);
606
607 xpos = par[0] - xCenterSCMX;
608 zpos = -parSCM0[3] + g->GetTrd1BondPaperThick() / 2.;
609 TVirtualMC::GetMC()->Gspos("PAP1", 1, "SCMX", xpos, ypos, zpos, 0, "ONLY");
610
611 for (auto iz : boost::irange(0, g->GetNECLayers() - 1)) {
612 nr = iz + 1;
613 Double_t dz = g->GetECScintThick() + g->GetTrd1BondPaperThick() + mSampleWidth * iz;
614
615 // PB + 2 paper sheets
616 par[2] = g->GetECPbRadThick() / 2. + g->GetTrd1BondPaperThick(); // z
617 par[0] = (parSCM0[0] + tanBetta * dz) / 2.;
618 std::string pa(Form("PA%2.2i", nr));
619 CreateEMCALVolume(pa, "BOX", ID_PAPER, par, 3);
620
621 xpos = par[0] - xCenterSCMX;
622 zpos = -parSCM0[3] + dz + par[2];
623 TVirtualMC::GetMC()->Gspos(pa.data(), 1, "SCMX", xpos, ypos, zpos, 0, "ONLY");
624
625 // Pb
626 std::string pb(Form("PB%2.2i", nr));
627 par[2] = g->GetECPbRadThick() / 2.; // z
628 CreateEMCALVolume(pb, "BOX", ID_PB, par, 3);
629 TVirtualMC::GetMC()->Gspos(pb.data(), 1, pa.data(), 0.0, 0.0, 0.0, 0, "ONLY");
630 }
631 }
632 }
633}
634
636{
637 // media number in idtmed are 1599 to 1698.
638 // --- Air ---
639 Float_t aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
640 Float_t zAir[4] = {6., 7., 8., 18.};
641 Float_t wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
642 Float_t dAir = 1.20479E-3;
643 Mixture(0, "Air$", aAir, zAir, dAir, 4, wAir);
644
645 // --- Lead ---
646 Material(1, "Pb$", 207.2, 82, 11.35, 0.56, 0., nullptr, 0);
647
648 // --- The polysterene scintillator (CH) ---
649 Float_t aP[2] = {12.011, 1.00794};
650 Float_t zP[2] = {6.0, 1.0};
651 Float_t wP[2] = {1.0, 1.0};
652 Float_t dP = 1.032;
653
654 Mixture(2, "Polystyrene$", aP, zP, dP, -2, wP);
655
656 // --- Aluminium ---
657 Material(3, "Al$", 26.98, 13., 2.7, 8.9, 999., nullptr, 0);
658 // --- Absorption length is ignored ^
659
660 // 25-aug-04 by PAI - see PMD/AliPMDv0.cxx for STEEL definition
661 Float_t asteel[4] = {55.847, 51.9961, 58.6934, 28.0855};
662 Float_t zsteel[4] = {26., 24., 28., 14.};
663 Float_t wsteel[4] = {.715, .18, .1, .005};
664 Mixture(4, "STAINLESS STEEL$", asteel, zsteel, 7.88, 4, wsteel);
665
666 // Oct 26,2010 : Multipurpose Copy Paper UNV-21200), weiht 75 g/m**2.
667 // *Cellulose C6H10O5
668 // Component C A=12.01 Z=6. W=6./21.
669 // Component H A=1. Z=1. W=10./21.
670 // Component O A=16. Z=8. W=5./21.
671 Float_t apaper[3] = {12.01, 1.0, 16.0};
672 Float_t zpaper[3] = {6.0, 1.0, 8.0};
673 Float_t wpaper[3] = {6. / 21., 10. / 21., 5. / 21.};
674 Mixture(5, "BondPaper$", apaper, zpaper, 0.75, 3, wpaper);
675
676 // DEFINITION OF THE TRACKING MEDIA
677 // Look to the $ALICE_ROOT/data/galice.cuts for particular values
678 // of cuts.
679 // Don't forget to add a new tracking medium with non-default cuts
680
681 // for EMCAL: idtmed[1599->1698] equivalent to fIdtmed[0->100]
682
683 Int_t isxfld = 2;
684 Float_t sxmgmx = 10.0;
686
687 // Air -> idtmed[1599]
688 Medium(ID_AIR, "Air$", 0, 0, isxfld, sxmgmx, 10.0, 1.0, 0.1, 0.1, 10.0, nullptr, 0);
689
690 // The Lead -> idtmed[1600]
691 Medium(ID_PB, "Lead$", 1, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, nullptr, 0);
692
693 // The scintillator of the CPV made of Polystyrene scintillator -> idtmed[1601]
694 float deemax = 0.1; // maximum fractional energy loss in one step (0 < DEEMAX < deemax )
695 Medium(ID_SC, "Scintillator$", 2, 1, isxfld, sxmgmx, 10.0, 0.001, deemax, 0.001, 0.001, nullptr, 0);
696
697 // Various Aluminium parts made of Al -> idtmed[1602]
698 Medium(ID_AL, "Al$", 3, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.001, 0.001, nullptr, 0);
699
700 // 25-aug-04 by PAI : see PMD/AliPMDv0.cxx for STEEL definition -> idtmed[1603]
701 Medium(ID_STEEL, "S steel$", 4, 0, isxfld, sxmgmx, 10.0, 0.01, 0.1, 0.001, 0.001, nullptr, 0);
702
703 // Oct 26,2010; Nov 24,2010 -> idtmed[1604]
704 deemax = 0.01;
705 Medium(ID_PAPER, "Paper$", 5, 0, isxfld, sxmgmx, 10.0, deemax, 0.1, 0.001, 0.001, nullptr, 0);
706
707 // Set constants for Birk's Law implentation
708 mBirkC0 = 1;
709 mBirkC1 = 0.013 / dP;
710 mBirkC2 = 9.6e-6 / (dP * dP);
711
712 std::array<std::string, 6> materialNames = {"Air", "Pb", "Scintillator", "Aluminium", "Steel", "Paper"};
713 for (int i = 0; i < 6; i++) {
714 LOG(debug) << "Created material of type " << materialNames[i] << " with global index " << getMediumID(i);
715 }
716}
717
718void Detector::CreateSupermoduleGeometry(const std::string_view mother)
719{
720 // 18-may-05; mother="XEN1";
721 // child="SMOD" from first to 10th, "SM10" (11th and 12th)
722 // "DCSM" from 13th to 18/22th (TRD1 case), "DCEXT"(18th and 19th) adapted for DCAL, Oct-23-2012
723
724 using boost::algorithm::contains;
726 std::string gn = g->GetName();
727 std::transform(gn.begin(), gn.end(), gn.begin(), ::toupper);
728
729 Double_t par[3], xpos = 0., ypos = 0., zpos = 0., rpos = 0., dphi = 0., phi = 0.0, phiRad = 0.;
730 Double_t parC[3] = {0};
731 std::string smName;
732 Int_t tmpType = -1;
733
734 // ===== define Super Module from air - 14x30 module ==== ;
735 LOG(debug2) << "\n ## Super Module | fSampleWidth " << std::setw(5) << std::setprecision(3) << mSampleWidth << " ## "
736 << gn;
737 par[0] = g->GetShellThickness() / 2.; // radial
738 par[1] = g->GetPhiModuleSize() * g->GetNPhi() / 2.; // phi
739 par[2] = g->GetEtaModuleSize() * g->GetNEta() / 2.; // eta
740
741 Int_t nSMod = g->GetNumberOfSuperModules();
742 Int_t nphism = nSMod / 2; // 20-may-05
743 if (nphism > 0) {
744 dphi = g->GetPhiSuperModule();
745 rpos = (g->GetEnvelop(0) + g->GetEnvelop(1)) / 2.;
746 LOG(debug2) << " rpos " << std::setw(8) << std::setprecision(2) << rpos << " : dphi " << std::setw(6)
747 << std::setprecision(1) << dphi << " degree ";
748 }
749
750 if (contains(gn, "WSUC")) {
751 Int_t nr = 0;
752 par[0] = g->GetPhiModuleSize() * g->GetNPhi() / 2.;
753 par[1] = g->GetShellThickness() / 2.;
754 par[2] = g->GetEtaModuleSize() * g->GetNZ() / 2. + 5;
755
756 CreateEMCALVolume("SMOD", "BOX", ID_AIR, par, 3);
757
758 LOG(debug2) << "SMOD in WSUC : tmed " << getMediumID(ID_AIR) << " | dx " << std::setw(7) << std::setprecision(2)
759 << par[0] << " dy " << std::setw(7) << std::setprecision(2) << par[1] << " dz " << std::setw(7)
760 << std::setprecision(2) << par[2] << " (SMOD, BOX)";
761 mSmodPar0 = par[0];
762 mSmodPar1 = par[1];
763 mSmodPar2 = par[2];
764 nphism = g->GetNumberOfSuperModules();
765 for (Int_t i = 0; i < nphism; i++) {
766 xpos = ypos = zpos = 0.0;
767 TVirtualMC::GetMC()->Gspos("SMOD", 1, mother.data(), xpos, ypos, zpos, 0, "ONLY");
768
769 LOG(debug2) << " fIdRotm " << std::setw(3) << 0 << " phi " << std::setw(7) << std::setprecision(1) << phi << "("
770 << std::setw(5) << std::setprecision(3) << phiRad << ") xpos " << std::setw(7) << std::setprecision(2)
771 << xpos << " ypos " << std::setw(7) << std::setprecision(2) << ypos << " zpos " << std::setw(7)
772 << std::setprecision(2) << zpos;
773
774 nr++;
775 }
776 } else { // ALICE
777 LOG(debug2) << " par[0] " << std::setw(7) << std::setprecision(2) << par[0] << " (old) ";
778 for (Int_t i = 0; i < 3; i++) {
779 par[i] = g->GetSuperModulesPar(i);
780 }
781 mSmodPar0 = par[0];
782 mSmodPar2 = par[2];
783
784 Int_t SMOrder = -1;
785 tmpType = -1;
786 for (auto smodnum : boost::irange(0, nSMod)) {
787 memcpy(parC, par, sizeof(double) * 3);
788 if (g->GetSMType(smodnum) == tmpType) {
789 SMOrder++;
790 } else {
791 tmpType = g->GetSMType(smodnum);
792 SMOrder = 1;
793 }
794
795 phiRad = g->GetPhiCenterOfSMSec(smodnum); // NEED phi= 90, 110, 130, 150, 170, 190(not center)...
796 phi = phiRad * 180. / TMath::Pi();
797 Double_t phiy = 90. + phi;
798 Double_t phiz = 0.;
799
800 xpos = rpos * TMath::Cos(phiRad);
801 ypos = rpos * TMath::Sin(phiRad);
802 zpos = mSmodPar2; // 21-sep-04
803 switch (tmpType) {
804 case EMCAL_STANDARD: {
805 smName = "SMOD";
806 break;
807 }
808 case EMCAL_HALF: {
809 smName = "SM10";
810 parC[1] /= 2.;
811 xpos += (par[1] / 2. * TMath::Sin(phiRad));
812 ypos -= (par[1] / 2. * TMath::Cos(phiRad));
813 break;
814 }
815 case EMCAL_THIRD: {
816 smName = "SM3rd";
817 parC[1] /= 3.;
818 xpos += (2. * par[1] / 3. * TMath::Sin(phiRad));
819 ypos -= (2. * par[1] / 3. * TMath::Cos(phiRad));
820 break;
821 }
822 case DCAL_STANDARD: {
823 smName = "DCSM";
824 parC[2] *= 2. / 3.;
825 // Extend DCAL SM by 7 cm in inner direction in order to leave space for tilted towers
826 parC[2] += mDCALInnerGap / 2.; // half gap as parameter uses half size (origin in centre of the SM)
827 zpos = mSmodPar2 + (g->GetDCALInnerEdge() - mDCALInnerGap) / 2.; // 21-sep-04
828 break;
829 }
830 case DCAL_EXT: {
831 smName = "DCEXT";
832 parC[1] /= 3.;
833 xpos += (2. * par[1] / 3. * TMath::Sin(phiRad));
834 ypos -= (2. * par[1] / 3. * TMath::Cos(phiRad));
835 break;
836 }
837 default:
838 LOG(error) << "Unkown SM Type!!";
839 break;
840 };
841
842 if (SMOrder == 1) { // first time, create the SM
843 CreateEMCALVolume(smName, "BOX", ID_AIR, parC, 3);
844 mSMVolNames[smName] = EMCALSMType(tmpType);
845
846 LOG(debug2) << R"( Super module with name \")" << smName << R"(\" was created in \"box\" with: par[0] = )"
847 << parC[0] << ", par[1] = " << parC[1] << ", par[2] = " << parC[2];
848 }
849
850 if (smodnum % 2 == 1) {
851 phiy += 180.;
852 if (phiy >= 360.) {
853 phiy -= 360.;
854 }
855 phiz = 180.;
856 zpos *= -1.;
857 }
858
859 Int_t rotMatrixID(-1);
860 Matrix(rotMatrixID, 90.0, phi, 90.0, phiy, phiz, 0.0);
861 TVirtualMC::GetMC()->Gspos(smName.data(), SMOrder, mother.data(), xpos, ypos + 30., zpos, rotMatrixID, "ONLY");
862
863 LOG(debug3) << smName << " : " << std::setw(2) << SMOrder << ", fIdRotm " << std::setw(3) << rotMatrixID
864 << " phi " << std::setw(6) << std::setprecision(1) << phi << "(" << std::setw(5)
865 << std::setprecision(3) << phiRad << ") xpos " << std::setw(7) << std::setprecision(2) << xpos
866 << " ypos " << std::setw(7) << std::setprecision(2) << ypos << " zpos " << std::setw(7)
867 << std::setprecision(2) << zpos << " : i " << smodnum;
868 }
869 }
870
871 LOG(debug2) << " Number of Super Modules " << nSMod;
872
873 // Steel plate
874 if (g->GetSteelFrontThickness() > 0.0) { // 28-mar-05
875 par[0] = g->GetSteelFrontThickness() / 2.;
876 CreateEMCALVolume("STPL", "BOX", ID_STEEL, par, 3);
877
878 LOG(debug1) << "tmed " << getMediumID(ID_STEEL) << " | dx " << std::setw(7) << std::setprecision(2) << par[0]
879 << " dy " << std::setw(7) << std::setprecision(2) << par[1] << " dz " << std::setw(7)
880 << std::setprecision(2) << par[2] << " (STPL) ";
881
882 xpos = -(g->GetShellThickness() - g->GetSteelFrontThickness()) / 2.;
883 TVirtualMC::GetMC()->Gspos("STPL", 1, "SMOD", xpos, 0.0, 0.0, 0, "ONLY");
884 }
885}
886
887void Detector::CreateEmcalModuleGeometry(const std::string_view mother, const std::string_view child)
888{
889 // 17-may-05; mother="SMOD"; child="EMOD"
890 // Oct 26,2010
891 using boost::algorithm::contains;
893 std::string gn = g->GetName();
894 std::transform(gn.begin(), gn.end(), gn.begin(), ::toupper);
895
896 // Module definition
897 Double_t xpos = 0., ypos = 0., zpos = 0.;
898 // Double_t trd1Angle = g->GetTrd1Angle()*TMath::DegToRad();tanTrd1 = TMath::Tan(trd1Angle/2.);
899
900 if (mother == "SMOD") {
901 mParEMOD[0] = g->GetEtaModuleSize() / 2.; // dx1
902 mParEMOD[1] = g->Get2Trd1Dx2() / 2.; // dx2
903 mParEMOD[2] = g->GetPhiModuleSize() / 2.; // dy
904 mParEMOD[3] = g->GetLongModuleSize() / 2.; // dz
905 CreateEMCALVolume(child, "TRD1", ID_STEEL, mParEMOD, 4);
906 }
907
908 Int_t nr = 0;
909 Int_t rotMatrixID(-1);
910 // X->Z(0, 0); Y->Y(90, 90); Z->X(90, 0)
911
912 for (auto iz : boost::irange(0, g->GetNZ())) {
913 const ShishKebabTrd1Module& mod = g->GetShishKebabTrd1Modules()[iz];
914 Double_t angle(mod.GetThetaInDegree()), phiOK(0.);
915
916 if (!contains(gn, "WSUC")) { // ALICE
917 Matrix(rotMatrixID, 90. - angle, 180., 90.0, 90.0, angle, 0.);
918 phiOK = mod.GetCenterOfModule().Phi() * 180. / TMath::Pi();
919 LOG(debug4) << std::setw(2) << iz + 1 << " | angle | " << std::setw(6) << std::setprecision(3) << angle << " - "
920 << std::setw(6) << std::setprecision(3) << phiOK << " = " << std::setw(6) << std::setprecision(3)
921 << angle - phiOK << "(eta " << std::setw(5) << std::setprecision(3) << mod.GetEtaOfCenterOfModule()
922 << ")";
923 xpos = mod.GetPosXfromR() + g->GetSteelFrontThickness() - mSmodPar0;
924 zpos = mod.GetPosZ() - mSmodPar2;
925
926 Int_t iyMax = g->GetNPhi();
927 if (mother == "SM10") {
928 iyMax /= 2;
929 } else if (mother == "SM3rd") {
930 iyMax /= 3;
931 } else if (mother == "DCEXT") {
932 iyMax /= 3;
933 } else if (mother == "DCSM") {
934 if (iz < 8) {
935 continue;
936 }
937 // Correct pack supermodule center position after increasing size for extruding fix
938 // z-pos. := abs. module z - abs origin of the mother volume
939 zpos = mod.GetPosZ() - mSmodPar2 - (g->GetDCALInnerEdge() - mDCALInnerGap) / 2.;
940 } else if (mother.compare("SMOD")) {
941 LOG(error) << "Unknown super module Type!!";
942 }
943
944 for (auto iy : boost::irange(0, iyMax)) { // flat in phi
945 ypos = g->GetPhiModuleSize() * (2 * iy + 1 - iyMax) / 2.;
946 TVirtualMC::GetMC()->Gspos(child.data(), ++nr, mother.data(), xpos, ypos, zpos, rotMatrixID, "ONLY");
947
948 // printf(" %2i xpos %7.2f ypos %7.2f zpos %7.2f fIdRotm %i\n", nr, xpos, ypos, zpos, fIdRotm);
949 LOG(debug3) << std::setw(3) << std::setprecision(3) << nr << "(" << std::setw(2) << std::setprecision(2)
950 << iy + 1 << "," << std::setw(2) << std::setprecision(2) << iz + 1 << ")";
951 }
952 // PH printf("\n");
953 } else { // WSUC
954 if (iz == 0) {
955 Matrix(rotMatrixID, 0., 0., 90., 0., 90., 90.); // (x')z; y'(x); z'(y)
956 } else {
957 Matrix(rotMatrixID, 90 - angle, 270., 90.0, 0.0, angle, 90.);
958 }
959
960 phiOK = mod.GetCenterOfModule().Phi() * 180. / TMath::Pi();
961
962 LOG(debug4) << std::setw(2) << iz + 1 << " | angle -phiOK | " << std::setw(6) << std::setprecision(3) << angle
963 << " - " << std::setw(6) << std::setprecision(3) << phiOK << " = " << std::setw(6)
964 << std::setprecision(3) << angle - phiOK << "(eta " << std::setw(5) << std::setprecision(3)
965 << mod.GetEtaOfCenterOfModule() << ")";
966
967 zpos = mod.GetPosZ() - mSmodPar2;
968 ypos = mod.GetPosXfromR() - mSmodPar1;
969
970 // printf(" zpos %7.2f ypos %7.2f fIdRotm %i\n xpos ", zpos, xpos, fIdRotm);
971
972 for (auto ix : boost::irange(0, g->GetNPhi())) { // flat in phi
973 xpos = g->GetPhiModuleSize() * (2 * ix + 1 - g->GetNPhi()) / 2.;
974 TVirtualMC::GetMC()->Gspos(child.data(), ++nr, mother.data(), xpos, ypos, zpos, rotMatrixID, "ONLY");
975 // printf(" %7.2f ", xpos);
976 }
977 // printf("");
978 }
979 }
980
981 LOG(debug2) << " Number of modules in Super Module(" << mother << ") " << nr;
982}
983
984void Detector::CreateAlFrontPlate(const std::string_view mother, const std::string_view child)
985{
986 // Oct 26,2010 : Al front plate : ALFP
988
989 Double_t trd1Angle = g->GetTrd1Angle() * TMath::DegToRad(), tanTrd1 = TMath::Tan(trd1Angle / 2.);
990 Double_t parALFP[5], zposALFP = 0.;
991
992 parALFP[0] = g->GetEtaModuleSize() / 2. - g->GetLateralSteelStrip(); // dx1
993 parALFP[1] = parALFP[0] + tanTrd1 * g->GetTrd1AlFrontThick(); // dx2
994 parALFP[2] = g->GetPhiModuleSize() / 2. - g->GetLateralSteelStrip(); // dy
995 parALFP[3] = g->GetTrd1AlFrontThick() / 2.; // dz
996
997 CreateEMCALVolume(child.data(), "TRD1", ID_AL, parALFP, 4);
998
999 zposALFP = -mParEMOD[3] + g->GetTrd1AlFrontThick() / 2.;
1000 TVirtualMC::GetMC()->Gspos(child.data(), 1, mother.data(), 0.0, 0.0, zposALFP, 0, "ONLY");
1001}
1002
1003int Detector::CreateEMCALVolume(const std::string_view name, const std::string_view shape, MediumType_t mediumID, Double_t* shapeParams, Int_t nparams)
1004{
1005 int volID = TVirtualMC::GetMC()->Gsvolu(name.data(), shape.data(), getMediumID(mediumID), shapeParams, nparams);
1006 mSensitive.emplace_back(name.data());
1007 return volID;
1008}
1009
1011{
1012 mCurrentPrimaryID = fMC->GetStack()->GetCurrentTrackNumber();
1013 LOG(debug) << "Starting primary " << mCurrentPrimaryID << " with energy " << fMC->GetStack()->GetCurrentTrack()->Energy();
1014}
1015
1017{
1018 LOG(debug) << "Finishing primary " << mCurrentPrimaryID << std::endl;
1019 // Resetting primary and parent ID
1020 mCurrentPrimaryID = -1;
1021}
Definition of the Stack class.
ClassImp(Detector)
std::ostringstream debug
int16_t charge
Definition RawEventData.h:5
int16_t time
Definition RawEventData.h:4
int32_t i
Timeframe settings Average distance in cm of events merged into Randomize distance around average distance of merged events Simulate correct bunch interactions instead of placing only the average number of events A value[n] sets TFlen for[n] collisions in Number of bunches per trainsort Number of bunch trains Instantaneous interaction rate Do not simulate border Total number of collisions to be placed in the interior of all time Do not select random but walk over array of events in stride steps h Event generator settings h configStandalone Use CPU for GPU Force usage of the specified GPU device no CPU fallback Continue processing after an error First event to Number of events to Number of iterations to Number of iterations to Number of initial iterations excluded from const char e
char error[CURL_ERROR_SIZE]
uint16_t pos
Definition RawData.h:3
Int_t GetDetId()
TVirtualMC * fMC
flag for initialisation
Definition FairModule.h:160
void RegisterAny(const char *name, T *&obj, Bool_t toFile)
static FairRootManager * Instance()
int registerSensitiveVolumeAndGetVolID(std::string const &name)
Definition Detector.cxx:190
void Matrix(Int_t &nmat, Double_t theta1, Double_t phi1, Double_t theta2, Double_t phi2, Double_t theta3, Double_t phi3) const
Definition Detector.cxx:104
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
int getMediumID(int imed) const
Definition Detector.h:136
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
Detector simulation class for the EMCAL detector.
Definition Detector.h:52
Hit * AddHit(Int_t trackID, Int_t primary, Double_t initialEnergy, Int_t detID, const math_utils::Point3D< float > &pos, const math_utils::Vector3D< float > &mom, Double_t time, Double_t energyloss)
Add EMCAL hit.
Definition Detector.cxx:322
void CreateEmcalModuleGeometry(const std::string_view mother="SMOD", const std::string_view child="EMOD")
Generate module geometry (2x2 towers)
Definition Detector.cxx:887
Double_t CalculateLightYield(Double_t energydeposit, Double_t tracklength, Int_t charge) const
Calculate the amount of light seen by the APD for a given track segment (charged particles only) acco...
Definition Detector.cxx:339
Parent * AddSuperparent(Int_t trackID, Int_t pdg, Double_t energy)
Definition Detector.cxx:332
Hit * FindHit(Int_t cellID, Int_t parentID)
Try to find hit with same cell and parent track ID.
void CreateSupermoduleGeometry(const std::string_view mother="XEN1")
Generate super module geometry.
Definition Detector.cxx:718
~Detector() override
Destructor.
Definition Detector.cxx:111
void InitializeO2Detector() override
Initializing detector.
Definition Detector.cxx:116
int CreateEMCALVolume(const std::string_view name, const std::string_view shape, MediumType_t mediumID, Double_t *shapeParams, Int_t nparams)
Create new EMCAL volume and add it to the list of sensitive volumes.
Geometry * GetGeometry()
Get the EMCAL geometry desciption.
Definition Detector.cxx:391
Detector()=default
Default constructor.
void CreateEmcalEnvelope()
Generate EMCAL envelop (mother volume of all supermodules)
Definition Detector.cxx:402
void Register() override
register container with hits
Definition Detector.cxx:374
void FinishPrimary() override
Finish current primary.
void ConstructGeometry() override
Definition Detector.cxx:142
void CreateMaterials()
Creating detector materials for the EMCAL detector and space frame.
Definition Detector.cxx:635
Bool_t ProcessHits(FairVolume *v=nullptr) final
Processing hit creation in the EMCAL scintillator volume.
Definition Detector.cxx:169
void EndOfEvent() final
Steps to be carried out at the end of the event.
Definition Detector.cxx:140
void BeginPrimary() override
Begin primaray.
void Reset() final
Clean point collection.
Definition Detector.cxx:379
void CreateShiskebabGeometry()
Generate tower geometry.
Definition Detector.cxx:454
void CreateAlFrontPlate(const std::string_view mother="EMOD", const std::string_view child="ALFP")
Generate aluminium plates geometry.
Definition Detector.cxx:984
EMCAL geometry definition.
Definition Geometry.h:42
static Geometry * GetInstanceFromRunNumber(Int_t runNumber, const std::string_view="", const std::string_view mcname="TGeant3", const std::string_view mctitle="")
Instanciate geometry depending on the run number. Mostly used in analysis and MC anchors.
Definition Geometry.cxx:182
std::tuple< int, int > GetCellPhiEtaIndexInSModule(int supermoduleID, int moduleID, int phiInModule, int etaInModule) const
Get eta-phi indexes of cell in SM.
Float_t GetSampling() const
Definition Geometry.h:208
Float_t GetArm1PhiMin() const
Definition Geometry.h:178
static Bool_t IsInitialized()
Definition Geometry.h:115
const Char_t * GetNameOfEMCALEnvelope() const
Definition Geometry.h:177
std::vector< Double_t > GetCentersOfCellsPhiDir() const
Definition Geometry.h:550
Float_t GetPhiSuperModule() const
Definition Geometry.h:218
const std::string & GetName() const
Definition Geometry.h:111
Float_t GetECScintThick() const
Definition Geometry.h:207
Float_t GetTrd1BondPaperThick() const
Definition Geometry.h:227
std::vector< Double_t > GetCentersOfCellsEtaDir() const
Definition Geometry.h:542
Int_t GetAbsCellIdFromCellIndexes(Int_t nSupMod, Int_t iphi, Int_t ieta) const
Transition from super module number (nSupMod) and cell indexes (ieta,iphi) to cell absolute ID number...
Definition Geometry.cxx:748
void DefineSamplingFraction(const std::string_view mcname="", const std::string_view mctitle="")
Set the value of the Sampling used to calibrate the MC hits energy (check)
Definition Geometry.cxx:249
Float_t GetEnvelop(Int_t index) const
Definition Geometry.h:183
Float_t GetECPbRadThick() const
Definition Geometry.h:206
Float_t GetArm1PhiMax() const
Definition Geometry.h:179
EMCAL simulation hit information.
Definition Hit.h:28
Main class for TRD1 geometry of Shish-Kebab case.
const TVector2 & GetCenterOfModule() const
Space Frame implementation.
Definition SpaceFrame.h:28
void CreateGeometry()
Assembles the Geometries and places them into the Alice master volume.
static ShmManager & Instance()
Definition ShmManager.h:62
GLboolean GLboolean g
Definition glcorearb.h:1233
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint64EXT * result
Definition glcorearb.h:5662
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
GLuint const GLchar * name
Definition glcorearb.h:781
GLint y
Definition glcorearb.h:270
GLintptr offset
Definition glcorearb.h:660
GLfloat angle
Definition glcorearb.h:4071
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
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.
Information about superparent (particle entering EMCAL)
Definition Detector.h:38
double mEnergy
Total energy.
Definition Detector.h:40
bool mHasTrackReference
Flag indicating whether parent has a track reference.
Definition Detector.h:41
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"