Skip to content

Commit 50c7080

Browse files
committed
Now no Neo object can have more than one parent, so we can clean up a bit
1 parent 63093d2 commit 50c7080

25 files changed

+66
-138
lines changed

doc/source/images/generate_diagram.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ def get_rect_height(name, obj):
2929
nlines += len(getattr(obj, '_all_attrs', []))
3030
nlines += len(getattr(obj, '_single_child_objects', []))
3131
nlines += len(getattr(obj, '_multi_child_objects', []))
32-
nlines += len(getattr(obj, '_multi_parent_objects', []))
3332
return nlines * line_heigth
3433

3534

@@ -100,8 +99,7 @@ def generate_diagram(filename, rect_pos, rect_width, figsize):
10099
for name, pos in rect_pos.items():
101100
htotal = all_h[name]
102101
obj = objs[name]
103-
allrelationship = (list(getattr(obj, '_child_containers', []))
104-
+ list(getattr(obj, '_multi_parent_containers', [])))
102+
allrelationship = list(getattr(obj, '_child_containers', []))
105103

106104
rect = Rectangle(pos, rect_width, htotal,
107105
facecolor='w', edgecolor='k', linewidth=2.)
@@ -123,8 +121,7 @@ def generate_diagram(filename, rect_pos, rect_width, figsize):
123121
ax.add_patch(rect)
124122

125123
# multi relationship
126-
relationship = (list(getattr(obj, '_multi_child_objects', []))
127-
+ list(getattr(obj, '_multi_parent_containers', [])))
124+
relationship = list(getattr(obj, '_multi_child_objects', []))
128125
pos2 = (pos[1] + htotal - line_heigth * (1.5 + len(relationship))
129126
- rect_height)
130127
rect_height = len(relationship) * line_heigth

