Skip to content

[Bug]: HTML repr broken for LINDI #1266

@bendichter

Description

@bendichter

What happened?

The HTML repr is broken for LINDI interfaces. This is making my demos look sloppy so I would very much appreciate a quick fix

Steps to Reproduce

# inside a jupyter notebook

import pynwb
import lindi

f = lindi.LindiH5pyFile.from_lindi_file("https://lindi.neurosift.org/dandi/dandisets/000582/assets/2b9e441b-56bc-4be2-893e-0e02d22d239d/nwb.lindi.json")
nwb = pynwb.NWBHDF5IO(file=f, mode='r').read()

nwb

Traceback

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
File ~/miniconda3/lib/python3.12/site-packages/IPython/core/formatters.py:406, in BaseFormatter.__call__(self, obj)
    404     method = get_real_method(obj, self.print_method)
    405     if method is not None:
--> 406         return method()
    407     return None
    408 else:

File ~/miniconda3/lib/python3.12/site-packages/hdmf/container.py:676, in Container._repr_html_(self)
    674 html_repr += "<div class='container-wrap'>"
    675 html_repr += f"<div class='container-header'><div class='xr-obj-type'><h3>{header_text}</h3></div></div>"
--> 676 html_repr += self._generate_html_repr(self.fields, is_field=True)
    677 html_repr += "</div>"
    678 return html_repr

File ~/miniconda3/lib/python3.12/site-packages/hdmf/container.py:690, in Container._generate_html_repr(self, fields, level, access_code, is_field)
    688             html_repr += value._generate_field_html(key, value, level, current_access_code)
    689         else:
--> 690             html_repr += self._generate_field_html(key, value, level, current_access_code)
    691 elif isinstance(fields, list):
    692     for index, item in enumerate(fields):

File ~/miniconda3/lib/python3.12/site-packages/hdmf/container.py:725, in Container._generate_field_html(self, key, value, level, access_code)
    723     html_content = self._generate_html_repr(value.fields, level + 1, access_code, is_field=True)
    724 elif isinstance(value, (list, dict, np.ndarray)):
--> 725     html_content = self._generate_html_repr(value, level + 1, access_code, is_field=False)
    726 else:
    727     html_content = f'<span class="field-key">{value}</span>'

File ~/miniconda3/lib/python3.12/site-packages/hdmf/container.py:688, in Container._generate_html_repr(self, fields, level, access_code, is_field)
    686 current_access_code = f"{access_code}.{key}" if is_field else f"{access_code}['{key}']"
    687 if hasattr(value, '_generate_field_html'):
--> 688     html_repr += value._generate_field_html(key, value, level, current_access_code)
    689 else:
    690     html_repr += self._generate_field_html(key, value, level, current_access_code)

File ~/miniconda3/lib/python3.12/site-packages/pynwb/base.py:342, in TimeSeries._generate_field_html(self, key, value, level, access_code)
    339     linked_key = 'timestamps' if key == 'timestamp_link' else 'data'
    340     value = [find_location_in_memory_nwbfile(linked_key, v) for v in value]
--> 342 return super()._generate_field_html(key, value, level, access_code)

File ~/miniconda3/lib/python3.12/site-packages/hdmf/container.py:723, in Container._generate_field_html(self, key, value, level, access_code)
    721     html_content = value.__repr_html__()
    722 elif hasattr(value, "fields"):  # Note that h5py.Dataset has a fields attribute so there is an implicit order
--> 723     html_content = self._generate_html_repr(value.fields, level + 1, access_code, is_field=True)
    724 elif isinstance(value, (list, dict, np.ndarray)):
    725     html_content = self._generate_html_repr(value, level + 1, access_code, is_field=False)

File ~/miniconda3/lib/python3.12/site-packages/hdmf/container.py:690, in Container._generate_html_repr(self, fields, level, access_code, is_field)
    688             html_repr += value._generate_field_html(key, value, level, current_access_code)
    689         else:
--> 690             html_repr += self._generate_field_html(key, value, level, current_access_code)
    691 elif isinstance(fields, list):
    692     for index, item in enumerate(fields):

File ~/miniconda3/lib/python3.12/site-packages/pynwb/base.py:342, in TimeSeries._generate_field_html(self, key, value, level, access_code)
    339     linked_key = 'timestamps' if key == 'timestamp_link' else 'data'
    340     value = [find_location_in_memory_nwbfile(linked_key, v) for v in value]
--> 342 return super()._generate_field_html(key, value, level, access_code)

File ~/miniconda3/lib/python3.12/site-packages/hdmf/container.py:717, in Container._generate_field_html(self, key, value, level, access_code)
    714 is_array_data = hasattr(value, "shape") and hasattr(value, "dtype")
    716 if is_array_data:
--> 717     html_content = self._generate_array_html(value, level + 1)
    718 elif hasattr(value, "generate_html_repr"):
    719     html_content = value.generate_html_repr(level + 1, access_code)

File ~/miniconda3/lib/python3.12/site-packages/hdmf/container.py:759, in Container._generate_array_html(self, array, level)
    753     repr_html = generate_array_html_repr(array_info_dict, array.data, "DataIO")
    754 elif it_was_read_with_io:
    755     # The backend handles the representation here. Two special cases worth noting:
    756     # 1. Array-type attributes (e.g., start_frame in ImageSeries) remain NumPy arrays
    757     #    even when their parent container has an IO
    758     # 2. Data may have been modified after being read from storage
--> 759     repr_html = read_io.generate_dataset_html(array)
    760 else:  # Not sure which object could get here
    761     object_class = array.__class__.__name__

File ~/miniconda3/lib/python3.12/site-packages/hdmf/backends/hdf5/h5tools.py:1544, in HDF5IO.generate_dataset_html(dataset)
   1542 dataset_type = "HDF5 dataset"
   1543 # get info from hdf5 dataset
-> 1544 compressed_size = dataset.id.get_storage_size()
   1545 if hasattr(dataset, "nbytes"):  # TODO: Remove this after h5py minimal version is larger than 3.0
   1546     uncompressed_size = dataset.nbytes

AttributeError: 'str' object has no attribute 'get_storage_size'

Operating System

macOS

Python Version

3.12

Package Versions

lindi==0.4.4
hdmf==4.0.0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions