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 "FairGeoNode.h"
24#include "FairRootManager.h"
25#include "FairVolume.h"
26
27#include "EMCALBase/Geometry.h"
28#include "EMCALBase/Hit.h"
32
33#include "DetectorsBase/Stack.h"
34
35#include <boost/algorithm/string/predicate.hpp>
36#include <boost/range/irange.hpp>
37
38using namespace o2::emcal;
39
41
43 : o2::base::DetImpl<Detector>("EMC", active),
44 mBirkC0(0),
45 mBirkC1(0.),
46 mBirkC2(0.),
47 mSensitive(),
48 mSMVolumeID(),
49 mSMVolNames(),
50 mVolumeIDScintillator(-1),
51 mHits(o2::utils::createSimVector<Hit>()),
52 mGeometry(nullptr),
53 mSuperParentsIndices(),
54 mSuperParents(),
55 mCurrentSuperparent(nullptr),
56 mCurrentTrack(-1),
57 mCurrentPrimaryID(-1),
58 mCurrentParentID(-1),
59 mSampleWidth(0.),
60 mSmodPar0(0.),
61 mSmodPar1(0.),
62 mSmodPar2(0.),
63 mInnerEdge(0.),
64 mDCALInnerGap(7)
65{
66 using boost::algorithm::contains;
67 memset(mParEMOD, 0, sizeof(Double_t) * 5);
68
69 Geometry* geo = GetGeometry();
70 if (!geo) {
71 LOG(fatal) << "Geometry is nullptr";
72 }
73 std::string gn = geo->GetName();
74 std::transform(gn.begin(), gn.end(), gn.begin(), ::toupper);
75
76 mSampleWidth = Double_t(geo->GetECPbRadThick() + geo->GetECScintThick());
77
78 if (contains(gn, "V1")) {
79 mSampleWidth += 2. * geo->GetTrd1BondPaperThick();
80 }
81}
82
84 : o2::base::DetImpl<Detector>(rhs),
85 mBirkC0(rhs.mBirkC0),
86 mBirkC1(rhs.mBirkC1),
87 mBirkC2(rhs.mBirkC2),
88 mSensitive(),
89 mSMVolumeID(),
90 mSMVolNames(),
91 mVolumeIDScintillator(-1),
92 mHits(o2::utils::createSimVector<Hit>()),
93 mGeometry(rhs.mGeometry),
94 mSuperParentsIndices(),
95 mSuperParents(),
96 mCurrentSuperparent(nullptr),
97 mCurrentTrack(-1),
98 mCurrentPrimaryID(-1),
99 mCurrentParentID(-1),
100 mSampleWidth(rhs.mSampleWidth),
101 mSmodPar0(rhs.mSmodPar0),
102 mSmodPar1(rhs.mSmodPar1),
103 mSmodPar2(rhs.mSmodPar2),
104 mInnerEdge(rhs.mInnerEdge),
105 mDCALInnerGap(rhs.mDCALInnerGap)
106{
107 for (int i = 0; i < 5; ++i) {
108 mParEMOD[i] = rhs.mParEMOD[i];
109 }
110}
111
116
118{
119 // All EMCAL volumes must be declared as sensitive, otherwise
120 // the decay chains are broken by volumes not processed in ProceeHits
121 for (const auto& child : mSensitive) {
122 LOG(debug1) << "Adding sensitive volume " << child;
123 auto svolID = registerSensitiveVolumeAndGetVolID(child);
124 if (child == "SCMX") {
125 LOG(debug1) << "Adding SCMX volume as sensitive volume with ID " << svolID;
126 mVolumeIDScintillator = svolID;
127 }
128 auto smtype = mSMVolNames.find(child);
129 if (smtype != mSMVolNames.end()) {
130 std::cout << "Adding supermodule type " << smtype->second << " for SM " << smtype->first << " with volume ID " << svolID << std::endl;
131 mSMVolumeID[svolID] = smtype->second;
132 }
133 }
134
135 LOG(debug1) << "Supermodule volume map: ";
136 for (auto [volID, volType] : mSMVolumeID) {
137 LOG(debug1) << "Volume " << volID << ", type " << int(volType);
138 }
139}
140
142
144{
145 using boost::algorithm::contains;
146 LOG(debug) << "Creating EMCAL geometry";
147
148 Geometry* geom = GetGeometry();
149 if (!(geom->IsInitialized())) {
150 LOG(error) << "ConstructGeometry: EMCAL Geometry class has not been set up.";
151 }
152
154
155 SpaceFrame emcalframe;
156 emcalframe.CreateGeometry();
157
158 // CreateEmcalEnvelope();
159
160 // COMPACT, TRD1
161 LOG(debug2) << "Shish-Kebab geometry : " << GetTitle();
163
164 geom->DefineSamplingFraction(TVirtualMC::GetMC()->GetName(), TVirtualMC::GetMC()->GetTitle());
165 LOG(info) << "Using EMCAL sampling fraction " << geom->GetSampling() << " for " << TVirtualMC::GetMC()->GetName() << " / " << TVirtualMC::GetMC()->GetTitle();
166
167 gGeoManager->CheckGeometry();
168}
169
170Bool_t Detector::ProcessHits(FairVolume* v)
171{
172 int track = fMC->GetStack()->GetCurrentTrackNumber(),
173 directparent = fMC->GetStack()->GetCurrentParentTrackNumber();
174 if (track != mCurrentTrack) {
175 LOG(debug4) << "Doing new track " << track << " current (" << mCurrentTrack << "), direct parent (" << directparent << ")" << std::endl;
176 // new current track - check parentage
177 auto hasSuperParent = mSuperParentsIndices.find(directparent);
178 if (hasSuperParent != mSuperParentsIndices.end()) {
179 // same superparent as direct parent
180 mCurrentParentID = hasSuperParent->second;
181 mSuperParentsIndices[track] = hasSuperParent->second;
182 auto superparent = mSuperParents.find(mCurrentParentID);
183 if (superparent != mSuperParents.end()) {
184 mCurrentSuperparent = &(superparent->second);
185 } else {
186 LOG(error) << "Attention: No superparent object found (parent " << mCurrentParentID << ")";
187 mCurrentSuperparent = nullptr;
188 }
189 LOG(debug4) << "Found superparent " << mCurrentParentID << std::endl;
190 } else {
191 // start of new chain
192 // for new incoming tracks the super parent index is equal to the track ID (for recursion)
193 mSuperParentsIndices[track] = track;
194 mCurrentSuperparent = AddSuperparent(track, fMC->TrackPid(), fMC->Etot());
195 mCurrentParentID = track;
196 }
197 mCurrentTrack = track;
198 }
199 if (v->getVolumeId() == mVolumeIDScintillator) {
200 LOG(debug4) << "We are in sensitive volume " << v->GetName() << ": " << fMC->CurrentVolPath() << std::endl;
201 // TODO Implement handling of parents and primary particle
202 Double_t eloss = fMC->Edep();
203 if (eloss < DBL_EPSILON) {
204 return false; // only process hits which actually deposit some energy in the EMCAL
205 }
206 Geometry* geom = GetGeometry();
207 // Obtain detector ID
208 // This is not equal to the volume ID of the fair volume
209 // EMCAL geometry implementation in VMC works with a copy of the volume and placing it n-times into the mother volume
210 // via translation / rotation, so the copy index is the index of a tower / module / supermodule node within a mother
211 // volume Additional care needs to be taken for the supermodule index: The copy is connected to a certain supermodule
212 // type, which differs for various parts of the detector
213 Int_t copyEta, copyPhi, copyMod, copySmod;
214 fMC->CurrentVolID(copyEta); // Tower in module - x-direction
215 fMC->CurrentVolOffID(1, copyPhi); // Tower in module - y-direction
216 fMC->CurrentVolOffID(3, copyMod); // Module in supermodule
217 auto smvolID = fMC->CurrentVolOffID(
218 4, copySmod); // Supermodule in EMCAL - attention, with respect to a given supermodule type (offsets needed)
219 int offset(0);
220 auto typeFromVolID = mSMVolumeID.find(smvolID);
221 if (typeFromVolID == mSMVolumeID.end()) {
222 LOG(error) << "No supermodule with volume ID " << smvolID << " found";
223 return false;
224 }
225 auto supermoduletype = typeFromVolID->second;
226 switch (supermoduletype) {
227 case EMCAL_STANDARD:
228 break;
229 case EMCAL_THIRD:
230 offset = 10;
231 break;
232 case DCAL_STANDARD:
233 offset = 12;
234 break;
235 case DCAL_EXT:
236 offset = 18;
237 break;
238 default:
239 break;
240 }
241
242 LOG(debug3) << "Supermodule copy " << copySmod << ", module copy " << copyMod << ", y-dir " << copyPhi << ", x-dir "
243 << copyEta << ", supermodule ID " << copySmod + offset - 1;
244 LOG(debug3) << "path " << fMC->CurrentVolPath();
245 LOG(debug3) << "Name of the supermodule type " << fMC->CurrentVolOffName(4) << ", Module name "
246 << fMC->CurrentVolOffName(3);
247
248 // porting from aliroot: circumvention of the index problem. GetAbsCellID cannot be used
249 // Int_t detID = geom->GetAbsCellId(offset + copySmod - 1, copyMod - 1, copyPhi - 1, copyEta - 1);
250 //
251 // Swap A side in Phi and C side in Eta due to wrong indexing.
252 //
253 Int_t smNumber = offset + copySmod - 1, smTypeID = 1;
254 auto [iphi, ieta] = geom->GetCellPhiEtaIndexInSModule(smNumber, copyMod - 1, copyPhi - 1, copyEta - 1);
255 // iphi = std::get<0>(posetaphi);
256 // ieta = std::get<1>(posetaphi);
257 if (smNumber % 2 == 0) {
258 if (supermoduletype == DCAL_STANDARD) {
259 smTypeID = 3; // DCal supermodule. previous design/idea
260 } else {
261 smTypeID = 2;
262 }
263 ieta = ((geom->GetCentersOfCellsEtaDir()).size() * 2 / smTypeID - 1) - ieta; // 47/31-ieta, revert the ordering on A side in order to keep convention.
264 } else {
265 if (supermoduletype == EMCAL_HALF) {
266 smTypeID = 2; // half supermodule. previous design/idea
267 }
268 if (supermoduletype == EMCAL_THIRD) {
269 smTypeID = 3; // one third (installed in 2012) supermodule
270 }
271 if (supermoduletype == DCAL_EXT) {
272 smTypeID = 3; // one third (installed in 2012) supermodule
273 }
274 iphi = ((geom->GetCentersOfCellsPhiDir()).size() / smTypeID - 1) - iphi; // 23/7-iphi, revert the ordering on C side in order to keep convention.
275 }
276
277 // Once we know the indexes, calculate the absolute ID
278 Int_t detID = geom->GetAbsCellIdFromCellIndexes(smNumber, iphi, ieta);
279
280 // In case of new parent track create new track reference
281 auto o2stack = static_cast<o2::data::Stack*>(fMC->GetStack());
282 if (!mCurrentSuperparent->mHasTrackReference) {
283 float x, y, z, px, py, pz, e;
284 fMC->TrackPosition(x, y, z);
285 fMC->TrackMomentum(px, py, pz, e);
286 o2::TrackReference trackref(x, y, z, px, py, pz, fMC->TrackLength(), fMC->TrackTime(), mCurrentParentID, GetDetId());
287 o2stack->addTrackReference(trackref);
288 mCurrentSuperparent->mHasTrackReference = true;
289 }
290
291 Double_t lightyield(eloss);
292 if (fMC->TrackCharge()) {
293 lightyield = CalculateLightYield(eloss, fMC->TrackStep(), fMC->TrackCharge());
294 }
295 lightyield *= geom->GetSampling();
296
297 auto currenthit = FindHit(detID, mCurrentParentID);
298 if (!currenthit) {
299 // Condition for new hit:
300 // - Processing different partent track (parent track must be produced outside EMCAL)
301 // - Inside different cell
302 // - First track of the event
303 Float_t posX, posY, posZ, momX, momY, momZ, energy;
304 fMC->TrackPosition(posX, posY, posZ);
305 fMC->TrackMomentum(momX, momY, momZ, energy);
306 Double_t time = fMC->TrackTime() * 1e9; // time in ns
307 LOG(debug3) << "Adding new hit for parent " << mCurrentParentID << " and cell " << detID << std::endl;
308
310 AddHit(mCurrentParentID, mCurrentPrimaryID, mCurrentSuperparent->mEnergy, detID, math_utils::Point3D<float>(posX, posY, posZ),
311 math_utils::Vector3D<float>(momX, momY, momZ), time, lightyield);
312 o2stack->addHit(GetDetId());
313 } else {
314 LOG(debug3) << "Adding energy to the current hit" << std::endl;
315 currenthit->SetEnergyLoss(currenthit->GetEnergyLoss() + lightyield);
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)
int16_t charge
Definition RawEventData.h:5
int16_t time
Definition RawEventData.h:4
int32_t i
uint16_t pos
Definition RawData.h:3
std::ostringstream debug
int registerSensitiveVolumeAndGetVolID(std::string const &name)
Definition Detector.cxx:190
void Matrix(Int_t &nmat, Float_t theta1, Float_t phi1, Float_t theta2, Float_t phi2, Float_t theta3, Float_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:135
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
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:112
void InitializeO2Detector() override
Initializing detector.
Definition Detector.cxx:117
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:143
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:170
void EndOfEvent() final
Steps to be carried out at the end of the event.
Definition Detector.cxx:141
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:40
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:219
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:206
Float_t GetArm1PhiMin() const
Definition Geometry.h:176
static Bool_t IsInitialized()
Definition Geometry.h:113
const Char_t * GetNameOfEMCALEnvelope() const
Definition Geometry.h:175
std::vector< Double_t > GetCentersOfCellsPhiDir() const
Definition Geometry.h:534
Float_t GetPhiSuperModule() const
Definition Geometry.h:216
const std::string & GetName() const
Definition Geometry.h:109
Float_t GetECScintThick() const
Definition Geometry.h:205
Float_t GetTrd1BondPaperThick() const
Definition Geometry.h:225
std::vector< Double_t > GetCentersOfCellsEtaDir() const
Definition Geometry.h:526
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:791
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:285
Float_t GetEnvelop(Int_t index) const
Definition Geometry.h:181
Float_t GetECPbRadThick() const
Definition Geometry.h:204
Float_t GetArm1PhiMax() const
Definition Geometry.h:177
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:61
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint64EXT * result
Definition glcorearb.h:5662
GLuint entry
Definition glcorearb.h:5735
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
GLboolean * data
Definition glcorearb.h:298
GLintptr offset
Definition glcorearb.h:660
GLboolean GLboolean g
Definition glcorearb.h:1233
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"