pynwb icon indicating copy to clipboard operation
pynwb copied to clipboard

problem reading older icephys file

Open bendichter opened this issue 3 years ago • 5 comments

Description

PyNWB no longer is able to open the file in dandiset 25, which uses the old style of icephys.

Steps to Reproduce

$ dandi download https://dandiarchive.org/dandiset/000025/draft
$ cd 000025/
$ ipython
from pynwb import NWBHDF5IO

In [2]: io = NWBHDF5IO('001_140709EXP_A1_ndx_v3.nwb','r', load_namespaces=True)

/Users/bendichter/opt/miniconda3/lib/python3.9/site-packages/hdmf/spec/namespace.py:532: UserWarning: Ignoring cached namespace 'hdmf-common' version 1.1.3 because version 1.5.0 is already loaded.
  warn("Ignoring cached namespace '%s' version %s because version %s is already loaded."
/Users/bendichter/opt/miniconda3/lib/python3.9/site-packages/hdmf/spec/namespace.py:532: UserWarning: Ignoring cached namespace 'core' version 2.1.0 because version 2.4.0 is already loaded.
  warn("Ignoring cached namespace '%s' version %s because version %s is already loaded."

In [3]: io.read()
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-e070f3e77a80> in <module>
----> 1 io.read()

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/backends/hdf5/h5tools.py in read(self, **kwargs)
    496                                        % (self.source, self.__mode))
    497         try:
--> 498             return call_docval_func(super().read, kwargs)
    499         except UnsupportedOperation as e:
    500             if str(e) == 'Cannot build data. There are no values.':  # pragma: no cover

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/utils.py in call_docval_func(func, kwargs)
    422 def call_docval_func(func, kwargs):
    423     fargs, fkwargs = fmt_docval_args(func, kwargs)
--> 424     return func(*fargs, **fkwargs)
    425 
    426 

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/utils.py in func_call(*args, **kwargs)
    581             def func_call(*args, **kwargs):
    582                 pargs = _check_args(args, kwargs)
--> 583                 return func(args[0], **pargs)
    584         else:
    585             def func_call(*args, **kwargs):

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/backends/io.py in read(self, **kwargs)
     39             # TODO also check that the keys are appropriate. print a better error message
     40             raise UnsupportedOperation('Cannot build data. There are no values.')
---> 41         container = self.__manager.construct(f_builder)
     42         return container
     43 

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/utils.py in func_call(*args, **kwargs)
    581             def func_call(*args, **kwargs):
    582                 pargs = _check_args(args, kwargs)
--> 583                 return func(args[0], **pargs)
    584         else:
    585             def func_call(*args, **kwargs):

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/build/manager.py in construct(self, **kwargs)
    278                 # we are at the top of the hierarchy,
    279                 # so it must be time to resolve parents
--> 280                 result = self.__type_map.construct(builder, self, None)
    281                 self.__resolve_parents(result)
    282             self.prebuilt(result, builder)

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/utils.py in func_call(*args, **kwargs)
    581             def func_call(*args, **kwargs):
    582                 pargs = _check_args(args, kwargs)
--> 583                 return func(args[0], **pargs)
    584         else:
    585             def func_call(*args, **kwargs):

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/build/manager.py in construct(self, **kwargs)
    783         if build_manager is None:
    784             build_manager = BuildManager(self)
--> 785         obj_mapper = self.get_map(builder)
    786         if obj_mapper is None:
    787             dt = builder.attributes[self.namespace_catalog.group_spec_cls.type_key()]

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/utils.py in func_call(*args, **kwargs)
    581             def func_call(*args, **kwargs):
    582                 pargs = _check_args(args, kwargs)
--> 583                 return func(args[0], **pargs)
    584         else:
    585             def func_call(*args, **kwargs):

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/build/manager.py in get_map(self, **kwargs)
    713                     break
    714             spec = self.__ns_catalog.get_spec(namespace, data_type)
--> 715             mapper = mapper_cls(spec)
    716             self.__mappers[container_cls] = mapper
    717         return mapper

~/opt/miniconda3/lib/python3.9/site-packages/pynwb/io/file.py in __init__(self, spec)
     53         self.map_spec('icephys_electrodes', icephys_spec.get_neurodata_type('IntracellularElectrode'))
     54         self.map_spec('sweep_table', icephys_spec.get_neurodata_type('SweepTable'))
---> 55         self.map_spec('intracellular_recordings', icephys_spec.get_neurodata_type('IntracellularRecordingsTable'))
     56         self.map_spec('icephys_simultaneous_recordings', icephys_spec.get_neurodata_type('SimultaneousRecordingsTable'))
     57         self.map_spec('icephys_sequential_recordings', icephys_spec.get_neurodata_type('SequentialRecordingsTable'))

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/utils.py in func_call(*args, **kwargs)
    580         if is_method:
    581             def func_call(*args, **kwargs):
--> 582                 pargs = _check_args(args, kwargs)
    583                 return func(args[0], **pargs)
    584         else:

~/opt/miniconda3/lib/python3.9/site-packages/hdmf/utils.py in _check_args(args, kwargs)
    573                 if parse_err:
    574                     msg = '%s: %s' % (func.__qualname__, ', '.join(parse_err))
--> 575                     raise ExceptionType(msg)
    576 
    577             return parsed['args']

TypeError: ObjectMapper.map_spec: None is not allowed for 'spec' (expected 'Spec', not None)

Environment

Python Executable: Conda
Python Version: Python 3.9
Operating System: macOS
HDMF Version: 3.1.1
PyNWB Version: 2.0.0

Checklist

  • [x] Have you ensured the bug was not already reported?
  • [x] Have you included a brief and descriptive title?
  • [x] Have you included a clear description of the problem you are trying to solve?
  • [x] Have you included a minimal code snippet that reproduces the issue you are encountering?
  • [x] Have you checked our Contributing document?

bendichter avatar Oct 01 '21 14:10 bendichter

Ok, that should not happen. I'll take a look. I opened an icephys files from dandiset 20 yesterday without an issue. I'm wondering whether something strange is happening where things might be colliding with an extension in the file.

oruebel avatar Oct 01 '21 18:10 oruebel

Validation output:

$python -m pynwb.validate 001_140709EXP_A1_ndx_v3.nwb 
Traceback (most recent call last):
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/pynwb/validate.py", line 136, in <module>
    main()
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/pynwb/validate.py", line 72, in main
    ns_deps = NWBHDF5IO.load_namespaces(catalog, path)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/utils.py", line 583, in func_call
    return func(args[0], **pargs)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/backends/hdf5/h5tools.py", line 147, in load_namespaces
    return cls.__load_namespaces(namespace_catalog, namespaces, open_file_obj)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/backends/hdf5/h5tools.py", line 181, in __load_namespaces
    d.update(namespace_catalog.load_namespaces(cls.__ns_spec_path, reader=reader))
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/utils.py", line 583, in func_call
    return func(args[0], **pargs)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/spec/namespace.py", line 538, in load_namespaces
    ret[ns['name']] = self.__load_namespace(ns, reader, resolve=resolve)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/spec/namespace.py", line 448, in __load_namespace
    self.__load_spec_file(reader, s['source'], catalog, types_to_load=types_to_load, resolve=resolve)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/spec/namespace.py", line 402, in __load_spec_file
    temp_dict = {k: None for k in __reg_spec(self.__group_spec_cls, spec_dict)}
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/spec/namespace.py", line 389, in __reg_spec
    return catalog.auto_register(spec_obj, spec_source)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/utils.py", line 583, in func_call
    return func(args[0], **pargs)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/spec/catalog.py", line 102, in auto_register
    ret.extend(self.auto_register(group_spec, source_file))
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/utils.py", line 583, in func_call
    return func(args[0], **pargs)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/spec/catalog.py", line 100, in auto_register
    self.register_spec(dataset_spec, source_file)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/utils.py", line 583, in func_call
    return func(args[0], **pargs)
  File "/home/firma/.pyenv/versions/3.8.6/lib/python3.8/site-packages/hdmf/spec/catalog.py", line 46, in register_spec
    raise ValueError("'%s' - cannot overwrite existing specification" % type_name)
ValueError: 'ScratchData' - cannot overwrite existing specification

t-b avatar Oct 13 '21 09:10 t-b

@t-b thanks for the additional case. Could you provide a link to the file. As far as I can tell the issue is somehow related to the use of extensions in the file. Loading existing (i.e., v2.3 and earlier) ICEphys files appears to work if the file doesn't use an extension, i.e., it seems that loading the extension from file triggers an edge-case we missed in the tests.

oruebel avatar Oct 13 '21 18:10 oruebel

@oruebel This is just the file from the dandi link.

t-b avatar Oct 15 '21 17:10 t-b

@t-b thanks for the clarification. Interesting that the validator fails differently than the normal read here. In particular, it seems that in the log output you provided for the validator, the error occurs already in the load_namespaces function during read. In contrast in the log output that Ben reported for reading the file, the error appears to happen much later in the ObjectMapper, even though both have load_namespaces enabled. This may mean that we are actually with two separate issues. We'll take a look.

oruebel avatar Oct 15 '21 18:10 oruebel