41 if (macroFile.empty()) {
45 if (!std::filesystem::exists(expandedHookFileName)) {
46 LOG(error) <<
"External geometry macro " << expandedHookFileName <<
" does not exist";
51 std::ifstream macroStream(expandedHookFileName, std::ios::in);
52 if (!macroStream.is_open()) {
53 LOG(error) <<
"Cannot open external geometry macro " << expandedHookFileName;
59 while (std::getline(macroStream, line)) {
60 auto firstNonSpace = line.find_first_not_of(
" \t");
61 if (firstNonSpace != std::string::npos && line[firstNonSpace] ==
'#') {
62 preamble += line +
"\n";
69 static std::atomic<int> instanceCounter{0};
70 std::string ns = std::string(
"o2_cadgeom_") + instanceTag +
"_" +
std::to_string(instanceCounter++);
72 if (!std::isalnum(
static_cast<unsigned char>(
c)) &&
c !=
'_') {
77 const std::string wrapped = preamble +
"\nnamespace " + ns +
" {\n" + body +
"\n}\n";
78 if (!gInterpreter->Declare(wrapped.c_str())) {
79 LOG(error) <<
"Failed to JIT external geometry macro " << expandedHookFileName;
84 const std::string globalName =
"__" + ns +
"_hook__";
85 gROOT->ProcessLine(Form(
"std::function<TGeoVolume*()> %s = %s::get_builder_hook_unchecked();",
86 globalName.c_str(), ns.c_str()));
87 auto global = gROOT->GetGlobal(globalName.c_str());
89 LOG(error) <<
"Could not retrieve geometry builder hook from macro " << expandedHookFileName;
92 auto hook = *
reinterpret_cast<std::function<TGeoVolume*()
>*>(global->GetAddress());
93 LOG(info) <<
"CAD geometry hook initialized from file " << expandedHookFileName <<
" (namespace " << ns <<
")";
97 LOG(error) <<
"CAD geometry macro " << expandedHookFileName <<
" did not return a top volume";
104 std::unordered_map<TGeoMedium*, TGeoMedium*> medium_ptr_mapping;
105 std::unordered_set<TGeoVolume*> volumes_already_treated;
107 std::unordered_map<std::string, int> material_index;
112 auto transform_media = [&](TGeoVolume* vol_) {
113 if (volumes_already_treated.find(vol_) != volumes_already_treated.end()) {
117 volumes_already_treated.insert(vol_);
119 if (
dynamic_cast<TGeoVolumeAssembly*
>(vol_)) {
124 auto medium = vol_->GetMedium();
129 auto iter = medium_ptr_mapping.find(medium);
130 if (iter != medium_ptr_mapping.end()) {
133 vol_->SetMedium(iter->second);
136 LOG(info) <<
"Transforming media with name " << medium->GetName() <<
" for volume " << vol_->GetName();
139 auto curr_mat = medium->GetMaterial();
143 const std::string matname(curr_mat->GetName());
144 auto itmat = material_index.find(matname);
146 if (itmat != material_index.end()) {
147 imat = itmat->second;
151 if (
auto* mix =
dynamic_cast<TGeoMixture*
>(curr_mat)) {
152 const Int_t nel = mix->GetNelements();
153 std::vector<Float_t>
a(nel),
z(nel),
w(nel);
154 for (Int_t
i = 0;
i < nel; ++
i) {
155 a[
i] = mix->GetAmixt()[
i];
156 z[
i] = mix->GetZmixt()[
i];
157 w[
i] = mix->GetWmixt()[
i];
159 matmgr.Mixture(modulename, imat, curr_mat->GetName(),
a.data(),
z.data(),
160 curr_mat->GetDensity(), nel,
w.data());
162 matmgr.Material(modulename, imat, curr_mat->GetName(), curr_mat->GetA(), curr_mat->GetZ(), curr_mat->GetDensity(), curr_mat->GetRadLen(), curr_mat->GetIntLen());
164 material_index[matname] = imat;
175 const auto isvol = medium->GetParam(0);
176 const auto isxfld = medium->GetParam(1);
177 const auto sxmgmx = medium->GetParam(2);
178 const auto tmaxfd = medium->GetParam(3);
179 const auto stemax = medium->GetParam(4);
180 const auto deemax = medium->GetParam(5);
181 const auto epsil = medium->GetParam(6);
182 const auto stmin = medium->GetParam(7);
184 matmgr.Medium(modulename,
counter, medium->GetName(), imat, isvol, isxfld, sxmgmx, tmaxfd, stemax, deemax, epsil, stmin);
187 auto new_med = matmgr.getTGeoMedium(modulename,
counter);
190 medium_ptr_mapping[medium] = new_med;
191 vol_->SetMedium(new_med);
197 std::function<
void(TGeoVolume*)> visit_volume;
198 visit_volume = [&](TGeoVolume* vol) ->
void {
204 transform_media(vol);
207 const int nd = vol->GetNdaughters();
208 for (
int i = 0;
i < nd; ++
i) {
209 TGeoNode*
node = vol->GetNode(
i);
213 TGeoVolume* child =
node->GetVolume();