3
3
nmpy - NeuroMatic in Python
4
4
Copyright 2019 Jason Rothman
5
5
"""
6
- # import math
6
+ import math
7
7
import numpy
8
8
9
9
# import numpy.typing as npt # No module named 'numpy.typing
10
10
from typing import Dict , Union
11
11
12
12
from pyneuromatic .nm_channel import NMChannel
13
13
from pyneuromatic .nm_dataseries import NMDataSeries , NMDataSeriesContainer
14
+ from pyneuromatic .nm_dimension import NMDimension , NMDimensionX
14
15
from pyneuromatic .nm_epoch import NMEpoch
15
16
from pyneuromatic .nm_object import NMObject
16
17
from pyneuromatic .nm_object_container import NMObjectContainer
17
18
import pyneuromatic .nm_preferences as nmp
18
- from pyneuromatic .nm_scale import NMScale , NMScaleX
19
19
import pyneuromatic .nm_utilities as nmu
20
20
21
21
45
45
class NMData (NMObject ):
46
46
"""
47
47
NM Data class
48
-
49
- np_array: NumPy N-dimensional array (ndarray)
50
48
"""
51
49
52
50
def __init__ (
53
51
self ,
54
52
parent : object = None ,
55
53
name : str = "NMData" ,
56
- np_array = None , # TODO: typing
57
- xscale : Union [dict , nmu .NMScaleXType ] = {},
58
- yscale : Union [dict , nmu .NMScaleType ] = {},
59
- # pass dictionary for independent scale
60
- # pass reference to NMscale (master)
54
+ xdim : Union [nmu .NMDimensionXType , None ] = None ,
55
+ ydim : Union [nmu .NMDimensionType , None ] = None ,
61
56
# dataseries: Union[nmu.NMDataSeriesType, None] = None,
62
57
dataseries_channel : Union [nmu .NMChannelType , None ] = None ,
63
58
dataseries_epoch : Union [nmu .NMEpochType , None ] = None ,
64
- copy : nmu .NMDataType = None , # see copy()
59
+ copy : nmu .NMDataType = None # see copy()
65
60
) -> None :
66
61
super ().__init__ (parent = parent , name = name , copy = copy ) # NMObject
67
62
68
- self .__np_array = None
69
63
# self.__dataseries = None
70
64
self .__dataseries_channel = None
71
65
self .__dataseries_epoch = None
72
66
73
67
if copy is None :
74
68
pass
75
69
elif isinstance (copy , NMData ):
76
- if isinstance (copy .np_array , numpy .ndarray ):
77
- np_array = copy .np_array .copy ()
78
- xscale = copy ._NMData__x .scale
79
- yscale = copy ._NMData__y .scale
70
+ xdim = copy .x .copy ()
71
+ ydim = copy .y .copy ()
80
72
# TODO
81
73
# dataseries = copy._NMData__dataseries
82
74
# dataseries_channel = copy._NMData__dataseries_channel
@@ -85,33 +77,25 @@ def __init__(
85
77
e = nmu .typeerror (copy , "copy" , "NMData" )
86
78
raise TypeError (e )
87
79
88
- if np_array is None :
89
- pass
90
- elif isinstance (np_array , numpy .ndarray ):
91
- self .__np_array = np_array
80
+ if xdim is None :
81
+ self .__x = NMDimensionX (self , "xscale" )
82
+ self .__x .start = 0
83
+ self .__x .delta = 1
84
+ elif isinstance (xdim , NMDimensionX ):
85
+ self .__x = xdim
92
86
else :
93
- e = nmu .typeerror (np_array , "np_array " , "NumPy.ndarray " )
87
+ e = nmu .typeerror (xdim , "xdim " , "NMDimensionX " )
94
88
raise TypeError (e )
95
89
96
- if isinstance (xscale , NMScaleX ):
97
- self .__x = xscale
98
- elif xscale is None :
99
- self .__x = NMScaleX (self , "xscale" )
100
- elif isinstance (xscale , dict ):
101
- self .__x = NMScaleX (self , "xscale" , scale = xscale )
90
+ if ydim is None :
91
+ self .__y = NMDimension (self , "yscale" )
92
+ elif isinstance (ydim , NMDimension ):
93
+ self .__y = ydim
102
94
else :
103
- e = nmu .typeerror (xscale , "xscale " , "dictionary or NMScaleX " )
95
+ e = nmu .typeerror (ydim , "ydim " , "NMDimension " )
104
96
raise TypeError (e )
105
97
106
- if isinstance (yscale , NMScale ):
107
- self .__y = yscale
108
- elif yscale is None :
109
- self .__y = NMScale (self , "yscale" )
110
- elif isinstance (yscale , dict ):
111
- self .__y = NMScale (self , "yscale" , scale = yscale )
112
- else :
113
- e = nmu .typeerror (yscale , "yscale" , "dictionary or NMScale" )
114
- raise TypeError (e )
98
+ self .__x .ypair = self .__y .nparray
115
99
116
100
self ._dataseries_set (dataseries_channel , dataseries_epoch )
117
101
@@ -131,38 +115,10 @@ def __eq__(
131
115
if not super ().__eq__ (other ):
132
116
return False
133
117
134
- if self .x != other .x :
135
- return False
136
- if self .y != other .y :
118
+ if self .__x != other .x :
137
119
return False
138
- # print(isinstance(self.__np_array, numpy.ndarray))
139
- if isinstance (self .__np_array , numpy .ndarray ):
140
- if isinstance (other .__np_array , numpy .ndarray ):
141
- if self .__np_array .dtype != other .np_array .dtype :
142
- return False
143
- if self .__np_array .shape != other .np_array .shape :
144
- return False
145
- if self .__np_array .nbytes != other .np_array .nbytes :
146
- return False
147
- if not numpy .array_equal (self .__np_array , other .np_array ):
148
- # array_equal returns false if both arrays filled with NANs
149
- if nmp .NAN_EQ_NAN :
150
- # compare array elements within a tolerance
151
- if not numpy .allclose (
152
- self .__np_array ,
153
- other .np_array ,
154
- rtol = 0 ,
155
- atol = 0 ,
156
- equal_nan = True ,
157
- ):
158
- return False
159
- else :
160
- return False
161
- else :
162
- return False
163
- elif isinstance (other .__np_array , numpy .ndarray ):
120
+ if self .__y != other .y :
164
121
return False
165
-
166
122
if self ._dataseries_channel != other ._dataseries_channel :
167
123
return False
168
124
if self ._dataseries_epoch != other ._dataseries_epoch :
@@ -174,12 +130,8 @@ def __eq__(
174
130
@property
175
131
def parameters (self ) -> Dict [str , object ]:
176
132
k = super ().parameters
177
- k .update ({"xscale" : self .x .scale })
178
- k .update ({"yscale" : self .y .scale })
179
- if isinstance (self .__np_array , numpy .ndarray ):
180
- k .update ({"np_array" : self .__np_array .dtype })
181
- else :
182
- k .update ({"np_array" : None })
133
+ k .update ({"x" : self .x .parameters })
134
+ k .update ({"y" : self .y .parameters })
183
135
ds = self ._dataseries
184
136
if isinstance (ds , NMDataSeries ):
185
137
k .update ({"dataseries" : ds .name })
@@ -196,102 +148,19 @@ def parameters(self) -> Dict[str, object]:
196
148
return k
197
149
198
150
@property
199
- def x (self ) -> nmu .NMScaleXType :
151
+ def x (self ) -> nmu .NMDimensionXType :
200
152
if isinstance (self .__dataseries_channel , NMChannel ):
201
- if isinstance (self .__dataseries_channel .x , NMScaleX ):
153
+ if isinstance (self .__dataseries_channel .x , NMDimensionX ):
202
154
return self .__dataseries_channel .x
203
155
return self .__x
204
156
205
157
@property
206
- def y (self ) -> nmu .NMScaleType :
158
+ def y (self ) -> nmu .NMDimensionType :
207
159
if isinstance (self .__dataseries_channel , NMChannel ):
208
- if isinstance (self .__dataseries_channel .y , NMScale ):
160
+ if isinstance (self .__dataseries_channel .y , NMDimension ):
209
161
return self .__dataseries_channel .y
210
162
return self .__y
211
163
212
- @property
213
- def np_array (self ):
214
- return self .__np_array
215
-
216
- @np_array .setter
217
- def np_array (self , np_array ) -> None :
218
- return self ._np_array_set (np_array )
219
-
220
- def _np_array_set (
221
- self ,
222
- np_array ,
223
- # quiet=nmp.QUIET
224
- ) -> None :
225
- if np_array is None :
226
- pass # ok
227
- elif not isinstance (np_array , numpy .ndarray ):
228
- e = nmu .typeerror (np_array , "np_array" , "NumPy.ndarray" )
229
- raise TypeError (e )
230
- if self .__np_array is None :
231
- old = None
232
- else :
233
- old = self .__np_array .__array_interface__ ["data" ][0 ]
234
- self .__np_array = np_array
235
- self .modified ()
236
- if self .__np_array is None :
237
- new = None
238
- else :
239
- new = self .__np_array .__array_interface__ ["data" ][0 ]
240
- h = nmu .history_change ("np_array reference" , old , new )
241
- # self.__notes_container.new(h)
242
- # self._history(h, quiet=quiet)
243
- return None
244
-
245
- def np_array_make (
246
- self ,
247
- shape ,
248
- fill_value = NP_FILL_VALUE ,
249
- dtype = NP_DTYPE ,
250
- order = NP_ORDER ,
251
- # quiet=nmp.QUIET
252
- ):
253
- # wrapper for NumPy.full
254
- self .__np_array = numpy .full (shape , fill_value , dtype = dtype , order = order )
255
- self .modified ()
256
- if not isinstance (self .__np_array , numpy .ndarray ):
257
- raise RuntimeError ("failed to create numpy array" )
258
- n = (
259
- "created numpy array (numpy.full): shape="
260
- + str (shape )
261
- + ", fill_value="
262
- + str (fill_value )
263
- + ", dtype="
264
- + str (dtype )
265
- )
266
- # self.__notes_container.new(n)
267
- # self._history(n, quiet=quiet)
268
- return True
269
-
270
- def np_array_make_random_normal (
271
- self ,
272
- shape ,
273
- mean = 0 ,
274
- stdv = 1 ,
275
- # quiet=nmp.QUIET
276
- ):
277
- # wrapper for NumPy.random.normal
278
- # dtype = float64
279
- self .__np_array = numpy .random .normal (mean , stdv , shape )
280
- self .modified ()
281
- if not isinstance (self .__np_array , numpy .ndarray ):
282
- raise RuntimeError ("failed to create numpy array" )
283
- n = (
284
- "created data array (numpy.random.normal): shape="
285
- + str (shape )
286
- + ", mean="
287
- + str (mean )
288
- + ", stdv="
289
- + str (stdv )
290
- )
291
- # self.__notes_container.new(n)
292
- # self._history(n, quiet=quiet)
293
- return True
294
-
295
164
@property
296
165
def _dataseries (self ) -> Union [nmu .NMDataSeriesType , None ]:
297
166
if not isinstance (self .__dataseries_channel , NMChannel ):
@@ -370,20 +239,17 @@ def content_type(self) -> str:
370
239
def new (
371
240
self ,
372
241
name : str = "default" ,
373
- np_array = None , # TODO: typing
374
- xscale : Union [dict , nmu .NMScaleXType ] = {},
375
- # TODO: can also be NMData?
376
- yscale : Union [dict , nmu .NMScaleType ] = {},
242
+ xdim : Union [nmu .NMDimensionXType , None ] = None ,
243
+ ydim : Union [nmu .NMDimensionType , None ] = None ,
377
244
select : bool = False ,
378
245
# quiet: bool = nmp.QUIET
379
246
) -> nmu .NMDataType :
380
247
name = self ._newkey (name )
381
248
d = NMData (
382
249
parent = self ._parent ,
383
250
name = name ,
384
- np_array = np_array ,
385
- xscale = xscale ,
386
- yscale = yscale ,
251
+ xdim = xdim ,
252
+ ydim = ydim
387
253
)
388
254
super ().new (d , select = select )
389
255
return d
0 commit comments