Skip to content

[Bug]: HTML repr broken for LINDI #1266

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions