Commit 0b3176001c676d5bbc46c2abac6fdb273d586098
1 parent
fec5faec
Exists in
master
added several modules
modified nan manipulation in data : changed -1**31 to np.nan objects added writing cef functions
Showing
5 changed files
with
359 additions
and
77 deletions
Show diff stats
__init__.py
ceflib_mods.py
1 | 1 | #! /bin/env python |
2 | 2 | # coding: utf8 |
3 | +import numpy as np | |
4 | +import datetime | |
3 | 5 | |
4 | 6 | class cefwrite(object) : |
5 | 7 | |
6 | - def __init__(self, data = None, filename = 'test.cef'): | |
8 | + def __init__(self, data = None, filename = 'test.cef', mode = 'w', checkVariableOrder = False): | |
7 | 9 | """ |
8 | - Data of the form data['field1'] = numpy array, and data['epoch'] = numpy time array | |
10 | + Write data into a cef file format | |
11 | + data must be of the form data['field1'] = numpy array, and data['epoch'] = numpy time array | |
12 | + provide filename (default is test.cef) | |
13 | + mode : 'w' start from fresh empty file | |
14 | + 'a' start from existing file and add only lines (variables must have same names) | |
15 | + default is 'w' | |
9 | 16 | """ |
10 | - self.data = data | |
17 | + self.data = {key:np.copy(data[key]) for key in data} | |
18 | + | |
11 | 19 | self.fichier = filename |
20 | + self.mode = mode | |
21 | + | |
22 | + self.variables = sorted(list(set(self.data.keys()) - set(['epoch']))) | |
23 | + | |
24 | + self.deleteAllNan() | |
25 | + self.changeNanToFillVal() | |
12 | 26 | |
27 | + if checkVariableOrder : print self.variables | |
28 | + | |
29 | + if mode == 'w': | |
30 | + self.makeHeader() | |
31 | + self.writeData() | |
32 | + elif mode == 'a': | |
33 | + self.writeData() | |
34 | + | |
35 | + def changeNanToFillVal(self): | |
36 | + """ | |
37 | + For CL : change NAN to -10E31 | |
38 | + seems to work fine :) | |
39 | + """ | |
40 | + for key in self.variables : self.data[key][np.isnan(self.data[key])] = -10**31 | |
41 | + | |
42 | + def deleteAnyNan(self): | |
43 | + """ | |
44 | + Delete all lines containing at least one np.nan | |
45 | + """ | |
46 | + for var in self.variables : | |
47 | + inds = np.where(np.isnan(self.data[var])) | |
48 | + for key in self.data : | |
49 | + self.data[key] = np.delete(self.data[key], inds) | |
50 | + | |
51 | + def deleteAllNan(self): | |
52 | + """ | |
53 | + Delete all lines where all data exept time are np.nan | |
54 | + """ | |
55 | + inds0 = set(np.where(np.isnan(self.data[self.variables[0]]))[0]) | |
56 | + for var in self.variables[1:] : | |
57 | + inds1 = set(np.where(np.isnan(self.data[var]))[0]).intersection(inds0) | |
58 | + inds0 = inds1 | |
59 | + | |
60 | + for key in self.data : | |
61 | + self.data[key] = np.delete(self.data[key], list(inds1)) | |
62 | + | |
63 | + def makeHeader(self): | |
13 | 64 | self.initializeHeader() |
14 | - variables = sorted(list(set(self.data.keys()) - set(['epoch']))) | |
15 | - for var in variables : self.addvariableHeader(var) | |
65 | + for var in self.variables : self.addvariableHeader(var) | |
16 | 66 | self.closeHeader() |
17 | - | |
67 | + | |
68 | + def writeData(self): | |
18 | 69 | out = open(self.fichier, 'a') |
19 | 70 | for i,t in enumerate(self.data['epoch']): |
20 | - | |
21 | - out.write(t.isoformat()) | |
22 | - #print >> out, t.isoformat() | |
23 | - for var in variables : | |
24 | - out.write(' ') | |
25 | - #print >> out, str(self.data[key][i]) | |
71 | + out.write(t.isoformat()+'Z') | |
72 | + for var in self.variables : | |
73 | + out.write(', ') | |
26 | 74 | out.write('{:f}'.format(self.data[var][i])) |
27 | - out.write('\n') | |
28 | - | |
75 | + out.write(';\n') | |
29 | 76 | out.close() |
30 | 77 | |
31 | 78 | def initializeHeader(self): |
32 | - | |
33 | 79 | #set time variable as first variable |
34 | 80 | out = open(self.fichier, 'w') |
35 | 81 | out.write( |
82 | + "!------------------------------------------------------------------------|\n" | |
83 | + "! |\n" | |
84 | + "! Generated by the mms_tools_lib, developped by Yoann Vernisse, IRAP |\n" | |
85 | + "! ASCII Format |\n" | |
86 | + "!------------------------------------------------------------------------|\n" | |
87 | + "\n" | |
88 | + 'FILE_FORMAT_VERSION = "CEF-2.0"\n' | |
89 | + "\n" | |
90 | + "\n" | |
91 | + "!------------------------------------------------------------------------|\n" | |
92 | + "! Global Metadata |\n" | |
93 | + "!------------------------------------------------------------------------|\n" | |
94 | + "\n" | |
95 | + "START_META = Generation_date\n" | |
96 | + " VALUE_TYPE = ISO_TIME\n" | |
97 | + " ENTRY = "+ datetime.datetime.now().isoformat() +"\n" | |
98 | + "END_META = Generation_date\n" | |
99 | + "\n" | |
100 | + "START_META = Generated_by\n" | |
101 | + ' ENTRY = "mms_tools_lib"\n' | |
102 | + "END_META = Generated_by\n" | |
103 | + "\n" | |
104 | + "START_META = Mission_Group\n" | |
105 | + ' ENTRY = "MMS"\n' | |
106 | + "END_META = Mission_Group\n" | |
107 | + "\n" | |
108 | + 'END_OF_RECORD_MARKER = ";"\n' | |
109 | + "\n" | |
110 | + "!------------------------------------------------------------------------|\n" | |
111 | + "! Variables |\n" | |
112 | + "!------------------------------------------------------------------------|\n" | |
113 | + "\n" | |
36 | 114 | 'START_VARIABLE = epoch \n' |
37 | - ' PARAMETER_TYPE = "Support_Data" \n' | |
38 | - ' VALUE_TYPE = ISO_TIME \n' | |
39 | - ' UNITS = "s" \n' | |
40 | - ' DELTA_PLUS = 0 \n' | |
41 | - ' DELTA_MINUS = 0 \n' | |
42 | - 'END_VARIABLE = epoch \n' | |
43 | - ' \n' | |
115 | + ' PARAMETER_TYPE = "Support_Data"\n' | |
116 | + ' VALUE_TYPE = ISO_TIME\n' | |
117 | + ' UNITS = "s"\n' | |
118 | + ' DELTA_PLUS = 0\n' | |
119 | + ' DELTA_MINUS = 0\n' | |
120 | + 'END_VARIABLE = epoch\n' | |
121 | + '\n' | |
44 | 122 | ) |
45 | 123 | |
46 | 124 | def addvariableHeader(self, variable): |
47 | 125 | |
48 | 126 | out = open(self.fichier, 'a') |
49 | 127 | out.write( |
50 | - 'START_VARIABLE = '+variable +'\n' | |
51 | - ' PARAMETER_TYPE = "Data" \n' | |
52 | - ' VALUE_TYPE = FLOAT \n' | |
53 | - ' FILLVAL = -1.000E+31 \n' | |
54 | - ' DEPEND_0 = epoch \n' | |
55 | - ' UNITS = "" \n' | |
56 | - ' FIELDNAM = "" \n' | |
128 | + 'START_VARIABLE = '+variable +'\n' | |
129 | + ' PARAMETER_TYPE = "Data"\n' | |
130 | + ' VALUE_TYPE = FLOAT\n' | |
131 | + ' FILLVAL = -1.000E+31\n' | |
132 | + ' DEPEND_0 = epoch\n' | |
133 | + ' UNITS = ""\n' | |
134 | + ' FIELDNAM = ""\n' | |
57 | 135 | 'END_VARIABLE = '+variable+ '\n' |
58 | - ' \n' | |
136 | + '\n' | |
59 | 137 | ) |
60 | 138 | |
61 | 139 | def closeHeader(self): |
62 | 140 | |
63 | 141 | out = open(self.fichier, 'a') |
64 | 142 | out.write( |
65 | - 'DATA_UNTIL = EOF \n' | |
66 | - ) | |
143 | + "!------------------------------------------------------------------------|\n" | |
144 | + "! Data |\n" | |
145 | + "!------------------------------------------------------------------------|\n" | |
146 | + '\n' | |
147 | + 'DATA_UNTIL = EOF\n' | |
148 | + ) | |
67 | 149 | |
68 | 150 | \ No newline at end of file | ... | ... |
display_lib.py
... | ... | @@ -4,8 +4,41 @@ |
4 | 4 | import numpy as np |
5 | 5 | import matplotlib.pyplot as plt |
6 | 6 | from mpl_toolkits.mplot3d import Axes3D |
7 | +import os | |
7 | 8 | |
8 | -class display1d(object): | |
9 | + | |
10 | +class display_general(object): | |
11 | + """ | |
12 | + Object with general functions for plotting objects | |
13 | + namely : save figure, show; others? | |
14 | + """ | |
15 | + | |
16 | + def __init__(self): | |
17 | + | |
18 | + self.setTitle('Figure_from_displaylib') | |
19 | + | |
20 | + def setTitle(self, title) : | |
21 | + self.title = title | |
22 | + | |
23 | + def getTitle(self) : | |
24 | + return self.title | |
25 | + | |
26 | + def savefig(self, f = None) : | |
27 | + if not f : | |
28 | + i = 0 | |
29 | + while i < 999 : | |
30 | + f = self.title + str(int(i)) + '.png' | |
31 | + if os.path.exists(os.path.join(os.curdir, f)) : i+=1 | |
32 | + else : break | |
33 | + print 'Saving figure in ', f | |
34 | + self.fig.savefig(f, bbox_inches='tight') | |
35 | + plt.close() | |
36 | + | |
37 | + def show(self): | |
38 | + plt.show() | |
39 | + | |
40 | + | |
41 | +class display1d(display_general): | |
9 | 42 | """ |
10 | 43 | Functions to easily add options to 1d objects plots |
11 | 44 | initialize as display1d(3,2) for 3 columns and 2 rows |
... | ... | @@ -15,8 +48,9 @@ class display1d(object): |
15 | 48 | add colorscale to a scatter plot |
16 | 49 | NOTE : Not made for timeseries!! |
17 | 50 | """ |
18 | - def __init__(self, ncols = 1, nrows = 1) : | |
51 | + def __init__(self, ncols = 1, nrows = 1, title = 'display1d') : | |
19 | 52 | |
53 | + self.setTitle(title) | |
20 | 54 | self.fig = plt.figure(figsize = (16, 10), dpi = 96) |
21 | 55 | self.ncols = int(ncols) |
22 | 56 | self.nrows = int(nrows) |
... | ... | @@ -27,7 +61,7 @@ class display1d(object): |
27 | 61 | for i in range(nrows*ncols-1) : |
28 | 62 | self.plots.append({}) |
29 | 63 | self.plots[-1]['label'] = {'data' : None, 'xaxis' : None, 'yaxis' : None, 'cbar' : None, 'title' : None} |
30 | - | |
64 | + | |
31 | 65 | #self.set_colorscale() |
32 | 66 | #self.set_errorbar(x = np.arange(len(self.y))/5.) |
33 | 67 | #self.set_logscale() |
... | ... | @@ -84,7 +118,9 @@ class display1d(object): |
84 | 118 | def set_colorscale(self, col_arr = [0], minmax = 'auto', cmap = 'plasma') : |
85 | 119 | i = self.get_actualPlotNumber() |
86 | 120 | self.plots[i]['col_arr'] = np.array(col_arr) |
87 | - if self.plots[i]['col_arr'].shape != self.plots[i]['data'].shape : self.plots[i]['col_arr'] = self.plots[i]['data'] | |
121 | + if len(self.plots[i]['col_arr']) != len(self.plots[i]['data']) : | |
122 | + print 'WRONG COLOR ARRAY SIZE, SETTING DATA IN COLOR INSTEAD' | |
123 | + self.plots[i]['col_arr'] = self.plots[i]['data'] | |
88 | 124 | |
89 | 125 | #self.new_val = (self.col_arr - self.col_arr.min())/(self.col_arr.max() - self.col_arr.min()) |
90 | 126 | #self.carray = plt.get_cmap(cmap)(self.new_val) |
... | ... | @@ -126,7 +162,100 @@ class display1d(object): |
126 | 162 | |
127 | 163 | |
128 | 164 | |
129 | -class display3d(object) : | |
165 | +class display2d(display_general): | |
166 | + """ | |
167 | + Grid used to make 2D plots. | |
168 | + This create ONLY linear grid plot. For non linear 2D plot, another routine should be made. | |
169 | + input : 2D numpy array | |
170 | + NOTE : meshgrid can be tricky regarding x/y indexing : check option indexing = 'ij' or 'xy' | |
171 | + """ | |
172 | + def __init__(self, z = None, title = '', Zinit = True): | |
173 | + #np.ndarray.__init__(self) | |
174 | + | |
175 | + self.x = {} | |
176 | + self.y = {} | |
177 | + self.z = {} | |
178 | + self.minmax = {} | |
179 | + self.title = title | |
180 | + self.layers = {} | |
181 | + | |
182 | + if z is None : z = np.zeros([10,10]) | |
183 | + | |
184 | + xsize = float(z.shape[0]) | |
185 | + ysize = float(z.shape[1]) | |
186 | + | |
187 | + self.initialize(xsize, ysize) | |
188 | + self.meshinit() | |
189 | + self.zmesh, tmp = np.meshgrid(np.zeros(z.shape[0]), np.zeros(z.shape[1])) | |
190 | + self.zmesh = self.zmesh[:-1, :-1] | |
191 | + if Zinit : self.zmesh = z.T[:-1, :-1] | |
192 | + | |
193 | + def initialize(self, xsize, ysize) : | |
194 | + self.minmax['xmin'] = 0. | |
195 | + self.minmax['xmax'] = xsize | |
196 | + self.x['res'] = xsize | |
197 | + | |
198 | + self.minmax['ymin'] = 0. | |
199 | + self.minmax['ymax'] = ysize | |
200 | + self.y['res'] = ysize | |
201 | + | |
202 | + def set_layers(self, layers = ['Name']): | |
203 | + for layer in layers : self.layers[layer] = np.zeros(self.zmesh.shape) | |
204 | + | |
205 | + def meshinit(self) : | |
206 | + self.x['points'] = np.linspace(self.minmax['xmin'], self.minmax['xmax'], num = self.x['res'], dtype = 'double', endpoint = True) | |
207 | + self.y['points'] = np.linspace(self.minmax['ymin'], self.minmax['ymax'], num = self.y['res'], dtype = 'double', endpoint = True) | |
208 | + self.xmesh, self.ymesh = np.meshgrid(self.x['points'], self.y['points']) | |
209 | + | |
210 | + def set_minmax(self, cle, val) : #cle = xmax, xmin, ymax, ymin, zmin, zmax | |
211 | + self.minmax[cle] = float(val) | |
212 | + self.meshinit() | |
213 | + | |
214 | + def set_layers_val(self, x, y, layers_val = {'Name' : 0}): | |
215 | + xind = self.postoindicex(x) | |
216 | + yind = self.postoindicey(y) | |
217 | + if xind is not None and yind is not None : | |
218 | + for layer in self.layers : self.layers[layer][yind, xind] = layers_val[layer] | |
219 | + | |
220 | + def set_val(self, x, y, val): #x et y en position, PAS EN INDICE!! | |
221 | + xind = self.postoindicex(x) | |
222 | + yind = self.postoindicey(y) | |
223 | + if xind is not None and yind is not None : self.zmesh[yind, xind] = val | |
224 | + | |
225 | + def postoindicex(self, x): | |
226 | + if self.minmax['xmin'] < x < self.minmax['xmax'] : return (abs(self.x['points'] - x)).argmin() | |
227 | + #else : print 'X OUT OF BOUNDS', x, self.x['min'], self.x['max'] | |
228 | + def postoindicey(self, x): | |
229 | + if self.minmax['ymin'] < x < self.minmax['ymax'] : return (abs(self.y['points'] - x)).argmin() | |
230 | + #else : print 'Y OUT OF BOUNDS', x, self.y['min'], self.y['max'] | |
231 | + | |
232 | + def add_plot(self, x, y) : | |
233 | + plt.plot(x, y, 'H', color = 'white') | |
234 | + | |
235 | + def plot(self, layer = None, autominmax = True, cmap = 'seismic') : | |
236 | + if layer : z = self.layers[layer] | |
237 | + else : z = self.zmesh | |
238 | + | |
239 | + if autominmax or 'zmin' not in self.minmax or 'zmax' not in self.minmax: | |
240 | + vmin = z.min() | |
241 | + vmax = z.max() | |
242 | + else : | |
243 | + vmin = self.minmax['zmin'] | |
244 | + vmax = self.minmax['zmax'] | |
245 | + | |
246 | + self.fig = plt.figure() | |
247 | + plt.pcolormesh(self.xmesh, self.ymesh, z, vmin = vmin, vmax = vmax, cmap = cmap) | |
248 | + plt.title(self.title) | |
249 | + plt.colorbar() | |
250 | + | |
251 | + def xlineplot(self, x) : | |
252 | + simumods.lineplot(self.zmesh[self.postoindicex(x), :], x = self.xmesh[self.postoindicex(0), :]) | |
253 | + def ylineplot(self, x) : | |
254 | + simumods.lineplot(self.zmesh[:, self.postoindicey(x)], x = self.ymesh[:, self.postoindicey(0)]) | |
255 | + | |
256 | + | |
257 | + | |
258 | +class display3d(display_general) : | |
130 | 259 | """ |
131 | 260 | 3D plotting object |
132 | 261 | works fine! init 3D coordinates as numpy arrays (x,y,z) |
... | ... | @@ -135,14 +264,16 @@ class display3d(object) : |
135 | 264 | Thus this object impose an invisible cube at first |
136 | 265 | use set_autoscatter for a default scatter plot of x,y,z (NOT generated by default, must be called!!) |
137 | 266 | """ |
138 | - def __init__(self, x, y, z) : | |
267 | + def __init__(self, x, y, z, title = 'display3d') : | |
139 | 268 | |
140 | 269 | self.x = x |
141 | 270 | self.y = y |
142 | 271 | self.z = z |
143 | 272 | self.planet = False |
273 | + self.trisurf = False | |
144 | 274 | self._initialize() |
145 | 275 | self.plots = {} |
276 | + self.setTitle(title) | |
146 | 277 | |
147 | 278 | def _initialize(self): |
148 | 279 | |
... | ... | @@ -152,10 +283,22 @@ class display3d(object) : |
152 | 283 | |
153 | 284 | ### Create a cube to force aspect ratio 1:1 |
154 | 285 | self.ax.set_aspect('equal') |
155 | - MAX = max(np.concatenate([abs(self.x),abs(self.y),abs(self.z)])) | |
286 | + self._max = max(np.concatenate([abs(self.x),abs(self.y),abs(self.z)])) | |
156 | 287 | for direction in (-1, 1): |
157 | - for point in np.diag(direction * MAX * np.array([1,1,1])): | |
288 | + for point in np.diag(direction * self._max * np.array([1,1,1])): | |
158 | 289 | self.ax.plot([point[0]], [point[1]], [point[2]], 'w') |
290 | + | |
291 | + self.set_xyzlabels() | |
292 | + | |
293 | + def set_xyzlabels(self, x = None, y = None, z = None): | |
294 | + | |
295 | + if x is None : x = 'X-axis' | |
296 | + if y is None : y = 'Y-axis' | |
297 | + if z is None : z = 'Z-axis' | |
298 | + | |
299 | + self.ax.set_xlabel(x) | |
300 | + self.ax.set_ylabel(y) | |
301 | + self.ax.set_zlabel(z) | |
159 | 302 | |
160 | 303 | def forceEqualRatio(self): |
161 | 304 | |
... | ... | @@ -164,12 +307,11 @@ class display3d(object) : |
164 | 307 | for key in self.plots : mlist.append(abs(np.concatenate(self.plots[key]['data'])).max()) |
165 | 308 | mlist.append(abs(np.concatenate([self.x,self.y,self.z])).max()) |
166 | 309 | #add any other data to the list |
167 | - MAX = max(mlist) | |
310 | + self._max = max(mlist) | |
168 | 311 | for direction in (-1, 1): |
169 | - for point in np.diag(direction * MAX * np.array([1,1,1])): | |
312 | + for point in np.diag(direction * self._max * np.array([1,1,1])): | |
170 | 313 | self.ax.plot([point[0]], [point[1]], [point[2]], 'w') |
171 | 314 | |
172 | - | |
173 | 315 | def redraw(self): |
174 | 316 | self._initialize() |
175 | 317 | if self.trisurf : self.set_trisurf(tripos = self.trisurf['tripos'], trival = self.trisurf['trival'], minmax = self.trisurf['minmax']) |
... | ... | @@ -201,10 +343,16 @@ class display3d(object) : |
201 | 343 | def set_scatter(self, scatter, c = None) : |
202 | 344 | self.scatter = self.ax.scatter(scatter[:,0], scatter[:,1], scatter[:,2], c = c, cmap = 'seismic') |
203 | 345 | |
204 | - def set_autoscatter(self, c = None, vmin = None, vmax = None): | |
205 | - self.autoscatter = self.ax.scatter(self.x, self.y, self.z, vmin = vmin, vmax = vmax, c = c, cmap = 'seismic') | |
206 | - cbar = self.fig.colorbar(self.autoscatter) | |
207 | - | |
346 | + def set_autoscatter(self, c = None, vmin = None, vmax = None, **kw): | |
347 | + self.autoscatter = self.ax.scatter(self.x, self.y, self.z, vmin = vmin, vmax = vmax, c = c, cmap = 'seismic', **kw) | |
348 | + if c is not None : cbar = self.fig.colorbar(self.autoscatter) | |
349 | + | |
350 | + | |
351 | + def set_centralAxis(self, linewidth = .5): | |
352 | + self.ax.plot([-self._max, self._max], [0,0], [0,0], '-k', linewidth = linewidth) | |
353 | + self.ax.plot([0,0], [-self._max, self._max], [0,0], '-k', linewidth = linewidth) | |
354 | + self.ax.plot([0,0], [0,0], [-self._max, self._max], '-k', linewidth = linewidth) | |
355 | + | |
208 | 356 | def set_planet(self) : |
209 | 357 | self.planet = True |
210 | 358 | u, v = np.mgrid[0:2*np.pi:20j, 0:np.pi:10j] |
... | ... | @@ -223,10 +371,6 @@ class display3d(object) : |
223 | 371 | if save : self.plots[len(self.plots)] = {'data' : plot, 'color' : color} |
224 | 372 | self.ax.plot(plot[:,0], plot[:,1], plot[:,2], linewidth = 3., color = color) |
225 | 373 | |
226 | - def show(self) : | |
227 | - plt.show() | |
228 | - | |
229 | - | |
230 | 374 | |
231 | 375 | |
232 | 376 | ... | ... |
mva.py
... | ... | @@ -23,7 +23,7 @@ class mva(object): |
23 | 23 | self.results = {} |
24 | 24 | self.calc(noprint = noprint) |
25 | 25 | #self.noprint = noprint |
26 | - if field2 != None : | |
26 | + if field2 is not None : | |
27 | 27 | self.field_cross = field2 # en entrรฉ : deux vecteurs de 3 composantes dรฉjร moyennรฉ |
28 | 28 | self.calc_cross(noprint = noprint) |
29 | 29 | ... | ... |
read_data.py
... | ... | @@ -7,6 +7,7 @@ from datetime import timedelta |
7 | 7 | import numpy as np |
8 | 8 | import os |
9 | 9 | import matplotlib.pyplot as plt |
10 | +import pickle | |
10 | 11 | |
11 | 12 | class donnee(object) : |
12 | 13 | |
... | ... | @@ -14,9 +15,15 @@ class donnee(object) : |
14 | 15 | """ |
15 | 16 | Donnee object : open data from cef file |
16 | 17 | This object is useful to manage timeseries with implemented calculation on timedeltas |
17 | - get metadata from ceffile and store it in self._metadata | |
18 | - to load data use self._get_data() (THIS MUST BE IMPROVED) | |
18 | + | |
19 | 19 | all data are stored in self.donnee |
20 | + REMAINING TO DO : Harmonize all methods conventional name (use either _ of capital) | |
21 | + Rename self.donnee into self.data | |
22 | + Rename the class into a more appropriate international word | |
23 | + Add Nan & Fillvall treatment to all methods | |
24 | + Add a write to cef file method | |
25 | + Add a get_as_tensor method (similar to get_as_field) | |
26 | + Vectorize all methods | |
20 | 27 | """ |
21 | 28 | ceflib.verbosity(0) |
22 | 29 | self._fichier = fichier |
... | ... | @@ -28,11 +35,14 @@ class donnee(object) : |
28 | 35 | ceflib.close() |
29 | 36 | |
30 | 37 | self.donnee = {} |
38 | + self.varattributes = {} | |
31 | 39 | self._get_time() |
32 | - | |
40 | + | |
33 | 41 | def _get_time(self) : |
34 | 42 | ceflib.read(self._fichier) |
35 | 43 | self.donnee['epoch'] = np.copy(np.array([datetime.utcfromtimestamp(ceflib.milli_to_timestamp(i)) for i in ceflib.var('epoch')])) |
44 | + self.varattributes['epoch'] = {} | |
45 | + for attribute in ceflib.vattributes('epoch') : self.varattributes['epoch'][attribute] = ceflib.vattr('epoch', attribute) | |
36 | 46 | ceflib.close() |
37 | 47 | |
38 | 48 | def get_time(self) : |
... | ... | @@ -42,14 +52,29 @@ class donnee(object) : |
42 | 52 | def get_varnames(self) : |
43 | 53 | return self._varnames |
44 | 54 | |
45 | - def _get_data(self, var = 'all') : | |
46 | - #self.donnee = {} | |
47 | - ceflib.read(self._fichier) | |
48 | - if var == 'all' : | |
49 | - for nom in self._varnames: | |
50 | - if nom not in ['epoch', 'K001', 'K002'] : self.donnee[nom] = np.copy(ceflib.var(nom)) | |
51 | - else : self.donnee[var] = np.copy(ceflib.var(var)) | |
52 | - ceflib.close() | |
55 | + #def _get_data(self, var = 'all') : | |
56 | + ##self.donnee = {} | |
57 | + #ceflib.read(self._fichier) | |
58 | + #if var == 'all' : | |
59 | + #for nom in self._varnames: | |
60 | + #if nom not in ['epoch', 'K001', 'K002'] : self.donnee[nom] = np.copy(ceflib.var(nom)) | |
61 | + #else : self.donnee[var] = np.copy(ceflib.var(var)) | |
62 | + #ceflib.close() | |
63 | + | |
64 | + def _modify_fillval_to_nan(self, var): | |
65 | + self.donnee[var][self.donnee[var] == float(self.varattributes[var]['FILLVAL'])] = np.nan | |
66 | + return self.donnee[var] | |
67 | + | |
68 | + def _load_var(self, var) : | |
69 | + if var not in self.donnee : | |
70 | + if var in self._varnames : | |
71 | + ceflib.read(self._fichier) | |
72 | + self.donnee[var] = np.copy(ceflib.var(var)) | |
73 | + self.varattributes[var] = {} | |
74 | + for attribute in ceflib.vattributes(var) : self.varattributes[var][attribute] = ceflib.vattr(var, attribute) | |
75 | + ceflib.close() | |
76 | + if 'FILLVAL' in self.varattributes[var] : self._modify_fillval_to_nan(var) | |
77 | + else : print "!!!Input Variable Not Found!!!" | |
53 | 78 | |
54 | 79 | def get_data(self, var) : |
55 | 80 | self._load_var(var) |
... | ... | @@ -99,11 +124,16 @@ class donnee(object) : |
99 | 124 | return out2 |
100 | 125 | |
101 | 126 | def get_mean(self, t1, t2, var) : |
127 | + """ | |
128 | + # NOTE: a.mean() when a posseses NaN return NaN -> treatment required | |
129 | + get mean value of an interval. NaN treatment implemented | |
130 | + """ | |
102 | 131 | self._load_var(var) |
103 | 132 | i1 = abs(self.donnee['epoch'] - t1).argmin() |
104 | 133 | i2 = abs(self.donnee['epoch'] - t2).argmin() |
105 | - return self.donnee[var][i1:i2].mean() | |
106 | - | |
134 | + return self.donnee[var][i1:i2][~np.isnan(self.donnee[var][i1:i2])].mean() | |
135 | + #return self.donnee[var][i1:i2].mean() | |
136 | + | |
107 | 137 | def getIndex(self, t = None): |
108 | 138 | if t : return abs(self.donnee['epoch'] - t).argmin() |
109 | 139 | else : return None |
... | ... | @@ -111,26 +141,26 @@ class donnee(object) : |
111 | 141 | def get_projected(self, varz, matrice, new_coord = ['l', 'm', 'n']) : |
112 | 142 | """ |
113 | 143 | !!! Only works with 3D array at the moment |
114 | - user must provide a transport matrix, with L,M,N in each colums of the matrix, so that : | |
115 | - new_vect = old_vect([x,y,z]) * matrix, or new_vect = inv(matrix) * old_vect[[x], [y], [z]] | |
144 | + user must provide a transport matrix, with L,M,N in each colums of the matrix, so that: | |
145 | + mat[:,0] = l, mat[:,1] = m, mat[:,2] = n, with mat being a numpy.mat object | |
146 | + and new_vect = old_vect([x,y,z]) * matrix, or new_vect = inv(matrix) * old_vect[[x], [y], [z]] | |
147 | + Example : l = numpy.array([ 0.16631492, -0.08297703, 0.98257527]) | |
148 | + m = numpy.array([-0.4464368 , -0.89481517, 0. ]) | |
149 | + n = numpy.array([ 0.87922325, -0.43865776, -0.18586511]) | |
150 | + matrice = numpy.mat([l,m,n]).transpose() | |
116 | 151 | """ |
117 | 152 | field = self.get_data_as_field(varz) |
118 | 153 | f = np.array([vect * matrice for vect in field])[:,0] |
119 | 154 | self.donnee[new_coord[0]] = f[:,0] |
120 | 155 | self.donnee[new_coord[1]] = f[:,1] |
121 | 156 | self.donnee[new_coord[2]] = f[:,2] |
122 | - | |
123 | - def _load_var(self, var) : | |
124 | - if var not in self.donnee : | |
125 | - ceflib.read(self._fichier) | |
126 | - self.donnee[var] = np.copy(ceflib.var(var)) | |
127 | - ceflib.close() | |
128 | - | |
157 | + return {new_coord[i] : self.donnee[new_coord[i]] for i in range(3)} | |
129 | 158 | |
130 | 159 | def addField(self, field, abscisse = None, name = 'New_interpolated_field') : |
131 | 160 | """ |
132 | 161 | Add new field in the donnee object, use old abscisse to interpolate on current absisse |
133 | 162 | If no abscisse is given... do something? |
163 | + TO DO : modify self._varnames ???? | |
134 | 164 | """ |
135 | 165 | def interp(xnew, xold, yold) : |
136 | 166 | def tofloat(d) : |
... | ... | @@ -143,7 +173,6 @@ class donnee(object) : |
143 | 173 | self.donnee[name] = interp(self.donnee['epoch'], abscisse, field) |
144 | 174 | return self.donnee[name] |
145 | 175 | |
146 | - | |
147 | 176 | def get_interval(self, var, t1 = None, t2 = None, include = False) : |
148 | 177 | """ |
149 | 178 | get part of the data set, between start time t1 and stop time t2 |
... | ... | @@ -175,7 +204,6 @@ class donnee(object) : |
175 | 204 | if show : plt.show() |
176 | 205 | |
177 | 206 | |
178 | - | |
179 | 207 | def time_interpolation(x1, x2, y2) : |
180 | 208 | """ |
181 | 209 | Time interpolation for 2D data : |
... | ... | @@ -194,8 +222,35 @@ def time_interpolation(x1, x2, y2) : |
194 | 222 | return y3 |
195 | 223 | |
196 | 224 | |
225 | +def pickleSave(filename = 'pickleSave', data = ''): | |
226 | + """ | |
227 | + Input filename WITHOUT any extension | |
228 | + a .save extension will be added to the name | |
229 | + This routine DO NOT allow overwriting!! | |
230 | + """ | |
231 | + if os.path.exists(filename) : | |
232 | + i = 0 | |
233 | + while os.path.exists(filename) : | |
234 | + filename = filename + str(i) | |
235 | + i+=1 | |
236 | + filename = filename + '.save' | |
237 | + print 'Saving data into ', filename | |
238 | + print 'FYI current working directory is ', os.get_cwd() | |
239 | + with open(filename, 'w') as sv : pickle.dump(data, sv) | |
240 | + return data | |
197 | 241 | |
198 | - | |
242 | +def pickleLoad(filename = 'pickleSave', filename_has_extension = False): | |
243 | + | |
244 | + if not filename_has_extension : | |
245 | + print 'Assume file extension is not provided, adding .save to the filename' | |
246 | + filename = filename + '.save' | |
247 | + | |
248 | + if os.path.exists(filename): | |
249 | + print 'returning data' | |
250 | + with open(savename, 'rb') as sv: return pickle.load(sv) | |
251 | + else : | |
252 | + print 'file not found, please check filename and extension ', filename | |
253 | + | |
199 | 254 | |
200 | 255 | |
201 | 256 | #class field(np.ndarray) : | ... | ... |