/usr/lib/python2.7/dist-packages/neo/description.py is in python-neo 0.3.3-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 | # -*- coding: utf-8 -*-
"""
This file is a bundle of utilities to describe Neo object representation
(attributes and relationships).
It can be used to:
* generate diagrams of neo
* some generics IO like (databases mapper, hdf5, neomatlab, ...)
* tests
* external SQL mappers (Cf OpenElectrophy, Gnode)
**classes_necessary_attributes**
This dict descibes attributes that are necessary to initialize an instance.
It a dict of list of tuples.
Each attribute is described by a tuple:
* for standard type, the tuple is: (name + python type)
* for np.ndarray type, the tuple is: (name + np.ndarray + ndim + dtype)
* for pq.Quantities, the tuple is: (name + pq.Quantity + ndim)
ndim is the dimensionaly of the array: 1=vector, 2=matrix, 3=cube, ...
Special case: ndim=0 means that neo expects a scalar, so Quantity.shape=(1,).
That is in fact a vector (ndim=1) with one element only in Quantities package.
For some neo.object, the data is not held by a field, but by the object itself.
This is the case for AnalogSignal, SpikeTrain: they inherit from Quantity,
which itself inherits from numpy.array.
In theses cases, the classes_inheriting_quantities dict provide a list of
classes inhiriting Quantity and there attribute that will become Quantity
itself.
**classes_recommended_attributes**
This dict describes recommended attributes, which are optional at
initialization. If present, they will be stored as attributes of the object.
The notation is the same as classes_necessary_attributes.
"""
from datetime import datetime
import numpy as np
import quantities as pq
from neo.core import objectlist
class_by_name = {}
name_by_class = {}
for ob in objectlist:
class_by_name[ob.__name__] = ob
name_by_class[ob] = ob.__name__
# parent to children
one_to_many_relationship = {
'Block': ['Segment', 'RecordingChannelGroup'],
'Segment': ['AnalogSignal', 'AnalogSignalArray',
'IrregularlySampledSignal', 'Event', 'EventArray',
'Epoch', 'EpochArray', 'SpikeTrain', 'Spike'],
'RecordingChannel': ['AnalogSignal', 'IrregularlySampledSignal'],
'RecordingChannelGroup': ['Unit', 'AnalogSignalArray'],
'Unit': ['SpikeTrain', 'Spike']
}
# reverse: child to parent
many_to_one_relationship = {}
for p, children in one_to_many_relationship.items():
for c in children:
if c not in many_to_one_relationship:
many_to_one_relationship[c] = []
if p not in many_to_one_relationship[c]:
many_to_one_relationship[c].append(p)
many_to_many_relationship = {
'RecordingChannel': ['RecordingChannelGroup'],
'RecordingChannelGroup': ['RecordingChannel'],
}
# check bijectivity
for p, children in many_to_many_relationship.items():
for c in children:
if c not in many_to_many_relationship:
many_to_many_relationship[c] = []
if p not in many_to_many_relationship[c]:
many_to_many_relationship[c].append(p)
# Some relationship shortcuts are accesible througth properties
property_relationship = {
'Block': ['Unit', 'RecordingChannel']
}
# these relationships are used by IOs which do not natively support non-tree
# structures like NEO to avoid object duplications when saving/retrieving
# objects from the data source. We can call em "secondary" connections
implicit_relationship = {
'RecordingChannel': ['AnalogSignal', 'IrregularlySampledSignal'],
'RecordingChannelGroup': ['AnalogSignalArray'],
'Unit': ['SpikeTrain', 'Spike']
}
classes_necessary_attributes = {
'Block': [],
'Segment': [],
'Event': [('time', pq.Quantity, 0),
('label', str)],
'EventArray': [('times', pq.Quantity, 1),
('labels', np.ndarray, 1, np.dtype('S'))],
'Epoch': [('time', pq.Quantity, 0),
('duration', pq.Quantity, 0),
('label', str)],
'EpochArray': [('times', pq.Quantity, 1),
('durations', pq.Quantity, 1),
('labels', np.ndarray, 1, np.dtype('S'))],
'Unit': [],
'SpikeTrain': [('times', pq.Quantity, 1),
('t_start', pq.Quantity, 0),
('t_stop', pq.Quantity, 0)],
'Spike': [('time', pq.Quantity, 0)],
'AnalogSignal': [('signal', pq.Quantity, 1),
('sampling_rate', pq.Quantity, 0),
('t_start', pq.Quantity, 0)],
'AnalogSignalArray': [('signal', pq.Quantity, 2),
('sampling_rate', pq.Quantity, 0),
('t_start', pq.Quantity, 0)],
'IrregularlySampledSignal': [('times', pq.Quantity, 1),
('signal', pq.Quantity, 1)],
'RecordingChannelGroup': [],
'RecordingChannel': [('index', int)],
}
classes_recommended_attributes = {
'Block': [('file_datetime', datetime),
('rec_datetime', datetime),
('index', int), ],
'Segment': [('file_datetime', datetime),
('rec_datetime', datetime),
('index', int)],
'Event': [],
'EventArray': [],
'Epoch': [],
'EpochArray': [],
'Unit': [],
'SpikeTrain': [('waveforms', pq.Quantity, 3),
('left_sweep', pq.Quantity, 0),
('sampling_rate', pq.Quantity, 0)],
'Spike': [('waveform', pq.Quantity, 2),
('left_sweep', pq.Quantity, 0),
('sampling_rate', pq.Quantity, 0)],
'AnalogSignal': [('channel_index', int)],
'Unit': [('channel_indexes', np.ndarray, 1, np.dtype('i'))],
'AnalogSignalArray': [('channel_indexes', np.ndarray, 1, np.dtype('i'))],
'IrregularlySampledSignal': [],
'RecordingChannelGroup': [('channel_indexes', np.ndarray,
1, np.dtype('i')),
('channel_names', np.ndarray,
1, np.dtype('S'))],
'RecordingChannel': [('coordinate', pq.Quantity, 1)],
}
# this list classes inheriting quantities with arguments that will become
# the quantity array
classes_inheriting_quantities = {
'SpikeTrain': 'times',
'AnalogSignal': 'signal',
'AnalogSignalArray': 'signal',
'IrregularlySampledSignal': 'signal',
}
# all classes can have name, description, file_origin
for k in classes_recommended_attributes.keys():
classes_recommended_attributes[k] += [('name', str),
('description', str),
('file_origin', str)]
|