Skip to content

ndx-pose fails to write properly when inside a contextmanager #36

@pauladkisson

Description

@pauladkisson

Related to catalystneuro/neuroconv#1114

Tracked this down to a minimal example with a contextmanager like neuroconv's make_or_load_nwbfile. Basically when the io is created in the first part of a context manager (before the yield) but used to write in the second part (after the yield), it doesn't write properly. This can be solved by changing the import location (ex. adding import ndx_pose at the top of the script would do it) or changing the io instantiation location (ex. moving io = NWBHDF5IO(nwbfile_path, "w") inside the finally block would do it).

Not sure if ndx_pose needs to fix this or if it's a deeper problem, but would love a thorough explanation to improve my understanding.

Minimal Example:

from pynwb import NWBFile
from datetime import datetime
from pynwb import NWBHDF5IO
import os
from contextlib import contextmanager
from pynwb import NWBHDF5IO
import numpy as np

class myDeepLabCutInterface():
    def add_to_nwbfile(self, nwbfile):
        from ndx_pose import PoseEstimation, PoseEstimationSeries
        pose_estimation_series = PoseEstimationSeries(
            name="name",
            data=np.random.rand(10, 3),
            rate=1.0,
            confidence=np.random.rand(10),
            reference_frame="reference_frame",
        )
        pose_estimation = PoseEstimation(
            name="PoseEstimation",
            pose_estimation_series=[pose_estimation_series],
        )
        nwbfile.create_processing_module(name="behavior", description="description")
        nwbfile.processing["behavior"].add(pose_estimation)

@contextmanager
def my_make_or_load_nwbfile(nwbfile, nwbfile_path):
    io = NWBHDF5IO(nwbfile_path, "w")
    try:
        yield nwbfile
    finally:
        io.write(nwbfile)

def main():
    nwbfile_path = "test.nwb"
    if os.path.exists(nwbfile_path):
        os.remove(nwbfile_path)

    dlc_interface = myDeepLabCutInterface()

    nwbfile = NWBFile(session_description="test", identifier="test", session_start_time=datetime.now())

    with my_make_or_load_nwbfile(nwbfile, nwbfile_path) as nwbfile_out:
        dlc_interface.add_to_nwbfile(nwbfile_out)
        # In memory, the pose_estimation_series is present in the nwbfile
        assert hasattr(nwbfile_out.processing["behavior"].data_interfaces['PoseEstimation'], "pose_estimation_series") # True

    with NWBHDF5IO(nwbfile_path, "r") as io:
        nwbfile = io.read()
        # After writing to disk, the pose_estimation_series is NOT present in the nwbfile
        assert hasattr(nwbfile.processing["behavior"].data_interfaces['PoseEstimation'], "pose_estimation_series") # False

if __name__ == "__main__":
    main()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions