Skip to content

Provenance crashes because it cannot serialise Astropy columns #2918

Description

@Voutsi

Describe the bug
Hello, while running the telescope cross calibration, I encountered the following error:

Traceback (most recent call last):
  File "/home/voutsi/miniforge3/envs/calibpipe/bin/calibpipe-cross-calibration", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/home/voutsi/Work/calibpipe/src/calibpipe/tools/telescope_cross_calibration_calculator.py", line 797, in main
    tool.run()
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/site-packages/ctapipe/core/tool.py", line 482, in run
    self.write_provenance()
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/site-packages/ctapipe/core/tool.py", line 497, in write_provenance
    provlog.write(Provenance().as_json(indent=3))
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/site-packages/ctapipe/core/provenance.py", line 421, in as_json
    return json.dumps(self.provenance, default=json_config_handler, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/json/__init__.py", line 238, in dumps
    **kw).encode(obj)
          ^^^^^^^^^^^
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/json/encoder.py", line 202, in encode
    chunks = list(chunks)
             ^^^^^^^^^^^^
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/json/encoder.py", line 430, in _iterencode
    yield from _iterencode_list(o, _current_indent_level)
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/json/encoder.py", line 326, in _iterencode_list
    yield from chunks
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/json/encoder.py", line 406, in _iterencode_dict
    yield from chunks
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/json/encoder.py", line 406, in _iterencode_dict
    yield from chunks
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/json/encoder.py", line 406, in _iterencode_dict
    yield from chunks
  [Previous line repeated 2 more times]
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/json/encoder.py", line 326, in _iterencode_list
    yield from chunks
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/json/encoder.py", line 439, in _iterencode
    o = _default(o)
        ^^^^^^^^^^^
  File "/home/voutsi/miniforge3/envs/calibpipe/lib/python3.12/site-packages/ctapipe/core/provenance.py", line 93, in json_config_handler
    raise TypeError(f"{obj!r} cannot be serialized to json")
TypeError: <Column name='obs_id' dtype='uint64' description='Observation Block ID' length=0>
 cannot be serialized to json

To Reproduce
Steps to reproduce the behavior: simply run the cross calibration tool (however is not yet merged in CalibPipe main branch, It lives in refactoring/dl2_tables)
1.calibpipe-cross-calibration -c docs/source/user_guide/array/test_locally_cross_calibration_configuration.yaml

Expected behavior
Provenance should be saved without errors. I produced a workaround with the help of AI tools that solves the problem. Is something like that of general interest?

from ctapipe.core import provenance as _prov

        _orig_handler = _prov.json_config_handler

        def _json_config_handler_extended(obj):
            # Handle astropy Columns in output_table_schema
            if isinstance(obj, Column):
                d = {
                    "name": obj.name,
                    "dtype": str(obj.dtype),
                }
                # these attributes might not exist on all Column-like objects
                if getattr(obj, "unit", None) is not None:
                    d["unit"] = str(obj.unit)
                if getattr(obj, "description", None):
                    d["description"] = obj.description
                return d

            # common nuisance types
            if isinstance(obj, np.integer | np.floating | np.bool_):
                return obj.item()

            return _orig_handler(obj)

        # monkeypatch ctapipe's handler used by Provenance().as_json(...)
        #_prov.json_config_handler = _json_config_handler_extended

Supporting information
I believe that the issue arises due to these lines in the tool setup:

cols = self._schema_dicts_to_columns(self.output_table_schema)
self.inter_loader.epp.output_table_schema = cols
self.cross_loader.epp.output_table_schema = cols

where I supply astropy columns to a component's config.

Has anyone else faced such issue? Shall we try to implement in ctapipe the proposed (or any other) workaround?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions