File indexing completed on 2025-08-05 08:10:07
0001 import pytest
0002 import os
0003 from pathlib import Path
0004 import multiprocessing
0005
0006 from helpers import (
0007 geant4Enabled,
0008 edm4hepEnabled,
0009 AssertCollectionExistsAlg,
0010 )
0011
0012 import acts
0013 from acts import PlanarModuleStepper, UnitConstants as u
0014 from acts.examples import (
0015 RootParticleWriter,
0016 RootParticleReader,
0017 RootMaterialTrackReader,
0018 RootTrackSummaryReader,
0019 CsvParticleWriter,
0020 CsvParticleReader,
0021 CsvMeasurementWriter,
0022 CsvMeasurementReader,
0023 CsvSimHitWriter,
0024 CsvSimHitReader,
0025 CsvPlanarClusterWriter,
0026 CsvPlanarClusterReader,
0027 PlanarSteppingAlgorithm,
0028 Sequencer,
0029 )
0030 from acts.examples.odd import getOpenDataDetector, getOpenDataDetectorDirectory
0031
0032
0033 @pytest.mark.root
0034 def test_root_particle_reader(tmp_path, conf_const, ptcl_gun):
0035
0036 s = Sequencer(numThreads=1, events=10, logLevel=acts.logging.WARNING)
0037 evGen = ptcl_gun(s)
0038
0039 file = tmp_path / "particles.root"
0040 s.addWriter(
0041 conf_const(
0042 RootParticleWriter,
0043 acts.logging.WARNING,
0044 inputParticles=evGen.config.outputParticles,
0045 filePath=str(file),
0046 )
0047 )
0048
0049 s.run()
0050
0051 del s
0052
0053
0054
0055 s2 = Sequencer(numThreads=1, logLevel=acts.logging.WARNING)
0056
0057 s2.addReader(
0058 conf_const(
0059 RootParticleReader,
0060 acts.logging.WARNING,
0061 outputParticles="particles_input",
0062 filePath=str(file),
0063 )
0064 )
0065
0066 alg = AssertCollectionExistsAlg(
0067 "particles_input", "check_alg", acts.logging.WARNING
0068 )
0069 s2.addAlgorithm(alg)
0070
0071 s2.run()
0072
0073 assert alg.events_seen == 10
0074
0075
0076 @pytest.mark.csv
0077 def test_csv_particle_reader(tmp_path, conf_const, ptcl_gun):
0078 s = Sequencer(numThreads=1, events=10, logLevel=acts.logging.WARNING)
0079 evGen = ptcl_gun(s)
0080
0081 out = tmp_path / "csv"
0082
0083 out.mkdir()
0084
0085 s.addWriter(
0086 conf_const(
0087 CsvParticleWriter,
0088 acts.logging.WARNING,
0089 inputParticles=evGen.config.outputParticles,
0090 outputStem="particle",
0091 outputDir=str(out),
0092 )
0093 )
0094
0095 s.run()
0096
0097
0098 s = Sequencer(numThreads=1, logLevel=acts.logging.WARNING)
0099
0100 s.addReader(
0101 conf_const(
0102 CsvParticleReader,
0103 acts.logging.WARNING,
0104 inputDir=str(out),
0105 inputStem="particle",
0106 outputParticles="input_particles",
0107 )
0108 )
0109
0110 alg = AssertCollectionExistsAlg(
0111 "input_particles", "check_alg", acts.logging.WARNING
0112 )
0113
0114 s.addAlgorithm(alg)
0115
0116 s.run()
0117
0118 assert alg.events_seen == 10
0119
0120
0121 @pytest.mark.parametrize(
0122 "reader",
0123 [RootParticleReader, RootTrackSummaryReader],
0124 )
0125 @pytest.mark.root
0126 def test_root_reader_interface(reader, conf_const, tmp_path):
0127 assert hasattr(reader, "Config")
0128
0129 config = reader.Config
0130
0131 assert hasattr(config, "filePath")
0132
0133 kw = {"level": acts.logging.INFO, "filePath": str(tmp_path / "file.root")}
0134
0135 assert conf_const(reader, **kw)
0136
0137
0138 @pytest.mark.slow
0139 @pytest.mark.root
0140 @pytest.mark.odd
0141 @pytest.mark.skipif(not geant4Enabled, reason="Geant4 not set up")
0142 def test_root_material_track_reader(material_recording):
0143 input_tracks = material_recording / "geant4_material_tracks.root"
0144 assert input_tracks.exists()
0145
0146 s = Sequencer(numThreads=1)
0147
0148 s.addReader(
0149 RootMaterialTrackReader(
0150 level=acts.logging.INFO,
0151 fileList=[str(input_tracks)],
0152 outputMaterialTracks="material-tracks",
0153 )
0154 )
0155
0156 alg = AssertCollectionExistsAlg(
0157 "material-tracks", "check_alg", acts.logging.WARNING
0158 )
0159 s.addAlgorithm(alg)
0160
0161 s.run()
0162
0163 assert alg.events_seen == 2
0164
0165
0166 @pytest.mark.csv
0167 def test_csv_meas_reader(tmp_path, fatras, trk_geo, conf_const):
0168 s = Sequencer(numThreads=1, events=10)
0169 evGen, simAlg, digiAlg = fatras(s)
0170
0171 out = tmp_path / "csv"
0172 out.mkdir()
0173
0174 s.addWriter(
0175 CsvMeasurementWriter(
0176 level=acts.logging.INFO,
0177 inputMeasurements=digiAlg.config.outputMeasurements,
0178 inputClusters=digiAlg.config.outputClusters,
0179 inputMeasurementSimHitsMap=digiAlg.config.outputMeasurementSimHitsMap,
0180 outputDir=str(out),
0181 )
0182 )
0183
0184
0185 s.addWriter(
0186 CsvSimHitWriter(
0187 level=acts.logging.INFO,
0188 inputSimHits=simAlg.config.outputSimHits,
0189 outputDir=str(out),
0190 outputStem="hits",
0191 )
0192 )
0193
0194 s.run()
0195
0196
0197 s = Sequencer(numThreads=1)
0198
0199 s.addReader(
0200 CsvSimHitReader(
0201 level=acts.logging.INFO,
0202 outputSimHits=simAlg.config.outputSimHits,
0203 inputDir=str(out),
0204 inputStem="hits",
0205 )
0206 )
0207
0208 s.addReader(
0209 conf_const(
0210 CsvMeasurementReader,
0211 level=acts.logging.WARNING,
0212 outputMeasurements="measurements",
0213 outputMeasurementSimHitsMap="simhitsmap",
0214 outputSourceLinks="sourcelinks",
0215 outputMeasurementParticlesMap="meas_ptcl_map",
0216 inputSimHits=simAlg.config.outputSimHits,
0217 inputDir=str(out),
0218 )
0219 )
0220
0221 algs = [
0222 AssertCollectionExistsAlg(k, f"check_alg_{k}", acts.logging.WARNING)
0223 for k in ("measurements", "simhitsmap", "sourcelinks", "meas_ptcl_map")
0224 ]
0225 for alg in algs:
0226 s.addAlgorithm(alg)
0227
0228 s.run()
0229
0230 for alg in algs:
0231 assert alg.events_seen == 10
0232
0233
0234 @pytest.mark.csv
0235 def test_csv_simhits_reader(tmp_path, fatras, conf_const):
0236 s = Sequencer(numThreads=1, events=10)
0237 evGen, simAlg, digiAlg = fatras(s)
0238
0239 out = tmp_path / "csv"
0240 out.mkdir()
0241
0242 s.addWriter(
0243 CsvSimHitWriter(
0244 level=acts.logging.INFO,
0245 inputSimHits=simAlg.config.outputSimHits,
0246 outputDir=str(out),
0247 outputStem="hits",
0248 )
0249 )
0250
0251 s.run()
0252
0253 s = Sequencer(numThreads=1)
0254
0255 s.addReader(
0256 conf_const(
0257 CsvSimHitReader,
0258 level=acts.logging.INFO,
0259 inputDir=str(out),
0260 inputStem="hits",
0261 outputSimHits="simhits",
0262 )
0263 )
0264
0265 alg = AssertCollectionExistsAlg("simhits", "check_alg", acts.logging.WARNING)
0266 s.addAlgorithm(alg)
0267
0268 s.run()
0269
0270 assert alg.events_seen == 10
0271
0272
0273 @pytest.mark.csv
0274 def test_csv_clusters_reader(tmp_path, fatras, conf_const, trk_geo, rng):
0275 s = Sequencer(numThreads=1, events=10)
0276 evGen, simAlg, _ = fatras(s)
0277 s = Sequencer(numThreads=1, events=10)
0278 s.addReader(evGen)
0279 s.addAlgorithm(simAlg)
0280 digiAlg = PlanarSteppingAlgorithm(
0281 level=acts.logging.WARNING,
0282 inputSimHits=simAlg.config.outputSimHits,
0283 outputClusters="clusters",
0284 outputSourceLinks="sourcelinks",
0285 outputDigiSourceLinks="digiSourceLink",
0286 outputMeasurements="measurements",
0287 outputMeasurementParticlesMap="meas_ptcl_map",
0288 outputMeasurementSimHitsMap="meas_sh_map",
0289 trackingGeometry=trk_geo,
0290 randomNumbers=rng,
0291 planarModuleStepper=PlanarModuleStepper(),
0292 )
0293 s.addAlgorithm(digiAlg)
0294
0295 out = tmp_path / "csv"
0296 out.mkdir()
0297
0298 s.addWriter(
0299 CsvPlanarClusterWriter(
0300 level=acts.logging.WARNING,
0301 outputDir=str(out),
0302 inputSimHits=simAlg.config.outputSimHits,
0303 inputClusters=digiAlg.config.outputClusters,
0304 trackingGeometry=trk_geo,
0305 )
0306 )
0307
0308 s.run()
0309
0310 s = Sequencer(numThreads=1)
0311
0312 s.addReader(
0313 conf_const(
0314 CsvPlanarClusterReader,
0315 level=acts.logging.WARNING,
0316 outputClusters="clusters",
0317 inputDir=str(out),
0318 outputHitIds="hits",
0319 outputMeasurementParticlesMap="meas_ptcl_map",
0320 outputSimHits="simhits",
0321 trackingGeometry=trk_geo,
0322 )
0323 )
0324
0325 algs = [
0326 AssertCollectionExistsAlg(k, f"check_alg_{k}", acts.logging.WARNING)
0327 for k in ("clusters", "simhits", "meas_ptcl_map")
0328 ]
0329 for alg in algs:
0330 s.addAlgorithm(alg)
0331
0332 s.run()
0333
0334 for alg in algs:
0335 assert alg.events_seen == 10
0336
0337
0338 def generate_input_test_edm4hep_simhit_reader(input, output):
0339 from DDSim.DD4hepSimulation import DD4hepSimulation
0340
0341 ddsim = DD4hepSimulation()
0342 if isinstance(ddsim.compactFile, list):
0343 ddsim.compactFile = [input]
0344 else:
0345 ddsim.compactFile = input
0346 ddsim.enableGun = True
0347 ddsim.gun.direction = (1, 0, 0)
0348 ddsim.gun.particle = "pi-"
0349 ddsim.gun.distribution = "eta"
0350 ddsim.numberOfEvents = 10
0351 ddsim.outputFile = output
0352 ddsim.run()
0353
0354
0355 @pytest.mark.slow
0356 @pytest.mark.edm4hep
0357 @pytest.mark.skipif(not edm4hepEnabled, reason="EDM4hep is not set up")
0358 def test_edm4hep_simhit_particle_reader(tmp_path):
0359 from acts.examples.edm4hep import EDM4hepReader
0360
0361 tmp_file = str(tmp_path / "output_edm4hep.root")
0362 odd_xml_file = str(getOpenDataDetectorDirectory() / "xml" / "OpenDataDetector.xml")
0363
0364 with multiprocessing.get_context("spawn").Pool() as pool:
0365 pool.apply(generate_input_test_edm4hep_simhit_reader, (odd_xml_file, tmp_file))
0366
0367 assert os.path.exists(tmp_file)
0368
0369 detector, trackingGeometry, decorators = getOpenDataDetector()
0370
0371 s = Sequencer(numThreads=1)
0372
0373 s.addReader(
0374 EDM4hepReader(
0375 level=acts.logging.INFO,
0376 inputPath=tmp_file,
0377 inputSimHits=[
0378 "PixelBarrelReadout",
0379 "PixelEndcapReadout",
0380 "ShortStripBarrelReadout",
0381 "ShortStripEndcapReadout",
0382 "LongStripBarrelReadout",
0383 "LongStripEndcapReadout",
0384 ],
0385 outputParticlesGenerator="particles_input",
0386 outputParticlesInitial="particles_initial",
0387 outputParticlesFinal="particles_final",
0388 outputSimHits="simhits",
0389 dd4hepDetector=detector,
0390 trackingGeometry=trackingGeometry,
0391 )
0392 )
0393
0394 alg = AssertCollectionExistsAlg("simhits", "check_alg", acts.logging.WARNING)
0395 s.addAlgorithm(alg)
0396
0397 alg = AssertCollectionExistsAlg(
0398 "particles_input", "check_alg", acts.logging.WARNING
0399 )
0400 s.addAlgorithm(alg)
0401
0402 s.run()
0403
0404 assert alg.events_seen == 10
0405
0406
0407 @pytest.mark.edm4hep
0408 @pytest.mark.skipif(not edm4hepEnabled, reason="EDM4hep is not set up")
0409 def test_edm4hep_measurement_reader(tmp_path, fatras, conf_const):
0410 from acts.examples.edm4hep import (
0411 EDM4hepMeasurementWriter,
0412 EDM4hepMeasurementReader,
0413 )
0414
0415 s = Sequencer(numThreads=1, events=10)
0416 _, simAlg, digiAlg = fatras(s)
0417
0418 out = tmp_path / "measurements_edm4hep.root"
0419
0420 config = EDM4hepMeasurementWriter.Config(
0421 inputMeasurements=digiAlg.config.outputMeasurements,
0422 inputClusters=digiAlg.config.outputClusters,
0423 outputPath=str(out),
0424 )
0425 s.addWriter(EDM4hepMeasurementWriter(level=acts.logging.INFO, config=config))
0426 s.run()
0427
0428
0429 s = Sequencer(numThreads=1)
0430
0431 s.addReader(
0432 conf_const(
0433 EDM4hepMeasurementReader,
0434 level=acts.logging.WARNING,
0435 outputMeasurements="measurements",
0436 outputMeasurementSimHitsMap="simhitsmap",
0437 outputSourceLinks="sourcelinks",
0438 inputPath=str(out),
0439 )
0440 )
0441
0442 algs = [
0443 AssertCollectionExistsAlg(k, f"check_alg_{k}", acts.logging.WARNING)
0444 for k in ("measurements", "simhitsmap", "sourcelinks")
0445 ]
0446 for alg in algs:
0447 s.addAlgorithm(alg)
0448
0449 s.run()
0450
0451 for alg in algs:
0452 assert alg.events_seen == 10
0453
0454
0455 @pytest.mark.edm4hep
0456 @pytest.mark.skipif(not edm4hepEnabled, reason="EDM4hep is not set up")
0457 def test_edm4hep_tracks_reader(tmp_path):
0458 from acts.examples.edm4hep import EDM4hepTrackWriter, EDM4hepTrackReader
0459
0460 detector, trackingGeometry, decorators = acts.examples.GenericDetector.create()
0461 field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T))
0462
0463 from truth_tracking_kalman import runTruthTrackingKalman
0464
0465 s = Sequencer(numThreads=1, events=10)
0466 runTruthTrackingKalman(
0467 trackingGeometry,
0468 field,
0469 digiConfigFile=Path(
0470 str(
0471 Path(__file__).parent.parent.parent.parent
0472 / "Examples/Algorithms/Digitization/share/default-smearing-config-generic.json"
0473 )
0474 ),
0475 outputDir=tmp_path,
0476 s=s,
0477 )
0478
0479 out = tmp_path / "tracks_edm4hep.root"
0480
0481 s.addWriter(
0482 EDM4hepTrackWriter(
0483 level=acts.logging.VERBOSE,
0484 inputTracks="kf_tracks",
0485 outputPath=str(out),
0486 Bz=2 * u.T,
0487 )
0488 )
0489
0490 s.run()
0491
0492 del s
0493
0494 s = Sequencer(numThreads=1)
0495 s.addReader(
0496 EDM4hepTrackReader(
0497 level=acts.logging.VERBOSE,
0498 outputTracks="kf_tracks",
0499 inputPath=str(out),
0500 Bz=2 * u.T,
0501 )
0502 )
0503
0504 s.run()