Skip to content

Commit 29d73f6

Browse files
Merge pull request #1266 from apdavison/autorel3
Automatic handling of relationships between objects
2 parents 0052055 + 425c285 commit 29d73f6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+482
-343
lines changed

doc/old_stuffs/grouping.rst

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ Using :class:`ChannelIndex`::
3434

3535
block = Block()
3636
segment = Segment()
37-
segment.block = block
3837
block.segments.append(segment)
3938

4039
for i in (0, 1):
@@ -55,7 +54,6 @@ Using array annotations, we annotate the channels of the :class:`AnalogSignal` d
5554

5655
block = Block()
5756
segment = Segment()
58-
segment.block = block
5957
block.segments.append(segment)
6058

6159
for i in (0, 1):
@@ -77,7 +75,6 @@ Each :class:`ChannelIndex` also contains the list of channels on which that neur
7775

7876
block = Block(name="probe data")
7977
segment = Segment()
80-
segment.block = block
8178
block.segments.append(segment)
8279

8380
# create 4-channel AnalogSignal with dummy data
@@ -119,7 +116,6 @@ Using :class:`ChannelView` and :class:`Group`::
119116

120117
block = Block(name="probe data")
121118
segment = Segment()
122-
segment.block = block
123119
block.segments.append(segment)
124120

125121
# create 4-channel AnalogSignal with dummy data

doc/old_stuffs/io_developers_guide.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ Miscellaneous
3838
=============
3939

4040
* If your IO supports several versions of a format (like ABF1, ABF2), upload to the gin.g-node.org test file repository all file versions possible. (for test coverage).
41-
* :py:func:`neo.core.Block.create_many_to_one_relationship` offers a utility to complete the hierarchy when all one-to-many relationships have been created.
4241
* In the docstring, explain where you obtained the file format specification if it is a closed one.
4342
* If your IO is based on a database mapper, keep in mind that the returned object MUST be detached,
4443
because this object can be written to another url for copying.

doc/source/images/generate_diagram.py

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ def get_rect_height(name, obj):
2828
nlines = 1.5
2929
nlines += len(getattr(obj, '_all_attrs', []))
3030
nlines += len(getattr(obj, '_single_child_objects', []))
31-
nlines += len(getattr(obj, '_multi_child_objects', []))
3231
return nlines * line_heigth
3332

3433

@@ -74,9 +73,7 @@ def generate_diagram(rect_pos, rect_width, figsize):
7473
alpha = [1., 1., 0.3]
7574
for name, pos in rect_pos.items():
7675
obj = objs[name]
77-
relationships = [getattr(obj, '_single_child_objects', []),
78-
getattr(obj, '_multi_child_objects', []),
79-
getattr(obj, '_child_properties', [])]
76+
relationships = [getattr(obj, '_single_child_objects', [])]
8077

8178
for r in range(3):
8279
for ch_name in relationships[r]:
@@ -122,16 +119,6 @@ def generate_diagram(rect_pos, rect_width, figsize):
122119
facecolor='c', edgecolor='k', alpha=.5)
123120
ax.add_patch(rect)
124121

125-
# multi relationship
126-
relationship = list(getattr(obj, '_multi_child_objects', []))
127-
pos2 = (pos[1] + htotal - line_heigth * (1.5 + len(relationship))
128-
- rect_height)
129-
rect_height = len(relationship) * line_heigth
130-
131-
rect = Rectangle((pos[0], pos2), rect_width, rect_height,
132-
facecolor='m', edgecolor='k', alpha=.5)
133-
ax.add_patch(rect)
134-
135122
# necessary attr
136123
pos2 = (pos[1] + htotal
137124
- line_heigth * (1.5 + len(allrelationship) + len(obj._necessary_attrs)))

doc/source/scripts/multi_tetrode_example.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535

3636
# Create dummy data, one segment at a time
3737
for segment in block.segments:
38-
segment.block = block
3938

4039
# create two 4-channel AnalogSignals with dummy data
4140
signals = {
@@ -46,8 +45,6 @@
4645
}
4746
if store_signals:
4847
segment.analogsignals.extend(signals.values())
49-
for signal in signals:
50-
signal.segment = segment
5148

5249
# create spike trains with dummy data
5350
# we will pretend the spikes have been extracted from the dummy signal
@@ -56,7 +53,6 @@
5653
spiketrain = SpikeTrain(np.random.uniform(0, 100, size=30) * ms, t_stop=100 * ms)
5754
# assign each spiketrain to the appropriate segment
5855
segment.spiketrains.append(spiketrain)
59-
spiketrain.segment = segment
6056
# assign each spiketrain to a given neuron
6157
current_group = next(iter_group)
6258
current_group.add(spiketrain)

examples/generated_data.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,6 @@ def generate_block(n_segments=3, n_channels=4, n_units=3,
5858
seg.spiketrains.append(train)
5959
u.spiketrains.append(train)
6060

61-
block.create_many_to_one_relationship()
6261
return block
6362

6463

neo/core/block.py

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@
1010
from datetime import datetime
1111

1212
from neo.core.container import Container, unique_objs
13+
from neo.core.group import Group
14+
from neo.core.objectlist import ObjectList
15+
from neo.core.regionofinterest import RegionOfInterest
16+
from neo.core.segment import Segment
1317

1418

1519
class Block(Container):
@@ -64,7 +68,6 @@ class Block(Container):
6468
'''
6569

6670
_container_child_objects = ('Segment', 'Group')
67-
_child_properties = ()
6871
_recommended_attrs = ((('file_datetime', datetime),
6972
('rec_datetime', datetime),
7073
('index', int)) +
@@ -86,9 +89,27 @@ def __init__(self, name=None, description=None, file_origin=None,
8689
self.file_datetime = file_datetime
8790
self.rec_datetime = rec_datetime
8891
self.index = index
89-
self.regionsofinterest = [] # temporary workaround.
90-
# the goal is to store all sub-classes of RegionOfInterest in a single list
91-
# but this will need substantial changes to container handling
92+
self._segments = ObjectList(Segment, parent=self)
93+
self._groups = ObjectList(Group, parent=self)
94+
self._regionsofinterest = ObjectList(RegionOfInterest, parent=self)
95+
96+
segments = property(
97+
fget=lambda self: self._get_object_list("_segments"),
98+
fset=lambda self, value: self._set_object_list("_segments", value),
99+
doc="list of Segments contained in this block"
100+
)
101+
102+
groups = property(
103+
fget=lambda self: self._get_object_list("_groups"),
104+
fset=lambda self, value: self._set_object_list("_groups", value),
105+
doc="list of Groups contained in this block"
106+
)
107+
108+
regionsofinterest = property(
109+
fget=lambda self: self._get_object_list("_regionsofinterest"),
110+
fset=lambda self, value: self._set_object_list("_regionsofinterest", value),
111+
doc="list of RegionOfInterest objects contained in this block"
112+
)
92113

93114
@property
94115
def data_children_recur(self):

0 commit comments

Comments
 (0)