Skip to content

Commit c4bea8d

Browse files
authored
Add hit manager output diagnostic (#1596)
1 parent 3245c1b commit c4bea8d

7 files changed

+190
-2
lines changed

src/accel/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ list(APPEND SOURCES
2424
SimpleOffload.cc
2525
detail/GeantSimpleCaloSD.cc
2626
detail/HitManager.cc
27+
detail/HitManagerOutput.cc
2728
detail/HitProcessor.cc
2829
detail/LevelTouchableUpdater.cc
2930
detail/NaviTouchableUpdater.cc

src/accel/SharedParams.cc

+3
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
#include "SetupOptions.hh"
6565

6666
#include "detail/HitManager.hh"
67+
#include "detail/HitManagerOutput.hh"
6768
#include "detail/OffloadWriter.hh"
6869

6970
namespace celeritas
@@ -649,6 +650,8 @@ void SharedParams::initialize_core(SetupOptions const& options)
649650
params_->max_streams());
650651
step_collector_
651652
= StepCollector::make_and_insert(*params_, {hit_manager_});
653+
output_reg_->insert(
654+
std::make_shared<detail::HitManagerOutput>(hit_manager_));
652655
}
653656

654657
// Add diagnostics

src/accel/detail/HitManager.hh

+3
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,9 @@ class HitManager final : public StepInterface
9595
//! Access mapped particles if recreating G4Tracks later
9696
VecParticle const& geant_particles() const { return particles_; }
9797

98+
//! Whether detailed volume information is reconstructed
99+
bool locate_touchable() const { return locate_touchable_; }
100+
98101
private:
99102
using VecLV = std::vector<G4LogicalVolume const*>;
100103

src/accel/detail/HitManagerOutput.cc

+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//------------------------------- -*- C++ -*- -------------------------------//
2+
// Copyright Celeritas contributors: see top-level COPYRIGHT file for details
3+
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
4+
//---------------------------------------------------------------------------//
5+
//! \file accel/detail/HitManagerOutput.cc
6+
//---------------------------------------------------------------------------//
7+
#include "HitManagerOutput.hh"
8+
9+
#include <G4LogicalVolume.hh>
10+
#include <G4VSensitiveDetector.hh>
11+
#include <nlohmann/json.hpp>
12+
13+
#include "corecel/cont/Range.hh"
14+
#include "corecel/io/JsonPimpl.hh"
15+
#include "corecel/sys/TypeDemangler.hh"
16+
17+
#include "HitManager.hh"
18+
19+
namespace celeritas
20+
{
21+
namespace detail
22+
{
23+
//---------------------------------------------------------------------------//
24+
/*!
25+
* Construct from hit manager.
26+
*/
27+
HitManagerOutput::HitManagerOutput(SPConstHitManager hits)
28+
: hits_(std::move(hits))
29+
{
30+
CELER_EXPECT(hits_);
31+
}
32+
33+
//---------------------------------------------------------------------------//
34+
/*!
35+
* Write output to the given JSON object.
36+
*/
37+
void HitManagerOutput::output(JsonPimpl* j) const
38+
{
39+
using json = nlohmann::json;
40+
41+
auto result = json::object();
42+
43+
// Save detectors
44+
{
45+
auto const& celer_vols = hits_->celer_vols();
46+
auto const& geant_vols = *hits_->geant_vols();
47+
TypeDemangler<G4VSensitiveDetector> demangle_sd;
48+
49+
auto vol_ids = json::array();
50+
auto gv_names = json::array();
51+
auto sd_names = json::array();
52+
auto sd_types = json::array();
53+
54+
for (auto i : range(celer_vols.size()))
55+
{
56+
vol_ids.push_back(celer_vols[i].get());
57+
58+
auto const* lv = geant_vols[i];
59+
G4VSensitiveDetector const* sd{nullptr};
60+
if (lv)
61+
{
62+
gv_names.push_back(lv->GetName());
63+
sd = lv->GetSensitiveDetector();
64+
}
65+
else
66+
{
67+
gv_names.push_back(nullptr);
68+
}
69+
70+
if (sd)
71+
{
72+
sd_names.push_back(sd->GetName());
73+
sd_types.push_back(demangle_sd(*sd));
74+
}
75+
else
76+
{
77+
sd_names.push_back(nullptr);
78+
sd_types.push_back(nullptr);
79+
}
80+
}
81+
82+
result["vol_id"] = std::move(vol_ids);
83+
result["lv_name"] = std::move(gv_names);
84+
result["sd_name"] = std::move(sd_names);
85+
result["sd_type"] = std::move(sd_types);
86+
}
87+
88+
// TODO: save filter selection
89+
result["locate_touchable"] = hits_->locate_touchable();
90+
91+
j->obj = std::move(result);
92+
}
93+
94+
//---------------------------------------------------------------------------//
95+
} // namespace detail
96+
} // namespace celeritas

