Skip to content

Commit

Permalink
feat: Use RootTracksummaryWriter without truth information (#3886)
Browse files Browse the repository at this point in the history
Since some people start to do tests within the examples framework with real data, we should extend our algorithms/writers to not require these information. This PR does the relevant changes for the `RootTracksummaryWriter`.
  • Loading branch information
benjaminhuth authored Nov 26, 2024
1 parent 4cd88af commit 832b327
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -49,9 +49,9 @@ class RootTrackSummaryWriter final : public WriterT<ConstTrackContainer> {
struct Config {
/// Input (fitted) tracks collection
std::string inputTracks;
/// Input particles collection.
/// Input particles collection (optional).
std::string inputParticles;
/// Input track-particle matching.
/// Input track-particle matching (optional).
std::string inputTrackParticleMatching;
/// Output filename.
std::string filePath = "tracksummary.root";
Expand Down
27 changes: 14 additions & 13 deletions Examples/Io/Root/src/RootTrackSummaryWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,16 @@ RootTrackSummaryWriter::RootTrackSummaryWriter(
: WriterT(config.inputTracks, "RootTrackSummaryWriter", level),
m_cfg(config) {
// tracks collection name is already checked by base ctor
if (m_cfg.inputParticles.empty()) {
throw std::invalid_argument("Missing particles input collection");
}
if (m_cfg.inputTrackParticleMatching.empty()) {
throw std::invalid_argument("Missing input track particles matching");
}
if (m_cfg.filePath.empty()) {
throw std::invalid_argument("Missing output filename");
}
if (m_cfg.treeName.empty()) {
throw std::invalid_argument("Missing tree name");
}

m_inputParticles.initialize(m_cfg.inputParticles);
m_inputTrackParticleMatching.initialize(m_cfg.inputTrackParticleMatching);
m_inputParticles.maybeInitialize(m_cfg.inputParticles);
m_inputTrackParticleMatching.maybeInitialize(
m_cfg.inputTrackParticleMatching);

// Setup ROOT I/O
auto path = m_cfg.filePath;
Expand Down Expand Up @@ -220,9 +215,16 @@ ProcessCode RootTrackSummaryWriter::finalize() {

ProcessCode RootTrackSummaryWriter::writeT(const AlgorithmContext& ctx,
const ConstTrackContainer& tracks) {
// Read additional input collections
const auto& particles = m_inputParticles(ctx);
const auto& trackParticleMatching = m_inputTrackParticleMatching(ctx);
// In case we do not have truth info, we bind to a empty collection
const static SimParticleContainer emptyParticles;
const static TrackParticleMatching emptyTrackParticleMatching;

const auto& particles =
m_inputParticles.isInitialized() ? m_inputParticles(ctx) : emptyParticles;
const auto& trackParticleMatching =
m_inputTrackParticleMatching.isInitialized()
? m_inputTrackParticleMatching(ctx)
: emptyTrackParticleMatching;

// For each particle within a track, how many hits did it contribute
std::vector<ParticleHitCount> particleHitCounts;
Expand All @@ -244,6 +246,7 @@ ProcessCode RootTrackSummaryWriter::writeT(const AlgorithmContext& ctx,
m_nSharedHits.push_back(track.nSharedHits());
m_chi2Sum.push_back(track.chi2());
m_NDF.push_back(track.nDoF());

{
std::vector<double> measurementChi2;
std::vector<std::uint32_t> measurementVolume;
Expand All @@ -266,8 +269,6 @@ ProcessCode RootTrackSummaryWriter::writeT(const AlgorithmContext& ctx,
measurementLayer.push_back(layer);
}
}
// IDs are stored as double (as the vector of vector of int is not known
// to ROOT)
m_measurementChi2.push_back(std::move(measurementChi2));
m_measurementVolume.push_back(std::move(measurementVolume));
m_measurementLayer.push_back(std::move(measurementLayer));
Expand Down
37 changes: 37 additions & 0 deletions Examples/Python/tests/test_writer.py
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,43 @@ def test_root_simhits_writer(tmp_path, fatras, conf_const, assert_root_hash):
assert_root_hash(out.name, out)


@pytest.mark.root
def test_root_tracksummary_writer(tmp_path, fatras, conf_const):
detector, trackingGeometry, decorators = GenericDetector.create()
field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T))
s = Sequencer(numThreads=1, events=10)

from truth_tracking_kalman import runTruthTrackingKalman

# This also runs the RootTrackSummaryWriter with truth information
runTruthTrackingKalman(
trackingGeometry,
field,
digiConfigFile=Path(
str(
Path(__file__).parent.parent.parent.parent
/ "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json"
)
),
outputDir=tmp_path,
s=s,
)

# Run the RootTrackSummaryWriter without the truth information
s.addWriter(
conf_const(
RootTrackSummaryWriter,
level=acts.logging.INFO,
inputTracks="tracks",
filePath=str(tmp_path / "track_summary_kf_no_truth.root"),
)
)

s.run()
assert (tmp_path / "tracksummary_kf.root").exists()
assert (tmp_path / "track_summary_kf_no_truth.root").exists()


@pytest.mark.csv
def test_csv_meas_writer(tmp_path, fatras, trk_geo, conf_const):
s = Sequencer(numThreads=1, events=10)
Expand Down

0 comments on commit 832b327

Please sign in to comment.