12 #include <boost/format.hpp>
13 #include <boost/foreach.hpp>
14 #include <boost/algorithm/string.hpp>
19 #include <G4LogicalVolume.hh>
20 #include <G4PVPlacement.hh>
21 #include <G4LogicalSkinSurface.hh>
22 #include <G4OpticalSurface.hh>
25 #include <G4SubtractionSolid.hh>
26 #include <G4Material.hh>
30 #include <arich/geometry/GeoARICHBtestCreator.h>
31 #include <arich/geometry/ARICHGeometryPar.h>
32 #include <arich/geometry/ARICHBtestGeometryPar.h>
34 #include <geometry/Materials.h>
35 #include <geometry/CreatorFactory.h>
36 #include <geometry/utilities.h>
37 #include <framework/gearbox/GearDir.h>
38 #include <framework/gearbox/Unit.h>
39 #include <framework/logging/Logger.h>
41 #include <framework/datastore/StoreObjPtr.h>
42 #include <framework/dataobjects/EventMetaData.h>
44 #include <arich/simulation/SensitiveDetector.h>
45 #include <arich/simulation/SensitiveAero.h>
48 using namespace boost;
56 using namespace geometry;
64 geometry::CreatorFactory<GeoARICHBtestCreator> GeoARICHBtestFactory(
"ARICHBtestCreator");
70 GeoARICHBtestCreator::GeoARICHBtestCreator():
94 B2INFO(
"GeoARICHBtestCreator::create");
98 PyObject* m = PyImport_AddModule(strdup(
"__main__"));
100 PyObject* v = PyObject_GetAttrString(m, strdup(
"runno"));
102 run = PyLong_AsLong(v);
105 B2INFO(
"GeoARICHBtestCreator::create runno = " << run);
108 B2INFO(
"eventMetaDataPtr run:" << run);
114 string Type = content.getString(
"@type",
"");
117 sprintf(nodestr,
"run[runno=%d]", run);
118 if (Type ==
"beamtest") {
119 BOOST_FOREACH(
const GearDir & runparam, content.getNodes(nodestr)) {
138 B2INFO(
"neve : " <<
m_neve);
144 B2INFO(
"rx : " <<
m_rx);
145 B2INFO(
"ry : " <<
m_ry);
154 sprintf(nodestr,
"setup/aerogel/row[@id=\"%s\"]",
m_aerogelID.c_str());
156 GearDir runparam(content, nodestr);
157 B2INFO(
"id : " << runparam.
getString(
"@id",
""));
158 BOOST_FOREACH(
const GearDir & aeroparam, runparam.
getNodes(
"aerogel")) {
159 aerogelname = aeroparam.
getString(
".",
"");
160 string stype = aeroparam.
getString(
"@type",
"");
161 B2INFO(stype <<
" aerogelname : " << aerogelname);
162 sprintf(nodestr,
"setup/aerogelinfo/row[@id=\"%s\"]", aerogelname.c_str());
163 GearDir infoparam(content, nodestr);
165 double agelrefind = infoparam.
getDouble(
"refind", 1);
166 double ageltrlen = infoparam.
getLength(
"trlen", 0);
167 double agelthickness = infoparam.
getLength(
"thickness", 0);
168 if (stype !=
string(
"left")) {
173 B2INFO(
"refind : " << agelrefind);
174 B2INFO(
"trlen : " << ageltrlen /
Unit::mm);
175 B2INFO(
"thickness : " << agelthickness /
Unit::mm);
182 char agelsupport =
m_hapdID.at(size - 1);
188 sprintf(nodestr,
"setup/hapd/row[@id=\"%s\"]",
m_hapdID.substr(0, size).c_str());
189 B2INFO(
"nodestr : " << nodestr);
191 GearDir hapdparam(content, nodestr);
215 G4MaterialPropertiesTable* mTable = material->GetMaterialPropertiesTable();
216 if (!mTable)
return 0;
217 G4MaterialPropertyVector* mVector = mTable->GetProperty(
"RINDEX");
218 if (!mVector)
return 0;
229 string wallMat =
Module.getString(
"wallMaterial");
230 string winMat =
Module.getString(
"windowMaterial");
231 string botMat =
Module.getString(
"Bottom/material");
239 if (!wref) B2WARNING(
"Material '" << winMat <<
240 "', required for ARICH photon detector window as no specified refractive index. Continuing, but no photons in ARICH will be detected.");
246 double wallThick =
Module.getLength(
"moduleWallThickness") /
Unit::mm;
247 double winThick =
Module.getLength(
"windowThickness") /
Unit::mm ;
249 double botThick =
Module.getLength(
"Bottom/thickness") /
Unit::mm;
252 if (sensXsize > modXsize - 2 * wallThick)
253 B2FATAL(
"ARICH photon detector module: Sensitive surface is too big. Doesn't fit into module box.");
254 if (winThick + botThick > modZsize)
255 B2FATAL(
"ARICH photon detector module: window + bottom thickness larger than module thickness.");
258 G4Box* moduleBox =
new G4Box(
"Box", modXsize / 2., modXsize / 2., modZsize / 2.);
259 G4LogicalVolume* lmoduleBox =
new G4LogicalVolume(moduleBox, boxFill,
"moduleBox");
262 G4Box* tempBox =
new G4Box(
"tempBox", modXsize / 2. - wallThick, modXsize / 2. - wallThick,
263 modZsize / 2. + 0.1);
264 G4SubtractionSolid* moduleWall =
new G4SubtractionSolid(
"Box-tempBox", moduleBox, tempBox);
265 G4LogicalVolume* lmoduleWall =
new G4LogicalVolume(moduleWall, wallMaterial,
"moduleWall");
266 setColor(*lmoduleWall,
"rgb(1.0,0.0,0.0,1.0)");
267 new G4PVPlacement(G4Transform3D(), lmoduleWall,
"moduleWall", lmoduleBox,
false, 1);
270 G4Box* winBox =
new G4Box(
"winBox", modXsize / 2. - wallThick, modXsize / 2. - wallThick, winThick / 2.);
271 G4LogicalVolume* lmoduleWin =
new G4LogicalVolume(winBox, windowMaterial,
"moduleWindow");
272 setColor(*lmoduleWin,
"rgb(0.7,0.7,0.7,1.0)");
273 G4Transform3D transform = G4Translate3D(0., 0., (-modZsize + winThick) / 2.);
274 new G4PVPlacement(transform, lmoduleWin,
"moduleWindow", lmoduleBox,
false, 1);
277 G4Box* botBox =
new G4Box(
"botBox", modXsize / 2. - wallThick, modXsize / 2. - wallThick, botThick / 2.);
278 G4LogicalVolume* lmoduleBot =
new G4LogicalVolume(botBox, bottomMaterial,
"moduleBottom");
280 setColor(*lmoduleBot,
"rgb(0.0,1.0,0.0,1.0)");
281 G4Transform3D transform1 = G4Translate3D(0., 0., (modZsize - botThick) / 2.);
287 new G4LogicalSkinSurface(
"bottomSurface", lmoduleBot, optSurf);
288 }
else B2INFO(
"ARICH: No optical properties are specified for detector module bottom surface.");
289 new G4PVPlacement(transform1, lmoduleBot,
"moduleBottom", lmoduleBox,
false, 1);
292 G4Box* sensBox =
new G4Box(
"sensBox", sensXsize / 2., sensXsize / 2., 0.1 *
Unit::mm);
293 G4LogicalVolume* lmoduleSens =
new G4LogicalVolume(sensBox, boxFill,
"moduleSensitive");
295 setColor(*lmoduleSens,
"rgb(0.5,0.5,0.5,1.0)");
296 G4Transform3D transform2 = G4Translate3D(0., 0., (-modZsize + 0.1) / 2. + winThick);
297 new G4PVPlacement(transform2, lmoduleSens,
"moduleSensitive", lmoduleBox,
false, 1);
308 G4double density = (RefractiveIndex - 1) / 0.21 * CLHEP::g / CLHEP::cm3;
309 B2INFO(
"Creating ARICH " << aeroname <<
" n=" << RefractiveIndex <<
" density=" << density / CLHEP::g * CLHEP::cm3 <<
" g/cm3");
311 G4Material* _aerogel =
new G4Material(aeroname, density, 4);
312 _aerogel->AddElement(materials.
getElement(
"O") , 0.665);
313 _aerogel->AddElement(materials.
getElement(
"H") , 0.042);
314 _aerogel->AddElement(materials.
getElement(
"Si") , 0.292);
315 _aerogel->AddElement(materials.
getElement(
"C") , 0.001);
318 const G4double AerogelAbsorbtionLength = 1000 *
Unit::mm;
320 const G4int NBins = 40;
321 G4double MomentumBins[NBins];
323 G4double AerogelRindex[NBins];
324 G4double AerogelAbsorption[NBins];
325 G4double AerogelRayleigh[NBins];
327 G4double MaxPhotonEnergy = 5 * CLHEP::eV;
328 G4double MinPhotonEnergy = 1.5 * CLHEP::eV;
330 for (G4int i = 0; i < NBins; i++) {
332 const G4double energy = float(i) / NBins * (MaxPhotonEnergy - MinPhotonEnergy) + MinPhotonEnergy;
334 MomentumBins[i] = energy;
335 AerogelRindex[i] = RefractiveIndex;
336 AerogelAbsorption[i] = AerogelAbsorbtionLength;
338 const G4double Lambda0 = 400 * 1e-6 * CLHEP::mm;
339 const G4double Lambda = 1240 * CLHEP::eV / energy * 1e-6 * CLHEP::mm;
340 G4double x = Lambda / Lambda0;
341 AerogelRayleigh[i] = AerogelTransmissionLength * x * x * x * x;
345 G4MaterialPropertiesTable* AeroProperty =
new G4MaterialPropertiesTable();
346 AeroProperty->AddProperty(
"RINDEX" , MomentumBins, AerogelRindex , NBins);
347 AeroProperty->AddProperty(
"ABSLENGTH", MomentumBins, AerogelAbsorption, NBins);
348 AeroProperty->AddProperty(
"RAYLEIGH" , MomentumBins, AerogelRayleigh, NBins);
351 _aerogel->SetMaterialPropertiesTable(AeroProperty);
361 B2INFO(
"ARICH Btest geometry will be built.");
368 GearDir boxParams(content,
"ExperimentalBox");
375 double zoffset = boxParams.
getLength(
"beamcenter/z") * CLHEP::mm /
Unit::mm - zBox / 2.;
376 G4ThreeVector roffset(xoffset, yoffset, zoffset);
382 string boxMat = boxParams.
getString(
"material");
384 G4Box* expBox =
new G4Box(
"ExperimentalBox", xBox / 2., yBox / 2., zBox / 2.);
385 G4LogicalVolume* topVolume =
new G4LogicalVolume(expBox, boxMaterial,
"ARICH.experimentalbox");
386 new G4PVPlacement(G4Transform3D(), topVolume,
"ARICH.experimentalbox", &topWorld,
false, 1);
389 TVector3 trackingshift(content.getLength(
"tracking/shift/x"),
390 content.getLength(
"tracking/shift/y"),
391 content.getLength(
"tracking/shift/z"));
394 sprintf(mnodestr,
"tracking/shift/run[@id=\"%d\"]",
m_runno);
395 if (content.exists(mnodestr)) {
396 GearDir runtrackingshift(content, mnodestr);
397 trackingshift[0] = runtrackingshift.
getLength(
"x");
398 trackingshift[1] = runtrackingshift.
getLength(
"y");
399 trackingshift[2] = runtrackingshift.
getLength(
"z");
404 BOOST_FOREACH(
const GearDir & mwpc, content.getNodes(
"tracking/mwpc")) {
413 G4Box* mwpcBox =
new G4Box(
"MwpcBox", x / 2., y / 2., z / 2.);
414 G4LogicalVolume* mwpcVol =
new G4LogicalVolume(mwpcBox,
Materials::get(mwpc.
getString(
"material")) ,
"ARICH.mwpc");
415 new G4PVPlacement(G4Transform3D(G4RotationMatrix(), G4ThreeVector(px, py, pz) + roffset), mwpcVol,
"ARICH.mwpc", topVolume,
false,
419 int id = mwpc.
getInt(
"@id", -1);
420 B2INFO(
"GeoARICHBtestCreator:: MWPC ID=" <<
id);
421 if (id < 4 && id >= 0) {
422 m_mwpc[id].
tdc[0] = mwpc.
getInt(
"tdc/y/up");
423 m_mwpc[id].
tdc[1] = mwpc.
getInt(
"tdc/y/down");
424 m_mwpc[id].
tdc[2] = mwpc.
getInt(
"tdc/x/left");
425 m_mwpc[id].
tdc[3] = mwpc.
getInt(
"tdc/x/right");
426 m_mwpc[id].
atdc = mwpc.
getInt(
"tdc/anode", 0);
444 istringstream mapstream;
446 mapstream.str(content.getString(
"hapdmap"));
447 while (mapstream >> mx >> my) {
454 mapstream.str(content.getString(
"hapdchmap"));
455 while (mapstream >> ipx >> ipy) {
460 GearDir frameParams(content,
"Frame");
464 string envMat = frameParams.
getString(
"material");
473 G4Box* envBox =
new G4Box(
"FrameBox", xFrame / 2., yFrame / 2., zFrame / 2.);
474 G4LogicalVolume* lenvBox =
new G4LogicalVolume(envBox, envMaterial,
"ARICH.frame");
475 G4ThreeVector frameOrigin0(
m_framedx + px, py, pz);
476 G4ThreeVector frameOrigin = frameOrigin0 + roffset;
477 G4RotationMatrix frameRotation;
478 frameRotation.rotateY(-
m_rotation1 * CLHEP::degree);
479 G4Transform3D frameTransformation = G4Transform3D(frameRotation, frameOrigin);
481 new G4PVPlacement(frameTransformation, lenvBox,
"ARICH.frame", topVolume,
false, 1);
484 TVector3 rotationCenter = TVector3(frameOrigin0.x() *
Unit::mm / CLHEP::mm, frameOrigin0.y() *
Unit::mm / CLHEP::mm,
485 frameOrigin0.z() *
Unit::mm / CLHEP::mm);
491 B2INFO(content.getPath());
493 GearDir hapdcontent(content, nodestr);
498 char mirrornodestr[256];
499 sprintf(mirrornodestr,
"Mirrors/setup[@id=\"%s\"]",
m_mirrorID.c_str());
501 GearDir mirrorcontent(content, mirrornodestr);
502 B2INFO(mirrorcontent.
getPath());
505 m_arichgp->
Initialize(hapdcontent, mirrorcontent);
508 GearDir moduleParam(hapdcontent,
"Detector/Module");
509 G4LogicalVolume* detModule =
buildModule(moduleParam);
511 double detZpos = hapdcontent.
getLength(
"Detector/Plane/zPosition") * CLHEP::mm /
Unit::mm;
512 double detThick = hapdcontent.
getLength(
"Detector/Module/moduleZSize") * CLHEP::mm /
Unit::mm;
515 for (
int i = 1; i <= nModules; i++) {
517 origin.setZ(detZpos + detThick / 2.);
521 G4Transform3D trans = G4Transform3D(Ra, origin);
522 new G4PVPlacement(G4Transform3D(Ra, origin), detModule,
"detModule", lenvBox,
false, i);
523 B2INFO(nodestr <<
"Module " << i <<
" is build ");
527 BOOST_FOREACH(
const double & ch, hapdcontent.
getArray(
"HotChannels")) {
528 int channelID = (int) ch;
529 int moduleID = (npx) ? channelID / (npx * npx) : 0;
530 channelID %= (npx * npx);
531 m_arichgp->
setActive(moduleID, channelID,
false);
532 B2INFO(
"HotChannel " << ch <<
" : Module " << moduleID <<
"channelID " << channelID <<
" disabled");
535 BOOST_FOREACH(
const double & ch, hapdcontent.
getArray(
"DeadChannels")) {
536 int channelID = (int) ch;
537 int moduleID = (npx) ? channelID / (npx * npx) : 0;
538 channelID %= (npx * npx);
539 m_arichgp->
setActive(moduleID, channelID,
false);
540 B2INFO(
"DeadChannel " << ch <<
" : Module " << moduleID <<
"channelID " << channelID <<
" disabled");
543 GearDir aerogelParam(content,
"Aerogel");
550 double meanrefind = 0;
551 double meantrlen = 0;
554 PyObject* m = PyImport_AddModule(strdup(
"__main__"));
557 PyObject* v = PyObject_GetAttrString(m, strdup(
"averageagel"));
559 averageagel = PyLong_AsLong(v);
562 B2INFO(
"Python averageagel = " << averageagel);
566 for (
unsigned int ilayer = 0; ilayer <
m_agelthickness.size(); ilayer++) {
568 sprintf(aeroname,
"Aerogel%u", ilayer + 1);
581 G4Box* tileBox =
new G4Box(
"tileBox", sizeX / 2., sizeY / 2., sizeZ / 2.);
582 G4LogicalVolume* lTile =
new G4LogicalVolume(tileBox, tileMaterial,
"Tile", 0, ilayer == 0 ?
m_sensitiveAero : 0);
583 setColor(*lTile,
"rgb(0.0, 1.0, 1.0,1.0)");
584 G4Transform3D trans = G4Translate3D(posX, posY, posZ + sizeZ / 2. - zFrame / 2.);
585 new G4PVPlacement(trans, lTile,
"ARICH.tile", lenvBox,
false, ilayer + 1);
589 B2INFO(
"Average aerogel will be used in the reconstruction ");
593 if (meantrlen > 0 && posZ > 0) meantrlen = 1 / meantrlen / posZ;
599 GearDir mirrorsParam(mirrorcontent,
"Mirrors");
603 string mirrMat = mirrorsParam.
getString(
"material");
605 G4Box* mirrBox =
new G4Box(
"mirrBox", thickness / 2., height / 2., width / 2.);
606 G4LogicalVolume* lmirror =
new G4LogicalVolume(mirrBox, mirrMaterial,
"mirror");
609 GearDir surface(mirrorsParam,
"Surface");
611 new G4LogicalSkinSurface(
"mirrorsSurface", lmirror, optSurf);
613 BOOST_FOREACH(
const GearDir & mirror, mirrorsParam.
getNodes(
"Mirror")) {
618 G4ThreeVector origin(xpos, ypos, zpos + width / 2. - zFrame / 2.);
621 G4Transform3D trans = G4Transform3D(Ra, origin);
622 new G4PVPlacement(G4Transform3D(Ra, origin), lmirror,
"ARICH.mirror", lenvBox,
false, iMirror);
626 m_arichbtgp->
Print();