src/accel/detail/HitManagerOutput.hh

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
//------------------------------- -*- C++ -*- -------------------------------//
2+
// Copyright Celeritas contributors: see top-level COPYRIGHT file for details
3+
// SPDX-License-Identifier: (Apache-2.0 OR MIT)
4+
//---------------------------------------------------------------------------//
5+
//! \file accel/detail/HitManagerOutput.hh
6+
//---------------------------------------------------------------------------//
7+
#pragma once
8+
9+
#include <memory>
10+
11+
#include "corecel/io/OutputInterface.hh"
12+
13+
namespace celeritas
14+
{
15+
namespace detail
16+
{
17+
class HitManager;
18+
19+
//---------------------------------------------------------------------------//
20+
/*!
21+
* Save debugging information about sensitive detector mappings.
22+
*/
23+
class HitManagerOutput final : public OutputInterface
24+
{
25+
public:
26+
//!@{
27+
//! \name Type aliases
28+
using SPConstHitManager = std::shared_ptr<HitManager const>;
29+
//!@}
30+
31+
public:
32+
// Construct from shared hit manager
33+
explicit HitManagerOutput(SPConstHitManager hits);
34+
35+
//! Category of data to write
36+
Category category() const final { return Category::internal; }
37+
38+
//! Name of the entry inside the category.
39+
std::string_view label() const final { return "hit-manager"; }
40+
41+
// Write output to the given JSON object
42+
void output(JsonPimpl*) const final;
43+
44+
private:
45+
SPConstHitManager hits_;
46+
};
47+
48+
//---------------------------------------------------------------------------//
49+
} // namespace detail
50+
} // namespace celeritas

src/accel/detail/SensDetInserter.cc

+2-2
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ VolumeId SensDetInserter::insert_impl(G4LogicalVolume const* lv)
6161
{
6262
CELER_LOG(debug)
6363
<< "Skipping automatic SD callback for logical volume \""
64-
<< lv->GetName() << "\" due to user option";
64+
<< PrintableLV{lv} << "\" due to user option";
6565
return {};
6666
}
6767

@@ -78,7 +78,7 @@ VolumeId SensDetInserter::insert_impl(G4LogicalVolume const* lv)
7878
// Add Geant4 volume and corresponding volume ID to list
7979
auto [iter, inserted] = found_->insert({id, lv});
8080

