-
Notifications
You must be signed in to change notification settings - Fork 0
feat: add smoke-test workflow #9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,24 @@ | ||
| #!/usr/bin/env bash | ||
| # SPDX-FileCopyrightText: 2026 CERN for the benefit of the SHiP Collaboration | ||
| # | ||
| # SPDX-License-Identifier: LGPL-3.0-or-later | ||
|
|
||
| # Quick smoke test for CI: generate a small simulation-like input, run the | ||
| # digitisation workflow end to end, and check that the outputs were produced. | ||
| set -euo pipefail | ||
|
|
||
| ./build/make_test_input smoke_input.root 10 | ||
|
|
||
| # Remove outputs from previous runs so stale files cannot pass the checks. | ||
| rm -f smoke_digi_output.root smoke_digi_validation.root | ||
|
|
||
| phlex -c workflows/smoke.jsonnet | ||
|
|
||
| for f in smoke_digi_output.root smoke_digi_validation.root; do | ||
| if ! [ -s "$f" ]; then | ||
| echo "missing output: $f" >&2 | ||
| exit 1 | ||
| fi | ||
| done | ||
| python scripts/validate_smoke.py smoke_digi_output.root smoke_digi_validation.root | ||
| echo "Smoke test OK" | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| #!/usr/bin/env python3 | ||
| # SPDX-FileCopyrightText: 2026 CERN for the benefit of the SHiP Collaboration | ||
| # | ||
| # SPDX-License-Identifier: LGPL-3.0-or-later | ||
|
|
||
| """Validate the smoke-test outputs of the digitisation workflow. | ||
|
|
||
| Checks that the digitised-output file contains all per-detector RNTuples and | ||
| that the validation file contains all histograms, each with entries. | ||
| """ | ||
|
|
||
| import os | ||
| import sys | ||
|
|
||
| import ROOT | ||
|
|
||
| NTUPLES = [ | ||
| "calorimeter_hits", | ||
| "sbt_hits", | ||
| "straw_tubes_hits", | ||
| "timing_detector_hits", | ||
| "ubt_hits", | ||
| ] | ||
|
|
||
| HISTOGRAMS = [ | ||
| "h_ubt_multiplicity", | ||
| "h_sbt_multiplicity", | ||
| "h_straw_tubes_multiplicity", | ||
| "h_calorimeter_multiplicity", | ||
| "h_timing_detector_multiplicity", | ||
| "h_hit_x", | ||
| "h_hit_y", | ||
| "h_hit_z", | ||
| ] | ||
|
|
||
|
|
||
| def check_ntuples(path): | ||
| errors = [] | ||
| for name in NTUPLES: | ||
| try: | ||
| reader = ROOT.RNTupleReader.Open(name, path) | ||
| except Exception as e: | ||
| errors.append(f"{path}: cannot open RNTuple '{name}': {e}") | ||
| continue | ||
| if reader.GetNEntries() == 0: | ||
| errors.append(f"{path}: RNTuple '{name}' has no entries") | ||
| return errors | ||
|
|
||
|
|
||
| def check_histograms(path): | ||
| try: | ||
| file = ROOT.TFile.Open(path) | ||
| except OSError as e: | ||
| return [f"{path}: cannot open file: {e}"] | ||
| if not file or file.IsZombie(): | ||
| return [f"{path}: cannot open file"] | ||
| errors = [] | ||
| for name in HISTOGRAMS: | ||
| hist = file.Get(name) | ||
| if not hist: | ||
| errors.append(f"{path}: missing histogram '{name}'") | ||
| elif hist.GetEntries() == 0: | ||
| errors.append(f"{path}: histogram '{name}' has no entries") | ||
| return errors | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| if len(sys.argv) != 3: | ||
| print(f"usage: {sys.argv[0]} <digi_output.root> <validation.root>", file=sys.stderr) | ||
| sys.exit(2) | ||
| errors = check_ntuples(sys.argv[1]) + check_histograms(sys.argv[2]) | ||
| for error in errors: | ||
| print(error, file=sys.stderr) | ||
| sys.stdout.flush() | ||
| sys.stderr.flush() | ||
| # Skip interpreter shutdown to dodge a PyROOT RNTuple teardown crash. | ||
| os._exit(1 if errors else 0) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,79 @@ | ||
| // SPDX-FileCopyrightText: 2026 CERN for the benefit of the SHiP Collaboration | ||
| // | ||
| // SPDX-License-Identifier: LGPL-3.0-or-later | ||
|
|
||
| // make_test_input.cpp — deterministic simulation-like input for smoke tests | ||
| // | ||
| // Writes an RNTuple in the layout produced by the simulation chain | ||
| // (sim_particles + sim_hits per event), with hits covering all detector | ||
| // IDs, so the digitisation workflow can run without Geant4 or aegir. | ||
|
|
||
| #include <ROOT/RNTupleModel.hxx> | ||
| #include <ROOT/RNTupleWriter.hxx> | ||
|
|
||
| #include <SHiP/SimHit.hpp> | ||
| #include <SHiP/SimParticle.hpp> | ||
| #include <SHiP/detectors/detector_id.hpp> | ||
| #include <cstdint> | ||
| #include <cstdio> | ||
| #include <limits> | ||
| #include <philox_rng.hpp> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
| int main(int argc, char* argv[]) { | ||
| std::string const filename = argc > 1 ? argv[1] : "smoke_input.root"; | ||
| auto const n_events = argc > 2 ? std::stoul(argv[2]) : 10UL; | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| // The event loop counts (and seeds the RNG) with a uint32_t. | ||
| if (n_events > std::numeric_limits<std::uint32_t>::max()) { | ||
| std::fprintf(stderr, "n_events out of range: %lu\n", n_events); | ||
| return 1; | ||
| } | ||
|
|
||
| auto model = ROOT::RNTupleModel::Create(); | ||
| auto particles = model->MakeField<std::vector<SHiP::SimParticle>>("sim_particles"); | ||
| auto hits = model->MakeField<std::vector<SHiP::SimHit>>("sim_hits"); | ||
| auto writer = ROOT::RNTupleWriter::Recreate(std::move(model), "events", filename); | ||
|
|
||
| constexpr SHiP::detector_id detectors[] = { | ||
| SHiP::detector_id::UpstreamTagger, SHiP::detector_id::SurroundTagger, | ||
| SHiP::detector_id::StrawTubes, SHiP::detector_id::Calorimeter, | ||
| SHiP::detector_id::TimingDetector}; | ||
|
|
||
| for (std::uint32_t event = 0; event < n_events; ++event) { | ||
| Shannon::PhiloxRng rng{0, 0x7E57DA7A, event}; | ||
|
|
||
| particles->clear(); | ||
| hits->clear(); | ||
|
|
||
| auto const n_tracks = 1 + static_cast<int>(rng.uniform(0.0, 3.0)); | ||
| for (int track = 0; track < n_tracks; ++track) { | ||
| SHiP::SimParticle particle; | ||
| particle.trackId = track; | ||
| particle.parentId = -1; | ||
| particle.pdgCode = 13; | ||
| particle.momentum = {rng.uniform(-0.5, 0.5), rng.uniform(-0.5, 0.5), | ||
| rng.uniform(10.0, 100.0)}; | ||
| particle.energy = particle.momentum[2]; | ||
| particles->push_back(particle); | ||
|
|
||
| for (auto const detector : detectors) { | ||
| SHiP::SimHit hit; | ||
| hit.detectorId = static_cast<std::int32_t>(detector); | ||
| hit.trackId = track; | ||
| hit.pdgCode = particle.pdgCode; | ||
| hit.position = {rng.uniform(-500.0, 500.0), rng.uniform(-500.0, 500.0), | ||
| rng.uniform(0.0, 10000.0)}; | ||
| hit.momentum = particle.momentum; | ||
| hit.energyDeposit = rng.uniform(0.0, 0.1); | ||
| hit.time = rng.uniform(0.0, 100.0); | ||
| hit.pathLength = rng.uniform(0.0, 10.0); | ||
| hits->push_back(hit); | ||
| } | ||
| } | ||
| writer->Fill(); | ||
| } | ||
|
|
||
| std::printf("Wrote %lu events to %s\n", n_events, filename.c_str()); | ||
| return 0; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,33 @@ | ||
| { | ||
| driver: { | ||
| cpp: 'generate_layers', | ||
| layers: { | ||
| spill: { parent: 'job', total: 10 }, | ||
| }, | ||
| }, | ||
|
|
||
| sources: { | ||
| rntuple_source: { | ||
| cpp: 'read_sim_file', | ||
| input_file: 'smoke_input.root', | ||
| ntuple_name: 'events', | ||
| layer: 'spill', | ||
| }, | ||
| }, | ||
|
|
||
| modules: { | ||
| digitise_hits: { | ||
| cpp: 'digitise_hits', | ||
| layer: 'spill', | ||
| seed: 42, | ||
| }, | ||
| digitised_output: { | ||
| cpp: 'digitised_output_module', | ||
| mode: 'digi', | ||
| rntuple_file: 'smoke_digi_output.root', | ||
| histo_file: 'smoke_digi_validation.root', | ||
| creator: 'digitise_hits', | ||
| layer: 'spill', | ||
| }, | ||
| }, | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.