neo/core/analogsignal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ class AnalogSignal(BaseSignal):
160160
161161
'''
162162

163-
_single_parent_objects = ('Segment', 'ChannelIndex')
164-
_single_parent_attrs = ('segment', 'channel_index')
163+
_parent_objects = ('Segment', 'ChannelIndex')
164+
_parent_attrs = ('segment', 'channel_index')
165165
_quantity_attr = 'signal'
166166
_necessary_attrs = (('signal', pq.Quantity, 2),
167167
('sampling_rate', pq.Quantity, 0),

neo/core/baseneo.py

Lines changed: 22 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,6 @@
1818
Number, Decimal,
1919
np.number, np.bool_)
2020

21-
# handle both Python 2 and Python 3
22-
try:
23-
ALLOWED_ANNOTATION_TYPES += (long, unicode)
24-
except NameError:
25-
pass
26-
2721
logger = logging.getLogger("Neo")
2822

2923

@@ -179,20 +173,13 @@ class BaseNeo:
179173
and also sets up the :attr:`annotations` dict for additional arguments.
180174
181175
Each class can define one or more of the following class attributes:
182-
:_single_parent_objects: Neo objects that can be parents of this
183-
object. This attribute is used in cases where
184-
only one parent of this class is allowed.
185-
An instance attribute named
186-
class.__name__.lower() will be automatically
187-
defined to hold this parent and will be
188-
initialized to None.
189-
:_multi_parent_objects: Neo objects that can be parents of this
190-
object. This attribute is used in cases where
191-
multiple parents of this class is allowed.
192-
An instance attribute named
193-
class.__name__.lower()+'s' will be
194-
automatically defined to hold this parent and
195-
will be initialized to an empty list.
176+
:_parent_objects: Neo objects that can be parents of this
177+
object. Note that no Neo object can have
178+
more than one parent.
179+
An instance attribute named
180+
class.__name__.lower() will be automatically
181+
defined to hold this parent and will be
182+
initialized to None.
196183
:_necessary_attrs: A list of tuples containing the attributes that the
197184
class must have. The tuple can have 2-4 elements.
198185
The first element is the attribute name.
@@ -210,15 +197,8 @@ class must have. The tuple can have 2-4 elements.
210197
pretty-printing using iPython.
211198
212199
The following helper properties are available:
213-
:_parent_objects: All parent objects.
214-
:_single_parent_objects: + :_multi_parent_objects:
215-
:_single_parent_containers: The names of the container attributes used
216-
to store :_single_parent_objects:
217-
:_multi_parent_containers: The names of the container attributes used
218-
to store :_multi_parent_objects:
219-
:_parent_containers: All parent container attributes.
220-
:_single_parent_containers: +
221-
:_multi_parent_containers:
200+
:_parent_containers: The names of the container attributes used
201+
to store :_parent_objects:
222202
:parents: All objects that are parents of the current object.
223203
:_all_attrs: All required and optional attributes.
224204
:_necessary_attrs: + :_recommended_attrs:
@@ -264,11 +244,9 @@ class attributes. :_recommended_attrs: should append
264244
# these attributes control relationships, they need to be
265245
# specified in each child class
266246
# Parent objects whose children can have a single parent
267-
_single_parent_objects = ()
268-
# Attribute names corresponding to _single_parent_objects
269-
_single_parent_attrs = ()
270-
# Parent objects whose children can have multiple parents
271-
_multi_parent_objects = ()
247+
_parent_objects = ()
248+
# Attribute names corresponding to _parent_objects
249+
_parent_attrs = ()
272250

273251
# Attributes that an instance is required to have defined
274252
_necessary_attrs = ()
@@ -298,10 +276,8 @@ def __init__(self, name=None, description=None, file_origin=None,
298276
self.file_origin = file_origin
299277

300278
# initialize parent containers
301-
for parent in self._single_parent_containers:
279+
for parent in self._parent_containers:
302280
setattr(self, parent, None)
303-
for parent in self._multi_parent_containers:
304-
setattr(self, parent, [])
305281

306282
def annotate(self, **annotations):
307283
"""
@@ -341,46 +317,21 @@ def _repr_pretty_(self, pp, cycle):
341317
pp.breakable()
342318
self._repr_pretty_attrs_(pp, cycle)
343319

344-
@property
345-
def _single_parent_containers(self):
346-
"""
347-
Containers for parent objects whose children can have a single parent.
348-
"""
349-
return tuple([_reference_name(parent) for parent in
350-
self._single_parent_objects])
351-
352-
@property
353-
def _multi_parent_containers(self):
354-
"""
355-
Containers for parent objects whose children can have multiple parents.
356-
"""
357-
return tuple([_container_name(parent) for parent in
358-
self._multi_parent_objects])
359-
360-
@property
361-
def _parent_objects(self):
362-
"""
363-
All types for parent objects.
364-
"""
365-
return self._single_parent_objects + self._multi_parent_objects
366-
367320
@property
368321
def _parent_containers(self):
369322
"""
370-
All containers for parent objects.
323+
Containers for parent objects.
371324
"""
372-
return self._single_parent_containers + self._multi_parent_containers
325+
return tuple([_reference_name(parent) for parent in
326+
self._parent_objects])
373327

374328
@property
375329
def parents(self):
376330
"""
377331
All parent objects storing the current object.
378332
"""
379-
single = [getattr(self, attr) for attr in
380-
self._single_parent_containers]
381-
multi = [list(getattr(self, attr)) for attr in
382-
self._multi_parent_containers]
383-
return tuple(single + sum(multi, []))
333+
return tuple([getattr(self, attr) for attr in
334+
self._parent_containers])
384335

385336
@property
386337
def _all_attrs(self):
@@ -420,9 +371,9 @@ def set_parent(self, obj):
420371
Set the appropriate "parent" attribute of this object
421372
according to the type of "obj"
422373
"""
423-
if obj.__class__.__name__ not in self._single_parent_objects:
374+
if obj.__class__.__name__ not in self._parent_objects:
424375
raise TypeError("{} can only have parents of type {}, not {}".format(
425-
self.__class__.__name__, self._single_parent_objects, obj.__class__.__name__))
426-
loc = self._single_parent_objects.index(obj.__class__.__name__)
427-
parent_attr = self._single_parent_attrs[loc]
376+
self.__class__.__name__, self._parent_objects, obj.__class__.__name__))
377+
loc = self._parent_objects.index(obj.__class__.__name__)
378+
parent_attr = self._parent_attrs[loc]
428379
setattr(self, parent_attr, obj)

neo/core/channelindex.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class ChannelIndex(Container):
154154

155155
_container_child_objects = ('Unit',)
156156
_data_child_objects = ('AnalogSignal', 'IrregularlySampledSignal')
157-
_single_parent_objects = ('Block',)
157+
_parent_objects = ('Block',)
158158
_necessary_attrs = (('index', np.ndarray, 1, np.dtype('i')),)
159159
_recommended_attrs = ((('channel_names', np.ndarray, 1, np.dtype('U')),
160160
('channel_ids', np.ndarray, 1, np.dtype('i')),

neo/core/dataobject.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ def __deepcopy__(self, memo):
357357
# thus creating a lot of overhead
358358
# But keeping the reference to the same parent is not desired either, because this would be unidirectional
359359
# When deepcopying top-down, e.g. a whole block, the links will be handled by the parent
360-
if k in self._single_parent_attrs:
360+
if k in self._parent_attrs:
361361
setattr(new_obj, k, None)
362362
continue
363363
try:

neo/core/epoch.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ class Epoch(DataObject):
7272
7373
'''
7474