81-
if (CELER_UNLIKELY(!inserted)) // && iter->second != lv))
81+
if (CELER_UNLIKELY(!inserted))
8282
{
8383
if (iter->second != lv)
8484
{

test/accel/detail/HitManager.test.cc

+35
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "celeritas/geo/GeoParams.hh"
2222
#include "accel/SDTestBase.hh"
2323
#include "accel/SetupOptions.hh"
24+
#include "accel/detail/HitManagerOutput.hh"
2425

2526
#include "celeritas_test.hh"
2627

@@ -101,6 +102,13 @@ class SimpleCmsTest : public ::celeritas::test::SDTestBase,
101102
return result;
102103
}
103104

105+
std::string get_diagnostics(HitManager const& hm)
106+
{
107+
HitManagerOutput out(
108+
std::shared_ptr<HitManager const>(&hm, [](HitManager const*) {}));
109+
return to_string(out);
110+
}
111+
104112
protected:
105113
SDSetupOptions sd_setup_;
106114
::celeritas::test::ScopedLogStorer scoped_log_{&celeritas::world_logger()};
@@ -124,6 +132,13 @@ TEST_F(SimpleCmsTest, no_change)
124132
{
125133
EXPECT_TRUE(scoped_log_.empty()) << scoped_log_;
126134
}
135+
136+
if (CELERITAS_CORE_GEO == CELERITAS_CORE_GEO_ORANGE)
137+
{
138+
EXPECT_JSON_EQ(
139+
R"json({"_category":"internal","_label":"hit-manager","locate_touchable":true,"lv_name":["em_calorimeter","had_calorimeter"],"sd_name":["em_calorimeter","had_calorimeter"],"sd_type":["celeritas::test::SimpleSensitiveDetector","celeritas::test::SimpleSensitiveDetector"],"vol_id":[3,4]})json",
140+
this->get_diagnostics(man));
141+
}
127142
}
128143

129144
TEST_F(SimpleCmsTest, delete_one)
@@ -150,6 +165,13 @@ TEST_F(SimpleCmsTest, delete_one)
150165
{
151166
EXPECT_TRUE(scoped_log_.empty()) << scoped_log_;
152167
}
168+
169+
if (CELERITAS_CORE_GEO == CELERITAS_CORE_GEO_ORANGE)
170+
{
171+
EXPECT_JSON_EQ(
172+
R"json({"_category":"internal","_label":"hit-manager","locate_touchable":true,"lv_name":["em_calorimeter"],"sd_name":["em_calorimeter"],"sd_type":["celeritas::test::SimpleSensitiveDetector"],"vol_id":[3]})json",
173+
this->get_diagnostics(man));
174+
}
153175
}
154176

155177
TEST_F(SimpleCmsTest, add_duplicate)
@@ -180,6 +202,13 @@ TEST_F(SimpleCmsTest, add_duplicate)
180202
= {"debug", "debug", "debug"};
181203
EXPECT_VEC_EQ(expected_log_levels, scoped_log_.levels());
182204
}
205+
206+
if (CELERITAS_CORE_GEO == CELERITAS_CORE_GEO_ORANGE)
207+
{
208+
EXPECT_JSON_EQ(
209+
R"json({"_category":"internal","_label":"hit-manager","locate_touchable":true,"lv_name":["em_calorimeter","had_calorimeter"],"sd_name":["em_calorimeter","had_calorimeter"],"sd_type":["celeritas::test::SimpleSensitiveDetector","celeritas::test::SimpleSensitiveDetector"],"vol_id":[3,4]})json",
210+
this->get_diagnostics(man));
211+
}
183212
}
184213

185214
TEST_F(SimpleCmsTest, add_one)
@@ -199,6 +228,12 @@ TEST_F(SimpleCmsTest, add_one)
199228
{
200229
EXPECT_TRUE(scoped_log_.empty()) << scoped_log_;
201230
}
231+
if (CELERITAS_CORE_GEO == CELERITAS_CORE_GEO_ORANGE)
232+
{
233+
EXPECT_JSON_EQ(
234+
R"json({"_category":"internal","_label":"hit-manager","locate_touchable":true,"lv_name":["si_tracker","em_calorimeter","had_calorimeter"],"sd_name":[null,"em_calorimeter","had_calorimeter"],"sd_type":[null,"celeritas::test::SimpleSensitiveDetector","celeritas::test::SimpleSensitiveDetector"],"vol_id":[2,3,4]})json",
235+
this->get_diagnostics(man));
236+
}
202237
}
203238

204239
TEST_F(SimpleCmsTest, no_detector)

0 commit comments

Comments
 (0)