diff --git a/CI/physmon/phys_perf_mon.sh b/CI/physmon/phys_perf_mon.sh index fa3027bb8f6..841fad5c376 100755 --- a/CI/physmon/phys_perf_mon.sh +++ b/CI/physmon/phys_perf_mon.sh @@ -20,8 +20,8 @@ shopt -s extglob mode=${1:-all} -if ! [[ $mode = @(all|kf|gsf|gx2f|fullchains|simulation) ]]; then - echo "Usage: $0 (outdir)" +if ! [[ $mode = @(all|kf|gsf|gx2f|refit_kf|refit_gsf|fullchains|simulation) ]]; then + echo "Usage: $0 (outdir)" exit 1 fi @@ -152,6 +152,12 @@ fi if [[ "$mode" == "all" || "$mode" == "gx2f" ]]; then run_physmon_gen "Truth Tracking GX2F" "trackfitting_gx2f" fi +if [[ "$mode" == "all" || "$mode" == "refit_kf" ]]; then + run_physmon_gen "Truth Tracking KF refit" "trackrefitting_kf" +fi +if [[ "$mode" == "all" || "$mode" == "refit_gsf" ]]; then + run_physmon_gen "Truth Tracking GSF refit" "trackrefitting_gsf" +fi if [[ "$mode" == "all" || "$mode" == "fullchains" ]]; then run_physmon_gen "CKF single muon" "trackfinding_1muon" run_physmon_gen "CKF muon 50" "trackfinding_4muon_50vertices" @@ -411,6 +417,26 @@ if [[ "$mode" == "all" || "$mode" == "gx2f" ]]; then --config CI/physmon/config/trackfitting_gx2f.yml fi +if [[ "$mode" == "all" || "$mode" == "kf_refit" ]]; then + run_histcmp \ + $outdir/data/trackrefitting_kf/performance_trackrefitting.root \ + $refdir/trackrefitting_kf/performance_trackrefitting.root \ + "Truth tracking (KF refit)" \ + trackrefitting_kf/performance_trackrefitting.html \ + trackrefitting_kf/performance_trackrefitting_plots \ + --config CI/physmon/config/trackfitting_kf.yml +fi + +if [[ "$mode" == "all" || "$mode" == "gsf_refit" ]]; then + run_histcmp \ + $outdir/data/trackrefitting_gsf/performance_trackrefitting.root \ + $refdir/trackrefitting_gsf/performance_trackrefitting.root \ + "Truth tracking (GSF refit)" \ + trackrefitting_gsf/performance_trackrefitting.html \ + trackrefitting_gsf/performance_trackrefitting_plots \ + --config CI/physmon/config/trackfitting_gsf.yml +fi + if [[ "$mode" == "all" || "$mode" == "fullchains" ]]; then trackfinding "trackfinding | single muon | truth smeared seeding" trackfinding_1muon/truth_smeared trackfinding "trackfinding | single muon | truth estimated seeding" trackfinding_1muon/truth_estimated diff --git a/CI/physmon/reference/trackrefitting_gsf/performance_trackrefitting.root b/CI/physmon/reference/trackrefitting_gsf/performance_trackrefitting.root new file mode 100644 index 00000000000..d888ad406d8 Binary files /dev/null and b/CI/physmon/reference/trackrefitting_gsf/performance_trackrefitting.root differ diff --git a/CI/physmon/reference/trackrefitting_kf/performance_trackrefitting.root b/CI/physmon/reference/trackrefitting_kf/performance_trackrefitting.root new file mode 100644 index 00000000000..aade25ba5a2 Binary files /dev/null and b/CI/physmon/reference/trackrefitting_kf/performance_trackrefitting.root differ diff --git a/CI/physmon/workflows/physmon_trackrefitting_gsf.py b/CI/physmon/workflows/physmon_trackrefitting_gsf.py new file mode 100755 index 00000000000..5477121942a --- /dev/null +++ b/CI/physmon/workflows/physmon_trackrefitting_gsf.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import tempfile +from pathlib import Path +import shutil + +import acts +from truth_tracking_gsf_refitting import runRefittingGsf + +from physmon_common import makeSetup + +setup = makeSetup() + +with tempfile.TemporaryDirectory() as temp: + s = acts.examples.Sequencer( + events=10000, + numThreads=-1, + logLevel=acts.logging.INFO, + ) + + tp = Path(temp) + runRefittingGsf( + trackingGeometry=setup.trackingGeometry, + field=setup.field, + digiConfigFile=setup.digiConfig, + outputDir=tp, + s=s, + ) + + s.run() + + perf_file = tp / "performance_gsf_refit.root" + assert perf_file.exists(), "Performance file not found" + shutil.copy(perf_file, setup.outdir / "performance_trackrefitting.root") diff --git a/CI/physmon/workflows/physmon_trackrefitting_kf.py b/CI/physmon/workflows/physmon_trackrefitting_kf.py new file mode 100755 index 00000000000..ea82d26c701 --- /dev/null +++ b/CI/physmon/workflows/physmon_trackrefitting_kf.py @@ -0,0 +1,34 @@ +#!/usr/bin/env python3 + +import tempfile +from pathlib import Path +import shutil + +import acts +from truth_tracking_kalman_refitting import runRefittingKf + +from physmon_common import makeSetup + +setup = makeSetup() + +with tempfile.TemporaryDirectory() as temp: + s = acts.examples.Sequencer( + events=10000, + numThreads=-1, + logLevel=acts.logging.INFO, + ) + + tp = Path(temp) + runRefittingKf( + trackingGeometry=setup.trackingGeometry, + field=setup.field, + digiConfigFile=setup.digiConfig, + outputDir=tp, + s=s, + ) + + s.run() + + perf_file = tp / "performance_kf_refit.root" + assert perf_file.exists(), "Performance file not found" + shutil.copy(perf_file, setup.outdir / "performance_trackrefitting.root") diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index 5eb50dee1b7..6ddb1a405cd 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -74,10 +74,10 @@ test_exatrkx[cpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc8 test_exatrkx[gpu-onnx]__performance_track_finding.root: 9090de10ffb1489d3f1993e2a3081a3038227e3e5c453e98a9a4f33ea3d6d817 test_exatrkx[gpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc87943366f4af4440f7eea6887afb763871ac149b05 test_ML_Ambiguity_Solver__performance_ambiML.root: 284ff5c3a08c0b810938e4ac2f8ba8fe2babb17d4c202b624ed69fff731a9006 -test_refitting[odd]__trackstates_gsf_refit.root: 75cac3d6c0d9ce02169637cff739ab1e72b00c8fd3db9e99945d40b34c35b70b -test_refitting[odd]__tracksummary_gsf_refit.root: 90b9c9b3e24441066376f8cf529df10119b31f83563f001ac438fa70874dcb16 -test_refitting[generic]__trackstates_gsf_refit.root: 4424fdf2f27575db825c1a59f8e53a1595946211cbd5b2c8d3a2f71cdcc77ae9 -test_refitting[generic]__tracksummary_gsf_refit.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 +test_refitting[odd]__trackstates_gsf_refit.root: a61fe2d80d5d10d3b3505000e8abb589d88302bf5f54b625948793418f2a7fe8 +test_refitting[odd]__tracksummary_gsf_refit.root: 082789fc1a85e578b3cf9a750723d2dcee01b5019e871c6a63e0b271f4e907b1 +test_refitting[generic]__trackstates_gsf_refit.root: 9fa7af9eff12081504c0d648f6debae64f6996e0ca610cf58187d23aa5a13251 +test_refitting[generic]__tracksummary_gsf_refit.root: 35b5ac6f208cae093fff94038d217a2e9915a5ce075da2a95718dda696f2d4a2 test_truth_tracking_kalman[generic-False-0.0]__trackstates_kf.root: 9f77962b92037cb760b1629a602b1dae61f45e659c45d9a87baa784f6190960e test_truth_tracking_kalman[generic-False-0.0]__tracksummary_kf.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 test_truth_tracking_kalman[generic-False-1000.0]__trackstates_kf.root: 56a1bd989b9c1316b9098c65fa75df9e6683e62e35ae68d8f72d27220be0fd7d diff --git a/Examples/Python/tests/test_examples.py b/Examples/Python/tests/test_examples.py index 46044a9513c..0e34a8a3c1c 100644 --- a/Examples/Python/tests/test_examples.py +++ b/Examples/Python/tests/test_examples.py @@ -689,7 +689,7 @@ def test_refitting(tmp_path, detector_config, assert_root_hash): field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) seq = Sequencer( - events=10, + events=3, numThreads=1, ) @@ -699,6 +699,7 @@ def test_refitting(tmp_path, detector_config, assert_root_hash): runRefittingGsf( trackingGeometry=trackingGeometry, field=field, + digiConfigFile=detector_config.digiConfigFile, outputDir=tmp_path, s=seq, ).run() diff --git a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py index 138540db2af..797bfc59569 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py @@ -11,19 +11,16 @@ def runRefittingGsf( - trackingGeometry, - field, - outputDir, + trackingGeometry: acts.TrackingGeometry, + field: acts.MagneticFieldProvider, + digiConfigFile: Path, + outputDir: Path, s: acts.examples.Sequencer = None, ): - srcdir = Path(__file__).resolve().parent.parent.parent.parent - s = runTruthTrackingKalman( trackingGeometry, field, - digiConfigFile=srcdir - / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json", - # "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json", + digiConfigFile=digiConfigFile, outputDir=outputDir, s=s, ) @@ -41,7 +38,7 @@ def runRefittingGsf( acts.examples.RefittingAlgorithm( acts.logging.INFO, inputTracks="kf_tracks", - outputTracks="gsf_tracks", + outputTracks="gsf_refit_tracks", fit=acts.examples.makeGsfFitterFunction( trackingGeometry, field, **gsfOptions ), @@ -51,7 +48,7 @@ def runRefittingGsf( s.addAlgorithm( acts.examples.TrackTruthMatcher( level=acts.logging.INFO, - inputTracks="gsf_tracks", + inputTracks="gsf_refit_tracks", inputParticles="truth_seeds_selected", inputMeasurementParticlesMap="measurement_particles_map", outputTrackParticleMatching="refit_track_particle_matching", @@ -62,7 +59,7 @@ def runRefittingGsf( s.addWriter( acts.examples.RootTrackStatesWriter( level=acts.logging.INFO, - inputTracks="gsf_tracks", + inputTracks="gsf_refit_tracks", inputParticles="truth_seeds_selected", inputTrackParticleMatching="refit_track_particle_matching", inputSimHits="simhits", @@ -87,7 +84,7 @@ def runRefittingGsf( inputTracks="tracks", inputParticles="truth_seeds_selected", inputTrackParticleMatching="track_particle_matching", - filePath=str(outputDir / "performance_refitter.root"), + filePath=str(outputDir / "performance_gsf_refit.root"), ) ) @@ -95,10 +92,28 @@ def runRefittingGsf( if __name__ == "__main__": - outputDir = Path.cwd() + srcdir = Path(__file__).resolve().parent.parent.parent.parent + + # ODD + from acts.examples.odd import getOpenDataDetector + + detector, trackingGeometry, decorators = getOpenDataDetector() + digiConfigFile = ( + srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" + ) + + ## GenericDetector + # detector, trackingGeometry, _ = acts.examples.GenericDetector.create() + # digiConfigFile = ( + # srcdir + # / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json" + # ) - # detector, trackingGeometry, decorators = getOpenDataDetector() - detector, trackingGeometry, decorators = acts.examples.GenericDetector.create() field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) - runRefittingGsf(trackingGeometry, field, outputDir).run() + runRefittingGsf( + trackingGeometry=trackingGeometry, + field=field, + digiConfigFile=digiConfigFile, + outputDir=Path.cwd(), + ).run() diff --git a/Examples/Scripts/Python/truth_tracking_kalman_refitting.py b/Examples/Scripts/Python/truth_tracking_kalman_refitting.py new file mode 100755 index 00000000000..7e795b9e310 --- /dev/null +++ b/Examples/Scripts/Python/truth_tracking_kalman_refitting.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 + +from pathlib import Path + +import acts +import acts.examples + +from truth_tracking_kalman import runTruthTrackingKalman + +u = acts.UnitConstants + + +def runRefittingKf( + trackingGeometry: acts.TrackingGeometry, + field: acts.MagneticFieldProvider, + digiConfigFile: Path, + outputDir: Path, + multipleScattering: bool = True, + energyLoss: bool = True, + reverseFilteringMomThreshold=0 * u.GeV, + s: acts.examples.Sequencer = None, +): + s = runTruthTrackingKalman( + trackingGeometry, + field, + digiConfigFile=digiConfigFile, + outputDir=outputDir, + s=s, + ) + + kalmanOptions = { + "multipleScattering": multipleScattering, + "energyLoss": energyLoss, + "reverseFilteringMomThreshold": reverseFilteringMomThreshold, + "freeToBoundCorrection": acts.examples.FreeToBoundCorrection(False), + "level": acts.logging.INFO, + } + + s.addAlgorithm( + acts.examples.RefittingAlgorithm( + level=acts.logging.INFO, + inputTracks="kf_tracks", + outputTracks="kf_refit_tracks", + fit=acts.examples.makeKalmanFitterFunction( + trackingGeometry, field, **kalmanOptions + ), + ) + ) + + s.addAlgorithm( + acts.examples.TrackTruthMatcher( + level=acts.logging.INFO, + inputTracks="kf_refit_tracks", + inputParticles="truth_seeds_selected", + inputMeasurementParticlesMap="measurement_particles_map", + outputTrackParticleMatching="refit_track_particle_matching", + outputParticleTrackMatching="refit_particle_track_matching", + ) + ) + + s.addWriter( + acts.examples.RootTrackStatesWriter( + level=acts.logging.INFO, + inputTracks="kf_refit_tracks", + inputParticles="truth_seeds_selected", + inputTrackParticleMatching="refit_track_particle_matching", + inputSimHits="simhits", + inputMeasurementSimHitsMap="measurement_simhits_map", + filePath=str(outputDir / "trackstates_kf_refit.root"), + ) + ) + + s.addWriter( + acts.examples.RootTrackSummaryWriter( + level=acts.logging.INFO, + inputTracks="tracks", + inputParticles="truth_seeds_selected", + inputTrackParticleMatching="refit_track_particle_matching", + filePath=str(outputDir / "tracksummary_kf_refit.root"), + ) + ) + + s.addWriter( + acts.examples.TrackFitterPerformanceWriter( + level=acts.logging.INFO, + inputTracks="tracks", + inputParticles="truth_seeds_selected", + inputTrackParticleMatching="track_particle_matching", + filePath=str(outputDir / "performance_kf_refit.root"), + ) + ) + + return s + + +if __name__ == "__main__": + srcdir = Path(__file__).resolve().parent.parent.parent.parent + outputDir = Path.cwd() + + # ODD + from acts.examples.odd import getOpenDataDetector + + detector, trackingGeometry, decorators = getOpenDataDetector() + digiConfigFile = ( + srcdir / "thirdparty/OpenDataDetector/config/odd-digi-smearing-config.json" + ) + + ## GenericDetector + # detector, trackingGeometry, _ = acts.examples.GenericDetector.create() + # digiConfigFile = ( + # srcdir + # / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json" + # ) + + field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) + + runRefittingKf( + trackingGeometry=trackingGeometry, + field=field, + digiConfigFile=digiConfigFile, + outputDir=Path.cwd(), + ).run()