From 4c643dca82c78f2b12fd29f22a6fdfe5eb9353ed Mon Sep 17 00:00:00 2001 From: tmadlener Date: Fri, 6 Sep 2024 18:42:48 +0200 Subject: [PATCH] Add check for complete EDM4hep file --- scripts/createEDM4hepFile.py | 2 +- test/CMakeLists.txt | 2 + test/backwards_compat/CMakeLists.txt | 11 + test/backwards_compat/conftest.py | 6 + test/backwards_compat/test_EDM4hepFile.py | 479 ++++++++++++++++++++++ 5 files changed, 499 insertions(+), 1 deletion(-) create mode 100644 test/backwards_compat/CMakeLists.txt create mode 100644 test/backwards_compat/conftest.py create mode 100644 test/backwards_compat/test_EDM4hepFile.py diff --git a/scripts/createEDM4hepFile.py b/scripts/createEDM4hepFile.py index 7b8bc5458..6200c54bf 100755 --- a/scripts/createEDM4hepFile.py +++ b/scripts/createEDM4hepFile.py @@ -253,7 +253,7 @@ def create_TrackCollection(vectorsize, tracker_hit): ) state.covMatrix = create_CovMatrixNf(6) track.addToTrackStates(state) - track.addToSubdetectorHoleNumbers(next(counter)) + track.addToTrackerHits(tracker_hit) track.addToTracks(track) track.setNholes(next(counter)) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 65c816322..3d8965e16 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -95,3 +95,5 @@ endif() add_subdirectory(utils) add_subdirectory(tools) + +add_subdirectory(backwards_compat) diff --git a/test/backwards_compat/CMakeLists.txt b/test/backwards_compat/CMakeLists.txt new file mode 100644 index 000000000..498654076 --- /dev/null +++ b/test/backwards_compat/CMakeLists.txt @@ -0,0 +1,11 @@ +add_test(NAME check_complete_file COMMAND pytest --inputfile=${CMAKE_BINARY_DIR}/test/edm4hep_example.root -v) + +set_test_env(check_complete_file) + +set_tests_properties( + check_complete_file + + PROPERTIES + DEPENDS "Create an EDM4hep data file" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} +) diff --git a/test/backwards_compat/conftest.py b/test/backwards_compat/conftest.py new file mode 100644 index 000000000..3e8283bf2 --- /dev/null +++ b/test/backwards_compat/conftest.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 +"""pytest config module to make passing of input file name possible""" + + +def pytest_addoption(parser): + parser.addoption("--inputfile", action="store", default="heeeeyyyoooo") diff --git a/test/backwards_compat/test_EDM4hepFile.py b/test/backwards_compat/test_EDM4hepFile.py new file mode 100644 index 000000000..901970862 --- /dev/null +++ b/test/backwards_compat/test_EDM4hepFile.py @@ -0,0 +1,479 @@ +#!/usr/bin/env python3 +"""Script that can be used to check whether the file that has been created by +scripts/createEDM4hepFile.py has the expected contents +""" + +import os +import podio +import edm4hep +import pytest +from itertools import count + +# For new simply copy these from createEDM4hepFile.py +FRAMES = 3 +VECTORSIZE = 5 + + +@pytest.fixture(scope="module") +def inputfile_name(pytestconfig): + """Get the inputfile name that has been passed via commandline""" + return pytestconfig.getoption("inputfile") + + +@pytest.fixture(scope="module") +def reader(inputfile_name): + """Get the reader for the passed filename""" + return podio.reading.get_reader(inputfile_name) + + +@pytest.fixture(scope="module") +def events(reader): + """Get the events from the reader""" + return reader.get("events") + + +@pytest.fixture(scope="module") +def event(events): + """Get the first event from the events. Since all events have the same + contents, we simply assume that everything is alright if we simply check the + first one + """ + return events[0] + + +@pytest.fixture(scope="module") +def particle(event): + """Get the particle that is used in some relations""" + return event.get("MCParticleCollection")[0] + + +@pytest.fixture(scope="module") +def reco_particle(event): + """Get the reconstructed particle that is used in some relations""" + return event.get("ReconstructedParticleCollection")[0] + + +@pytest.fixture(scope="module") +def track(event): + """Get the track that is used in some relations""" + return event.get("TrackCollection")[0] + + +def check_cov_matrix(cov_matrix, n_dim): + """Check the contents of the passed covariance matrix""" + counter = count() + # for val in cov_matrix: # Doesn't work as expected with root + for i in range(n_dim * (n_dim + 1) // 2): + assert cov_matrix[i] == next(counter) + + +def test_basic_file_contents(events): + """Make sure the basic file contents are OK""" + assert len(events) == FRAMES + + +def test_EventHeaderCollection(event): + """Check an EventHeaderCollection""" + counter = count() + header = event.get("EventHeader") + assert len(header) == 1 + h = header[0] + assert h.getEventNumber() == next(counter) + assert h.getRunNumber() == next(counter) + assert h.getTimeStamp() == next(counter) + assert h.getWeight() == 1.0 + assert len(h.getWeights()) == VECTORSIZE + for weight in h.getWeights(): + assert weight == next(counter) + + +def test_MCParticleCollection(event): + """Check the MCParticleCollection""" + counter = count() + particles = event.get("MCParticleCollection") + assert len(particles) == 3 + for i in range(3): + particle = particles[i] + assert particle.getPDG() == next(counter) + assert particle.getGeneratorStatus() == next(counter) + assert particle.getSimulatorStatus() == next(counter) + assert particle.getCharge() == next(counter) + assert particle.getTime() == next(counter) + assert particle.getMass() == next(counter) + assert particle.getVertex() == edm4hep.Vector3d( + next(counter), next(counter), next(counter) + ) + assert particle.getEndpoint() == edm4hep.Vector3d( + next(counter), next(counter), next(counter) + ) + assert particle.getMomentum() == edm4hep.Vector3d( + next(counter), next(counter), next(counter) + ) + assert particle.getMomentumAtEndpoint() == edm4hep.Vector3d( + next(counter), next(counter), next(counter) + ) + assert particle.getSpin() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + assert particle.getColorFlow() == edm4hep.Vector2i(next(counter), next(counter)) + + assert particles[0].getDaughters()[0] == particles[1] + assert particles[0].getParents()[0] == particles[2] + + +def test_SimTrackerHitCollection(event, particle): + """Check the SimTrackerHitCollection""" + counter = count() + hits = event.get("SimTrackerHitCollection") + assert len(hits) == 1 + hit = hits[0] + assert hit.getCellID() == next(counter) + assert hit.getEDep() == next(counter) + assert hit.getTime() == next(counter) + assert hit.getPathLength() == next(counter) + assert hit.getQuality() == next(counter) + assert hit.getPosition() == edm4hep.Vector3d( + next(counter), next(counter), next(counter) + ) + assert hit.getMomentum() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + + assert hit.getParticle() == particle + + +def test_CaloHitContributionCollection(event, particle): + """Check the CaloHitContributionCollection""" + counter = count() + hits = event.get("CaloHitContributionCollection") + assert len(hits) == 1 + hit = hits[0] + assert hit.getPDG() == next(counter) + assert hit.getEnergy() == next(counter) + assert hit.getTime() == next(counter) + assert hit.getStepPosition() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + + assert hit.getParticle() == particle + + +def test_SimCalorimeterHitCollection(event): + """Check the SimCalorimeterHitCollection""" + counter = count() + hits = event.get("SimCalorimeterHitCollection") + assert len(hits) == 1 + hit = hits[0] + assert hit.getCellID() == next(counter) + assert hit.getEnergy() == next(counter) + assert hit.getPosition() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + + calo_contrib = event.get("CaloHitContributionCollection")[0] + assert len(hit.getContributions()) == 1 + assert hit.getContributions()[0] == calo_contrib + + +def test_RawCalorimeterHitCollection(event): + """Check the RawCalorimeterHitCollection""" + counter = count() + hits = event.get("RawCalorimeterHitCollection") + assert len(hits) == 1 + hit = hits[0] + assert hit.getCellID() == next(counter) + assert hit.getAmplitude() == next(counter) + assert hit.getTimeStamp() == next(counter) + + +def test_CalorimeterHitCollection(event): + """Check the CalorimeterHitCollection""" + counter = count() + hits = event.get("CalorimeterHitCollection") + assert len(hits) == 1 + hit = hits[0] + assert hit.getCellID() == next(counter) + assert hit.getEnergy() == next(counter) + assert hit.getEnergyError() == next(counter) + assert hit.getTime() == next(counter) + assert hit.getPosition() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + assert hit.getType() == next(counter) + + +def test_ParticleIDCollection(event, reco_particle): + """Check the ParticleIDCollection""" + counter = count() + pids = event.get("ParticleIDCollection") + assert len(pids) == 1 + pid = pids[0] + assert pid.getType() == next(counter) + assert pid.getPDG() == next(counter) + assert pid.getAlgorithmType() == next(counter) + assert pid.getLikelihood() == next(counter) + assert len(pid.getParameters()) == VECTORSIZE + for param in pid.getParameters(): + assert param == next(counter) + + assert pid.getParticle() == reco_particle + + +def test_ClusterCollection(event): + """Check the ClusterCollection""" + counter = count() + clusters = event.get("ClusterCollection") + assert len(clusters) == 1 + cluster = clusters[0] + assert cluster.getType() == next(counter) + assert cluster.getEnergy() == next(counter) + assert cluster.getEnergyError() == next(counter) + assert cluster.getPosition() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + check_cov_matrix(cluster.getPositionError(), 3) + assert cluster.getITheta() == next(counter) + assert cluster.getPhi() == next(counter) + assert cluster.getDirectionError() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + + assert len(cluster.getShapeParameters()) == VECTORSIZE + assert len(cluster.getSubdetectorEnergies()) == VECTORSIZE + for j in range(VECTORSIZE): + cluster.getShapeParameters()[j] == next(counter) + cluster.getSubdetectorEnergies()[j] == next(counter) + + assert len(cluster.getClusters()) == 1 + assert cluster.getClusters()[0] == cluster + + calo_hit = event.get("CalorimeterHitCollection")[0] + assert len(cluster.getHits()) == 1 + assert cluster.getHits()[0] == calo_hit + cluster.addToHits(calo_hit) + + +def test_TrackerHit3DCollection(event): + """Check the TrackerHit3DCollection""" + counter = count() + hits = event.get("TrackerHit3DCollection") + assert len(hits) == 1 + hit = hits[0] + assert hit.getCellID() == next(counter) + assert hit.getType() == next(counter) + assert hit.getQuality() == next(counter) + assert hit.getTime() == next(counter) + assert hit.getEDep() == next(counter) + assert hit.getEDepError() == next(counter) + assert hit.getPosition() == edm4hep.Vector3d( + next(counter), next(counter), next(counter) + ) + check_cov_matrix(hit.getCovMatrix(), 3) + + +def test_TrackerHitPlaneCollection(event): + """Check the TrackerHitPlaneCollection""" + counter = count() + hits = event.get("TrackerHitPlaneCollection") + assert len(hits) == 1 + hit = hits[0] + assert hit.getCellID() == next(counter) + assert hit.getType() == next(counter) + assert hit.getQuality() == next(counter) + assert hit.getTime() == next(counter) + assert hit.getEDep() == next(counter) + assert hit.getEDepError() == next(counter) + assert hit.getU() == edm4hep.Vector2f(next(counter), next(counter)) + assert hit.getV() == edm4hep.Vector2f(next(counter), next(counter)) + assert hit.getDu() == next(counter) + assert hit.getDv() == next(counter) + assert hit.getPosition() == edm4hep.Vector3d( + next(counter), next(counter), next(counter) + ) + check_cov_matrix(hit.getCovMatrix(), 3) + + +def test_RawTimeSeriesCollection(event): + """Check a RawTimeSeriesCollection""" + counter = count() + series = event.get("RawTimeSeriesCollection") + assert len(series) == 1 + serie = series[0] + assert serie.getCellID() == next(counter) + assert serie.getQuality() == next(counter) + assert serie.getTime() == next(counter) + assert serie.getCharge() == next(counter) + assert serie.getInterval() == next(counter) + assert len(serie.getAdcCounts()) == VECTORSIZE + for val in serie.getAdcCounts(): + assert val == next(counter) + + +def test_TrackCollection(event): + """Check the TrackCollection""" + counter = count() + tracks = event.get("TrackCollection") + assert len(tracks) == 1 + track = tracks[0] + assert track.getType() == next(counter) + assert track.getChi2() == next(counter) + assert track.getNdf() == next(counter) + + subdetHitNumbers = track.getSubdetectorHitNumbers() + assert len(subdetHitNumbers) == VECTORSIZE + subdetHoleNumbers = track.getSubdetectorHoleNumbers() + assert len(subdetHoleNumbers) == VECTORSIZE + trackStates = track.getTrackStates() + assert len(trackStates) == VECTORSIZE + + for j in range(VECTORSIZE): + subdetHitNumbers[j] == next(counter) + subdetHoleNumbers[j] == next(counter) + + state = trackStates[j] + assert state.location == next(counter) + assert state.D0 == next(counter) + assert state.phi == next(counter) + assert state.omega == next(counter) + assert state.Z0 == next(counter) + assert state.tanLambda == next(counter) + assert state.time == next(counter) + assert state.referencePoint == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + check_cov_matrix(state.covMatrix, 6) + + assert track.getNholes() == next(counter) + + tracker_hit = event.get("TrackerHit3DCollection")[0] + assert len(track.getTrackerHits()) == 1 + assert track.getTrackerHits()[0] == tracker_hit + + assert len(track.getTracks()) == 1 + assert track.getTracks()[0] == track + + +def test_VertexCollection(event, reco_particle): + """Check the VertexCollection""" + counter = count() + vertex = event.get("VertexCollection") + assert len(vertex) == 1 + v = vertex[0] + assert v.getType() == next(counter) + assert v.getChi2() == next(counter) + assert v.getNdf() == next(counter) + assert v.getPosition() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + check_cov_matrix(v.getCovMatrix(), 3) + assert v.getAlgorithmType() == next(counter) + assert len(v.getParameters()) == VECTORSIZE + for val in v.getParameters(): + assert val == next(counter) + + assert len(v.getParticles()) == 1 + assert v.getParticles()[0] == reco_particle + + +def test_ReconstructedParticleCollection(event, track): + """Check the ReconstructedParticleCollection""" + counter = count() + rparticles = event.get("ReconstructedParticleCollection") + assert len(rparticles) == 1 + rparticle = rparticles[0] + assert rparticle.getPDG() == next(counter) + assert rparticle.getEnergy() == next(counter) + assert rparticle.getMomentum() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + assert rparticle.getReferencePoint() == edm4hep.Vector3f( + next(counter), next(counter), next(counter) + ) + assert rparticle.getCharge() == next(counter) + assert rparticle.getMass() == next(counter) + assert rparticle.getGoodnessOfPID() == next(counter) + check_cov_matrix(rparticle.getCovMatrix(), 4) + + vertex = event.get("VertexCollection")[0] + assert rparticle.getDecayVertex() == vertex + + assert len(rparticle.getClusters()) == 1 + cluster = event.get("ClusterCollection")[0] + assert rparticle.getClusters()[0] == cluster + + assert len(rparticle.getTracks()) == 1 + assert rparticle.getTracks()[0] == track + + assert len(rparticle.getParticles()) == 1 + assert rparticle.getParticles()[0] == rparticle + + +def test_TimeSeriesCollection(event): + """Check the TimeSeriesCollection""" + counter = count() + timeseries = event.get("TimeSeriesCollection") + assert len(timeseries) == 1 + serie = timeseries[0] + assert serie.getCellID() == next(counter) + assert serie.getTime() == next(counter) + assert serie.getInterval() == next(counter) + assert len(serie.getAmplitude()) == VECTORSIZE + for val in serie.getAmplitude(): + assert val == next(counter) + + +def test_RecDqdxCollection(event, track): + """Check the RecDqdxCollection""" + counter = count() + recdqdx = event.get("RecDqdxCollection") + assert len(recdqdx) == 1 + dqdx = recdqdx[0] + q = dqdx.getDQdx() + assert q.type == next(counter) + assert q.value == next(counter) + assert q.error == next(counter) + assert dqdx.getTrack() == track + + +def test_GeneratorEventParametersCollection(event, particle): + """Check the GeneratorEventParametersCollection""" + counter = count() + gep_coll = event.get("GeneratorEventParametersCollection") + assert len(gep_coll) == 1 + gep = gep_coll[0] + assert gep.getEventScale() == next(counter) + assert gep.getAlphaQED() == next(counter) + assert gep.getAlphaQCD() == next(counter) + assert gep.getSignalProcessId() == next(counter) + assert gep.getSqrts() == next(counter) + xsecs = gep.getCrossSections() + xsec_errors = gep.getCrossSectionErrors() + assert len(xsecs) == VECTORSIZE + assert len(xsec_errors) == VECTORSIZE + for i in range(VECTORSIZE): + assert xsecs[i] == next(counter) + assert xsec_errors[i] == next(counter) + + assert len(gep.getSignalVertex()) == 1 + assert gep.getSignalVertex()[0] == particle + + +def test_GeneratorPdfInfoCollection(event): + """Check the GeneratorPdfInfoCollection""" + counter = count() + gpi_coll = event.get("GeneratorPdfInfoCollection") + assert len(gpi_coll) == 1 + gpi = gpi_coll[0] + assert gpi.getPartonId(0) == next(counter) + assert gpi.getPartonId(1) == next(counter) + assert gpi.getLhapdfId(0) == next(counter) + assert gpi.getLhapdfId(1) == next(counter) + assert gpi.getX(0) == next(counter) + assert gpi.getX(1) == next(counter) + assert gpi.getXf(0) == next(counter) + assert gpi.getXf(1) == next(counter) + + assert gpi.getScale() == next(counter) + + +# TODO: LINKS