Skip to content

Commit 5f490a4

Browse files
authored
Merge pull request #1343 from cta-observatory/dl1dl2tool
DL1 to DL2 tool
2 parents d74e165 + 57af1bb commit 5f490a4

File tree

7 files changed

+262
-98
lines changed

7 files changed

+262
-98
lines changed

docs/introduction.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ Here is an example configuration file for this step.
7878
DL1 to DL2
7979
----------
8080

81-
Use ``lstchain.scripts.lstchain_dl1_to_dl2`` for real data and MC.
81+
Use ``lstchain.tools.lstchain_dl1_to_dl2`` for real data and MC.
8282

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

docs/lstchain_api/scripts/index.rst

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ The scripts to be executed from the command line are described below:
1414
* `lstchain_data_create_time_calibration_file`_
1515
* `lstchain_data_r0_to_dl1`_
1616
* `lstchain_dl1_muon_analysis`_
17-
* `lstchain_dl1_to_dl2`_
1817
* `lstchain_dl1ab`_
1918
* `lstchain_dump_config`_
2019
* `lstchain_find_pedestals`_
@@ -99,19 +98,6 @@ Usage
9998
:func: parser
10099
:prog: lstchain_dl1_muon_analysis
101100

102-
.. _lstchain_dl1_to_dl2:
103-
104-
lstchain_dl1_to_dl2
105-
+++++++++++++++++++
106-
107-
.. automodule:: lstchain.scripts.lstchain_dl1_to_dl2
108-
109-
Usage
110-
-----
111-
.. argparse::
112-
:module: lstchain.scripts.lstchain_dl1_to_dl2
113-
:func: parser
114-
:prog: lstchain_dl1_to_dl2
115101

116102
.. _lstchain_dl1ab:
117103

docs/lstchain_api/tools/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,5 @@ Reference/API
2424
:no-inheritance-diagram:
2525
.. automodapi:: lstchain.tools.lstchain_fit_intensity_scan
2626
:no-inheritance-diagram:
27+
.. automodapi:: lstchain.tools.lstchain_dl1_to_dl2
28+
:no-inheritance-diagram:

lstchain/io/provenance.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
import json
2+
import h5py
3+
from ctapipe.core import Provenance
4+
import logging
5+
6+
logger = logging.getLogger()
7+
8+
def write_provenance(hdf5_file_path, stage_name):
9+
"""
10+
Write JSON provenance information to an HDF5 file.
11+
It uses the current activity's provenance information and should typically be called within a ctapipe Tool.
12+
13+
Parameters:
14+
-----------
15+
hdf5_file_path : str or Path
16+
Path to the HDF5 file
17+
stage_name : str
18+
Name of the stage generating the provenance
19+
20+
Returns:
21+
--------
22+
None
23+
"""
24+
try:
25+
with h5py.File(hdf5_file_path, 'a') as h5file:
26+
if 'provenance' not in h5file:
27+
h5file.create_group('provenance')
28+
29+
# Get the provenance dictionary from the current activity
30+
provenance_data = Provenance().current_activity.provenance
31+
# Dump the dictionary to a JSON string and write it to the HDF5 file
32+
h5file['provenance'].create_dataset(stage_name, data=json.dumps(provenance_data, default=str))
33+
34+
except Exception as e:
35+
raise Exception(f"Error writing provenance: {e}")
36+
37+
38+
def read_provenance(hdf5_file_path, dataset_name):
39+
"""
40+
Read JSON provenance from HDF5 file's dataset attributes.
41+
42+
Parameters:
43+
-----------
44+
hdf5_file_path : str
45+
Path to the HDF5 file
46+
dataset_name : s
47+
Name of the dataset containing provenance
48+
49+
Returns:
50+
--------
51+
dict
52+
Provenance information as JSON-decoded dictionary
53+
"""
54+
logger.log(logging.INFO, f"reading provenance from {hdf5_file_path}")
55+
with h5py.File(hdf5_file_path, 'r') as h5file:
56+
if 'provenance' not in h5file:
57+
raise ValueError("No provenance found in HDF5 file")
58+
elif dataset_name not in h5file['provenance']:
59+
raise ValueError(f"No provenance found for {dataset_name}")
60+
else:
61+
return json.loads(h5file['provenance'][dataset_name][()])
62+
63+
64+
def read_dl2_provenance(hdf5_file_path):
65+
"""
66+
Read JSON provenance from HDF5 file's dataset attributes.
67+
This function is a wrapper around read_provenance() that reads the provenance for the 'dl2' dataset.
68+
69+
Parameters:
70+
-----------
71+
hdf5_file_path : str
72+
Path to the HDF5 file
73+
74+
Returns:
75+
--------
76+
dict
77+
Provenance information as JSON-decoded dictionary
78+
"""
79+
return read_provenance(hdf5_file_path, 'dl1_to_dl2')

lstchain/io/tests/test_provenance.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import pytest
2+
import h5py
3+
from lstchain.io.provenance import write_provenance, read_provenance
4+
from ctapipe.core import Provenance
5+
6+
@pytest.fixture
7+
def hdf5_file(tmp_path):
8+
test_file = tmp_path / 'test_provenance.h5'
9+
yield test_file
10+
11+
def test_write_provenance(hdf5_file):
12+
stage_name = 'test_stage'
13+
p = Provenance()
14+
p.add_input_file('input file', role='test input file')
15+
p.add_output_file('output file', role='test output file')
16+
write_provenance(hdf5_file, stage_name)
17+
with h5py.File(hdf5_file, 'r') as h5file:
18+
assert 'provenance' in h5file
19+
assert stage_name in h5file['provenance']
20+
21+
22+
def test_read_provenance(hdf5_file):
23+
stage_name = 'test_stage'
24+
write_provenance(hdf5_file, stage_name)
25+
result = read_provenance(hdf5_file, stage_name)
26+
assert 'activity_name' in result
27+
assert 'activity_uuid' in result
28+

lstchain/scripts/tests/test_lstchain_scripts.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
from ctapipe.io import read_table
1818
from ctapipe.io import EventSource
1919
from ctapipe.containers import EventType
20+
from lstchain.io.provenance import read_dl2_provenance
2021

2122

2223
from lstchain.io.config import get_srcdep_config, get_standard_config
@@ -365,6 +366,7 @@ def test_lstchain_merged_dl1_to_dl2(
365366
"lstchain_dl1_to_dl2",
366367
"-f",
367368
simulated_dl1_file_,
369+
"-f",
368370
merged_simulated_dl1_file,
369371
"-p",
370372
rf_models["path"],
@@ -385,6 +387,12 @@ def test_lstchain_dl1_to_dl2(simulated_dl2_file):
385387
assert "reco_disp_dy" in dl2_df.columns
386388
assert "reco_src_x" in dl2_df.columns
387389
assert "reco_src_y" in dl2_df.columns
390+
391+
prov = read_dl2_provenance(simulated_dl2_file)
392+
assert "activity_name" in prov
393+
assert "config" in prov
394+
assert "path_models" in prov['config']['DL1ToDL2Tool']
395+
assert prov['config']['DL1ToDL2Tool']['path_models'] is not None
388396

389397

390398
def test_lstchain_dl1_to_dl2_srcdep(simulated_srcdep_dl2_file):

0 commit comments

Comments
 (0)