Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge fails for object in both Segment and Group #1308

Open
kjohnsen opened this issue Jul 14, 2023 · 0 comments
Open

merge fails for object in both Segment and Group #1308

kjohnsen opened this issue Jul 14, 2023 · 0 comments
Labels
Milestone

Comments

@kjohnsen
Copy link
Contributor

Describe the bug
I'm trying to merge two blocks together, each having one segment, into one block with two segments. But I have problems calling merge since I have spike trains in groups. Why am I told SpikeTrain can only have Segment, not Group parents? No errors popped up before merging. From what I understand, an object can be in more than one container, but only have one parent.

To Reproduce

#%%
import neo
#%%
blocks = []
for i in range(2):
    block = neo.Block()
    seg = neo.Segment(name=f'segment {i}')
    block.segments.append(seg)
    g = neo.Group()
    st = neo.SpikeTrain([1,2,3], t_stop=4, units='ms')
    g.spiketrains.append(st)
    block.groups.append(g)
    seg.spiketrains.append(st)
    blocks.append(block)
blocks
# %%
blocks[0].merge(blocks[1])
blocks[0]
Output:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
/home/kyle/scratch/python-neo/test.py in line 2
      [16](file:///home/kyle/scratch/python-neo/test.py?line=15) # %%
----> [17](file:///home/kyle/scratch/python-neo/test.py?line=16) blocks[0].merge(blocks[1])
      [18](file:///home/kyle/scratch/python-neo/test.py?line=17) blocks[0]

File [~/scratch/python-neo/neo/core/container.py:491](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/home/kyle/scratch/python-neo/~/scratch/python-neo/neo/core/container.py:491), in Container.merge(self, other)
    [489](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=488)     continue
    [490](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=489) if obj.name in lookup:
--> [491](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=490)     lookup[obj.name].merge(obj)
    [492](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=491) else:
    [493](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=492)     lookup[obj.name] = obj

File [~/scratch/python-neo/neo/core/container.py:519](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/home/kyle/scratch/python-neo/~/scratch/python-neo/neo/core/container.py:519), in Container.merge(self, other)
    [516](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=515)             getattr(self, container).append(obj)
    [517](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=516)         # if self.__class__.__name__ in obj._parent_objects:
    [518](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=517)             # obj.set_parent(self)
--> [519](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=518)         obj.set_parent(self)
    [521](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=520) # use the BaseNeo merge as well
    [522](file:///home/kyle/scratch/python-neo/neo/core/container.py?line=521) super().merge(other)

File [~/scratch/python-neo/neo/core/baseneo.py:369](https://vscode-remote+wsl-002bubuntu.vscode-resource.vscode-cdn.net/home/kyle/scratch/python-neo/~/scratch/python-neo/neo/core/baseneo.py:369), in BaseNeo.set_parent(self, obj)
    [364](file:///home/kyle/scratch/python-neo/neo/core/baseneo.py?line=363) """
    [365](file:///home/kyle/scratch/python-neo/neo/core/baseneo.py?line=364) Set the appropriate "parent" attribute of this object
    [366](file:///home/kyle/scratch/python-neo/neo/core/baseneo.py?line=365) according to the type of "obj"
    [367](file:///home/kyle/scratch/python-neo/neo/core/baseneo.py?line=366) """
    [368](file:///home/kyle/scratch/python-neo/neo/core/baseneo.py?line=367) if obj.__class__.__name__ not in self._parent_objects:
--> [369](file:///home/kyle/scratch/python-neo/neo/core/baseneo.py?line=368)     raise TypeError("{} can only have parents of type {}, not {}".format(
    [370](file:///home/kyle/scratch/python-neo/neo/core/baseneo.py?line=369)         self.__class__.__name__, self._parent_objects, obj.__class__.__name__))
    [371](file:///home/kyle/scratch/python-neo/neo/core/baseneo.py?line=370) loc = self._parent_objects.index(obj.__class__.__name__)
    [372](file:///home/kyle/scratch/python-neo/neo/core/baseneo.py?line=371) parent_attr = self._parent_attrs[loc]

TypeError: SpikeTrain can only have parents of type ('Segment',), not Group

Expected behaviour
The blocks to merge with set_parent on children objects only applied to the true parent. I don't know enough of the codebase to know if this will cause problems anywhere else, but changing obj.set_parent(self) in Container.merge() to this does the trick:

                if self.__class__.__name__ in obj._parent_objects:
                    obj.set_parent(self)

Then I get what I expected out of the MRE:

Block with 2 segments, 1 groups
# segments (N=2)
0: Segment with 1 spiketrains name: 'segment 0' # analogsignals (N=0)
1: Segment with 1 spiketrains name: 'segment 1' # analogsignals (N=0)

Environment:

  • OS: Linux
  • Python version: 3.9
  • Neo version: 0.13.0.dev0
  • NumPy version: 1.25.1

Additional context
Add any other context about the problem here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants