Skip to content
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

DL1 to DL2 tool #1343

Merged
merged 18 commits into from
Feb 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/introduction.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ Here is an example configuration file for this step.
DL1 to DL2
----------

Use ``lstchain.scripts.lstchain_dl1_to_dl2`` for real data and MC.
Use ``lstchain.tools.lstchain_dl1_to_dl2`` for real data and MC.

For more information, try ``--help`` or see the :doc:`lstchain_api/index`.

Expand Down
14 changes: 0 additions & 14 deletions docs/lstchain_api/scripts/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ The scripts to be executed from the command line are described below:
* `lstchain_data_create_time_calibration_file`_
* `lstchain_data_r0_to_dl1`_
* `lstchain_dl1_muon_analysis`_
* `lstchain_dl1_to_dl2`_
* `lstchain_dl1ab`_
* `lstchain_dump_config`_
* `lstchain_find_pedestals`_
Expand Down Expand Up @@ -99,19 +98,6 @@ Usage
:func: parser
:prog: lstchain_dl1_muon_analysis

.. _lstchain_dl1_to_dl2:

lstchain_dl1_to_dl2
+++++++++++++++++++

.. automodule:: lstchain.scripts.lstchain_dl1_to_dl2

Usage
-----
.. argparse::
:module: lstchain.scripts.lstchain_dl1_to_dl2
:func: parser
:prog: lstchain_dl1_to_dl2

.. _lstchain_dl1ab:

Expand Down
2 changes: 2 additions & 0 deletions docs/lstchain_api/tools/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ Reference/API
:no-inheritance-diagram:
.. automodapi:: lstchain.tools.lstchain_fit_intensity_scan
:no-inheritance-diagram:
.. automodapi:: lstchain.tools.lstchain_dl1_to_dl2
:no-inheritance-diagram:
79 changes: 79 additions & 0 deletions lstchain/io/provenance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import json
import h5py
from ctapipe.core import Provenance
import logging

logger = logging.getLogger()

def write_provenance(hdf5_file_path, stage_name):
"""
Write JSON provenance information to an HDF5 file.
It uses the current activity's provenance information and should typically be called within a ctapipe Tool.

Parameters:
-----------
hdf5_file_path : str or Path
Path to the HDF5 file
stage_name : str
Name of the stage generating the provenance

Returns:
--------
None
"""
try:
with h5py.File(hdf5_file_path, 'a') as h5file:
if 'provenance' not in h5file:
h5file.create_group('provenance')

# Get the provenance dictionary from the current activity
provenance_data = Provenance().current_activity.provenance
# Dump the dictionary to a JSON string and write it to the HDF5 file
h5file['provenance'].create_dataset(stage_name, data=json.dumps(provenance_data, default=str))

except Exception as e:
raise Exception(f"Error writing provenance: {e}")

Check warning on line 35 in lstchain/io/provenance.py

View check run for this annotation

Codecov / codecov/patch

lstchain/io/provenance.py#L34-L35

Added lines #L34 - L35 were not covered by tests


def read_provenance(hdf5_file_path, dataset_name):
"""
Read JSON provenance from HDF5 file's dataset attributes.

Parameters:
-----------
hdf5_file_path : str
Path to the HDF5 file
dataset_name : s
Name of the dataset containing provenance

Returns:
--------
dict
Provenance information as JSON-decoded dictionary
"""
logger.log(logging.INFO, f"reading provenance from {hdf5_file_path}")
with h5py.File(hdf5_file_path, 'r') as h5file:
if 'provenance' not in h5file:
raise ValueError("No provenance found in HDF5 file")

Check warning on line 57 in lstchain/io/provenance.py

View check run for this annotation

Codecov / codecov/patch

lstchain/io/provenance.py#L57

Added line #L57 was not covered by tests
elif dataset_name not in h5file['provenance']:
raise ValueError(f"No provenance found for {dataset_name}")

Check warning on line 59 in lstchain/io/provenance.py

View check run for this annotation

Codecov / codecov/patch

lstchain/io/provenance.py#L59

Added line #L59 was not covered by tests
else:
return json.loads(h5file['provenance'][dataset_name][()])


def read_dl2_provenance(hdf5_file_path):
"""
Read JSON provenance from HDF5 file's dataset attributes.
This function is a wrapper around read_provenance() that reads the provenance for the 'dl2' dataset.

Parameters:
-----------
hdf5_file_path : str
Path to the HDF5 file

Returns:
--------
dict
Provenance information as JSON-decoded dictionary
"""
return read_provenance(hdf5_file_path, 'dl1_to_dl2')
28 changes: 28 additions & 0 deletions lstchain/io/tests/test_provenance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import pytest
import h5py
from lstchain.io.provenance import write_provenance, read_provenance
from ctapipe.core import Provenance

@pytest.fixture
def hdf5_file(tmp_path):
test_file = tmp_path / 'test_provenance.h5'
yield test_file

def test_write_provenance(hdf5_file):
stage_name = 'test_stage'
p = Provenance()
p.add_input_file('input file', role='test input file')
p.add_output_file('output file', role='test output file')
write_provenance(hdf5_file, stage_name)
with h5py.File(hdf5_file, 'r') as h5file:
assert 'provenance' in h5file
assert stage_name in h5file['provenance']


def test_read_provenance(hdf5_file):
stage_name = 'test_stage'
write_provenance(hdf5_file, stage_name)
result = read_provenance(hdf5_file, stage_name)
assert 'activity_name' in result
assert 'activity_uuid' in result

8 changes: 8 additions & 0 deletions lstchain/scripts/tests/test_lstchain_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
from ctapipe.io import read_table
from ctapipe.io import EventSource
from ctapipe.containers import EventType
from lstchain.io.provenance import read_dl2_provenance


from lstchain.io.config import get_srcdep_config, get_standard_config
Expand Down Expand Up @@ -365,6 +366,7 @@ def test_lstchain_merged_dl1_to_dl2(
"lstchain_dl1_to_dl2",
"-f",
simulated_dl1_file_,
"-f",
merged_simulated_dl1_file,
"-p",
rf_models["path"],
Expand All @@ -385,6 +387,12 @@ def test_lstchain_dl1_to_dl2(simulated_dl2_file):
assert "reco_disp_dy" in dl2_df.columns
assert "reco_src_x" in dl2_df.columns
assert "reco_src_y" in dl2_df.columns

prov = read_dl2_provenance(simulated_dl2_file)
assert "activity_name" in prov
assert "config" in prov
assert "path_models" in prov['config']['DL1ToDL2Tool']
assert prov['config']['DL1ToDL2Tool']['path_models'] is not None


def test_lstchain_dl1_to_dl2_srcdep(simulated_srcdep_dl2_file):
Expand Down
Loading