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#include <map>
15
16#include "TGeoManager.h"
17#include "TGeoVolume.h"
18#include "TVirtualMC.h"
19#include "TGeoPhysicalNode.h"
20
21#include "FairGeoNode.h"
22#include "FairRootManager.h"
23#include "FairVolume.h"
24
25#include "CPVBase/Geometry.h"
26#include "DataFormatsCPV/Hit.h"
30
32#include "DetectorsBase/Stack.h"
33
34#include <boost/algorithm/string/predicate.hpp>
35#include <boost/range/irange.hpp>
36
37using namespace o2::cpv;
38
40
42 : o2::base::DetImpl<Detector>("CPV", active),
43 mHits(o2::utils::createSimVector<o2::cpv::Hit>())
44{
45}
46
48 : o2::base::DetImpl<Detector>(rhs),
49 mHits(o2::utils::createSimVector<o2::cpv::Hit>())
50{
51}
52
57
59{
60 Reset();
61
62 // Define sensitive volumes
63 defineSensitiveVolumes();
64}
65
67{
68 Reset();
69}
71{
72 // Sort Hits
73 // Add duplicates if any and remove them
74
75 if (!mHits || mHits->size() == 0) {
76 return;
77 }
78
79 auto first = mHits->begin();
80 auto last = mHits->end();
81
82 std::sort(first, last);
83
84 first = mHits->begin();
85 last = mHits->end();
86
87 // this is copy of std::unique() method with addition: adding identical Hits
88 auto itr = first;
89 while (++first != last) {
90 if (*itr == *first) {
91 *itr += *first;
92 } else {
93 *(++itr) = *first;
94 }
95 }
96 ++itr;
97
98 mHits->erase(itr, mHits->end());
99
100 // printf("hits: %d \n",mHits->size()) ;
101 // int c=0;
102 // for(const Hit &h : *mHits){ if(h.GetDetectorID()<c){printf("Ht %d < %d\n",h.GetDetectorID(),c) ;} c=h.GetDetectorID() ;}
103}
105{
106 if (!o2::utils::ShmManager::Instance().isOperational()) {
107 mHits->clear();
108 }
109}
110
111void Detector::Register() { FairRootManager::Instance()->RegisterAny(addNameTo("Hit").data(), mHits, kTRUE); }
112
113Bool_t Detector::ProcessHits(FairVolume* v)
114{
115 // ------------------------------------------------------------------------
116 // Digitize one CPV hit:
117 // use exact 4-momentum p and position zxhit of the hit,
118 // find the pad response around this hit and
119 // put the amplitudes in the pads into array digits
120 //
121 // Author: Yuri Kharlov (after Serguei Sadovsky)
122 // 2 October 2000
123 // ported from AliRoot 2019
124 // ------------------------------------------------------------------------
125
126 // analyze only charged
127 if (fMC->TrackCharge() == 0) {
128 fMC->SetMaxStep(1.e10);
129 return false;
130 }
131
132 if (!fMC->IsTrackEntering()) { // simulate once per track
133 return false;
134 }
135
136 int moduleNumber;
137 fMC->CurrentVolOffID(2, moduleNumber);
138
139 double time = fMC->TrackTime() * 1.e+9; // time in ns?? To be consistent with PHOS/EMCAL
140
141 float xyzm[3], xyzd[3];
142 fMC->TrackPosition(xyzm[0], xyzm[1], xyzm[2]);
143
144 fMC->Gmtod(xyzm, xyzd, 1); // transform coordinate from master to daughter system
145
146 // Current momentum of the hit's track in the local ref. system
147 float pm[3], pd[3], energy = 0.;
148 fMC->TrackMomentum(pm[0], pm[1], pm[2], energy);
149 fMC->Gmtod(pm, pd, 2); // transform 3-momentum from master to daughter system
150
151 // Just a reminder on axes notation in the CPV module:
152 // axis Z goes along the beam
153 // axis X goes across the beam in the module plane
154 // axis Y is a normal to the module plane showing from the IP
155
156 auto& cpvparam = o2::cpv::CPVSimParams::Instance();
157 // Digitize the current CPV hit:
158 // find pad response
159 float hitX = xyzd[0]; // hit coordinate in daugter frame
160 float hitZ = xyzd[2]; // z-coordinate of track in daugter frame
161 float pX = pd[0];
162 float pZ = pd[2];
163 float pNorm = -pd[1];
164 float dZY = pZ / pNorm * cpvparam.mCPVGasThickness;
165 float dXY = pX / pNorm * cpvparam.mCPVGasThickness;
166 float rnor1 = 0., rnor2 = 0.;
167 gRandom->Rannor(rnor1, rnor2);
168 float eloss = cpvparam.mdEdx * (1 + cpvparam.mDetR * rnor1) *
169 TMath::Sqrt((1. + (pow(dZY, 2) + pow(dXY, 2)) / pow(cpvparam.mCPVGasThickness, 2)));
170 float zhit1 = hitZ + cpvparam.mPadSizeZ * cpvparam.mnCellZ / 2 - dZY / 2;
171 float xhit1 = hitX + cpvparam.mPadSizeX * cpvparam.mnCellX / 2 - dXY / 2;
172 float zhit2 = zhit1 + dZY;
173 float xhit2 = xhit1 + dXY;
174
175 int iwht1 = (int)(xhit1 / cpvparam.CellWr()); // wire (x) coordinate "in"
176 int iwht2 = (int)(xhit2 / cpvparam.CellWr()); // wire (x) coordinate "out"
177
178 int nIter;
179 float zxe[3][5];
180 if (iwht1 == iwht2) { // incline 1-wire hit
181 nIter = 2;
182 zxe[0][0] = (zhit1 + zhit2 - dZY * 0.57735) / 2;
183 zxe[1][0] = (iwht1 + 0.5) * cpvparam.CellWr();
184 zxe[2][0] = eloss / 2;
185 zxe[0][1] = (zhit1 + zhit2 + dZY * 0.57735) / 2;
186 zxe[1][1] = (iwht1 + 0.5) * cpvparam.CellWr();
187 zxe[2][1] = eloss / 2;
188 } else if (TMath::Abs(iwht1 - iwht2) != 1) { // incline 3-wire hit
189 nIter = 3;
190 int iwht3 = (iwht1 + iwht2) / 2;
191 float xwht1 = (iwht1 + 0.5) * cpvparam.CellWr(); // wire 1
192 float xwht2 = (iwht2 + 0.5) * cpvparam.CellWr(); // wire 2
193 float xwht3 = (iwht3 + 0.5) * cpvparam.CellWr(); // wire 3
194 float xwr13 = (xwht1 + xwht3) / 2; // center 13
195 float xwr23 = (xwht2 + xwht3) / 2; // center 23
196 float dxw1 = xhit1 - xwr13;
197 float dxw2 = xhit2 - xwr23;
198 float egm1 = TMath::Abs(dxw1) / (TMath::Abs(dxw1) + TMath::Abs(dxw2) + cpvparam.CellWr());
199 float egm2 = TMath::Abs(dxw2) / (TMath::Abs(dxw1) + TMath::Abs(dxw2) + cpvparam.CellWr());
200 float egm3 = cpvparam.CellWr() / (TMath::Abs(dxw1) + TMath::Abs(dxw2) + cpvparam.CellWr());
201 zxe[0][0] = (dXY * (xwr13 - xwht1) / dXY + zhit1 + zhit1) / 2;
202 zxe[1][0] = xwht1;
203 zxe[2][0] = eloss * egm1;
204 zxe[0][1] = (dXY * (xwr23 - xwht1) / dXY + zhit1 + zhit2) / 2;
205 zxe[1][1] = xwht2;
206 zxe[2][1] = eloss * egm2;
207 zxe[0][2] = dXY * (xwht3 - xwht1) / dXY + zhit1;
208 zxe[1][2] = xwht3;
209 zxe[2][2] = eloss * egm3;
210 } else { // incline 2-wire hit
211 nIter = 2;
212 float xwht1 = (iwht1 + 0.5) * cpvparam.CellWr();
213 float xwht2 = (iwht2 + 0.5) * cpvparam.CellWr();
214 float xwr12 = (xwht1 + xwht2) / 2;
215 float dxw1 = xhit1 - xwr12;
216 float dxw2 = xhit2 - xwr12;
217 float egm1 = TMath::Abs(dxw1) / (TMath::Abs(dxw1) + TMath::Abs(dxw2));
218 float egm2 = TMath::Abs(dxw2) / (TMath::Abs(dxw1) + TMath::Abs(dxw2));
219 zxe[0][0] = (zhit1 + zhit2 - dZY * egm1) / 2;
220 zxe[1][0] = xwht1;
221 zxe[2][0] = eloss * egm1;
222 zxe[0][1] = (zhit1 + zhit2 + dZY * egm2) / 2;
223 zxe[1][1] = xwht2;
224 zxe[2][1] = eloss * egm2;
225 }
226
227 // Finite size of ionization region
228
229 int nz3 = (cpvparam.mNgamz + 1) / 2;
230 int nx3 = (cpvparam.mNgamx + 1) / 2;
231
232 o2::data::Stack* stack = static_cast<o2::data::Stack*>(fMC->GetStack());
233 stack->addHit(GetDetId());
234 const int partID = stack->GetCurrentTrackNumber();
235
236 for (int iter = 0; iter < nIter; iter++) {
237
238 float zhit = zxe[0][iter];
239 float xhit = zxe[1][iter];
240 float qhit = zxe[2][iter];
241 float zcell = zhit / cpvparam.mPadSizeZ;
242 float xcell = xhit / cpvparam.mPadSizeX;
243 if (zcell <= 0 || xcell <= 0 ||
244 zcell >= cpvparam.mnCellZ || xcell >= cpvparam.mnCellX) {
245 return true; // beyond CPV
246 }
247 int izcell = (int)zcell;
248 int ixcell = (int)xcell;
249 float zc = zcell - izcell - 0.5;
250 float xc = xcell - ixcell - 0.5;
251 for (int iz = 0; iz < cpvparam.mNgamz; iz++) {
252 int kzg = izcell + iz - nz3;
253 if (kzg < 0 || kzg >= cpvparam.mnCellZ) {
254 continue;
255 }
256 float zg = (float)(iz - nz3) - zc;
257 for (int ix = 0; ix < cpvparam.mNgamx; ix++) {
258 int kxg = ixcell + ix - nx3;
259 if (kxg < 0 || kxg >= cpvparam.mnCellX) {
260 continue;
261 }
262 float xg = (float)(ix - nx3) - xc;
263
264 // Now calculate pad response
265 double qpad = padResponseFunction(qhit, zg, xg);
266 if (qpad < 0) {
267 continue;
268 }
269 // Fill hit with pad response ID and amplitude
270 // hist will be sorted and merged later if necessary
271 int detID = Geometry::relToAbsId(moduleNumber, kxg, kzg);
272 addHit(partID, detID, math_utils::Point3D<float>(xyzm[0], xyzm[1], xyzm[2]), time, qpad);
273 }
274 }
275 }
276 return true;
277}
278
279float Detector::padResponseFunction(float qhit, float zhit, float xhit)
280{
281 // ------------------------------------------------------------------------
282 // Calculate the amplitude in one CPV pad using the
283 // cumulative pad response function
284 // Author: Yuri Kharlov (after Serguei Sadovski)
285 // 3 October 2000
286 // ------------------------------------------------------------------------
287
288 auto& cpvparam = o2::cpv::CPVSimParams::Instance();
289 float dz = cpvparam.mPadSizeZ / 2;
290 float dx = cpvparam.mPadSizeX / 2;
291 float z = zhit * cpvparam.mPadSizeZ;
292 float x = xhit * cpvparam.mPadSizeX;
293 float amplitude = qhit *
294 (CPVCumulPadResponse(z + dz, x + dx) - CPVCumulPadResponse(z + dz, x - dx) -
295 CPVCumulPadResponse(z - dz, x + dx) + CPVCumulPadResponse(z - dz, x - dx));
296 return amplitude;
297}
298
300{
301 // ------------------------------------------------------------------------
302 // Cumulative pad response function
303 // It includes several terms from the CF decomposition in electrostatics
304 // Note: this cumulative function is wrong since omits some terms
305 // but the cell amplitude obtained with it is correct because
306 // these omitting terms cancel
307 // Author: Yuri Kharlov (after Serguei Sadovski)
308 // 3 October 2000
309 // ------------------------------------------------------------------------
310
311 auto& cpvparam = o2::cpv::CPVSimParams::Instance();
312 float r2 = x * x + y * y;
313 float xy = x * y;
314 float cumulPRF = 0;
315 for (Int_t i = 0; i <= 4; i++) {
316 float b1 = (2 * i + 1) * cpvparam.mB;
317 cumulPRF += TMath::Power(-1, i) * TMath::ATan(xy / (b1 * TMath::Sqrt(b1 * b1 + r2)));
318 }
319 cumulPRF *= cpvparam.mA / (2 * TMath::Pi());
320 return cumulPRF;
321}
322
323void Detector::addHit(int trackID, short detID, const math_utils::Point3D<float>& pos, double time, float qdep)
324{
325 LOG(debug) << "Adding hit for track " << trackID << " in a pad " << detID << " with position (" << pos.X() << ", "
326 << pos.Y() << ", " << pos.Z() << "), time" << time << ", qdep =" << qdep << std::endl;
327 mHits->emplace_back(trackID, detID, pos, time, qdep);
328 // register hit creation with MCStack
329 static_cast<o2::data::Stack*>(fMC->GetStack())->addHit(GetDetId());
330}
331
333{
334 // Create geometry description of CPV depector for Geant simulations.
335
336 using boost::algorithm::contains;
337
338 cpv::GeometryParams* geomParams = cpv::GeometryParams::GetInstance("CPVRun3Params");
339
340 if (!geomParams) {
341 LOG(error) << "ConstructGeometry: CPV Geometry class has not been set up.\n";
342 }
343
344 if (!fMC) {
345 fMC = TVirtualMC::GetMC();
346 }
347
348 // Configure geometry So far we have only one: Run3
349 {
350 mActiveModule[0] = kFALSE;
351 mActiveModule[1] = kFALSE;
352 mActiveModule[2] = kTRUE;
353 mActiveModule[3] = kTRUE;
354 mActiveModule[4] = kTRUE;
355 }
356
357 // First create necessary materials
359
360 // Create a CPV modules-containers which will be filled with the stuff later.
361 float par[3], x, y, z;
362
363 // The box containing all CPV filled with air
364 par[0] = geomParams->GetCPVBoxSize(0) / 2.0;
365 par[1] = geomParams->GetCPVBoxSize(1) / 2.0;
366 par[2] = geomParams->GetCPVBoxSize(2) / 2.0;
367 fMC->Gsvolu("CPV", "BOX ", getMediumID(ID_AIR), par, 3);
368
369 // --- Position CPV modules in ALICE setup ---
370 int idrotm[5];
371 for (int iModule = 0; iModule < 5; iModule++) {
372 if (!mActiveModule[iModule]) {
373 continue;
374 }
375 float angle[3][2] = {0};
376 geomParams->GetModuleAngle(iModule, angle);
377 Matrix(idrotm[iModule], angle[0][0], angle[0][1], angle[1][0], angle[1][1], angle[2][0], angle[2][1]);
378
379 float pos[3] = {0};
380 geomParams->GetModuleCenter(iModule, pos);
381
382 fMC->Gspos("CPV", iModule, "barrel", pos[0], pos[1] + 30., pos[2], idrotm[iModule], "ONLY");
383 }
384
385 // start filling CPV moodules
386 // Gassiplex board
387 par[0] = geomParams->GetGassiplexChipSize(0) / 2.;
388 par[1] = geomParams->GetGassiplexChipSize(1) / 2.;
389 par[2] = geomParams->GetGassiplexChipSize(2) / 2.;
390 fMC->Gsvolu("CPVG", "BOX ", getMediumID(ID_TEXTOLIT), par, 3);
391
392 // Cu+Ni foil covers Gassiplex board
393 par[1] = geomParams->GetCPVCuNiFoilThickness() / 2;
394 fMC->Gsvolu("CPVC", "BOX ", getMediumID(ID_CU), par, 3);
395 y = -(geomParams->GetGassiplexChipSize(1) / 2 - par[1]);
396 fMC->Gspos("CPVC", 1, "CPVG", 0, y, 0, 0, "ONLY");
397
398 // Position of the chip inside CPV
399 float xStep = geomParams->GetCPVActiveSize(0) / (geomParams->GetNumberOfCPVChipsPhi() + 1);
400 float zStep = geomParams->GetCPVActiveSize(1) / (geomParams->GetNumberOfCPVChipsZ() + 1);
401 int copy = 0;
402 y = geomParams->GetCPVFrameSize(1) / 2 - geomParams->GetFTPosition(0) +
403 geomParams->GetCPVTextoliteThickness() / 2 + geomParams->GetGassiplexChipSize(1) / 2 + 0.1;
404 for (int ix = 0; ix < geomParams->GetNumberOfCPVChipsPhi(); ix++) {
405 x = xStep * (ix + 1) - geomParams->GetCPVActiveSize(0) / 2;
406 for (int iz = 0; iz < geomParams->GetNumberOfCPVChipsZ(); iz++) {
407 copy++;
408 z = zStep * (iz + 1) - geomParams->GetCPVActiveSize(1) / 2;
409 fMC->Gspos("CPVG", copy, "CPV", x, y, z, 0, "ONLY");
410 }
411 }
412
413 // Foiled textolite (1 mm of textolite + 50 mkm of Cu + 6 mkm of Ni)
414 par[0] = geomParams->GetCPVActiveSize(0) / 2;
415 par[1] = geomParams->GetCPVTextoliteThickness() / 2;
416 par[2] = geomParams->GetCPVActiveSize(1) / 2;
417 fMC->Gsvolu("CPVF", "BOX ", getMediumID(ID_TEXTOLIT), par, 3);
418
419 // Argon gas volume
420 par[1] = (geomParams->GetFTPosition(2) - geomParams->GetFTPosition(1) - geomParams->GetCPVTextoliteThickness()) / 2;
421 fMC->Gsvolu("CPVAr", "BOX ", getMediumID(ID_AR), par, 3);
422
423 for (int i = 0; i < 4; i++) {
424 y = geomParams->GetCPVFrameSize(1) / 2 - geomParams->GetFTPosition(i) + geomParams->GetCPVTextoliteThickness() / 2;
425 fMC->Gspos("CPVF", i + 1, "CPV", 0, y, 0, 0, "ONLY");
426 if (i == 1) {
427 y -= (geomParams->GetFTPosition(2) - geomParams->GetFTPosition(1)) / 2;
428 fMC->Gspos("CPVAr", 1, "CPV ", 0, y, 0, 0, "ONLY");
429 }
430 }
431
432 // Dummy sensitive plane in the middle of argone gas volume
433 par[1] = 0.001;
434 fMC->Gsvolu("CPVQ", "BOX ", getMediumID(ID_AR), par, 3);
435 fMC->Gspos("CPVQ", 1, "CPVAr", 0, 0, 0, 0, "ONLY");
436
437 // Cu+Ni foil covers textolite
438 par[1] = geomParams->GetCPVCuNiFoilThickness() / 2;
439 fMC->Gsvolu("CPVP1", "BOX ", getMediumID(ID_CU), par, 3);
440 y = geomParams->GetCPVTextoliteThickness() / 2 - par[1];
441 fMC->Gspos("CPVP1", 1, "CPVF", 0, y, 0, 0, "ONLY");
442
443 // Aluminum frame around CPV
444 par[0] = geomParams->GetCPVFrameSize(0) / 2;
445 par[1] = geomParams->GetCPVFrameSize(1) / 2;
446 par[2] = geomParams->GetCPVBoxSize(2) / 2;
447 fMC->Gsvolu("CPVF1", "BOX ", getMediumID(ID_AL), par, 3);
448
449 par[0] = geomParams->GetCPVBoxSize(0) / 2 - geomParams->GetCPVFrameSize(0);
450 par[1] = geomParams->GetCPVFrameSize(1) / 2;
451 par[2] = geomParams->GetCPVFrameSize(2) / 2;
452 fMC->Gsvolu("CPVF2", "BOX ", getMediumID(ID_AL), par, 3);
453
454 for (int j = 0; j <= 1; j++) {
455 x = TMath::Sign(1, 2 * j - 1) * (geomParams->GetCPVBoxSize(0) - geomParams->GetCPVFrameSize(0)) / 2;
456 fMC->Gspos("CPVF1", j + 1, "CPV", x, 0, 0, 0, "ONLY");
457 z = TMath::Sign(1, 2 * j - 1) * (geomParams->GetCPVBoxSize(2) - geomParams->GetCPVFrameSize(2)) / 2;
458 fMC->Gspos("CPVF2", j + 1, "CPV", 0, 0, z, 0, "ONLY");
459 }
460
461 gGeoManager->CheckGeometry();
462}
463//-----------------------------------------
465{
466 // Definitions of materials to build CPV and associated tracking media.
467
468 int isxfld = 2;
469 float sxmgmx = 10.0;
471
472 // --- Air ---
473 float aAir[4] = {12.0107, 14.0067, 15.9994, 39.948};
474 float zAir[4] = {6., 7., 8., 18.};
475 float wAir[4] = {0.000124, 0.755267, 0.231781, 0.012827};
476 float dAir = 1.20479E-3;
477
478 Mixture(ID_AIR, "Air", aAir, zAir, dAir, 4, wAir);
479 Medium(ID_AIR, "Air", ID_AIR, 0, isxfld, sxmgmx, 10.0, 1.0, 0.1, 0.1, 10.0, nullptr, 0);
480
481 // The Textolit which makes up the box which contains the calorimeter module -> idtmed[707]
482 float aTX[4] = {16.0, 28.09, 12.011, 1.00794};
483 float zTX[4] = {8.0, 14.0, 6.0, 1.0};
484 float wTX[4] = {292.0, 68.0, 462.0, 736.0};
485 float dTX = 1.75;
486
487 Mixture(ID_TEXTOLIT, "Textolit", aTX, zTX, dTX, -4, wTX);
488 Medium(ID_TEXTOLIT, "Textolit", ID_TEXTOLIT, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, nullptr, 0);
489
490 // Copper -> idtmed[710]
491 Material(ID_CU, "Cupr", 63.546, 29, 8.96, 1.43, 14.8, nullptr, 0);
492 Medium(ID_CU, "Cupr", ID_CU, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.0001, nullptr, 0);
493
494 // The gas mixture: ArCo2 -> idtmed[715]
495 // Ar+CO2 Mixture (80% / 20%)
496 // --- The gas mixture ---
497 // Co2
498 // float aCO[2] = {12.0, 16.0} ;
499 // float zCO[2] = {6.0, 8.0} ;
500 // float wCO[2] = {1.0, 2.0} ;
501 float dCO = 0.001977; // Co2 density
502 float dAr = 0.001782; // Argon density
503
504 float arContent = 0.80; // Ar-content of the ArCO2-mixture
505 float aArCO[3] = {39.948, 12.0, 16.0};
506 float zArCO[3] = {18.0, 6.0, 8.0};
507 float wArCO[3];
508 wArCO[0] = arContent;
509 wArCO[1] = (1 - arContent) * 1;
510 wArCO[2] = (1 - arContent) * 2;
511 float dArCO = arContent * dAr + (1 - arContent) * dCO;
512 Mixture(ID_AR, "ArCo2", aArCO, zArCO, dArCO, -3, wArCO);
513 Medium(ID_AR, "ArCo2", ID_AR, 1, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.01, nullptr, 0);
514
515 // Various Aluminium parts made of Al -> idtmed[701]
516 Material(ID_AL, "Al", 26.98, 13., 2.7, 8.9, 999., nullptr, 0);
517 Medium(ID_AL, "Alparts", ID_AL, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.001, 0.001, nullptr, 0);
518
519 // --- Stainless steel (let it be pure iron) ---
520 Material(ID_FE, "Steel", 55.845, 26, 7.87, 1.76, 0., nullptr, 0);
521 Medium(ID_FE, "Steel", ID_FE, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.0001, nullptr, 0);
522
523 // Fibergalss -> getMediumID(ID_FIBERGLASS)
524 // Medium(ID_FIBERGLASS, "Fiberglass", ID_FIBERGLASS, 0, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, nullptr, 0);
525
526 // The scintillator of the CPV made of Polystyrene scintillator -> idtmed[700]
527 // Medium(ID_SC, "CPVscint", ID_SC, 1, isxfld, sxmgmx, 10.0, 0.1, 0.1, 0.1, 0.1, 0, 0) ;
528}
529
530//-----------------------------------------
531void Detector::defineSensitiveVolumes()
532{
533 if (fActive) {
534 TGeoVolume* vsense = gGeoManager->GetVolume("CPVQ");
535 if (vsense) {
536 AddSensitiveVolume(vsense);
537 } else {
538 LOG(error) << "CPV Sensitive volume CPVQ not found ... No hit creation!\n";
539 }
540 }
541}
542//-----------------------------------------
544{
545 //
546 // Create entries for alignable volumes associating the symbolic volume
547 // name with the corresponding volume path.
548
550
551 // Alignable modules
552 // Volume path /cave_1/CPV_<i> => symbolic name /CPV/Module<i>, <i>=1,2,3,4,5
553
555
556 TString physModulePath = "/cave_1/barrel_1/CPV_";
557
558 TString symbModuleName = "CPV/Module";
559
560 for (Int_t iModule = 0; iModule < geom->GetNModules(); iModule++) {
561
562 if (!mActiveModule[iModule]) {
563 continue;
564 }
565 TString volPath(physModulePath);
566 volPath += iModule;
567
568 TString symName(symbModuleName);
569 symName += iModule;
570
571 int modUID = o2::base::GeometryManager::getSensID(idCPV, iModule);
572
573 LOG(debug) << "--------------------------------------------"
574 << "\n";
575 LOG(debug) << "Alignable object" << iModule << "\n";
576 LOG(debug) << "volPath=" << volPath << "\n";
577 LOG(debug) << "symName=" << symName << "\n";
578 LOG(debug) << "--------------------------------------------"
579 << "\n";
580
581 LOG(debug) << "Check for alignable entry: " << symName;
582
583 if (!gGeoManager->SetAlignableEntry(symName.Data(), volPath.Data(), modUID)) {
584 LOG(error) << "Alignable entry " << symName << " NOT set";
585 }
586 LOG(debug) << "Alignable entry " << symName << " set";
587
588 // Create the Tracking to Local transformation matrix for PHOS modules
589 TGeoPNEntry* alignableEntry = gGeoManager->GetAlignableEntryByUID(modUID);
590 LOG(debug) << "Got TGeoPNEntry " << alignableEntry;
591
592 if (alignableEntry) {
593 Float_t angle = geom->GetCPVAngle(iModule);
594 TGeoHMatrix* globMatrix = alignableEntry->GetGlobalOrig();
595
596 TGeoHMatrix* matTtoL = new TGeoHMatrix;
597 matTtoL->RotateZ(270. + angle);
598 const TGeoHMatrix& globmatrixi = globMatrix->Inverse();
599 matTtoL->MultiplyLeft(&globmatrixi);
600 alignableEntry->SetMatrix(matTtoL);
601 }
602 }
603}
ClassImp(Detector)
Definition of the GeometryManager class.
Definition of the Stack class.
int16_t time
Definition RawEventData.h:4
int32_t i
const GPUTPCGMMerger::trackCluster & b1
uint16_t pos
Definition RawData.h:3
uint32_t j
Definition RawData.h:0
uint32_t stack
Definition RawData.h:1
std::ostringstream debug
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
static int getSensID(o2::detectors::DetID detid, int sensid)
Detector class for the CPV detector.
Definition Detector.h:41
float CPVCumulPadResponse(float x, float y)
Definition Detector.cxx:299
~Detector() override
Definition Detector.cxx:53
void addHit(int trackID, short detID, const math_utils::Point3D< float > &pos, double time, float qdep)
Definition Detector.cxx:323
Detector()=default
float padResponseFunction(float qhit, float zhit, float xhit)
Definition Detector.cxx:279
void Register() override
Definition Detector.cxx:111
void ConstructGeometry() override
Definition Detector.cxx:332
void InitializeO2Detector() final
Definition Detector.cxx:58
void addAlignableVolumes() const override
Definition Detector.cxx:543
Bool_t ProcessHits(FairVolume *v=nullptr) final
Definition Detector.cxx:113
void EndOfEvent() final
Definition Detector.cxx:66
void FinishEvent() final
Sort final hist.
Definition Detector.cxx:70
void Reset() final
Definition Detector.cxx:104
float GetCPVAngle(Int_t index) const
static GeometryParams * GetInstance(const std::string_view name="CPVRun3Params")
Get singleton (create if necessary)
float GetCPVFrameSize(int index) const
int GetNumberOfCPVChipsZ() const
float GetFTPosition(int index) const
void GetModuleCenter(int module, float *pos) const
void GetModuleAngle(int module, float angle[3][2]) const
float GetCPVActiveSize(int index) const
float GetGassiplexChipSize(int index) const
float GetCPVTextoliteThickness() const
int GetNumberOfCPVChipsPhi() const
float GetCPVCuNiFoilThickness() const
float GetCPVBoxSize(int index) const
static unsigned short relToAbsId(short moduleNumber, short iphi, short iz)
Definition Geometry.cxx:19
CPV simulation hit information.
Definition Hit.h:25
void addHit(int iDet)
Definition Stack.cxx:638
static constexpr ID CPV
Definition DetID.h:68
static ShmManager & Instance()
Definition ShmManager.h:61
GLint GLenum GLint x
Definition glcorearb.h:403
const GLdouble * v
Definition glcorearb.h:832
GLint first
Definition glcorearb.h:399
GLint y
Definition glcorearb.h:270
GLboolean * data
Definition glcorearb.h:298
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.
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"