NeuralEnsemble / python-neo

Neo is a package for representing electrophysiology data in Python, together with support for reading a wide range of neurophysiology file formats
http://neo.readthedocs.io/en/latest/
BSD 3-Clause "New" or "Revised" License
325 stars 248 forks source link

[IgorIO] Not all .pxp files have "xUnits" in the header #1530

Closed apdavison closed 1 month ago

apdavison commented 3 months ago

Describe the bug

Loading blocks from a .pxp file with IgorIO results in a KeyError.

To Reproduce

The error occurs with files from this EBRAINS dataset.

from neo import io
filename = io.IgorIO(filename = 'sbj4-170614/cell8/original/hbp-00940_ephy-ChIN-STR_sbj4-170614_cell8_original__md_20170614_cell_7_8_ChIN.pxp')
block = filename.read_block()

Error:

KeyError                                  Traceback (most recent call last)
Cell In[1], line 3
      1 from neo import io
      2 filename = io.IgorIO(filename='sbj4-170614/cell8/original/hbp-00940_ephy-ChIN-STR_sbj4-170614_cell8_original__md_20170614_cell_7_8_ChIN.pxp')
----> 3 block = filename.read_block()

File ~/dev/analysis/neo/neo/io/igorproio.py:76, in IgorIO.read_block(self, lazy)
     73     raise NeoReadWriteError("This IO does not support lazy reading")
     75 block = Block(file_origin=str(self.filename))
---> 76 block.segments.append(self.read_segment(lazy=lazy))
     77 return block

File ~/dev/analysis/neo/neo/io/igorproio.py:96, in IgorIO.read_segment(self, lazy)
     93             signal = self._wave_to_analogsignal(value.wave["wave"], dirpath)
     94             segment.analogsignals.append(signal)
---> 96     pxp.walk(self.filesystem, callback)
     97 else:
     98     segment.analogsignals.append(self.read_analogsignal(lazy=lazy))

File ~/dev/analysis/env-202307/lib/python3.11/site-packages/igor2/packed.py:185, in walk(filesystem, callback, dirpath)
    183 callback(dirpath, key, value)
    184 if isinstance(value, dict):
--> 185     walk(filesystem=value, callback=callback, dirpath=dirpath + [key])

File ~/dev/analysis/env-202307/lib/python3.11/site-packages/igor2/packed.py:183, in walk(filesystem, callback, dirpath)
    181     dirpath = []
    182 for key, value in sorted((_bytes(k), v) for k, v in filesystem.items()):
--> 183     callback(dirpath, key, value)
    184     if isinstance(value, dict):
    185         walk(filesystem=value, callback=callback, dirpath=dirpath + [key])

File ~/dev/analysis/neo/neo/io/igorproio.py:93, in IgorIO.read_segment.<locals>.callback(dirpath, key, value)
     91 def callback(dirpath, key, value):
     92     if isinstance(value, WaveRecord):
---> 93         signal = self._wave_to_analogsignal(value.wave["wave"], dirpath)
     94         segment.analogsignals.append(signal)

File ~/dev/analysis/neo/neo/io/igorproio.py:136, in IgorIO._wave_to_analogsignal(self, content, dirpath)
    134 name = str(header["bname"].decode("utf-8"))
    135 units = "".join([x.decode() for x in header["dataUnits"]])
--> 136 time_units = "".join([x.decode() for x in header["xUnits"]])
    137 if len(time_units) == 0:
    138     time_units = "s"

KeyError: 'xUnits'

Expected behaviour

The code should return a Block containing the data.

Environment: