18#include <TGeoManager.h>
19#include <TGeoVolume.h>
20#include <TGeoMatrix.h>
21#include <rapidjson/document.h>
22#include <rapidjson/error/en.h>
23#include <rapidjson/istreamwrapper.h>
47 auto anchor = gGeoManager->FindVolumeFast(mOptions.
anchor_volume.c_str());
49 LOG(error) <<
"Anchor volume " << mOptions.
anchor_volume <<
" not found. Aborting";
52 anchor->AddNode(module_top, 1,
const_cast<TGeoMatrix*
>(mOptions.
placement));
59TGeoMatrix* makePlacementFromJSON(
const rapidjson::Value& placement)
61 auto combi =
new TGeoCombiTrans();
62 if (placement.HasMember(
"rotation_deg") && placement[
"rotation_deg"].IsArray()) {
63 const auto&
r = placement[
"rotation_deg"];
65 combi->RotateX(
r[0].GetDouble());
66 combi->RotateY(
r[1].GetDouble());
67 combi->RotateZ(
r[2].GetDouble());
69 LOG(warning) <<
"ExternalModule placement 'rotation_deg' must have 3 entries; ignoring";
72 if (placement.HasMember(
"translation") && placement[
"translation"].IsArray()) {
73 const auto& t = placement[
"translation"];
75 combi->SetDx(t[0].GetDouble());
76 combi->SetDy(t[1].GetDouble());
77 combi->SetDz(t[2].GetDouble());
79 LOG(warning) <<
"ExternalModule placement 'translation' must have 3 entries; ignoring";
88 std::vector<ExternalModule*>
result;
91 std::ifstream fileStream(expanded, std::ios::in);
92 if (!fileStream.is_open()) {
93 LOG(error) <<
"Cannot open external geometry config file '" << expanded <<
"'";
97 rapidjson::IStreamWrapper isw(fileStream);
98 rapidjson::Document doc;
100 if (doc.HasParseError()) {
101 LOG(error) <<
"Error parsing external geometry JSON '" << expanded <<
"': "
102 << rapidjson::GetParseError_En(doc.GetParseError())
103 <<
" (offset " << doc.GetErrorOffset() <<
")";
106 if (!doc.HasMember(
"externalModules") || !doc[
"externalModules"].IsArray()) {
107 LOG(error) <<
"External geometry JSON '" << expanded <<
"' must contain an 'externalModules' array";
111 auto getString = [](
const rapidjson::Value&
v,
const char*
key) -> std::string {
112 if (
v.HasMember(
key) &&
v[
key].IsString()) {
113 return v[
key].GetString();
115 return std::string();
118 for (
const auto&
entry : doc[
"externalModules"].GetArray()) {
119 if (!
entry.IsObject()) {
120 LOG(error) <<
"Skipping non-object entry in 'externalModules'";
123 const auto name = getString(
entry,
"name");
125 LOG(error) <<
"Skipping external module entry without 'name'";
132 LOG(error) <<
"External module '" <<
name <<
"' requires both 'macro' and 'anchor'; skipping";
135 if (
entry.HasMember(
"placement") &&
entry[
"placement"].IsObject()) {
138 auto title = getString(
entry,
"title");
Helpers to inject CAD-derived (TGeo) geometry into O2 simulation.
void ConstructGeometry() override
static std::vector< ExternalModule * > createFromJSON(const std::string &jsonfile)
a common base class for passive modules - implementing generic functions
GLuint const GLchar * name
TGeoVolume * buildCADVolumeFromMacro(const std::string ¯oFile, const std::string &instanceTag)
void remapCADMedia(TGeoVolume *top, const char *modulename)
std::string expandShellVarsInFileName(std::string const &input)
std::string root_macro_file
TGeoMatrix const * placement
std::string anchor_volume
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"