75-
_single_parent_objects = ('Segment',)
76-
_single_parent_attrs = ('segment',)
75+
_parent_objects = ('Segment',)
76+
_parent_attrs = ('segment',)
7777
_quantity_attr = 'times'
7878
_necessary_attrs = (('times', pq.Quantity, 1), ('durations', pq.Quantity, 1),
7979
('labels', np.ndarray, 1, np.dtype('U')))

neo/core/event.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ class Event(DataObject):
6565
6666
'''
6767

68-
_single_parent_objects = ('Segment',)
69-
_single_parent_attrs = ('segment',)
68+
_parent_objects = ('Segment',)
69+
_parent_attrs = ('segment',)
7070
_quantity_attr = 'times'
7171
_necessary_attrs = (('times', pq.Quantity, 1), ('labels', np.ndarray, 1, np.dtype('U')))
7272

neo/core/group.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ class Group(Container):
4242
'Event', 'Epoch', 'ChannelView', 'ImageSequence'
4343
)
4444
_container_child_objects = ('Segment', 'Group')
45-
_single_parent_objects = ('Block',)
45+
_parent_objects = ('Block',)
4646

4747
def __init__(self, objects=None, name=None, description=None, file_origin=None,
4848
allowed_types=None, **annotations):

neo/core/imagesequence.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ class ImageSequence(BaseSignal):
8686
(:attr:`t_start` + :attr:`duration`)
8787
"""
8888

89-
_single_parent_objects = ("Segment",)
90-
_single_parent_attrs = ("segment",)
89+
_parent_objects = ("Segment",)
90+
_parent_attrs = ("segment",)
9191
_quantity_attr = "image_data"
9292
_necessary_attrs = (
9393
("image_data", pq.Quantity, 3),

neo/core/irregularlysampledsignal.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,8 +123,8 @@ class IrregularlySampledSignal(BaseSignal):
123123
124124
'''
125125

126-
_single_parent_objects = ('Segment', 'ChannelIndex')
127-
_single_parent_attrs = ('segment', 'channel_index')
126+
_parent_objects = ('Segment', 'ChannelIndex')
127+
_parent_attrs = ('segment', 'channel_index')
128128
_quantity_attr = 'signal'
129129
_necessary_attrs = (('times', pq.Quantity, 1), ('signal', pq.Quantity, 2))
130130

0 commit comments

Comments
 (0)