Belle II Software development
GeoARICHBtestCreator.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8#include <sstream>
9#include <string.h>
10
11//#include <geant4/G4LogicalVolume.hh>
12
13// Geant4
14#include <G4LogicalVolume.hh>
15#include <G4PVPlacement.hh>
16#include <G4LogicalSkinSurface.hh>
17#include <G4OpticalSurface.hh>
18// Geant4 Shapes
19#include <G4Box.hh>
20#include <G4SubtractionSolid.hh>
21#include <G4Material.hh>
22
23#include <Python.h>
24
25#include <arich/geometry/GeoARICHBtestCreator.h>
26#include <arich/geometry/ARICHGeometryPar.h>
27#include <arich/geometry/ARICHBtestGeometryPar.h>
28
29#include <geometry/Materials.h>
30#include <geometry/CreatorFactory.h>
31#include <geometry/utilities.h>
32#include <framework/gearbox/GearDir.h>
33#include <framework/gearbox/Unit.h>
34#include <framework/logging/Logger.h>
35// Framework - DataStore
36#include <framework/datastore/StoreObjPtr.h>
37#include <framework/dataobjects/EventMetaData.h>
38
39#include <arich/simulation/SensitiveDetector.h>
40#include <arich/simulation/SensitiveAero.h>
41
42using namespace std;
43
44namespace Belle2 {
49
50 using namespace geometry;
51
52 namespace arich {
53
54 //-----------------------------------------------------------------
55 // Register the Creator
56 //-----------------------------------------------------------------
57
58 geometry::CreatorFactory<GeoARICHBtestCreator> GeoARICHBtestFactory("ARICHBtestCreator");
59
60 //-----------------------------------------------------------------
61 // Implementation
62 //-----------------------------------------------------------------
63
78
83
84
85 void GeoARICHBtestCreator::create(const GearDir& content, G4LogicalVolume& topVolume, GeometryTypes)
86 {
87
88 B2INFO("GeoARICHBtestCreator::create");
89 StoreObjPtr<EventMetaData> eventMetaDataPtr;
90
91 int run = 68;
92 [[clang::suppress]]
93 PyObject* m = PyImport_AddModule(strdup("__main__"));
94 if (m) {
95 [[clang::suppress]]
96 PyObject* v = PyObject_GetAttrString(m, strdup("runno"));
97 if (v) {
98 run = PyLong_AsLong(v);
99 Py_DECREF(v);
100 }
101 B2INFO("GeoARICHBtestCreator::create runno = " << run);
102 }
103
104 B2INFO("eventMetaDataPtr run:" << run);
105 // eventMetaDataPtr->setEndOfData();
106
107
108
109
110 string Type = content.getString("@type", "");
111
112 char nodestr[100];
113 sprintf(nodestr, "run[runno=%d]", run);
114 if (Type == "beamtest") {
115 for (const GearDir& runparam : content.getNodes(nodestr)) {
116 m_runno = runparam.getInt("runno", -1);
117 m_author = runparam.getString("author", "");
118 m_neve = runparam.getInt("neve", -1);
119 m_runtype = runparam.getString("calibration", "pion");
120 m_hapdID = runparam.getString("setup1", "unknown");
121 m_aerogelID = runparam.getString("aerogel1", "unknown");
122 m_mirrorID = runparam.getString("mirror", "unknown");
123 m_rotation = runparam.getDouble("rotation", 0);
124 m_rx = runparam.getDouble("positionx", 0);
125 m_ry = runparam.getDouble("positiony", 0);
126 m_mytype = runparam.getString("type1", "unknown");
127 m_daqqa = runparam.getString("daqqa1", "unknown");
128 m_comment = runparam.getString("comment1", "unknown");
129 m_datum = runparam.getString("datum", "unknown");
130
131
132 B2INFO("runno : " << m_runno);
133 B2INFO("author : " << m_author);
134 B2INFO("neve : " << m_neve);
135 B2INFO("runtype : " << m_runtype);
136 B2INFO("hapdID : " << m_hapdID);
137 B2INFO("aerogelID: " << m_aerogelID);
138 B2INFO("mirrorID : " << m_mirrorID);
139 B2INFO("rotation : " << m_rotation);
140 B2INFO("rx : " << m_rx);
141 B2INFO("ry : " << m_ry);
142 B2INFO("runtype : " << m_mytype);
143 B2INFO("daqqa : " << m_daqqa);
144 B2INFO("comment : " << m_comment);
145 B2INFO("datum : " << m_datum);
146
147
148 }
149 string aerogelname;
150 sprintf(nodestr, "setup/aerogel/row[@id=\"%s\"]", m_aerogelID.c_str());
151
152 GearDir runparam(content, nodestr);
153 B2INFO("id : " << runparam.getString("@id", ""));
154 for (const GearDir& aeroparam : runparam.getNodes("aerogel")) {
155 aerogelname = aeroparam.getString(".", "");
156 string stype = aeroparam.getString("@type", "");
157 B2INFO(stype << " aerogelname : " << aerogelname);
158 sprintf(nodestr, "setup/aerogelinfo/row[@id=\"%s\"]", aerogelname.c_str());
159 GearDir infoparam(content, nodestr);
160
161 double agelrefind = infoparam.getDouble("refind", 1);
162 double ageltrlen = infoparam.getLength("trlen", 0);
163 double agelthickness = infoparam.getLength("thickness", 0);
164 if (stype != string("left")) {
165 m_ageltrlen.push_back(ageltrlen);
166 m_agelrefind.push_back(agelrefind);
167 m_agelthickness.push_back(agelthickness);
168 }
169 B2INFO("refind : " << agelrefind);
170 B2INFO("trlen : " << ageltrlen / Unit::mm);
171 B2INFO("thickness : " << agelthickness / Unit::mm);
172
173 }
174 int size = m_hapdID.size();
175
176 m_aerosupport = 0;
177 if (size > 0) {
178 char agelsupport = m_hapdID.at(size - 1);
179 if (agelsupport == 'a') m_aerosupport = 1;
180 if (agelsupport == 'b') m_aerosupport = 2;
181 }
182
183 if (m_aerosupport) size--;
184 sprintf(nodestr, "setup/hapd/row[@id=\"%s\"]", m_hapdID.substr(0, size).c_str());
185 B2INFO("nodestr : " << nodestr);
186 B2INFO("aerogelsupport : " << m_aerosupport);
187 GearDir hapdparam(content, nodestr);
188 //for (const GearDir& runparam : content.getNodes(nodestr)) {
189 m_aerogeldx = hapdparam.getLength("aerogeldx", 0);
190 m_framedx = hapdparam.getLength("framedx", 0) * CLHEP::mm / Unit::mm ;
191 m_rotation1 = hapdparam.getDouble("rotation", 0);
192 m_configuration = hapdparam.getInt("setup", 0);
193 m_comment1 = hapdparam.getString("comment", "");
194
195
196 B2INFO("aerogeldx : " << m_aerogeldx);
197 B2INFO("framedx : " << m_framedx);
198 B2INFO("rotation : " << m_rotation1);
199 B2INFO("configuration : " << m_configuration);
200 B2INFO("comment : " << m_comment);
201 //}
202
203 GearDir setup(content, "setup");
204
205 createBtestGeometry(setup, topVolume);
206 }
207 }
208
209 double GeoARICHBtestCreator::getAvgRINDEX(G4Material* material)
210 {
211 G4MaterialPropertiesTable* mTable = material->GetMaterialPropertiesTable();
212 if (!mTable) return 0;
213 G4MaterialPropertyVector* mVector = mTable->GetProperty("RINDEX");
214 if (!mVector) return 0;
215 G4bool b;
216 return mVector->GetValue(2 * Unit::eV / Unit::MeV, b);
217 }
218
220 {
221
222 // get detector module parameters
223
224 // get module materials
225 string wallMat = Module.getString("wallMaterial");
226 string winMat = Module.getString("windowMaterial");
227 string botMat = Module.getString("Bottom/material");
228 G4Material* wallMaterial = Materials::get(wallMat);
229 G4Material* windowMaterial = Materials::get(winMat);
230 G4Material* bottomMaterial = Materials::get(botMat);
231 G4Material* boxFill = Materials::get("ARICH_Vacuum");
232
233 // check that module window material has specified refractive index
234 double wref = getAvgRINDEX(windowMaterial);
235 if (!wref) B2WARNING("Material '" << winMat <<
236 "', required for ARICH photon detector window as no specified refractive index. Continuing, but no photons in ARICH will be detected.");
238 m_arichgp->setWindowRefIndex(wref);
239 // get module dimensions
240 double modXsize = Module.getLength("moduleXSize") / Unit::mm;
241 double modZsize = Module.getLength("moduleZSize") / Unit::mm;
242 double wallThick = Module.getLength("moduleWallThickness") / Unit::mm;
243 double winThick = Module.getLength("windowThickness") / Unit::mm ;
244 double sensXsize = m_arichgp->getSensitiveSurfaceSize() / Unit::mm;
245 double botThick = Module.getLength("Bottom/thickness") / Unit::mm;
246
247 // some trivial checks of overlaps
248 if (sensXsize > modXsize - 2 * wallThick)
249 B2FATAL("ARICH photon detector module: Sensitive surface is too big. Doesn't fit into module box.");
250 if (winThick + botThick > modZsize)
251 B2FATAL("ARICH photon detector module: window + bottom thickness larger than module thickness.");
252
253 // module master volume
254 G4Box* moduleBox = new G4Box("Box", modXsize / 2., modXsize / 2., modZsize / 2.);
255 G4LogicalVolume* lmoduleBox = new G4LogicalVolume(moduleBox, boxFill, "moduleBox");
256
257 // build and place module wall
258 G4Box* tempBox = new G4Box("tempBox", modXsize / 2. - wallThick, modXsize / 2. - wallThick,
259 modZsize / 2. + 0.1); // Don't care about "+0.1", needs to be there.
260 G4SubtractionSolid* moduleWall = new G4SubtractionSolid("Box-tempBox", moduleBox, tempBox);
261 G4LogicalVolume* lmoduleWall = new G4LogicalVolume(moduleWall, wallMaterial, "moduleWall");
262 setColor(*lmoduleWall, "rgb(1.0,0.0,0.0,1.0)");
263 new G4PVPlacement(G4Transform3D(), lmoduleWall, "moduleWall", lmoduleBox, false, 1);
264
265 // build module window
266 G4Box* winBox = new G4Box("winBox", modXsize / 2. - wallThick, modXsize / 2. - wallThick, winThick / 2.);
267 G4LogicalVolume* lmoduleWin = new G4LogicalVolume(winBox, windowMaterial, "moduleWindow");
268 setColor(*lmoduleWin, "rgb(0.7,0.7,0.7,1.0)");
269 G4Transform3D transform = G4Translate3D(0., 0., (-modZsize + winThick) / 2.);
270 new G4PVPlacement(transform, lmoduleWin, "moduleWindow", lmoduleBox, false, 1);
271
272 // build module bottom
273 G4Box* botBox = new G4Box("botBox", modXsize / 2. - wallThick, modXsize / 2. - wallThick, botThick / 2.);
274 G4LogicalVolume* lmoduleBot = new G4LogicalVolume(botBox, bottomMaterial, "moduleBottom");
275 // if (isBeamBkgStudy) lmoduleBot->SetSensitiveDetector(new BkgSensitiveDetector("ARICH", 1));
276 setColor(*lmoduleBot, "rgb(0.0,1.0,0.0,1.0)");
277 G4Transform3D transform1 = G4Translate3D(0., 0., (modZsize - botThick) / 2.);
278 // add surface optical properties if specified
279 Materials& materials = Materials::getInstance();
280 GearDir bottomParam(Module, "Bottom/Surface");
281 if (bottomParam) {
282 G4OpticalSurface* optSurf = materials.createOpticalSurface(bottomParam);
283 new G4LogicalSkinSurface("bottomSurface", lmoduleBot, optSurf);
284 } else B2INFO("ARICH: No optical properties are specified for detector module bottom surface.");
285 new G4PVPlacement(transform1, lmoduleBot, "moduleBottom", lmoduleBox, false, 1);
286
287 // build sensitive surface
288 G4Box* sensBox = new G4Box("sensBox", sensXsize / 2., sensXsize / 2., 0.1 * Unit::mm);
289 G4LogicalVolume* lmoduleSens = new G4LogicalVolume(sensBox, boxFill, "moduleSensitive");
290 lmoduleSens->SetSensitiveDetector(m_sensitive);
291 setColor(*lmoduleSens, "rgb(0.5,0.5,0.5,1.0)");
292 G4Transform3D transform2 = G4Translate3D(0., 0., (-modZsize + 0.1) / 2. + winThick);
293 new G4PVPlacement(transform2, lmoduleSens, "moduleSensitive", lmoduleBox, false, 1);
294
295 // module is build, return module logical volume
296 return lmoduleBox;
297 }
298
299
300 G4Material* GeoARICHBtestCreator::createAerogel(const char* aeroname, double RefractiveIndex, double AerogelTransmissionLength)
301 {
302
303
304 G4double density = (RefractiveIndex - 1) / 0.21 * CLHEP::g / CLHEP::cm3;
305 B2INFO("Creating ARICH " << aeroname << " n=" << RefractiveIndex << " density=" << density / CLHEP::g * CLHEP::cm3 << " g/cm3");
306 Materials& materials = Materials::getInstance();
307 G4Material* _aerogel = new G4Material(aeroname, density, 4);
308 _aerogel->AddElement(materials.getElement("O"), 0.665);
309 _aerogel->AddElement(materials.getElement("H"), 0.042);
310 _aerogel->AddElement(materials.getElement("Si"), 0.292);
311 _aerogel->AddElement(materials.getElement("C"), 0.001);
312
313
314 const G4double AerogelAbsorbtionLength = 1000 * Unit::mm;
315
316 const G4int NBins = 40;
317 G4double MomentumBins[NBins];
318
319 G4double AerogelRindex[NBins];
320 G4double AerogelAbsorption[NBins];
321 G4double AerogelRayleigh[NBins];
322
323 G4double MaxPhotonEnergy = 5 * CLHEP::eV;
324 G4double MinPhotonEnergy = 1.5 * CLHEP::eV;
325
326 for (G4int i = 0; i < NBins; i++) {
327
328 const G4double energy = float(i) / NBins * (MaxPhotonEnergy - MinPhotonEnergy) + MinPhotonEnergy;
329
330 MomentumBins[i] = energy;
331 AerogelRindex[i] = RefractiveIndex;
332 AerogelAbsorption[i] = AerogelAbsorbtionLength;
333
334 const G4double Lambda0 = 400 * 1e-6 * CLHEP::mm;
335 const G4double Lambda = 1240 * CLHEP::eV / energy * 1e-6 * CLHEP::mm;
336 G4double x = Lambda / Lambda0;
337 AerogelRayleigh[i] = AerogelTransmissionLength * x * x * x * x;
338 }
339
340
341 G4MaterialPropertiesTable* AeroProperty = new G4MaterialPropertiesTable();
342 AeroProperty->AddProperty("RINDEX", MomentumBins, AerogelRindex, NBins);
343 AeroProperty->AddProperty("ABSLENGTH", MomentumBins, AerogelAbsorption, NBins);
344 AeroProperty->AddProperty("RAYLEIGH", MomentumBins, AerogelRayleigh, NBins);
345
346
347 _aerogel->SetMaterialPropertiesTable(AeroProperty);
348
349
350 return _aerogel;
351 }
352
353
354 void GeoARICHBtestCreator::createBtestGeometry(const GearDir& content, G4LogicalVolume& topWorld)
355 {
356
357 B2INFO("ARICH Btest geometry will be built.");
359
361
362 // experimental box
363
364 GearDir boxParams(content, "ExperimentalBox");
365 double xBox = boxParams.getLength("xSize") * CLHEP::mm / Unit::mm;
366 double yBox = boxParams.getLength("ySize") * CLHEP::mm / Unit::mm;
367 double zBox = boxParams.getLength("zSize") * CLHEP::mm / Unit::mm;
368
369 double xoffset = boxParams.getLength("beamcenter/x") * CLHEP::mm / Unit::mm;
370 double yoffset = boxParams.getLength("beamcenter/y") * CLHEP::mm / Unit::mm;
371 double zoffset = boxParams.getLength("beamcenter/z") * CLHEP::mm / Unit::mm - zBox / 2.;
372 G4ThreeVector roffset(xoffset, yoffset, zoffset);
373
374 ROOT::Math::XYZVector sh(boxParams.getLength("beamcenter/x"), boxParams.getLength("beamcenter/y"),
375 boxParams.getLength("beamcenter/z") - boxParams.getLength("zSize") / 2.);
376 m_arichbtgp->setOffset(sh);
377
378 string boxMat = boxParams.getString("material");
379 G4Material* boxMaterial = Materials::get(boxMat);
380 G4Box* expBox = new G4Box("ExperimentalBox", xBox / 2., yBox / 2., zBox / 2.);
381 G4LogicalVolume* topVolume = new G4LogicalVolume(expBox, boxMaterial, "ARICH.experimentalbox");
382 new G4PVPlacement(G4Transform3D(), topVolume, "ARICH.experimentalbox", &topWorld, false, 1);
383 setVisibility(*topVolume, false);
384
385 ROOT::Math::XYZVector trackingshift(content.getLength("tracking/shift/x"),
386 content.getLength("tracking/shift/y"),
387 content.getLength("tracking/shift/z"));
388
389 char mnodestr[256];
390 sprintf(mnodestr, "tracking/shift/run[@id=\"%d\"]", m_runno);
391 if (content.exists(mnodestr)) {
392 GearDir runtrackingshift(content, mnodestr);
393 trackingshift.SetXYZ(runtrackingshift.getLength("x"),
394 runtrackingshift.getLength("y"),
395 runtrackingshift.getLength("z"));
396 }
397 m_arichbtgp->setTrackingShift(trackingshift);
398 ARICHTracking* m_mwpc = new ARICHTracking[4];
399 m_arichbtgp->setMwpc(m_mwpc);
400 for (const GearDir& mwpc : content.getNodes("tracking/mwpc")) {
401 double x = mwpc.getLength("size/x") * CLHEP::mm / Unit::mm;
402 double y = mwpc.getLength("size/y") * CLHEP::mm / Unit::mm;
403 double z = mwpc.getLength("size/z") * CLHEP::mm / Unit::mm;
404
405 double px = mwpc.getLength("position/x") * CLHEP::mm / Unit::mm;
406 double py = mwpc.getLength("position/y") * CLHEP::mm / Unit::mm;
407 double pz = mwpc.getLength("position/z") * CLHEP::mm / Unit::mm;
408
409 G4Box* mwpcBox = new G4Box("MwpcBox", x / 2., y / 2., z / 2.);
410 G4LogicalVolume* mwpcVol = new G4LogicalVolume(mwpcBox, Materials::get(mwpc.getString("material")), "ARICH.mwpc");
411 new G4PVPlacement(G4Transform3D(G4RotationMatrix(), G4ThreeVector(px, py, pz) + roffset), mwpcVol, "ARICH.mwpc", topVolume, false,
412 1);
413 //setVisibility(*mwpc, true);
414
415 int id = mwpc.getInt("@id", -1);
416 B2INFO("GeoARICHBtestCreator::" << LogVar("MWPC ID", id));
417 if (id < 4 && id >= 0) {
418 m_mwpc[id].tdc[0] = mwpc.getInt("tdc/y/up");
419 m_mwpc[id].tdc[1] = mwpc.getInt("tdc/y/down");
420 m_mwpc[id].tdc[2] = mwpc.getInt("tdc/x/left");
421 m_mwpc[id].tdc[3] = mwpc.getInt("tdc/x/right");
422 m_mwpc[id].atdc = mwpc.getInt("tdc/anode", 0);
423 m_mwpc[id].slp[0] = mwpc.getDouble("slope/x");
424 m_mwpc[id].slp[1] = mwpc.getDouble("slope/y");
425 m_mwpc[id].offset[0] = mwpc.getDouble("offset/x");
426 m_mwpc[id].offset[1] = mwpc.getDouble("offset/y");
427 m_mwpc[id].cutll[0] = mwpc.getInt("tdccut/y/min");
428 m_mwpc[id].cutll[1] = mwpc.getInt("tdccut/x/min");
429 m_mwpc[id].cutul[0] = mwpc.getInt("tdccut/y/max");
430 m_mwpc[id].cutul[1] = mwpc.getInt("tdccut/x/max");
431 m_mwpc[id].pos[0] = mwpc.getDouble("position/x");
432 m_mwpc[id].pos[1] = mwpc.getDouble("position/y");
433 m_mwpc[id].pos[2] = mwpc.getDouble("position/z");
434 // m_mwpc[id].Print();
435 }
436
437 }
438 // physical position of the hapd channels
439
440 istringstream mapstream;
441 double mx, my;
442 mapstream.str(content.getString("hapdmap"));
443 while (mapstream >> mx >> my) {
444 m_arichbtgp->AddHapdChannelPositionPair(mx, my);
445 }
446 mapstream.clear();
447
448 // mapping of the electronic channels
449 int ipx, ipy;
450 mapstream.str(content.getString("hapdchmap"));
451 while (mapstream >> ipx >> ipy) {
452 m_arichbtgp->AddHapdElectronicMapPair(ipx, ipy);
453 }
454 // experimental frame consisting of detector plane, aerogel and mirrors
455
456 GearDir frameParams(content, "Frame");
457 double xFrame = frameParams.getLength("xSize") * CLHEP::mm / Unit::mm;
458 double yFrame = frameParams.getLength("ySize") * CLHEP::mm / Unit::mm;
459 double zFrame = frameParams.getLength("zSize") * CLHEP::mm / Unit::mm;
460 string envMat = frameParams.getString("material");
461
462 double px = frameParams.getLength("position/x") * CLHEP::mm / Unit::mm;
463 double py = frameParams.getLength("position/y") * CLHEP::mm / Unit::mm;
464 double pz = frameParams.getLength("position/z") * CLHEP::mm / Unit::mm;
465
466 G4Material* envMaterial = Materials::get(envMat);
467
468
469 G4Box* envBox = new G4Box("FrameBox", xFrame / 2., yFrame / 2., zFrame / 2.);
470 G4LogicalVolume* lenvBox = new G4LogicalVolume(envBox, envMaterial, "ARICH.frame");
471 G4ThreeVector frameOrigin0(m_framedx + px, py, pz); // rotation point of the detector frame wrt beamcenter
472 G4ThreeVector frameOrigin = frameOrigin0 + roffset;
473 G4RotationMatrix frameRotation;
474 frameRotation.rotateY(-m_rotation1 * CLHEP::degree);
475 G4Transform3D frameTransformation = G4Transform3D(frameRotation, frameOrigin);
476
477 new G4PVPlacement(frameTransformation, lenvBox, "ARICH.frame", topVolume, false, 1);
478 //setVisibility(*lenvBox, false);
479
480 ROOT::Math::XYZVector rotationCenter(frameOrigin0.x() * Unit::mm / CLHEP::mm,
481 frameOrigin0.y() * Unit::mm / CLHEP::mm,
482 frameOrigin0.z() * Unit::mm / CLHEP::mm);
483 m_arichbtgp->setFrameRotation(m_rotation1 * CLHEP::degree);
484 m_arichbtgp->setRotationCenter(rotationCenter);
485
486
487 char nodestr[256];
488 B2INFO(content.getPath());
489 sprintf(nodestr, "PhotonDetector/setup[@id=\"%d\"]", m_configuration);
490 GearDir hapdcontent(content, nodestr);
491 B2INFO(hapdcontent.getPath());
492
493
494
495 char mirrornodestr[256];
496 sprintf(mirrornodestr, "Mirrors/setup[@id=\"%s\"]", m_mirrorID.c_str());
497
498 GearDir mirrorcontent(content, mirrornodestr);
499 B2INFO(mirrorcontent.getPath());
500
501 // detectors
502 m_arichgp->Initialize(hapdcontent, mirrorcontent);
503
504
505 GearDir moduleParam(hapdcontent, "Detector/Module");
506 G4LogicalVolume* detModule = buildModule(moduleParam);
507
508 double detZpos = hapdcontent.getLength("Detector/Plane/zPosition") * CLHEP::mm / Unit::mm;
509 double detThick = hapdcontent.getLength("Detector/Module/moduleZSize") * CLHEP::mm / Unit::mm;
510 int nModules = m_arichgp->getNMCopies();
511
512 for (int i = 1; i <= nModules; i++) {
513 G4ThreeVector origin = m_arichgp->getOriginG4(i);
514 origin.setZ(detZpos + detThick / 2.);
515 double angle = m_arichgp->getModAngle(i);
516 G4RotationMatrix Ra;
517 Ra.rotateZ(angle);
518 G4Transform3D trans = G4Transform3D(Ra, origin);
519 new G4PVPlacement(G4Transform3D(Ra, origin), detModule, "detModule", lenvBox, false, i);
520 B2INFO(nodestr << "Module " << i << " is build ");
521 }
522 // mask hot channels
523 int npx = m_arichgp->getDetectorXPadNumber();
524 for (const double& ch : hapdcontent.getArray("HotChannels")) {
525 int channelID = (int) ch;
526 int moduleID = (npx) ? channelID / (npx * npx) : 0;
527 channelID %= (npx * npx);
528 m_arichgp->setActive(moduleID, channelID, false);
529 B2INFO("HotChannel " << ch << " : Module " << moduleID << "channelID " << channelID << " disabled");
530 }
531 // mask dead channels
532 for (const double& ch : hapdcontent.getArray("DeadChannels")) {
533 int channelID = (int) ch;
534 int moduleID = (npx) ? channelID / (npx * npx) : 0;
535 channelID %= (npx * npx);
536 m_arichgp->setActive(moduleID, channelID, false);
537 B2INFO("DeadChannel " << ch << " : Module " << moduleID << "channelID " << channelID << " disabled");
538 }
539 // place aerogel tiles
540 GearDir aerogelParam(content, "Aerogel");
541 double sizeX = aerogelParam.getLength("tileXSize") * CLHEP::mm / Unit::mm;
542 double sizeY = aerogelParam.getLength("tileYSize") * CLHEP::mm / Unit::mm;
543 double posX = aerogelParam.getLength("tileXPos") * CLHEP::mm / Unit::mm;
544 double posY = aerogelParam.getLength("tileYPos") * CLHEP::mm / Unit::mm;
545 double posZ = aerogelParam.getLength("tileZPos") * CLHEP::mm / Unit::mm;
546 double posZ0 = posZ;
547 double meanrefind = 0;
548 double meantrlen = 0;
549
550 // get parameter from python script
551 [[clang::suppress]]
552 PyObject* m = PyImport_AddModule(strdup("__main__"));
553 if (m) {
554 int averageagel = 0;
555 [[clang::suppress]]
556 PyObject* v = PyObject_GetAttrString(m, strdup("averageagel"));
557 if (v) {
558 averageagel = PyLong_AsLong(v);
559 Py_DECREF(v);
560 }
561 B2INFO("Python averageagel = " << averageagel);
562 m_arichbtgp->setAverageAgel(averageagel > 0);
563 }
564
565 for (unsigned int ilayer = 0; ilayer < m_agelthickness.size(); ilayer++) {
566 char aeroname[100];
567 sprintf(aeroname, "Aerogel%u", ilayer + 1);
568 G4Material* tileMaterial = createAerogel(aeroname, m_agelrefind[ilayer], m_ageltrlen[ilayer]);
569 double sizeZ = m_agelthickness[ilayer] * CLHEP::mm / Unit::mm;
570
571 if (!m_arichbtgp->getAverageAgel()) {
572 m_arichgp->setAeroRefIndex(ilayer, m_agelrefind[ilayer]);
573 m_arichgp->setAerogelZPosition(ilayer, (posZ - zFrame / 2.) * Unit::mm / CLHEP::mm);
574 m_arichgp->setAerogelThickness(ilayer, sizeZ * Unit::mm / CLHEP::mm);
575 m_arichgp->setAeroTransLength(ilayer, m_ageltrlen[ilayer]);
576 }
577
578 meantrlen += sizeZ / m_ageltrlen[ilayer];
579 meanrefind += m_agelrefind[ilayer];
580 G4Box* tileBox = new G4Box("tileBox", sizeX / 2., sizeY / 2., sizeZ / 2.);
581 G4LogicalVolume* lTile = new G4LogicalVolume(tileBox, tileMaterial, "Tile", 0, ilayer == 0 ? m_sensitiveAero : 0);
582 setColor(*lTile, "rgb(0.0, 1.0, 1.0,1.0)");
583 G4Transform3D trans = G4Translate3D(posX, posY, posZ + sizeZ / 2. - zFrame / 2.);
584 new G4PVPlacement(trans, lTile, "ARICH.tile", lenvBox, false, ilayer + 1);
585 posZ += sizeZ;
586 }
587 if (m_arichbtgp->getAverageAgel() && m_agelthickness.size()) {
588 B2INFO("Average aerogel will be used in the reconstruction ");
589 m_arichgp->setAeroRefIndex(0, meanrefind / m_agelthickness.size());
590 m_arichgp->setAerogelZPosition(0, (posZ0 - zFrame)* Unit::mm / CLHEP::mm);
591 m_arichgp->setAerogelThickness(0, posZ * Unit::mm / CLHEP::mm);
592 if (meantrlen > 0 && posZ > 0) meantrlen = 1 / meantrlen / posZ;
593 m_arichgp->setAeroTransLength(0, meantrlen);
594 }
595
596
597 // place mirrors
598 GearDir mirrorsParam(mirrorcontent, "Mirrors");
599 double height = mirrorsParam.getLength("height") * CLHEP::mm / Unit::mm;
600 double width = mirrorsParam.getLength("width") * CLHEP::mm / Unit::mm;
601 double thickness = mirrorsParam.getLength("thickness") * CLHEP::mm / Unit::mm;
602 string mirrMat = mirrorsParam.getString("material");
603 G4Material* mirrMaterial = Materials::get(mirrMat);
604 G4Box* mirrBox = new G4Box("mirrBox", thickness / 2., height / 2., width / 2.);
605 G4LogicalVolume* lmirror = new G4LogicalVolume(mirrBox, mirrMaterial, "mirror");
606
607 Materials& materials = Materials::getInstance();
608 GearDir surface(mirrorsParam, "Surface");
609 G4OpticalSurface* optSurf = materials.createOpticalSurface(surface);
610 new G4LogicalSkinSurface("mirrorsSurface", lmirror, optSurf);
611 int iMirror = 0;
612 for (const GearDir& mirror : mirrorsParam.getNodes("Mirror")) {
613 double xpos = mirror.getLength("xPos") * CLHEP::mm / Unit::mm;
614 double ypos = mirror.getLength("yPos") * CLHEP::mm / Unit::mm;
615 double zpos = mirror.getLength("zPos") * CLHEP::mm / Unit::mm;
616 double angle = mirror.getAngle("angle") / Unit::rad;
617 G4ThreeVector origin(xpos, ypos, zpos + width / 2. - zFrame / 2.);
618 G4RotationMatrix Ra;
619 Ra.rotateZ(angle);
620 G4Transform3D trans = G4Transform3D(Ra, origin);
621 new G4PVPlacement(G4Transform3D(Ra, origin), lmirror, "ARICH.mirror", lenvBox, false, iMirror);
622 iMirror++;
623 }
624 m_arichgp->Print();
625 m_arichbtgp->Print();
626 }
627
628
629 }
631}
The Class for ARICH Beamtest Geometry Parameters.
The Class for ARICH Geometry Parameters.
Beamtest ARICH Geometry Tracking Class.
float slp[2]
Calibration constants of the MWPC ( ) - slopes for x an y direction.
int cutll[2]
Cuts on the tdc sums - lower levels.
float pos[3]
MWPC chamber position.
int tdc[4]
TDC of the 4 cathode signals.
int atdc
TDC of the anode signal.
float offset[2]
Calibration constants of the MWPC - offsets for x an y direction.
int cutul[2]
Cuts on the tdc sums - upper levels.
GearDir is the basic class used for accessing the parameter store.
Definition GearDir.h:31
virtual std::string getString(const std::string &path="") const noexcept(false) override
Get the parameter path as a string.
Definition GearDir.h:69
Base class for Modules.
Definition Module.h:72
Type-safe access to single objects in the data store.
Definition StoreObjPtr.h:96
static const double mm
[millimeters]
Definition Unit.h:70
static const double rad
Standard of [angle].
Definition Unit.h:50
static const double eV
[electronvolt]
Definition Unit.h:112
static const double MeV
[megaelectronvolt]
Definition Unit.h:114
std::string m_comment
comment in the runlog
int m_aerosupport
Type of aerogel support - not used at the moment.
std::string m_aerogelID
ID of the aerogel configuration setup.
double m_rotation1
rotation angle of the frame
std::string m_runtype
Type of the beamtest run.
std::vector< double > m_agelrefind
vector of aerogel refractive indices
void createBtestGeometry(const GearDir &content, G4LogicalVolume &topVolume)
Creation of the beamtest geometry.
G4Material * createAerogel(const char *aeroname, double rind, double trl)
create aerogel material
double m_ry
y shift of the prototype ARICH frame
std::vector< double > m_ageltrlen
vector of aerogel transmission lengths
virtual ~GeoARICHBtestCreator()
The destructor of the GeoPXDCreator class.
G4LogicalVolume * buildModule(GearDir Module)
Build the module.
double getAvgRINDEX(G4Material *material)
Get the average refractive index if the material.
std::string m_mirrorID
ID of the mirror configuration setup.
virtual void create(const GearDir &content, G4LogicalVolume &topVolume, geometry::GeometryTypes type)
Creates the ROOT Objects for the ARICH Beamtest 2011 geometry.
double m_aerogeldx
shift of the aerogel center
std::string m_datum
datum of the runlog
SensitiveAero * m_sensitiveAero
pointer to the sesnitive aerogel
std::string m_author
Beamtest runlog record author.
GeoARICHBtestCreator()
Constructor of the GeoPXDCreator class.
std::string m_daqqa
classification of the run
std::string m_hapdID
ID of the HAPD configuration setup.
std::vector< double > m_agelthickness
vector of aerogel thicknesses
double m_rotation
rotation angle of the setup
SensitiveDetector * m_sensitive
pointer to the sensitive detector
double m_rx
x shift of the prototype ARICH frame
int m_neve
Number of event in the beamtest run.
int m_configuration
configuration number of the HAPD
This is optional (temporary) class that provides information on track parameters on aerogel plane,...
The Class for ARICH Sensitive Detector.
std::vector< double > getArray(const std::string &path) const noexcept(false)
Get the parameter path as a list of double values converted to the standard unit.
Definition Interface.cc:123
double getDouble(const std::string &path="") const noexcept(false)
Get the parameter path as a double.
Definition Interface.cc:41
std::string getPath() const
Return path of the current interface.
Definition Interface.h:70
double getLength(const std::string &path="") const noexcept(false)
Get the parameter path as a double converted to the standard length unit.
Definition Interface.h:259
std::vector< GearDir > getNodes(const std::string &path="") const
Get vector of GearDirs which point to all the nodes the given path evaluates to.
Definition Interface.cc:21
int getInt(const std::string &path="") const noexcept(false)
Get the parameter path as a int.
Definition Interface.cc:60
Thin wrapper around the Geant4 Material system.
Definition Materials.h:48
static G4Material * get(const std::string &name)
Find given material.
Definition Materials.h:63
static Materials & getInstance()
Get a reference to the singleton instance.
Definition Materials.cc:85
G4OpticalSurface * createOpticalSurface(const gearbox::Interface &parameters)
Create an optical surface from parameters, will abort on error.
Definition Materials.cc:295
G4Element * getElement(const std::string &name)
Find given chemical element.
Definition Materials.cc:150
Class to store variables with their name which were sent to the logging service.
void setOffset(const ROOT::Math::XYZVector &)
Set of the setup global offset.
int getDetectorXPadNumber()
get number of pads of detector module (in one direction)
void setAeroTransLength(int ilayer, double trlen)
set transmission length of "ilayer" aerogel layer
int AddHapdElectronicMapPair(int, int)
Set the mapping of the electronic channel to the HAPD module nr and the channel number.
void setRotationCenter(const ROOT::Math::XYZVector &)
Set the rotation center of the Aerogel RICH frame.
void setAerogelThickness(int ilayer, double thick)
set thickness of "ilayer" aerogel layer
void setTrackingShift(const ROOT::Math::XYZVector &)
Set the tracking shift.
double getSensitiveSurfaceSize() const
get size of detector sensitive surface (size of two chips + gap between)
bool getAverageAgel()
Get the flag for the reconstruction by using the average aerogel refractive index.
void setFrameRotation(double)
Set the rotation angle of the Aerogel RICH frame.
void setMwpc(ARICHTracking *m_mwpc)
Set the pointer of the tracking MWPCs.
void Initialize(const GearDir &content)
calculates detector parameters needed for geometry build and reconstruction.
void setAerogelZPosition(int ilayer, double zPos)
set z position of "ilayer" aerogel layer
static ARICHBtestGeometryPar * Instance()
Static method to get a reference to the ARICHBtestGeometryPar instance.
void Print(void) const
Print some debug information.
static ARICHGeometryPar * Instance()
Static method to get a reference to the ARICHGeometryPar instance.
void setAeroRefIndex(int ilayer, double n)
set refractive index of "ilayer" aerogel layer
double getModAngle(int copyno)
get the angle of copyno-th HAPD rotation
G4ThreeVector getOriginG4(int copyNo)
get the position of copyNo-th HAPD module origin (returns G4ThreeVector)
void setAverageAgel(bool)
Set the flag for the reconstruction by using the average aerogel refractive index.
int getNMCopies() const
get the total number of HAPD modules
void setActive(int module, int channel, bool val)
set the channel on/off
int AddHapdChannelPositionPair(double, double)
Set the position of the HAPD channel.
void setWindowRefIndex(double refInd)
set detector module window refractive index
Common code concerning the geometry representation of the detector.
Definition CreatorBase.h:25
void setVisibility(G4LogicalVolume &volume, bool visible)
Helper function to quickly set the visibility of a given volume.
Definition utilities.cc:108
void setColor(G4LogicalVolume &volume, const std::string &color)
Set the color of a logical volume.
Definition utilities.cc:100
GeometryTypes
Flag indicating the type of geometry to be used.
Abstract base class for different kinds of events.
STL namespace.