##// END OF EJS Templates
Fix HDFReader, update metadata list for spectra
Juan C. Espinoza -
r1552:634b09aabe58
parent child
Show More
@@ -1,1170 +1,1169
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
2 # All rights reserved.
3 #
3 #
4 # Distributed under the terms of the BSD 3-clause license.
4 # Distributed under the terms of the BSD 3-clause license.
5 """Definition of diferent Data objects for different types of data
5 """Definition of diferent Data objects for different types of data
6
6
7 Here you will find the diferent data objects for the different types
7 Here you will find the diferent data objects for the different types
8 of data, this data objects must be used as dataIn or dataOut objects in
8 of data, this data objects must be used as dataIn or dataOut objects in
9 processing units and operations. Currently the supported data objects are:
9 processing units and operations. Currently the supported data objects are:
10 Voltage, Spectra, SpectraHeis, Fits, Correlation and Parameters
10 Voltage, Spectra, SpectraHeis, Fits, Correlation and Parameters
11 """
11 """
12
12
13 import copy
13 import copy
14 import numpy
14 import numpy
15 import datetime
15 import datetime
16 import json
16 import json
17
17
18 import schainpy.admin
18 import schainpy.admin
19 from schainpy.utils import log
19 from schainpy.utils import log
20 from .jroheaderIO import SystemHeader, RadarControllerHeader
20 from .jroheaderIO import SystemHeader, RadarControllerHeader
21 from schainpy.model.data import _noise
21 from schainpy.model.data import _noise
22
22
23
23
24 def getNumpyDtype(dataTypeCode):
24 def getNumpyDtype(dataTypeCode):
25
25
26 if dataTypeCode == 0:
26 if dataTypeCode == 0:
27 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
27 numpyDtype = numpy.dtype([('real', '<i1'), ('imag', '<i1')])
28 elif dataTypeCode == 1:
28 elif dataTypeCode == 1:
29 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
29 numpyDtype = numpy.dtype([('real', '<i2'), ('imag', '<i2')])
30 elif dataTypeCode == 2:
30 elif dataTypeCode == 2:
31 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
31 numpyDtype = numpy.dtype([('real', '<i4'), ('imag', '<i4')])
32 elif dataTypeCode == 3:
32 elif dataTypeCode == 3:
33 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
33 numpyDtype = numpy.dtype([('real', '<i8'), ('imag', '<i8')])
34 elif dataTypeCode == 4:
34 elif dataTypeCode == 4:
35 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
35 numpyDtype = numpy.dtype([('real', '<f4'), ('imag', '<f4')])
36 elif dataTypeCode == 5:
36 elif dataTypeCode == 5:
37 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
37 numpyDtype = numpy.dtype([('real', '<f8'), ('imag', '<f8')])
38 else:
38 else:
39 raise ValueError('dataTypeCode was not defined')
39 raise ValueError('dataTypeCode was not defined')
40
40
41 return numpyDtype
41 return numpyDtype
42
42
43
43
44 def getDataTypeCode(numpyDtype):
44 def getDataTypeCode(numpyDtype):
45
45
46 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
46 if numpyDtype == numpy.dtype([('real', '<i1'), ('imag', '<i1')]):
47 datatype = 0
47 datatype = 0
48 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
48 elif numpyDtype == numpy.dtype([('real', '<i2'), ('imag', '<i2')]):
49 datatype = 1
49 datatype = 1
50 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
50 elif numpyDtype == numpy.dtype([('real', '<i4'), ('imag', '<i4')]):
51 datatype = 2
51 datatype = 2
52 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
52 elif numpyDtype == numpy.dtype([('real', '<i8'), ('imag', '<i8')]):
53 datatype = 3
53 datatype = 3
54 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
54 elif numpyDtype == numpy.dtype([('real', '<f4'), ('imag', '<f4')]):
55 datatype = 4
55 datatype = 4
56 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
56 elif numpyDtype == numpy.dtype([('real', '<f8'), ('imag', '<f8')]):
57 datatype = 5
57 datatype = 5
58 else:
58 else:
59 datatype = None
59 datatype = None
60
60
61 return datatype
61 return datatype
62
62
63
63
64 def hildebrand_sekhon(data, navg):
64 def hildebrand_sekhon(data, navg):
65 """
65 """
66 This method is for the objective determination of the noise level in Doppler spectra. This
66 This method is for the objective determination of the noise level in Doppler spectra. This
67 implementation technique is based on the fact that the standard deviation of the spectral
67 implementation technique is based on the fact that the standard deviation of the spectral
68 densities is equal to the mean spectral density for white Gaussian noise
68 densities is equal to the mean spectral density for white Gaussian noise
69
69
70 Inputs:
70 Inputs:
71 Data : heights
71 Data : heights
72 navg : numbers of averages
72 navg : numbers of averages
73
73
74 Return:
74 Return:
75 mean : noise's level
75 mean : noise's level
76 """
76 """
77
77
78 sortdata = numpy.sort(data, axis=None)
78 sortdata = numpy.sort(data, axis=None)
79 #print(numpy.shape(data))
79 #print(numpy.shape(data))
80 #exit()
80 #exit()
81 '''
81 '''
82 lenOfData = len(sortdata)
82 lenOfData = len(sortdata)
83 nums_min = lenOfData*0.2
83 nums_min = lenOfData*0.2
84
84
85 if nums_min <= 5:
85 if nums_min <= 5:
86
86
87 nums_min = 5
87 nums_min = 5
88
88
89 sump = 0.
89 sump = 0.
90 sumq = 0.
90 sumq = 0.
91
91
92 j = 0
92 j = 0
93 cont = 1
93 cont = 1
94
94
95 while((cont == 1)and(j < lenOfData)):
95 while((cont == 1)and(j < lenOfData)):
96
96
97 sump += sortdata[j]
97 sump += sortdata[j]
98 sumq += sortdata[j]**2
98 sumq += sortdata[j]**2
99
99
100 if j > nums_min:
100 if j > nums_min:
101 rtest = float(j)/(j-1) + 1.0/navg
101 rtest = float(j)/(j-1) + 1.0/navg
102 if ((sumq*j) > (rtest*sump**2)):
102 if ((sumq*j) > (rtest*sump**2)):
103 j = j - 1
103 j = j - 1
104 sump = sump - sortdata[j]
104 sump = sump - sortdata[j]
105 sumq = sumq - sortdata[j]**2
105 sumq = sumq - sortdata[j]**2
106 cont = 0
106 cont = 0
107
107
108 j += 1
108 j += 1
109
109
110 lnoise = sump / j
110 lnoise = sump / j
111 '''
111 '''
112 return _noise.hildebrand_sekhon(sortdata, navg)
112 return _noise.hildebrand_sekhon(sortdata, navg)
113
113
114
114
115 class Beam:
115 class Beam:
116
116
117 def __init__(self):
117 def __init__(self):
118 self.codeList = []
118 self.codeList = []
119 self.azimuthList = []
119 self.azimuthList = []
120 self.zenithList = []
120 self.zenithList = []
121
121
122
122
123 class GenericData(object):
123 class GenericData(object):
124
124
125 flagNoData = True
125 flagNoData = True
126
126
127 def copy(self, inputObj=None):
127 def copy(self, inputObj=None):
128
128
129 if inputObj == None:
129 if inputObj == None:
130 return copy.deepcopy(self)
130 return copy.deepcopy(self)
131
131
132 for key in list(inputObj.__dict__.keys()):
132 for key in list(inputObj.__dict__.keys()):
133
133
134 attribute = inputObj.__dict__[key]
134 attribute = inputObj.__dict__[key]
135
135
136 # If this attribute is a tuple or list
136 # If this attribute is a tuple or list
137 if type(inputObj.__dict__[key]) in (tuple, list):
137 if type(inputObj.__dict__[key]) in (tuple, list):
138 self.__dict__[key] = attribute[:]
138 self.__dict__[key] = attribute[:]
139 continue
139 continue
140
140
141 # If this attribute is another object or instance
141 # If this attribute is another object or instance
142 if hasattr(attribute, '__dict__'):
142 if hasattr(attribute, '__dict__'):
143 self.__dict__[key] = attribute.copy()
143 self.__dict__[key] = attribute.copy()
144 continue
144 continue
145
145
146 self.__dict__[key] = inputObj.__dict__[key]
146 self.__dict__[key] = inputObj.__dict__[key]
147
147
148 def deepcopy(self):
148 def deepcopy(self):
149
149
150 return copy.deepcopy(self)
150 return copy.deepcopy(self)
151
151
152 def isEmpty(self):
152 def isEmpty(self):
153
153
154 return self.flagNoData
154 return self.flagNoData
155
155
156 def isReady(self):
156 def isReady(self):
157
157
158 return not self.flagNoData
158 return not self.flagNoData
159
159
160
160
161 class JROData(GenericData):
161 class JROData(GenericData):
162
162
163 systemHeaderObj = SystemHeader()
163 systemHeaderObj = SystemHeader()
164 radarControllerHeaderObj = RadarControllerHeader()
164 radarControllerHeaderObj = RadarControllerHeader()
165 type = None
165 type = None
166 datatype = None # dtype but in string
166 datatype = None # dtype but in string
167 nProfiles = None
167 nProfiles = None
168 heightList = None
168 heightList = None
169 channelList = None
169 channelList = None
170 flagDiscontinuousBlock = False
170 flagDiscontinuousBlock = False
171 useLocalTime = False
171 useLocalTime = False
172 utctime = None
172 utctime = None
173 timeZone = None
173 timeZone = None
174 dstFlag = None
174 dstFlag = None
175 errorCount = None
175 errorCount = None
176 blocksize = None
176 blocksize = None
177 flagDecodeData = False # asumo q la data no esta decodificada
177 flagDecodeData = False # asumo q la data no esta decodificada
178 flagDeflipData = False # asumo q la data no esta sin flip
178 flagDeflipData = False # asumo q la data no esta sin flip
179 flagShiftFFT = False
179 flagShiftFFT = False
180 nCohInt = None
180 nCohInt = None
181 windowOfFilter = 1
181 windowOfFilter = 1
182 C = 3e8
182 C = 3e8
183 frequency = 49.92e6
183 frequency = 49.92e6
184 realtime = False
184 realtime = False
185 beacon_heiIndexList = None
185 beacon_heiIndexList = None
186 last_block = None
186 last_block = None
187 blocknow = None
187 blocknow = None
188 azimuth = None
188 azimuth = None
189 zenith = None
189 zenith = None
190 beam = Beam()
190 beam = Beam()
191 profileIndex = None
191 profileIndex = None
192 error = None
192 error = None
193 data = None
193 data = None
194 nmodes = None
194 nmodes = None
195 metadata_list = ['heightList', 'timeZone', 'type']
195 metadata_list = ['heightList', 'timeZone', 'type']
196
196
197 def __str__(self):
197 def __str__(self):
198
198
199 return '{} - {}'.format(self.type, self.datatime())
199 return '{} - {}'.format(self.type, self.datatime)
200
200
201 def getNoise(self):
201 def getNoise(self):
202
202
203 raise NotImplementedError
203 raise NotImplementedError
204
204
205 @property
205 @property
206 def nChannels(self):
206 def nChannels(self):
207
207
208 return len(self.channelList)
208 return len(self.channelList)
209
209
210 @property
210 @property
211 def channelIndexList(self):
211 def channelIndexList(self):
212
212
213 return list(range(self.nChannels))
213 return list(range(self.nChannels))
214
214
215 @property
215 @property
216 def nHeights(self):
216 def nHeights(self):
217
217
218 return len(self.heightList)
218 return len(self.heightList)
219
219
220 def getDeltaH(self):
220 def getDeltaH(self):
221
221
222 return self.heightList[1] - self.heightList[0]
222 return self.heightList[1] - self.heightList[0]
223
223
224 @property
224 @property
225 def ltctime(self):
225 def ltctime(self):
226
226
227 if self.useLocalTime:
227 if self.useLocalTime:
228 return self.utctime - self.timeZone * 60
228 return self.utctime - self.timeZone * 60
229
229
230 return self.utctime
230 return self.utctime
231
231
232 @property
232 @property
233 def datatime(self):
233 def datatime(self):
234
234
235 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
235 datatimeValue = datetime.datetime.utcfromtimestamp(self.ltctime)
236 return datatimeValue
236 return datatimeValue
237
237
238 def getTimeRange(self):
238 def getTimeRange(self):
239
239
240 datatime = []
240 datatime = []
241
241
242 datatime.append(self.ltctime)
242 datatime.append(self.ltctime)
243 datatime.append(self.ltctime + self.timeInterval + 1)
243 datatime.append(self.ltctime + self.timeInterval + 1)
244
244
245 datatime = numpy.array(datatime)
245 datatime = numpy.array(datatime)
246
246
247 return datatime
247 return datatime
248
248
249 def getFmaxTimeResponse(self):
249 def getFmaxTimeResponse(self):
250
250
251 period = (10 ** -6) * self.getDeltaH() / (0.15)
251 period = (10 ** -6) * self.getDeltaH() / (0.15)
252
252
253 PRF = 1. / (period * self.nCohInt)
253 PRF = 1. / (period * self.nCohInt)
254
254
255 fmax = PRF
255 fmax = PRF
256
256
257 return fmax
257 return fmax
258
258
259 def getFmax(self):
259 def getFmax(self):
260 PRF = 1. / (self.ippSeconds * self.nCohInt)
260 PRF = 1. / (self.ippSeconds * self.nCohInt)
261
261
262 fmax = PRF
262 fmax = PRF
263 return fmax
263 return fmax
264
264
265 def getVmax(self):
265 def getVmax(self):
266
266
267 _lambda = self.C / self.frequency
267 _lambda = self.C / self.frequency
268
268
269 vmax = self.getFmax() * _lambda / 2
269 vmax = self.getFmax() * _lambda / 2
270
270
271 return vmax
271 return vmax
272
272
273 @property
273 @property
274 def ippSeconds(self):
274 def ippSeconds(self):
275 '''
275 '''
276 '''
276 '''
277 return self.radarControllerHeaderObj.ippSeconds
277 return self.radarControllerHeaderObj.ippSeconds
278
278
279 @ippSeconds.setter
279 @ippSeconds.setter
280 def ippSeconds(self, ippSeconds):
280 def ippSeconds(self, ippSeconds):
281 '''
281 '''
282 '''
282 '''
283 self.radarControllerHeaderObj.ippSeconds = ippSeconds
283 self.radarControllerHeaderObj.ippSeconds = ippSeconds
284
284
285 @property
285 @property
286 def code(self):
286 def code(self):
287 '''
287 '''
288 '''
288 '''
289 return self.radarControllerHeaderObj.code
289 return self.radarControllerHeaderObj.code
290
290
291 @code.setter
291 @code.setter
292 def code(self, code):
292 def code(self, code):
293 '''
293 '''
294 '''
294 '''
295 self.radarControllerHeaderObj.code = code
295 self.radarControllerHeaderObj.code = code
296
296
297 @property
297 @property
298 def nCode(self):
298 def nCode(self):
299 '''
299 '''
300 '''
300 '''
301 return self.radarControllerHeaderObj.nCode
301 return self.radarControllerHeaderObj.nCode
302
302
303 @nCode.setter
303 @nCode.setter
304 def nCode(self, ncode):
304 def nCode(self, ncode):
305 '''
305 '''
306 '''
306 '''
307 self.radarControllerHeaderObj.nCode = ncode
307 self.radarControllerHeaderObj.nCode = ncode
308
308
309 @property
309 @property
310 def nBaud(self):
310 def nBaud(self):
311 '''
311 '''
312 '''
312 '''
313 return self.radarControllerHeaderObj.nBaud
313 return self.radarControllerHeaderObj.nBaud
314
314
315 @nBaud.setter
315 @nBaud.setter
316 def nBaud(self, nbaud):
316 def nBaud(self, nbaud):
317 '''
317 '''
318 '''
318 '''
319 self.radarControllerHeaderObj.nBaud = nbaud
319 self.radarControllerHeaderObj.nBaud = nbaud
320
320
321 @property
321 @property
322 def ipp(self):
322 def ipp(self):
323 '''
323 '''
324 '''
324 '''
325 return self.radarControllerHeaderObj.ipp
325 return self.radarControllerHeaderObj.ipp
326
326
327 @ipp.setter
327 @ipp.setter
328 def ipp(self, ipp):
328 def ipp(self, ipp):
329 '''
329 '''
330 '''
330 '''
331 self.radarControllerHeaderObj.ipp = ipp
331 self.radarControllerHeaderObj.ipp = ipp
332
332
333 @property
333 @property
334 def metadata(self):
334 def metadata(self):
335 '''
335 '''
336 '''
336 '''
337
337
338 return {attr: getattr(self, attr) for attr in self.metadata_list}
338 return {attr: getattr(self, attr) for attr in self.metadata_list}
339
339
340
340
341 class Voltage(JROData):
341 class Voltage(JROData):
342
342
343 dataPP_POW = None
343 dataPP_POW = None
344 dataPP_DOP = None
344 dataPP_DOP = None
345 dataPP_WIDTH = None
345 dataPP_WIDTH = None
346 dataPP_SNR = None
346 dataPP_SNR = None
347
347
348 def __init__(self):
348 def __init__(self):
349 '''
349 '''
350 Constructor
350 Constructor
351 '''
351 '''
352
352
353 self.useLocalTime = True
353 self.useLocalTime = True
354 self.radarControllerHeaderObj = RadarControllerHeader()
354 self.radarControllerHeaderObj = RadarControllerHeader()
355 self.systemHeaderObj = SystemHeader()
355 self.systemHeaderObj = SystemHeader()
356 self.type = "Voltage"
356 self.type = "Voltage"
357 self.data = None
357 self.data = None
358 self.nProfiles = None
358 self.nProfiles = None
359 self.heightList = None
359 self.heightList = None
360 self.channelList = None
360 self.channelList = None
361 self.flagNoData = True
361 self.flagNoData = True
362 self.flagDiscontinuousBlock = False
362 self.flagDiscontinuousBlock = False
363 self.utctime = None
363 self.utctime = None
364 self.timeZone = 0
364 self.timeZone = 0
365 self.dstFlag = None
365 self.dstFlag = None
366 self.errorCount = None
366 self.errorCount = None
367 self.nCohInt = None
367 self.nCohInt = None
368 self.blocksize = None
368 self.blocksize = None
369 self.flagCohInt = False
369 self.flagCohInt = False
370 self.flagDecodeData = False # asumo q la data no esta decodificada
370 self.flagDecodeData = False # asumo q la data no esta decodificada
371 self.flagDeflipData = False # asumo q la data no esta sin flip
371 self.flagDeflipData = False # asumo q la data no esta sin flip
372 self.flagShiftFFT = False
372 self.flagShiftFFT = False
373 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
373 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
374 self.profileIndex = 0
374 self.profileIndex = 0
375 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
375 self.metadata_list = ['type', 'heightList', 'timeZone', 'nProfiles', 'channelList', 'nCohInt',
376 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp']
376 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp']
377
377
378 def getNoisebyHildebrand(self, channel=None):
378 def getNoisebyHildebrand(self, channel=None):
379 """
379 """
380 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
380 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
381
381
382 Return:
382 Return:
383 noiselevel
383 noiselevel
384 """
384 """
385
385
386 if channel != None:
386 if channel != None:
387 data = self.data[channel]
387 data = self.data[channel]
388 nChannels = 1
388 nChannels = 1
389 else:
389 else:
390 data = self.data
390 data = self.data
391 nChannels = self.nChannels
391 nChannels = self.nChannels
392
392
393 noise = numpy.zeros(nChannels)
393 noise = numpy.zeros(nChannels)
394 power = data * numpy.conjugate(data)
394 power = data * numpy.conjugate(data)
395
395
396 for thisChannel in range(nChannels):
396 for thisChannel in range(nChannels):
397 if nChannels == 1:
397 if nChannels == 1:
398 daux = power[:].real
398 daux = power[:].real
399 else:
399 else:
400 daux = power[thisChannel, :].real
400 daux = power[thisChannel, :].real
401 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
401 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
402
402
403 return noise
403 return noise
404
404
405 def getNoise(self, type=1, channel=None):
405 def getNoise(self, type=1, channel=None):
406
406
407 if type == 1:
407 if type == 1:
408 noise = self.getNoisebyHildebrand(channel)
408 noise = self.getNoisebyHildebrand(channel)
409
409
410 return noise
410 return noise
411
411
412 def getPower(self, channel=None):
412 def getPower(self, channel=None):
413
413
414 if channel != None:
414 if channel != None:
415 data = self.data[channel]
415 data = self.data[channel]
416 else:
416 else:
417 data = self.data
417 data = self.data
418
418
419 power = data * numpy.conjugate(data)
419 power = data * numpy.conjugate(data)
420 powerdB = 10 * numpy.log10(power.real)
420 powerdB = 10 * numpy.log10(power.real)
421 powerdB = numpy.squeeze(powerdB)
421 powerdB = numpy.squeeze(powerdB)
422
422
423 return powerdB
423 return powerdB
424
424
425 @property
425 @property
426 def timeInterval(self):
426 def timeInterval(self):
427
427
428 return self.ippSeconds * self.nCohInt
428 return self.ippSeconds * self.nCohInt
429
429
430 noise = property(getNoise, "I'm the 'nHeights' property.")
430 noise = property(getNoise, "I'm the 'nHeights' property.")
431
431
432
432
433 class CrossProds(JROData):
433 class CrossProds(JROData):
434
434
435 # data es un numpy array de 2 dmensiones (canales, alturas)
435 # data es un numpy array de 2 dmensiones (canales, alturas)
436 data = None
436 data = None
437
437
438 def __init__(self):
438 def __init__(self):
439 '''
439 '''
440 Constructor
440 Constructor
441 '''
441 '''
442
442
443 self.useLocalTime = True
443 self.useLocalTime = True
444 '''
444 '''
445 self.radarControllerHeaderObj = RadarControllerHeader()
445 self.radarControllerHeaderObj = RadarControllerHeader()
446 self.systemHeaderObj = SystemHeader()
446 self.systemHeaderObj = SystemHeader()
447 self.type = "Voltage"
447 self.type = "Voltage"
448 self.data = None
448 self.data = None
449 # self.dtype = None
449 # self.dtype = None
450 # self.nChannels = 0
450 # self.nChannels = 0
451 # self.nHeights = 0
451 # self.nHeights = 0
452 self.nProfiles = None
452 self.nProfiles = None
453 self.heightList = None
453 self.heightList = None
454 self.channelList = None
454 self.channelList = None
455 # self.channelIndexList = None
455 # self.channelIndexList = None
456 self.flagNoData = True
456 self.flagNoData = True
457 self.flagDiscontinuousBlock = False
457 self.flagDiscontinuousBlock = False
458 self.utctime = None
458 self.utctime = None
459 self.timeZone = None
459 self.timeZone = None
460 self.dstFlag = None
460 self.dstFlag = None
461 self.errorCount = None
461 self.errorCount = None
462 self.nCohInt = None
462 self.nCohInt = None
463 self.blocksize = None
463 self.blocksize = None
464 self.flagDecodeData = False # asumo q la data no esta decodificada
464 self.flagDecodeData = False # asumo q la data no esta decodificada
465 self.flagDeflipData = False # asumo q la data no esta sin flip
465 self.flagDeflipData = False # asumo q la data no esta sin flip
466 self.flagShiftFFT = False
466 self.flagShiftFFT = False
467 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
467 self.flagDataAsBlock = False # Asumo que la data es leida perfil a perfil
468 self.profileIndex = 0
468 self.profileIndex = 0
469
469
470
470
471 def getNoisebyHildebrand(self, channel=None):
471 def getNoisebyHildebrand(self, channel=None):
472
472
473
473
474 if channel != None:
474 if channel != None:
475 data = self.data[channel]
475 data = self.data[channel]
476 nChannels = 1
476 nChannels = 1
477 else:
477 else:
478 data = self.data
478 data = self.data
479 nChannels = self.nChannels
479 nChannels = self.nChannels
480
480
481 noise = numpy.zeros(nChannels)
481 noise = numpy.zeros(nChannels)
482 power = data * numpy.conjugate(data)
482 power = data * numpy.conjugate(data)
483
483
484 for thisChannel in range(nChannels):
484 for thisChannel in range(nChannels):
485 if nChannels == 1:
485 if nChannels == 1:
486 daux = power[:].real
486 daux = power[:].real
487 else:
487 else:
488 daux = power[thisChannel, :].real
488 daux = power[thisChannel, :].real
489 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
489 noise[thisChannel] = hildebrand_sekhon(daux, self.nCohInt)
490
490
491 return noise
491 return noise
492
492
493 def getNoise(self, type=1, channel=None):
493 def getNoise(self, type=1, channel=None):
494
494
495 if type == 1:
495 if type == 1:
496 noise = self.getNoisebyHildebrand(channel)
496 noise = self.getNoisebyHildebrand(channel)
497
497
498 return noise
498 return noise
499
499
500 def getPower(self, channel=None):
500 def getPower(self, channel=None):
501
501
502 if channel != None:
502 if channel != None:
503 data = self.data[channel]
503 data = self.data[channel]
504 else:
504 else:
505 data = self.data
505 data = self.data
506
506
507 power = data * numpy.conjugate(data)
507 power = data * numpy.conjugate(data)
508 powerdB = 10 * numpy.log10(power.real)
508 powerdB = 10 * numpy.log10(power.real)
509 powerdB = numpy.squeeze(powerdB)
509 powerdB = numpy.squeeze(powerdB)
510
510
511 return powerdB
511 return powerdB
512
512
513 def getTimeInterval(self):
513 def getTimeInterval(self):
514
514
515 timeInterval = self.ippSeconds * self.nCohInt
515 timeInterval = self.ippSeconds * self.nCohInt
516
516
517 return timeInterval
517 return timeInterval
518
518
519 noise = property(getNoise, "I'm the 'nHeights' property.")
519 noise = property(getNoise, "I'm the 'nHeights' property.")
520 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
520 timeInterval = property(getTimeInterval, "I'm the 'timeInterval' property")
521 '''
521 '''
522 def getTimeInterval(self):
522 def getTimeInterval(self):
523
523
524 timeInterval = self.ippSeconds * self.nCohInt
524 timeInterval = self.ippSeconds * self.nCohInt
525
525
526 return timeInterval
526 return timeInterval
527
527
528
528
529
529
530 class Spectra(JROData):
530 class Spectra(JROData):
531
531
532 def __init__(self):
532 def __init__(self):
533 '''
533 '''
534 Constructor
534 Constructor
535 '''
535 '''
536
536
537 self.data_dc = None
537 self.data_dc = None
538 self.data_spc = None
538 self.data_spc = None
539 self.data_cspc = None
539 self.data_cspc = None
540 self.useLocalTime = True
540 self.useLocalTime = True
541 self.radarControllerHeaderObj = RadarControllerHeader()
541 self.radarControllerHeaderObj = RadarControllerHeader()
542 self.systemHeaderObj = SystemHeader()
542 self.systemHeaderObj = SystemHeader()
543 self.type = "Spectra"
543 self.type = "Spectra"
544 self.timeZone = 0
544 self.timeZone = 0
545 self.nProfiles = None
545 self.nProfiles = None
546 self.heightList = None
546 self.heightList = None
547 self.channelList = None
547 self.channelList = None
548 self.pairsList = None
548 self.pairsList = None
549 self.flagNoData = True
549 self.flagNoData = True
550 self.flagDiscontinuousBlock = False
550 self.flagDiscontinuousBlock = False
551 self.utctime = None
551 self.utctime = None
552 self.nCohInt = None
552 self.nCohInt = None
553 self.nIncohInt = None
553 self.nIncohInt = None
554 self.blocksize = None
554 self.blocksize = None
555 self.nFFTPoints = None
555 self.nFFTPoints = None
556 self.wavelength = None
556 self.wavelength = None
557 self.flagDecodeData = False # asumo q la data no esta decodificada
557 self.flagDecodeData = False # asumo q la data no esta decodificada
558 self.flagDeflipData = False # asumo q la data no esta sin flip
558 self.flagDeflipData = False # asumo q la data no esta sin flip
559 self.flagShiftFFT = False
559 self.flagShiftFFT = False
560 self.ippFactor = 1
560 self.ippFactor = 1
561 self.beacon_heiIndexList = []
561 self.beacon_heiIndexList = []
562 self.noise_estimation = None
562 self.noise_estimation = None
563 self.spc_noise = None
563 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
564 self.metadata_list = ['type', 'heightList', 'timeZone', 'pairsList', 'channelList', 'nCohInt',
564 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp', 'nIncohInt', 'nFFTPoints', 'nProfiles']
565 'code', 'nCode', 'nBaud', 'ippSeconds', 'ipp', 'nIncohInt', 'nFFTPoints', 'nProfiles', 'flagDecodeData']
565
566
566 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
567 def getNoisebyHildebrand(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
567 """
568 """
568 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
569 Determino el nivel de ruido usando el metodo Hildebrand-Sekhon
569
570
570 Return:
571 Return:
571 noiselevel
572 noiselevel
572 """
573 """
573
574
574 noise = numpy.zeros(self.nChannels)
575 noise = numpy.zeros(self.nChannels)
575
576
576 for channel in range(self.nChannels):
577 for channel in range(self.nChannels):
577 daux = self.data_spc[channel,
578 daux = self.data_spc[channel,
578 xmin_index:xmax_index, ymin_index:ymax_index]
579 xmin_index:xmax_index, ymin_index:ymax_index]
579 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
580 noise[channel] = hildebrand_sekhon(daux, self.nIncohInt)
580
581
581 return noise
582 return noise
582
583
583 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
584 def getNoise(self, xmin_index=None, xmax_index=None, ymin_index=None, ymax_index=None):
584
585
585 if self.noise_estimation is not None:
586 if self.spc_noise is not None:
587 # this was estimated by getNoise Operation defined in jroproc_parameters.py
588 return self.spc_noise
589 elif self.noise_estimation is not None:
586 # this was estimated by getNoise Operation defined in jroproc_spectra.py
590 # this was estimated by getNoise Operation defined in jroproc_spectra.py
587 return self.noise_estimation
591 return self.noise_estimation
588 else:
592 else:
589 noise = self.getNoisebyHildebrand(
593 noise = self.getNoisebyHildebrand(
590 xmin_index, xmax_index, ymin_index, ymax_index)
594 xmin_index, xmax_index, ymin_index, ymax_index)
591 return noise
595 return noise
592
596
593 def getFreqRangeTimeResponse(self, extrapoints=0):
597 def getFreqRangeTimeResponse(self, extrapoints=0):
594
598
595 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
599 deltafreq = self.getFmaxTimeResponse() / (self.nFFTPoints * self.ippFactor)
596 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
600 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
597
601
598 return freqrange
602 return freqrange
599
603
600 def getAcfRange(self, extrapoints=0):
604 def getAcfRange(self, extrapoints=0):
601
605
602 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
606 deltafreq = 10. / (self.getFmax() / (self.nFFTPoints * self.ippFactor))
603 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
607 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
604
608
605 return freqrange
609 return freqrange
606
610
607 def getFreqRange(self, extrapoints=0):
611 def getFreqRange(self, extrapoints=0):
608
612
609 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
613 deltafreq = self.getFmax() / (self.nFFTPoints * self.ippFactor)
610 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
614 freqrange = deltafreq * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.) - deltafreq / 2
611
615
612 return freqrange
616 return freqrange
613
617
614 def getVelRange(self, extrapoints=0):
618 def getVelRange(self, extrapoints=0):
615
619
616 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
620 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
617 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
621 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
618
622
619 if self.nmodes:
623 if self.nmodes:
620 return velrange / self.nmodes
624 return velrange / self.nmodes
621 else:
625 else:
622 return velrange
626 return velrange
623
627
624 @property
628 @property
625 def nPairs(self):
629 def nPairs(self):
626
630
627 return len(self.pairsList)
631 return len(self.pairsList)
628
632
629 @property
633 @property
630 def pairsIndexList(self):
634 def pairsIndexList(self):
631
635
632 return list(range(self.nPairs))
636 return list(range(self.nPairs))
633
637
634 @property
638 @property
635 def normFactor(self):
639 def normFactor(self):
636
640
637 pwcode = 1
641 pwcode = 1
638
642
639 if self.flagDecodeData:
643 if self.flagDecodeData:
640 pwcode = numpy.sum(self.code[0] ** 2)
644 pwcode = numpy.sum(self.code[0] ** 2)
641 # normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
645 # normFactor = min(self.nFFTPoints,self.nProfiles)*self.nIncohInt*self.nCohInt*pwcode*self.windowOfFilter
642 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
646 normFactor = self.nProfiles * self.nIncohInt * self.nCohInt * pwcode * self.windowOfFilter
643
647
644 return normFactor
648 return normFactor
645
649
646 @property
650 @property
647 def flag_cspc(self):
651 def flag_cspc(self):
648
652
649 if self.data_cspc is None:
653 if self.data_cspc is None:
650 return True
654 return True
651
655
652 return False
656 return False
653
657
654 @property
658 @property
655 def flag_dc(self):
659 def flag_dc(self):
656
660
657 if self.data_dc is None:
661 if self.data_dc is None:
658 return True
662 return True
659
663
660 return False
664 return False
661
665
662 @property
666 @property
663 def timeInterval(self):
667 def timeInterval(self):
664
668
665 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
669 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt * self.nProfiles * self.ippFactor
666 if self.nmodes:
670 if self.nmodes:
667 return self.nmodes * timeInterval
671 return self.nmodes * timeInterval
668 else:
672 else:
669 return timeInterval
673 return timeInterval
670
674
671 def getPower(self):
675 def getPower(self):
672
676
673 factor = self.normFactor
677 factor = self.normFactor
674 z = self.data_spc / factor
678 z = self.data_spc / factor
675 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
679 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
676 avg = numpy.average(z, axis=1)
680 avg = numpy.average(z, axis=1)
677
681
678 return 10 * numpy.log10(avg)
682 return 10 * numpy.log10(avg)
679
683
680 def getCoherence(self, pairsList=None, phase=False):
684 def getCoherence(self, pairsList=None, phase=False):
681
685
682 z = []
686 z = []
683 if pairsList is None:
687 if pairsList is None:
684 pairsIndexList = self.pairsIndexList
688 pairsIndexList = self.pairsIndexList
685 else:
689 else:
686 pairsIndexList = []
690 pairsIndexList = []
687 for pair in pairsList:
691 for pair in pairsList:
688 if pair not in self.pairsList:
692 if pair not in self.pairsList:
689 raise ValueError("Pair %s is not in dataOut.pairsList" % (
693 raise ValueError("Pair %s is not in dataOut.pairsList" % (
690 pair))
694 pair))
691 pairsIndexList.append(self.pairsList.index(pair))
695 pairsIndexList.append(self.pairsList.index(pair))
692 for i in range(len(pairsIndexList)):
696 for i in range(len(pairsIndexList)):
693 pair = self.pairsList[pairsIndexList[i]]
697 pair = self.pairsList[pairsIndexList[i]]
694 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
698 ccf = numpy.average(self.data_cspc[pairsIndexList[i], :, :], axis=0)
695 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
699 powa = numpy.average(self.data_spc[pair[0], :, :], axis=0)
696 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
700 powb = numpy.average(self.data_spc[pair[1], :, :], axis=0)
697 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
701 avgcoherenceComplex = ccf / numpy.sqrt(powa * powb)
698 if phase:
702 if phase:
699 data = numpy.arctan2(avgcoherenceComplex.imag,
703 data = numpy.arctan2(avgcoherenceComplex.imag,
700 avgcoherenceComplex.real) * 180 / numpy.pi
704 avgcoherenceComplex.real) * 180 / numpy.pi
701 else:
705 else:
702 data = numpy.abs(avgcoherenceComplex)
706 data = numpy.abs(avgcoherenceComplex)
703
707
704 z.append(data)
708 z.append(data)
705
709
706 return numpy.array(z)
710 return numpy.array(z)
707
711
708 def setValue(self, value):
712 def setValue(self, value):
709
713
710 print("This property should not be initialized")
714 print("This property should not be initialized")
711
715
712 return
716 return
713
717
714 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
718 noise = property(getNoise, setValue, "I'm the 'nHeights' property.")
715
719
716
720
717 class SpectraHeis(Spectra):
721 class SpectraHeis(Spectra):
718
722
719 def __init__(self):
723 def __init__(self):
720
724
721 self.radarControllerHeaderObj = RadarControllerHeader()
725 self.radarControllerHeaderObj = RadarControllerHeader()
722 self.systemHeaderObj = SystemHeader()
726 self.systemHeaderObj = SystemHeader()
723 self.type = "SpectraHeis"
727 self.type = "SpectraHeis"
724 self.nProfiles = None
728 self.nProfiles = None
725 self.heightList = None
729 self.heightList = None
726 self.channelList = None
730 self.channelList = None
727 self.flagNoData = True
731 self.flagNoData = True
728 self.flagDiscontinuousBlock = False
732 self.flagDiscontinuousBlock = False
729 self.utctime = None
733 self.utctime = None
730 self.blocksize = None
734 self.blocksize = None
731 self.profileIndex = 0
735 self.profileIndex = 0
732 self.nCohInt = 1
736 self.nCohInt = 1
733 self.nIncohInt = 1
737 self.nIncohInt = 1
734
738
735 @property
739 @property
736 def normFactor(self):
740 def normFactor(self):
737 pwcode = 1
741 pwcode = 1
738 if self.flagDecodeData:
742 if self.flagDecodeData:
739 pwcode = numpy.sum(self.code[0] ** 2)
743 pwcode = numpy.sum(self.code[0] ** 2)
740
744
741 normFactor = self.nIncohInt * self.nCohInt * pwcode
745 normFactor = self.nIncohInt * self.nCohInt * pwcode
742
746
743 return normFactor
747 return normFactor
744
748
745 @property
749 @property
746 def timeInterval(self):
750 def timeInterval(self):
747
751
748 return self.ippSeconds * self.nCohInt * self.nIncohInt
752 return self.ippSeconds * self.nCohInt * self.nIncohInt
749
753
750
754
751 class Fits(JROData):
755 class Fits(JROData):
752
756
753 def __init__(self):
757 def __init__(self):
754
758
755 self.type = "Fits"
759 self.type = "Fits"
756 self.nProfiles = None
760 self.nProfiles = None
757 self.heightList = None
761 self.heightList = None
758 self.channelList = None
762 self.channelList = None
759 self.flagNoData = True
763 self.flagNoData = True
760 self.utctime = None
764 self.utctime = None
761 self.nCohInt = 1
765 self.nCohInt = 1
762 self.nIncohInt = 1
766 self.nIncohInt = 1
763 self.useLocalTime = True
767 self.useLocalTime = True
764 self.profileIndex = 0
768 self.profileIndex = 0
765 self.timeZone = 0
769 self.timeZone = 0
766
770
767 def getTimeRange(self):
771 def getTimeRange(self):
768
772
769 datatime = []
773 datatime = []
770
774
771 datatime.append(self.ltctime)
775 datatime.append(self.ltctime)
772 datatime.append(self.ltctime + self.timeInterval)
776 datatime.append(self.ltctime + self.timeInterval)
773
777
774 datatime = numpy.array(datatime)
778 datatime = numpy.array(datatime)
775
779
776 return datatime
780 return datatime
777
781
778 def getChannelIndexList(self):
782 def getChannelIndexList(self):
779
783
780 return list(range(self.nChannels))
784 return list(range(self.nChannels))
781
785
782 def getNoise(self, type=1):
786 def getNoise(self, type=1):
783
787
784
788
785 if type == 1:
789 if type == 1:
786 noise = self.getNoisebyHildebrand()
790 noise = self.getNoisebyHildebrand()
787
791
788 if type == 2:
792 if type == 2:
789 noise = self.getNoisebySort()
793 noise = self.getNoisebySort()
790
794
791 if type == 3:
795 if type == 3:
792 noise = self.getNoisebyWindow()
796 noise = self.getNoisebyWindow()
793
797
794 return noise
798 return noise
795
799
796 @property
800 @property
797 def timeInterval(self):
801 def timeInterval(self):
798
802
799 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
803 timeInterval = self.ippSeconds * self.nCohInt * self.nIncohInt
800
804
801 return timeInterval
805 return timeInterval
802
806
803 @property
807 @property
804 def ippSeconds(self):
808 def ippSeconds(self):
805 '''
809 '''
806 '''
810 '''
807 return self.ipp_sec
811 return self.ipp_sec
808
812
809 noise = property(getNoise, "I'm the 'nHeights' property.")
813 noise = property(getNoise, "I'm the 'nHeights' property.")
810
814
811
815
812 class Correlation(JROData):
816 class Correlation(JROData):
813
817
814 def __init__(self):
818 def __init__(self):
815 '''
819 '''
816 Constructor
820 Constructor
817 '''
821 '''
818 self.radarControllerHeaderObj = RadarControllerHeader()
822 self.radarControllerHeaderObj = RadarControllerHeader()
819 self.systemHeaderObj = SystemHeader()
823 self.systemHeaderObj = SystemHeader()
820 self.type = "Correlation"
824 self.type = "Correlation"
821 self.data = None
825 self.data = None
822 self.dtype = None
826 self.dtype = None
823 self.nProfiles = None
827 self.nProfiles = None
824 self.heightList = None
828 self.heightList = None
825 self.channelList = None
829 self.channelList = None
826 self.flagNoData = True
830 self.flagNoData = True
827 self.flagDiscontinuousBlock = False
831 self.flagDiscontinuousBlock = False
828 self.utctime = None
832 self.utctime = None
829 self.timeZone = 0
833 self.timeZone = 0
830 self.dstFlag = None
834 self.dstFlag = None
831 self.errorCount = None
835 self.errorCount = None
832 self.blocksize = None
836 self.blocksize = None
833 self.flagDecodeData = False # asumo q la data no esta decodificada
837 self.flagDecodeData = False # asumo q la data no esta decodificada
834 self.flagDeflipData = False # asumo q la data no esta sin flip
838 self.flagDeflipData = False # asumo q la data no esta sin flip
835 self.pairsList = None
839 self.pairsList = None
836 self.nPoints = None
840 self.nPoints = None
837
841
838 def getPairsList(self):
842 def getPairsList(self):
839
843
840 return self.pairsList
844 return self.pairsList
841
845
842 def getNoise(self, mode=2):
846 def getNoise(self, mode=2):
843
847
844 indR = numpy.where(self.lagR == 0)[0][0]
848 indR = numpy.where(self.lagR == 0)[0][0]
845 indT = numpy.where(self.lagT == 0)[0][0]
849 indT = numpy.where(self.lagT == 0)[0][0]
846
850
847 jspectra0 = self.data_corr[:, :, indR, :]
851 jspectra0 = self.data_corr[:, :, indR, :]
848 jspectra = copy.copy(jspectra0)
852 jspectra = copy.copy(jspectra0)
849
853
850 num_chan = jspectra.shape[0]
854 num_chan = jspectra.shape[0]
851 num_hei = jspectra.shape[2]
855 num_hei = jspectra.shape[2]
852
856
853 freq_dc = jspectra.shape[1] / 2
857 freq_dc = jspectra.shape[1] / 2
854 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
858 ind_vel = numpy.array([-2, -1, 1, 2]) + freq_dc
855
859
856 if ind_vel[0] < 0:
860 if ind_vel[0] < 0:
857 ind_vel[list(range(0, 1))] = ind_vel[list(
861 ind_vel[list(range(0, 1))] = ind_vel[list(
858 range(0, 1))] + self.num_prof
862 range(0, 1))] + self.num_prof
859
863
860 if mode == 1:
864 if mode == 1:
861 jspectra[:, freq_dc, :] = (
865 jspectra[:, freq_dc, :] = (
862 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
866 jspectra[:, ind_vel[1], :] + jspectra[:, ind_vel[2], :]) / 2 # CORRECCION
863
867
864 if mode == 2:
868 if mode == 2:
865
869
866 vel = numpy.array([-2, -1, 1, 2])
870 vel = numpy.array([-2, -1, 1, 2])
867 xx = numpy.zeros([4, 4])
871 xx = numpy.zeros([4, 4])
868
872
869 for fil in range(4):
873 for fil in range(4):
870 xx[fil, :] = vel[fil] ** numpy.asarray(list(range(4)))
874 xx[fil, :] = vel[fil] ** numpy.asarray(list(range(4)))
871
875
872 xx_inv = numpy.linalg.inv(xx)
876 xx_inv = numpy.linalg.inv(xx)
873 xx_aux = xx_inv[0, :]
877 xx_aux = xx_inv[0, :]
874
878
875 for ich in range(num_chan):
879 for ich in range(num_chan):
876 yy = jspectra[ich, ind_vel, :]
880 yy = jspectra[ich, ind_vel, :]
877 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
881 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
878
882
879 junkid = jspectra[ich, freq_dc, :] <= 0
883 junkid = jspectra[ich, freq_dc, :] <= 0
880 cjunkid = sum(junkid)
884 cjunkid = sum(junkid)
881
885
882 if cjunkid.any():
886 if cjunkid.any():
883 jspectra[ich, freq_dc, junkid.nonzero()] = (
887 jspectra[ich, freq_dc, junkid.nonzero()] = (
884 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
888 jspectra[ich, ind_vel[1], junkid] + jspectra[ich, ind_vel[2], junkid]) / 2
885
889
886 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
890 noise = jspectra0[:, freq_dc, :] - jspectra[:, freq_dc, :]
887
891
888 return noise
892 return noise
889
893
890 @property
894 @property
891 def timeInterval(self):
895 def timeInterval(self):
892
896
893 return self.ippSeconds * self.nCohInt * self.nProfiles
897 return self.ippSeconds * self.nCohInt * self.nProfiles
894
898
895 def splitFunctions(self):
899 def splitFunctions(self):
896
900
897 pairsList = self.pairsList
901 pairsList = self.pairsList
898 ccf_pairs = []
902 ccf_pairs = []
899 acf_pairs = []
903 acf_pairs = []
900 ccf_ind = []
904 ccf_ind = []
901 acf_ind = []
905 acf_ind = []
902 for l in range(len(pairsList)):
906 for l in range(len(pairsList)):
903 chan0 = pairsList[l][0]
907 chan0 = pairsList[l][0]
904 chan1 = pairsList[l][1]
908 chan1 = pairsList[l][1]
905
909
906 # Obteniendo pares de Autocorrelacion
910 # Obteniendo pares de Autocorrelacion
907 if chan0 == chan1:
911 if chan0 == chan1:
908 acf_pairs.append(chan0)
912 acf_pairs.append(chan0)
909 acf_ind.append(l)
913 acf_ind.append(l)
910 else:
914 else:
911 ccf_pairs.append(pairsList[l])
915 ccf_pairs.append(pairsList[l])
912 ccf_ind.append(l)
916 ccf_ind.append(l)
913
917
914 data_acf = self.data_cf[acf_ind]
918 data_acf = self.data_cf[acf_ind]
915 data_ccf = self.data_cf[ccf_ind]
919 data_ccf = self.data_cf[ccf_ind]
916
920
917 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
921 return acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf
918
922
919 @property
923 @property
920 def normFactor(self):
924 def normFactor(self):
921 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
925 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.splitFunctions()
922 acf_pairs = numpy.array(acf_pairs)
926 acf_pairs = numpy.array(acf_pairs)
923 normFactor = numpy.zeros((self.nPairs, self.nHeights))
927 normFactor = numpy.zeros((self.nPairs, self.nHeights))
924
928
925 for p in range(self.nPairs):
929 for p in range(self.nPairs):
926 pair = self.pairsList[p]
930 pair = self.pairsList[p]
927
931
928 ch0 = pair[0]
932 ch0 = pair[0]
929 ch1 = pair[1]
933 ch1 = pair[1]
930
934
931 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
935 ch0_max = numpy.max(data_acf[acf_pairs == ch0, :, :], axis=1)
932 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
936 ch1_max = numpy.max(data_acf[acf_pairs == ch1, :, :], axis=1)
933 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
937 normFactor[p, :] = numpy.sqrt(ch0_max * ch1_max)
934
938
935 return normFactor
939 return normFactor
936
940
937
941
938 class Parameters(Spectra):
942 class Parameters(Spectra):
939
943
940 groupList = None # List of Pairs, Groups, etc
944 groupList = None # List of Pairs, Groups, etc
941 data_param = None # Parameters obtained
945 data_param = None # Parameters obtained
942 data_pre = None # Data Pre Parametrization
946 data_pre = None # Data Pre Parametrization
943 data_SNR = None # Signal to Noise Ratio
947 data_SNR = None # Signal to Noise Ratio
944 abscissaList = None # Abscissa, can be velocities, lags or time
948 abscissaList = None # Abscissa, can be velocities, lags or time
945 utctimeInit = None # Initial UTC time
949 utctimeInit = None # Initial UTC time
946 paramInterval = None # Time interval to calculate Parameters in seconds
950 paramInterval = None # Time interval to calculate Parameters in seconds
947 useLocalTime = True
951 useLocalTime = True
948 # Fitting
952 # Fitting
949 data_error = None # Error of the estimation
953 data_error = None # Error of the estimation
950 constants = None
954 constants = None
951 library = None
955 library = None
952 # Output signal
956 # Output signal
953 outputInterval = None # Time interval to calculate output signal in seconds
957 outputInterval = None # Time interval to calculate output signal in seconds
954 data_output = None # Out signal
958 data_output = None # Out signal
955 nAvg = None
959 nAvg = None
956 noise_estimation = None
960 noise_estimation = None
957 GauSPC = None # Fit gaussian SPC
961 GauSPC = None # Fit gaussian SPC
962 spc_noise = None
958
963
959 def __init__(self):
964 def __init__(self):
960 '''
965 '''
961 Constructor
966 Constructor
962 '''
967 '''
963 self.radarControllerHeaderObj = RadarControllerHeader()
968 self.radarControllerHeaderObj = RadarControllerHeader()
964 self.systemHeaderObj = SystemHeader()
969 self.systemHeaderObj = SystemHeader()
965 self.type = "Parameters"
970 self.type = "Parameters"
966 self.timeZone = 0
971 self.timeZone = 0
967 self.ippFactor = 1
972 self.ippFactor = 1
968
973
969 def getTimeRange1(self, interval):
974 def getTimeRange1(self, interval):
970
975
971 datatime = []
976 datatime = []
972
977
973 if self.useLocalTime:
978 if self.useLocalTime:
974 time1 = self.utctimeInit - self.timeZone * 60
979 time1 = self.utctimeInit - self.timeZone * 60
975 else:
980 else:
976 time1 = self.utctimeInit
981 time1 = self.utctimeInit
977
982
978 datatime.append(time1)
983 datatime.append(time1)
979 datatime.append(time1 + interval)
984 datatime.append(time1 + interval)
980 datatime = numpy.array(datatime)
985 datatime = numpy.array(datatime)
981
986
982 return datatime
987 return datatime
983
988
984 @property
989 @property
985 def timeInterval(self):
990 def timeInterval(self):
986
991
987 if hasattr(self, 'timeInterval1'):
992 if hasattr(self, 'timeInterval1'):
988 return self.timeInterval1
993 return self.timeInterval1
989 else:
994 else:
990 return self.paramInterval
995 return self.paramInterval
991
996
992
997
993 def setValue(self, value):
998 def setValue(self, value):
994
999
995 print("This property should not be initialized")
1000 print("This property should not be initialized")
996
1001
997 return
1002 return
998
1003
999 def getNoise(self):
1000
1001 return self.spc_noise
1002
1003 noise = property(getNoise, setValue, "I'm the 'Noise' property.")
1004
1005
1004
1006 class PlotterData(object):
1005 class PlotterData(object):
1007 '''
1006 '''
1008 Object to hold data to be plotted
1007 Object to hold data to be plotted
1009 '''
1008 '''
1010
1009
1011 MAXNUMX = 200
1010 MAXNUMX = 200
1012 MAXNUMY = 200
1011 MAXNUMY = 200
1013
1012
1014 def __init__(self, code, exp_code, localtime=True):
1013 def __init__(self, code, exp_code, localtime=True):
1015
1014
1016 self.key = code
1015 self.key = code
1017 self.exp_code = exp_code
1016 self.exp_code = exp_code
1018 self.ready = False
1017 self.ready = False
1019 self.flagNoData = False
1018 self.flagNoData = False
1020 self.localtime = localtime
1019 self.localtime = localtime
1021 self.data = {}
1020 self.data = {}
1022 self.meta = {}
1021 self.meta = {}
1023 self.__heights = []
1022 self.__heights = []
1024
1023
1025 def __str__(self):
1024 def __str__(self):
1026 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1025 dum = ['{}{}'.format(key, self.shape(key)) for key in self.data]
1027 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
1026 return 'Data[{}][{}]'.format(';'.join(dum), len(self.times))
1028
1027
1029 def __len__(self):
1028 def __len__(self):
1030 return len(self.data)
1029 return len(self.data)
1031
1030
1032 def __getitem__(self, key):
1031 def __getitem__(self, key):
1033 if isinstance(key, int):
1032 if isinstance(key, int):
1034 return self.data[self.times[key]]
1033 return self.data[self.times[key]]
1035 elif isinstance(key, str):
1034 elif isinstance(key, str):
1036 ret = numpy.array([self.data[x][key] for x in self.times])
1035 ret = numpy.array([self.data[x][key] for x in self.times])
1037 if ret.ndim > 1:
1036 if ret.ndim > 1:
1038 ret = numpy.swapaxes(ret, 0, 1)
1037 ret = numpy.swapaxes(ret, 0, 1)
1039 return ret
1038 return ret
1040
1039
1041 def __contains__(self, key):
1040 def __contains__(self, key):
1042 return key in self.data[self.min_time]
1041 return key in self.data[self.min_time]
1043
1042
1044 def setup(self):
1043 def setup(self):
1045 '''
1044 '''
1046 Configure object
1045 Configure object
1047 '''
1046 '''
1048 self.type = ''
1047 self.type = ''
1049 self.ready = False
1048 self.ready = False
1050 del self.data
1049 del self.data
1051 self.data = {}
1050 self.data = {}
1052 self.__heights = []
1051 self.__heights = []
1053 self.__all_heights = set()
1052 self.__all_heights = set()
1054
1053
1055 def shape(self, key):
1054 def shape(self, key):
1056 '''
1055 '''
1057 Get the shape of the one-element data for the given key
1056 Get the shape of the one-element data for the given key
1058 '''
1057 '''
1059
1058
1060 if len(self.data[self.min_time][key]):
1059 if len(self.data[self.min_time][key]):
1061 return self.data[self.min_time][key].shape
1060 return self.data[self.min_time][key].shape
1062 return (0,)
1061 return (0,)
1063
1062
1064 def update(self, data, tm, meta={}):
1063 def update(self, data, tm, meta={}):
1065 '''
1064 '''
1066 Update data object with new dataOut
1065 Update data object with new dataOut
1067 '''
1066 '''
1068
1067
1069 self.data[tm] = data
1068 self.data[tm] = data
1070
1069
1071 for key, value in meta.items():
1070 for key, value in meta.items():
1072 setattr(self, key, value)
1071 setattr(self, key, value)
1073
1072
1074 def normalize_heights(self):
1073 def normalize_heights(self):
1075 '''
1074 '''
1076 Ensure same-dimension of the data for different heighList
1075 Ensure same-dimension of the data for different heighList
1077 '''
1076 '''
1078
1077
1079 H = numpy.array(list(self.__all_heights))
1078 H = numpy.array(list(self.__all_heights))
1080 H.sort()
1079 H.sort()
1081 for key in self.data:
1080 for key in self.data:
1082 shape = self.shape(key)[:-1] + H.shape
1081 shape = self.shape(key)[:-1] + H.shape
1083 for tm, obj in list(self.data[key].items()):
1082 for tm, obj in list(self.data[key].items()):
1084 h = self.__heights[self.times.tolist().index(tm)]
1083 h = self.__heights[self.times.tolist().index(tm)]
1085 if H.size == h.size:
1084 if H.size == h.size:
1086 continue
1085 continue
1087 index = numpy.where(numpy.in1d(H, h))[0]
1086 index = numpy.where(numpy.in1d(H, h))[0]
1088 dummy = numpy.zeros(shape) + numpy.nan
1087 dummy = numpy.zeros(shape) + numpy.nan
1089 if len(shape) == 2:
1088 if len(shape) == 2:
1090 dummy[:, index] = obj
1089 dummy[:, index] = obj
1091 else:
1090 else:
1092 dummy[index] = obj
1091 dummy[index] = obj
1093 self.data[key][tm] = dummy
1092 self.data[key][tm] = dummy
1094
1093
1095 self.__heights = [H for tm in self.times]
1094 self.__heights = [H for tm in self.times]
1096
1095
1097 def jsonify(self, tm, plot_name, plot_type, decimate=False):
1096 def jsonify(self, tm, plot_name, plot_type, decimate=False):
1098 '''
1097 '''
1099 Convert data to json
1098 Convert data to json
1100 '''
1099 '''
1101
1100
1102 meta = {}
1101 meta = {}
1103 meta['xrange'] = []
1102 meta['xrange'] = []
1104 dy = int(len(self.yrange) / self.MAXNUMY) + 1
1103 dy = int(len(self.yrange) / self.MAXNUMY) + 1
1105 tmp = self.data[tm][self.key]
1104 tmp = self.data[tm][self.key]
1106 shape = tmp.shape
1105 shape = tmp.shape
1107 if len(shape) == 2:
1106 if len(shape) == 2:
1108 data = self.roundFloats(self.data[tm][self.key][::, ::dy].tolist())
1107 data = self.roundFloats(self.data[tm][self.key][::, ::dy].tolist())
1109 elif len(shape) == 3:
1108 elif len(shape) == 3:
1110 dx = int(self.data[tm][self.key].shape[1] / self.MAXNUMX) + 1
1109 dx = int(self.data[tm][self.key].shape[1] / self.MAXNUMX) + 1
1111 data = self.roundFloats(
1110 data = self.roundFloats(
1112 self.data[tm][self.key][::, ::dx, ::dy].tolist())
1111 self.data[tm][self.key][::, ::dx, ::dy].tolist())
1113 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1112 meta['xrange'] = self.roundFloats(self.xrange[2][::dx].tolist())
1114 else:
1113 else:
1115 data = self.roundFloats(self.data[tm][self.key].tolist())
1114 data = self.roundFloats(self.data[tm][self.key].tolist())
1116
1115
1117 ret = {
1116 ret = {
1118 'plot': plot_name,
1117 'plot': plot_name,
1119 'code': self.exp_code,
1118 'code': self.exp_code,
1120 'time': float(tm),
1119 'time': float(tm),
1121 'data': data,
1120 'data': data,
1122 }
1121 }
1123 meta['type'] = plot_type
1122 meta['type'] = plot_type
1124 meta['interval'] = float(self.interval)
1123 meta['interval'] = float(self.interval)
1125 meta['localtime'] = self.localtime
1124 meta['localtime'] = self.localtime
1126 meta['yrange'] = self.roundFloats(self.yrange[::dy].tolist())
1125 meta['yrange'] = self.roundFloats(self.yrange[::dy].tolist())
1127 meta.update(self.meta)
1126 meta.update(self.meta)
1128 ret['metadata'] = meta
1127 ret['metadata'] = meta
1129 return json.dumps(ret)
1128 return json.dumps(ret)
1130
1129
1131 @property
1130 @property
1132 def times(self):
1131 def times(self):
1133 '''
1132 '''
1134 Return the list of times of the current data
1133 Return the list of times of the current data
1135 '''
1134 '''
1136
1135
1137 ret = [t for t in self.data]
1136 ret = [t for t in self.data]
1138 ret.sort()
1137 ret.sort()
1139 return numpy.array(ret)
1138 return numpy.array(ret)
1140
1139
1141 @property
1140 @property
1142 def min_time(self):
1141 def min_time(self):
1143 '''
1142 '''
1144 Return the minimun time value
1143 Return the minimun time value
1145 '''
1144 '''
1146
1145
1147 return self.times[0]
1146 return self.times[0]
1148
1147
1149 @property
1148 @property
1150 def max_time(self):
1149 def max_time(self):
1151 '''
1150 '''
1152 Return the maximun time value
1151 Return the maximun time value
1153 '''
1152 '''
1154
1153
1155 return self.times[-1]
1154 return self.times[-1]
1156
1155
1157 # @property
1156 # @property
1158 # def heights(self):
1157 # def heights(self):
1159 # '''
1158 # '''
1160 # Return the list of heights of the current data
1159 # Return the list of heights of the current data
1161 # '''
1160 # '''
1162
1161
1163 # return numpy.array(self.__heights[-1])
1162 # return numpy.array(self.__heights[-1])
1164
1163
1165 @staticmethod
1164 @staticmethod
1166 def roundFloats(obj):
1165 def roundFloats(obj):
1167 if isinstance(obj, list):
1166 if isinstance(obj, list):
1168 return list(map(PlotterData.roundFloats, obj))
1167 return list(map(PlotterData.roundFloats, obj))
1169 elif isinstance(obj, float):
1168 elif isinstance(obj, float):
1170 return round(obj, 2)
1169 return round(obj, 2)
@@ -1,873 +1,873
1 import os
1 import os
2 import time
2 import time
3 import datetime
3 import datetime
4
4
5 import numpy
5 import numpy
6 import h5py
6 import h5py
7
7
8 import schainpy.admin
8 import schainpy.admin
9 from schainpy.model.data.jrodata import *
9 from schainpy.model.data.jrodata import *
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
10 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
11 from schainpy.model.io.jroIO_base import *
11 from schainpy.model.io.jroIO_base import *
12 from schainpy.utils import log
12 from schainpy.utils import log
13
13
14
14
15 class HDFReader(Reader, ProcessingUnit):
15 class HDFReader(Reader, ProcessingUnit):
16 """Processing unit to read HDF5 format files
16 """Processing unit to read HDF5 format files
17
17
18 This unit reads HDF5 files created with `HDFWriter` operation contains
18 This unit reads HDF5 files created with `HDFWriter` operation contains
19 by default two groups Data and Metadata all variables would be saved as `dataOut`
19 by default two groups Data and Metadata all variables would be saved as `dataOut`
20 attributes.
20 attributes.
21 It is possible to read any HDF5 file by given the structure in the `description`
21 It is possible to read any HDF5 file by given the structure in the `description`
22 parameter, also you can add extra values to metadata with the parameter `extras`.
22 parameter, also you can add extra values to metadata with the parameter `extras`.
23
23
24 Parameters:
24 Parameters:
25 -----------
25 -----------
26 path : str
26 path : str
27 Path where files are located.
27 Path where files are located.
28 startDate : date
28 startDate : date
29 Start date of the files
29 Start date of the files
30 endDate : list
30 endDate : list
31 End date of the files
31 End date of the files
32 startTime : time
32 startTime : time
33 Start time of the files
33 Start time of the files
34 endTime : time
34 endTime : time
35 End time of the files
35 End time of the files
36 description : dict, optional
36 description : dict, optional
37 Dictionary with the description of the HDF5 file
37 Dictionary with the description of the HDF5 file
38 extras : dict, optional
38 extras : dict, optional
39 Dictionary with extra metadata to be be added to `dataOut`
39 Dictionary with extra metadata to be be added to `dataOut`
40
40
41 Examples
41 Examples
42 --------
42 --------
43
43
44 desc = {
44 desc = {
45 'Data': {
45 'Data': {
46 'data_output': ['u', 'v', 'w'],
46 'data_output': ['u', 'v', 'w'],
47 'utctime': 'timestamps',
47 'utctime': 'timestamps',
48 } ,
48 } ,
49 'Metadata': {
49 'Metadata': {
50 'heightList': 'heights'
50 'heightList': 'heights'
51 }
51 }
52 }
52 }
53
53
54 desc = {
54 desc = {
55 'Data': {
55 'Data': {
56 'data_output': 'winds',
56 'data_output': 'winds',
57 'utctime': 'timestamps'
57 'utctime': 'timestamps'
58 },
58 },
59 'Metadata': {
59 'Metadata': {
60 'heightList': 'heights'
60 'heightList': 'heights'
61 }
61 }
62 }
62 }
63
63
64 extras = {
64 extras = {
65 'timeZone': 300
65 'timeZone': 300
66 }
66 }
67
67
68 reader = project.addReadUnit(
68 reader = project.addReadUnit(
69 name='HDFReader',
69 name='HDFReader',
70 path='/path/to/files',
70 path='/path/to/files',
71 startDate='2019/01/01',
71 startDate='2019/01/01',
72 endDate='2019/01/31',
72 endDate='2019/01/31',
73 startTime='00:00:00',
73 startTime='00:00:00',
74 endTime='23:59:59',
74 endTime='23:59:59',
75 # description=json.dumps(desc),
75 # description=json.dumps(desc),
76 # extras=json.dumps(extras),
76 # extras=json.dumps(extras),
77 )
77 )
78
78
79 """
79 """
80
80
81 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
81 __attrs__ = ['path', 'startDate', 'endDate', 'startTime', 'endTime', 'description', 'extras']
82
82
83 def __init__(self):
83 def __init__(self):
84 ProcessingUnit.__init__(self)
84 ProcessingUnit.__init__(self)
85 self.dataOut = Parameters()
85 self.dataOut = Parameters()
86 self.ext = ".hdf5"
86 self.ext = ".hdf5"
87 self.optchar = "D"
87 self.optchar = "D"
88 self.meta = {}
88 self.meta = {}
89 self.data = {}
89 self.data = {}
90 self.open_file = h5py.File
90 self.open_file = h5py.File
91 self.open_mode = 'r'
91 self.open_mode = 'r'
92 self.description = {}
92 self.description = {}
93 self.extras = {}
93 self.extras = {}
94 self.filefmt = "*%Y%j***"
94 self.filefmt = "*%Y%j***"
95 self.folderfmt = "*%Y%j"
95 self.folderfmt = "*%Y%j"
96 self.utcoffset = 0
96 self.utcoffset = 0
97
97
98 def setup(self, **kwargs):
98 def setup(self, **kwargs):
99
99
100 self.set_kwargs(**kwargs)
100 self.set_kwargs(**kwargs)
101 if not self.ext.startswith('.'):
101 if not self.ext.startswith('.'):
102 self.ext = '.{}'.format(self.ext)
102 self.ext = '.{}'.format(self.ext)
103
103
104 if self.online:
104 if self.online:
105 log.log("Searching files in online mode...", self.name)
105 log.log("Searching files in online mode...", self.name)
106
106
107 for nTries in range(self.nTries):
107 for nTries in range(self.nTries):
108 fullpath = self.searchFilesOnLine(self.path, self.startDate,
108 fullpath = self.searchFilesOnLine(self.path, self.startDate,
109 self.endDate, self.expLabel, self.ext, self.walk,
109 self.endDate, self.expLabel, self.ext, self.walk,
110 self.filefmt, self.folderfmt)
110 self.filefmt, self.folderfmt)
111 try:
111 try:
112 fullpath = next(fullpath)
112 fullpath = next(fullpath)
113 except:
113 except:
114 fullpath = None
114 fullpath = None
115
115
116 if fullpath:
116 if fullpath:
117 break
117 break
118
118
119 log.warning(
119 log.warning(
120 'Waiting {} sec for a valid file in {}: try {} ...'.format(
120 'Waiting {} sec for a valid file in {}: try {} ...'.format(
121 self.delay, self.path, nTries + 1),
121 self.delay, self.path, nTries + 1),
122 self.name)
122 self.name)
123 time.sleep(self.delay)
123 time.sleep(self.delay)
124
124
125 if not(fullpath):
125 if not(fullpath):
126 raise schainpy.admin.SchainError(
126 raise schainpy.admin.SchainError(
127 'There isn\'t any valid file in {}'.format(self.path))
127 'There isn\'t any valid file in {}'.format(self.path))
128
128
129 pathname, filename = os.path.split(fullpath)
129 pathname, filename = os.path.split(fullpath)
130 self.year = int(filename[1:5])
130 self.year = int(filename[1:5])
131 self.doy = int(filename[5:8])
131 self.doy = int(filename[5:8])
132 self.set = int(filename[8:11]) - 1
132 self.set = int(filename[8:11]) - 1
133 else:
133 else:
134 log.log("Searching files in {}".format(self.path), self.name)
134 log.log("Searching files in {}".format(self.path), self.name)
135 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
135 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
136 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
136 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
137
137
138 self.setNextFile()
138 self.setNextFile()
139
139
140 return
140 return
141
141
142 def readFirstHeader(self):
142 def readFirstHeader(self):
143 '''Read metadata and data'''
143 '''Read metadata and data'''
144
144
145 self.__readMetadata()
145 self.__readMetadata()
146 self.__readData()
146 self.__readData()
147 self.__setBlockList()
147 self.__setBlockList()
148
149 if 'type' in self.meta:
150 self.dataOut = eval(self.meta['type'])()
151
148
152 for attr in self.meta:
149 for attr in self.meta:
153 setattr(self.dataOut, attr, self.meta[attr])
150 setattr(self.dataOut, attr, self.meta[attr])
154
151
155 self.blockIndex = 0
152 self.blockIndex = 0
156
153
157 return
154 return
158
155
159 def __setBlockList(self):
156 def __setBlockList(self):
160 '''
157 '''
161 Selects the data within the times defined
158 Selects the data within the times defined
162
159
163 self.fp
160 self.fp
164 self.startTime
161 self.startTime
165 self.endTime
162 self.endTime
166 self.blockList
163 self.blockList
167 self.blocksPerFile
164 self.blocksPerFile
168
165
169 '''
166 '''
170
167
171 startTime = self.startTime
168 startTime = self.startTime
172 endTime = self.endTime
169 endTime = self.endTime
173 thisUtcTime = self.data['utctime'] + self.utcoffset
170 thisUtcTime = self.data['utctime'] + self.utcoffset
174 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
171 self.interval = numpy.min(thisUtcTime[1:] - thisUtcTime[:-1])
175 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
172 thisDatetime = datetime.datetime.utcfromtimestamp(thisUtcTime[0])
176
173
177 thisDate = thisDatetime.date()
174 thisDate = thisDatetime.date()
178 thisTime = thisDatetime.time()
175 thisTime = thisDatetime.time()
179
176
180 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
177 startUtcTime = (datetime.datetime.combine(thisDate, startTime) - datetime.datetime(1970, 1, 1)).total_seconds()
181 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
178 endUtcTime = (datetime.datetime.combine(thisDate, endTime) - datetime.datetime(1970, 1, 1)).total_seconds()
182
179
183 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
180 ind = numpy.where(numpy.logical_and(thisUtcTime >= startUtcTime, thisUtcTime < endUtcTime))[0]
184
181
185 self.blockList = ind
182 self.blockList = ind
186 self.blocksPerFile = len(ind)
183 self.blocksPerFile = len(ind)
187 return
184 return
188
185
189 def __readMetadata(self):
186 def __readMetadata(self):
190 '''
187 '''
191 Reads Metadata
188 Reads Metadata
192 '''
189 '''
193
190
194 meta = {}
191 meta = {}
195
192
196 if self.description:
193 if self.description:
197 for key, value in self.description['Metadata'].items():
194 for key, value in self.description['Metadata'].items():
198 meta[key] = self.fp[value][()]
195 meta[key] = self.fp[value][()]
199 else:
196 else:
200 grp = self.fp['Metadata']
197 grp = self.fp['Metadata']
201 for name in grp:
198 for name in grp:
202 meta[name] = grp[name][()]
199 meta[name] = grp[name][()]
203
200
204 if self.extras:
201 if self.extras:
205 for key, value in self.extras.items():
202 for key, value in self.extras.items():
206 meta[key] = value
203 meta[key] = value
207 self.meta = meta
204 self.meta = meta
208
205
209 return
206 return
210
207
211 def __readData(self):
208 def __readData(self):
212
209
213 data = {}
210 data = {}
214
211
215 if self.description:
212 if self.description:
216 for key, value in self.description['Data'].items():
213 for key, value in self.description['Data'].items():
217 if isinstance(value, str):
214 if isinstance(value, str):
218 if isinstance(self.fp[value], h5py.Dataset):
215 if isinstance(self.fp[value], h5py.Dataset):
219 data[key] = self.fp[value][()]
216 data[key] = self.fp[value][()]
220 elif isinstance(self.fp[value], h5py.Group):
217 elif isinstance(self.fp[value], h5py.Group):
221 array = []
218 array = []
222 for ch in self.fp[value]:
219 for ch in self.fp[value]:
223 array.append(self.fp[value][ch][()])
220 array.append(self.fp[value][ch][()])
224 data[key] = numpy.array(array)
221 data[key] = numpy.array(array)
225 elif isinstance(value, list):
222 elif isinstance(value, list):
226 array = []
223 array = []
227 for ch in value:
224 for ch in value:
228 array.append(self.fp[ch][()])
225 array.append(self.fp[ch][()])
229 data[key] = numpy.array(array)
226 data[key] = numpy.array(array)
230 else:
227 else:
231 grp = self.fp['Data']
228 grp = self.fp['Data']
232 for name in grp:
229 for name in grp:
233 if isinstance(grp[name], h5py.Dataset):
230 if isinstance(grp[name], h5py.Dataset):
234 array = grp[name][()]
231 array = grp[name][()]
235 elif isinstance(grp[name], h5py.Group):
232 elif isinstance(grp[name], h5py.Group):
236 array = []
233 array = []
237 for ch in grp[name]:
234 for ch in grp[name]:
238 array.append(grp[name][ch][()])
235 array.append(grp[name][ch][()])
239 array = numpy.array(array)
236 array = numpy.array(array)
240 else:
237 else:
241 log.warning('Unknown type: {}'.format(name))
238 log.warning('Unknown type: {}'.format(name))
242
239
243 if name in self.description:
240 if name in self.description:
244 key = self.description[name]
241 key = self.description[name]
245 else:
242 else:
246 key = name
243 key = name
247 data[key] = array
244 data[key] = array
248
245
249 self.data = data
246 self.data = data
250 return
247 return
251
248
252 def getData(self):
249 def getData(self):
253
250
254 for attr in self.data:
251 for attr in self.data:
255 if self.data[attr].ndim == 1:
252 if self.data[attr].ndim == 1:
256 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
253 setattr(self.dataOut, attr, self.data[attr][self.blockIndex])
257 else:
254 else:
258 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
255 setattr(self.dataOut, attr, self.data[attr][:, self.blockIndex])
259
256
260 self.dataOut.flagNoData = False
257 self.dataOut.flagNoData = False
261 self.blockIndex += 1
258 self.blockIndex += 1
262
259
263 log.log("Block No. {}/{} -> {}".format(
260 log.log("Block No. {}/{} -> {}".format(
264 self.blockIndex,
261 self.blockIndex,
265 self.blocksPerFile,
262 self.blocksPerFile,
266 self.dataOut.datatime.ctime()), self.name)
263 self.dataOut.datatime.ctime()), self.name)
267
264
268 return
265 return
269
266
270 def run(self, **kwargs):
267 def run(self, **kwargs):
271
268
272 if not(self.isConfig):
269 if not(self.isConfig):
273 self.setup(**kwargs)
270 self.setup(**kwargs)
274 self.isConfig = True
271 self.isConfig = True
275
272
276 if self.blockIndex == self.blocksPerFile:
273 if self.blockIndex == self.blocksPerFile:
277 self.setNextFile()
274 self.setNextFile()
278
275
279 self.getData()
276 self.getData()
280
277
278 if 'type' in self.meta:
279 self.dataOut.type = self.meta['type'].decode('utf-8')
280
281 return
281 return
282
282
283 @MPDecorator
283 @MPDecorator
284 class HDFWriter(Operation):
284 class HDFWriter(Operation):
285 """Operation to write HDF5 files.
285 """Operation to write HDF5 files.
286
286
287 The HDF5 file contains by default two groups Data and Metadata where
287 The HDF5 file contains by default two groups Data and Metadata where
288 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
288 you can save any `dataOut` attribute specified by `dataList` and `metadataList`
289 parameters, data attributes are normaly time dependent where the metadata
289 parameters, data attributes are normaly time dependent where the metadata
290 are not.
290 are not.
291 It is possible to customize the structure of the HDF5 file with the
291 It is possible to customize the structure of the HDF5 file with the
292 optional description parameter see the examples.
292 optional description parameter see the examples.
293
293
294 Parameters:
294 Parameters:
295 -----------
295 -----------
296 path : str
296 path : str
297 Path where files will be saved.
297 Path where files will be saved.
298 blocksPerFile : int
298 blocksPerFile : int
299 Number of blocks per file
299 Number of blocks per file
300 metadataList : list
300 metadataList : list
301 List of the dataOut attributes that will be saved as metadata
301 List of the dataOut attributes that will be saved as metadata
302 dataList : int
302 dataList : int
303 List of the dataOut attributes that will be saved as data
303 List of the dataOut attributes that will be saved as data
304 setType : bool
304 setType : bool
305 If True the name of the files corresponds to the timestamp of the data
305 If True the name of the files corresponds to the timestamp of the data
306 description : dict, optional
306 description : dict, optional
307 Dictionary with the desired description of the HDF5 file
307 Dictionary with the desired description of the HDF5 file
308
308
309 Examples
309 Examples
310 --------
310 --------
311
311
312 desc = {
312 desc = {
313 'data_output': {'winds': ['z', 'w', 'v']},
313 'data_output': {'winds': ['z', 'w', 'v']},
314 'utctime': 'timestamps',
314 'utctime': 'timestamps',
315 'heightList': 'heights'
315 'heightList': 'heights'
316 }
316 }
317 desc = {
317 desc = {
318 'data_output': ['z', 'w', 'v'],
318 'data_output': ['z', 'w', 'v'],
319 'utctime': 'timestamps',
319 'utctime': 'timestamps',
320 'heightList': 'heights'
320 'heightList': 'heights'
321 }
321 }
322 desc = {
322 desc = {
323 'Data': {
323 'Data': {
324 'data_output': 'winds',
324 'data_output': 'winds',
325 'utctime': 'timestamps'
325 'utctime': 'timestamps'
326 },
326 },
327 'Metadata': {
327 'Metadata': {
328 'heightList': 'heights'
328 'heightList': 'heights'
329 }
329 }
330 }
330 }
331
331
332 writer = proc_unit.addOperation(name='HDFWriter')
332 writer = proc_unit.addOperation(name='HDFWriter')
333 writer.addParameter(name='path', value='/path/to/file')
333 writer.addParameter(name='path', value='/path/to/file')
334 writer.addParameter(name='blocksPerFile', value='32')
334 writer.addParameter(name='blocksPerFile', value='32')
335 writer.addParameter(name='metadataList', value='heightList,timeZone')
335 writer.addParameter(name='metadataList', value='heightList,timeZone')
336 writer.addParameter(name='dataList',value='data_output,utctime')
336 writer.addParameter(name='dataList',value='data_output,utctime')
337 # writer.addParameter(name='description',value=json.dumps(desc))
337 # writer.addParameter(name='description',value=json.dumps(desc))
338
338
339 """
339 """
340
340
341 ext = ".hdf5"
341 ext = ".hdf5"
342 optchar = "D"
342 optchar = "D"
343 filename = None
343 filename = None
344 path = None
344 path = None
345 setFile = None
345 setFile = None
346 fp = None
346 fp = None
347 firsttime = True
347 firsttime = True
348 # Configurations
348 # Configurations
349 blocksPerFile = None
349 blocksPerFile = None
350 blockIndex = None
350 blockIndex = None
351 dataOut = None
351 dataOut = None
352 # Data Arrays
352 # Data Arrays
353 dataList = None
353 dataList = None
354 metadataList = None
354 metadataList = None
355 currentDay = None
355 currentDay = None
356 lastTime = None
356 lastTime = None
357
357
358 def __init__(self):
358 def __init__(self):
359
359
360 Operation.__init__(self)
360 Operation.__init__(self)
361 return
361 return
362
362
363 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None):
363 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataList=None, setType=None, description=None):
364 self.path = path
364 self.path = path
365 self.blocksPerFile = blocksPerFile
365 self.blocksPerFile = blocksPerFile
366 self.metadataList = metadataList
366 self.metadataList = metadataList
367 self.dataList = [s.strip() for s in dataList]
367 self.dataList = [s.strip() for s in dataList]
368 self.setType = setType
368 self.setType = setType
369 self.description = description
369 self.description = description
370
370
371 if self.metadataList is None:
371 if self.metadataList is None:
372 self.metadataList = self.dataOut.metadata_list
372 self.metadataList = self.dataOut.metadata_list
373
373
374 tableList = []
374 tableList = []
375 dsList = []
375 dsList = []
376
376
377 for i in range(len(self.dataList)):
377 for i in range(len(self.dataList)):
378 dsDict = {}
378 dsDict = {}
379 if hasattr(self.dataOut, self.dataList[i]):
379 if hasattr(self.dataOut, self.dataList[i]):
380 dataAux = getattr(self.dataOut, self.dataList[i])
380 dataAux = getattr(self.dataOut, self.dataList[i])
381 dsDict['variable'] = self.dataList[i]
381 dsDict['variable'] = self.dataList[i]
382 else:
382 else:
383 log.warning('Attribute {} not found in dataOut', self.name)
383 log.warning('Attribute {} not found in dataOut', self.name)
384 continue
384 continue
385
385
386 if dataAux is None:
386 if dataAux is None:
387 continue
387 continue
388 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
388 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
389 dsDict['nDim'] = 0
389 dsDict['nDim'] = 0
390 else:
390 else:
391 dsDict['nDim'] = len(dataAux.shape)
391 dsDict['nDim'] = len(dataAux.shape)
392 dsDict['shape'] = dataAux.shape
392 dsDict['shape'] = dataAux.shape
393 dsDict['dsNumber'] = dataAux.shape[0]
393 dsDict['dsNumber'] = dataAux.shape[0]
394 dsDict['dtype'] = dataAux.dtype
394 dsDict['dtype'] = dataAux.dtype
395
395
396 dsList.append(dsDict)
396 dsList.append(dsDict)
397
397
398 self.dsList = dsList
398 self.dsList = dsList
399 self.currentDay = self.dataOut.datatime.date()
399 self.currentDay = self.dataOut.datatime.date()
400
400
401 def timeFlag(self):
401 def timeFlag(self):
402 currentTime = self.dataOut.utctime
402 currentTime = self.dataOut.utctime
403 timeTuple = time.localtime(currentTime)
403 timeTuple = time.localtime(currentTime)
404 dataDay = timeTuple.tm_yday
404 dataDay = timeTuple.tm_yday
405
405
406 if self.lastTime is None:
406 if self.lastTime is None:
407 self.lastTime = currentTime
407 self.lastTime = currentTime
408 self.currentDay = dataDay
408 self.currentDay = dataDay
409 return False
409 return False
410
410
411 timeDiff = currentTime - self.lastTime
411 timeDiff = currentTime - self.lastTime
412
412
413 # Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
413 # Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
414 if dataDay != self.currentDay:
414 if dataDay != self.currentDay:
415 self.currentDay = dataDay
415 self.currentDay = dataDay
416 return True
416 return True
417 elif timeDiff > 3 * 60 * 60:
417 elif timeDiff > 3 * 60 * 60:
418 self.lastTime = currentTime
418 self.lastTime = currentTime
419 return True
419 return True
420 else:
420 else:
421 self.lastTime = currentTime
421 self.lastTime = currentTime
422 return False
422 return False
423
423
424 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
424 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
425 dataList=[], setType=None, description={}):
425 dataList=[], setType=None, description={}):
426
426
427 self.dataOut = dataOut
427 self.dataOut = dataOut
428 if not(self.isConfig):
428 if not(self.isConfig):
429 self.setup(path=path, blocksPerFile=blocksPerFile,
429 self.setup(path=path, blocksPerFile=blocksPerFile,
430 metadataList=metadataList, dataList=dataList,
430 metadataList=metadataList, dataList=dataList,
431 setType=setType, description=description)
431 setType=setType, description=description)
432
432
433 self.isConfig = True
433 self.isConfig = True
434 self.setNextFile()
434 self.setNextFile()
435
435
436 self.putData()
436 self.putData()
437 return
437 return
438
438
439 def setNextFile(self):
439 def setNextFile(self):
440
440
441 ext = self.ext
441 ext = self.ext
442 path = self.path
442 path = self.path
443 setFile = self.setFile
443 setFile = self.setFile
444
444
445 timeTuple = time.localtime(self.dataOut.utctime)
445 timeTuple = time.localtime(self.dataOut.utctime)
446 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
446 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
447 fullpath = os.path.join(path, subfolder)
447 fullpath = os.path.join(path, subfolder)
448
448
449 if os.path.exists(fullpath):
449 if os.path.exists(fullpath):
450 filesList = os.listdir(fullpath)
450 filesList = os.listdir(fullpath)
451 filesList = [k for k in filesList if k.startswith(self.optchar)]
451 filesList = [k for k in filesList if k.startswith(self.optchar)]
452 if len(filesList) > 0:
452 if len(filesList) > 0:
453 filesList = sorted(filesList, key=str.lower)
453 filesList = sorted(filesList, key=str.lower)
454 filen = filesList[-1]
454 filen = filesList[-1]
455 # el filename debera tener el siguiente formato
455 # el filename debera tener el siguiente formato
456 # 0 1234 567 89A BCDE (hex)
456 # 0 1234 567 89A BCDE (hex)
457 # x YYYY DDD SSS .ext
457 # x YYYY DDD SSS .ext
458 if isNumber(filen[8:11]):
458 if isNumber(filen[8:11]):
459 setFile = int(filen[8:11]) # inicializo mi contador de seteo al seteo del ultimo file
459 setFile = int(filen[8:11]) # inicializo mi contador de seteo al seteo del ultimo file
460 else:
460 else:
461 setFile = -1
461 setFile = -1
462 else:
462 else:
463 setFile = -1 # inicializo mi contador de seteo
463 setFile = -1 # inicializo mi contador de seteo
464 else:
464 else:
465 os.makedirs(fullpath)
465 os.makedirs(fullpath)
466 setFile = -1 # inicializo mi contador de seteo
466 setFile = -1 # inicializo mi contador de seteo
467
467
468 if self.setType is None:
468 if self.setType is None:
469 setFile += 1
469 setFile += 1
470 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
470 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
471 timeTuple.tm_year,
471 timeTuple.tm_year,
472 timeTuple.tm_yday,
472 timeTuple.tm_yday,
473 setFile,
473 setFile,
474 ext)
474 ext)
475 else:
475 else:
476 setFile = timeTuple.tm_hour * 60 + timeTuple.tm_min
476 setFile = timeTuple.tm_hour * 60 + timeTuple.tm_min
477 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
477 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
478 timeTuple.tm_year,
478 timeTuple.tm_year,
479 timeTuple.tm_yday,
479 timeTuple.tm_yday,
480 setFile,
480 setFile,
481 ext)
481 ext)
482
482
483 self.filename = os.path.join(path, subfolder, file)
483 self.filename = os.path.join(path, subfolder, file)
484
484
485 # Setting HDF5 File
485 # Setting HDF5 File
486 self.fp = h5py.File(self.filename, 'w')
486 self.fp = h5py.File(self.filename, 'w')
487 # write metadata
487 # write metadata
488 self.writeMetadata(self.fp)
488 self.writeMetadata(self.fp)
489 # Write data
489 # Write data
490 self.writeData(self.fp)
490 self.writeData(self.fp)
491
491
492 def getLabel(self, name, x=None):
492 def getLabel(self, name, x=None):
493
493
494 if x is None:
494 if x is None:
495 if 'Data' in self.description:
495 if 'Data' in self.description:
496 data = self.description['Data']
496 data = self.description['Data']
497 if 'Metadata' in self.description:
497 if 'Metadata' in self.description:
498 data.update(self.description['Metadata'])
498 data.update(self.description['Metadata'])
499 else:
499 else:
500 data = self.description
500 data = self.description
501 if name in data:
501 if name in data:
502 if isinstance(data[name], str):
502 if isinstance(data[name], str):
503 return data[name]
503 return data[name]
504 elif isinstance(data[name], list):
504 elif isinstance(data[name], list):
505 return None
505 return None
506 elif isinstance(data[name], dict):
506 elif isinstance(data[name], dict):
507 for key, value in data[name].items():
507 for key, value in data[name].items():
508 return key
508 return key
509 return name
509 return name
510 else:
510 else:
511 if 'Metadata' in self.description:
511 if 'Metadata' in self.description:
512 meta = self.description['Metadata']
512 meta = self.description['Metadata']
513 else:
513 else:
514 meta = self.description
514 meta = self.description
515 if name in meta:
515 if name in meta:
516 if isinstance(meta[name], list):
516 if isinstance(meta[name], list):
517 return meta[name][x]
517 return meta[name][x]
518 elif isinstance(meta[name], dict):
518 elif isinstance(meta[name], dict):
519 for key, value in meta[name].items():
519 for key, value in meta[name].items():
520 return value[x]
520 return value[x]
521 if 'cspc' in name:
521 if 'cspc' in name:
522 return 'pair{:02d}'.format(x)
522 return 'pair{:02d}'.format(x)
523 else:
523 else:
524 return 'channel{:02d}'.format(x)
524 return 'channel{:02d}'.format(x)
525
525
526 def writeMetadata(self, fp):
526 def writeMetadata(self, fp):
527
527
528 if self.description:
528 if self.description:
529 if 'Metadata' in self.description:
529 if 'Metadata' in self.description:
530 grp = fp.create_group('Metadata')
530 grp = fp.create_group('Metadata')
531 else:
531 else:
532 grp = fp
532 grp = fp
533 else:
533 else:
534 grp = fp.create_group('Metadata')
534 grp = fp.create_group('Metadata')
535
535
536 for i in range(len(self.metadataList)):
536 for i in range(len(self.metadataList)):
537 if not hasattr(self.dataOut, self.metadataList[i]):
537 if not hasattr(self.dataOut, self.metadataList[i]):
538 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
538 log.warning('Metadata: `{}` not found'.format(self.metadataList[i]), self.name)
539 continue
539 continue
540 value = getattr(self.dataOut, self.metadataList[i])
540 value = getattr(self.dataOut, self.metadataList[i])
541 if isinstance(value, bool):
541 if isinstance(value, bool):
542 if value is True:
542 if value is True:
543 value = 1
543 value = 1
544 else:
544 else:
545 value = 0
545 value = 0
546 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
546 grp.create_dataset(self.getLabel(self.metadataList[i]), data=value)
547 return
547 return
548
548
549 def writeData(self, fp):
549 def writeData(self, fp):
550
550
551 if self.description:
551 if self.description:
552 if 'Data' in self.description:
552 if 'Data' in self.description:
553 grp = fp.create_group('Data')
553 grp = fp.create_group('Data')
554 else:
554 else:
555 grp = fp
555 grp = fp
556 else:
556 else:
557 grp = fp.create_group('Data')
557 grp = fp.create_group('Data')
558
558
559 dtsets = []
559 dtsets = []
560 data = []
560 data = []
561
561
562 for dsInfo in self.dsList:
562 for dsInfo in self.dsList:
563 if dsInfo['nDim'] == 0:
563 if dsInfo['nDim'] == 0:
564 ds = grp.create_dataset(
564 ds = grp.create_dataset(
565 self.getLabel(dsInfo['variable']),
565 self.getLabel(dsInfo['variable']),
566 (self.blocksPerFile,),
566 (self.blocksPerFile,),
567 chunks=True,
567 chunks=True,
568 dtype=numpy.float64)
568 dtype=numpy.float64)
569 dtsets.append(ds)
569 dtsets.append(ds)
570 data.append((dsInfo['variable'], -1))
570 data.append((dsInfo['variable'], -1))
571 else:
571 else:
572 label = self.getLabel(dsInfo['variable'])
572 label = self.getLabel(dsInfo['variable'])
573 if label is not None:
573 if label is not None:
574 sgrp = grp.create_group(label)
574 sgrp = grp.create_group(label)
575 else:
575 else:
576 sgrp = grp
576 sgrp = grp
577 for i in range(dsInfo['dsNumber']):
577 for i in range(dsInfo['dsNumber']):
578 ds = sgrp.create_dataset(
578 ds = sgrp.create_dataset(
579 self.getLabel(dsInfo['variable'], i),
579 self.getLabel(dsInfo['variable'], i),
580 (self.blocksPerFile,) + dsInfo['shape'][1:],
580 (self.blocksPerFile,) + dsInfo['shape'][1:],
581 chunks=True,
581 chunks=True,
582 dtype=dsInfo['dtype'])
582 dtype=dsInfo['dtype'])
583 dtsets.append(ds)
583 dtsets.append(ds)
584 data.append((dsInfo['variable'], i))
584 data.append((dsInfo['variable'], i))
585 fp.flush()
585 fp.flush()
586
586
587 log.log('Creating file: {}'.format(fp.filename), self.name)
587 log.log('Creating file: {}'.format(fp.filename), self.name)
588
588
589 self.ds = dtsets
589 self.ds = dtsets
590 self.data = data
590 self.data = data
591 self.firsttime = True
591 self.firsttime = True
592 self.blockIndex = 0
592 self.blockIndex = 0
593 return
593 return
594
594
595 def putData(self):
595 def putData(self):
596
596
597 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
597 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
598 self.closeFile()
598 self.closeFile()
599 self.setNextFile()
599 self.setNextFile()
600
600
601 for i, ds in enumerate(self.ds):
601 for i, ds in enumerate(self.ds):
602 attr, ch = self.data[i]
602 attr, ch = self.data[i]
603 if ch == -1:
603 if ch == -1:
604 ds[self.blockIndex] = getattr(self.dataOut, attr)
604 ds[self.blockIndex] = getattr(self.dataOut, attr)
605 else:
605 else:
606 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
606 ds[self.blockIndex] = getattr(self.dataOut, attr)[ch]
607
607
608 self.fp.flush()
608 self.fp.flush()
609 self.blockIndex += 1
609 self.blockIndex += 1
610 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
610 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
611
611
612 return
612 return
613
613
614 def closeFile(self):
614 def closeFile(self):
615
615
616 if self.blockIndex != self.blocksPerFile:
616 if self.blockIndex != self.blocksPerFile:
617 for ds in self.ds:
617 for ds in self.ds:
618 ds.resize(self.blockIndex, axis=0)
618 ds.resize(self.blockIndex, axis=0)
619
619
620 if self.fp:
620 if self.fp:
621 self.fp.flush()
621 self.fp.flush()
622 self.fp.close()
622 self.fp.close()
623
623
624 def close(self):
624 def close(self):
625
625
626 self.closeFile()
626 self.closeFile()
627
627
628
628
629 @MPDecorator
629 @MPDecorator
630 class ASCIIWriter(Operation):
630 class ASCIIWriter(Operation):
631 """Operation to write data in ascii files.
631 """Operation to write data in ascii files.
632
632
633 Parameters:
633 Parameters:
634 -----------
634 -----------
635 path : str
635 path : str
636 Path where files will be saved.
636 Path where files will be saved.
637 blocksPerFile : int
637 blocksPerFile : int
638 Number of blocks per file
638 Number of blocks per file
639 metadataList : list
639 metadataList : list
640 List of the dataOut attributes that will be saved as metadata
640 List of the dataOut attributes that will be saved as metadata
641 dataDict : dict
641 dataDict : dict
642 Dictionary with the varaibles to be saved
642 Dictionary with the varaibles to be saved
643 setType : bool
643 setType : bool
644 If True the name of the files corresponds to the timestamp of the data
644 If True the name of the files corresponds to the timestamp of the data
645
645
646 Examples
646 Examples
647 --------
647 --------
648
648
649 data = {
649 data = {
650 'data_output': ['z', 'w', 'v'],
650 'data_output': ['z', 'w', 'v'],
651 'utctime': 'time',
651 'utctime': 'time',
652 'heightList': 'height'
652 'heightList': 'height'
653 }
653 }
654
654
655 writer = proc_unit.addOperation(name='ASCIIWriter')
655 writer = proc_unit.addOperation(name='ASCIIWriter')
656 writer.addParameter(name='path', value='/path/to/file')
656 writer.addParameter(name='path', value='/path/to/file')
657 writer.addParameter(name='blocksPerFile', value='32')
657 writer.addParameter(name='blocksPerFile', value='32')
658 writer.addParameter(name='dataDict',value=json.dumps(data))
658 writer.addParameter(name='dataDict',value=json.dumps(data))
659
659
660 """
660 """
661
661
662 ext = ".txt"
662 ext = ".txt"
663 optchar = "D"
663 optchar = "D"
664 filename = None
664 filename = None
665 path = None
665 path = None
666 setFile = None
666 setFile = None
667 fp = None
667 fp = None
668 firsttime = True
668 firsttime = True
669 # Configurations
669 # Configurations
670 blocksPerFile = None
670 blocksPerFile = None
671 blockIndex = None
671 blockIndex = None
672 dataOut = None
672 dataOut = None
673 # Data Arrays
673 # Data Arrays
674 dataDict = None
674 dataDict = None
675 metadataList = None
675 metadataList = None
676 currentDay = None
676 currentDay = None
677 lastTime = None
677 lastTime = None
678 localtime = True
678 localtime = True
679
679
680 def __init__(self):
680 def __init__(self):
681
681
682 Operation.__init__(self)
682 Operation.__init__(self)
683 return
683 return
684
684
685 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataDict=None, setType=None, localtime=True):
685 def setup(self, path=None, blocksPerFile=10, metadataList=None, dataDict=None, setType=None, localtime=True):
686 self.path = path
686 self.path = path
687 self.blocksPerFile = blocksPerFile
687 self.blocksPerFile = blocksPerFile
688 self.metadataList = metadataList
688 self.metadataList = metadataList
689 self.dataDict = dataDict
689 self.dataDict = dataDict
690 self.setType = setType
690 self.setType = setType
691 self.localtime = localtime
691 self.localtime = localtime
692
692
693 if self.metadataList is None:
693 if self.metadataList is None:
694 self.metadataList = self.dataOut.metadata_list
694 self.metadataList = self.dataOut.metadata_list
695
695
696 dsList = []
696 dsList = []
697
697
698 for key, value in self.dataDict.items():
698 for key, value in self.dataDict.items():
699 dsDict = {}
699 dsDict = {}
700 if hasattr(self.dataOut, key):
700 if hasattr(self.dataOut, key):
701 dataAux = getattr(self.dataOut, key)
701 dataAux = getattr(self.dataOut, key)
702 dsDict['variable'] = key
702 dsDict['variable'] = key
703 else:
703 else:
704 log.warning('Attribute {} not found in dataOut', self.name)
704 log.warning('Attribute {} not found in dataOut', self.name)
705 continue
705 continue
706
706
707 if dataAux is None:
707 if dataAux is None:
708 continue
708 continue
709 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
709 elif isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
710 dsDict['nDim'] = 0
710 dsDict['nDim'] = 0
711 else:
711 else:
712 dsDict['nDim'] = len(dataAux.shape)
712 dsDict['nDim'] = len(dataAux.shape)
713 dsDict['shape'] = dataAux.shape
713 dsDict['shape'] = dataAux.shape
714 dsDict['dsNumber'] = dataAux.shape[0]
714 dsDict['dsNumber'] = dataAux.shape[0]
715 dsDict['dtype'] = dataAux.dtype
715 dsDict['dtype'] = dataAux.dtype
716
716
717 dsList.append(dsDict)
717 dsList.append(dsDict)
718 self.dsList = dsList
718 self.dsList = dsList
719 self.currentDay = self.dataOut.datatime.date()
719 self.currentDay = self.dataOut.datatime.date()
720
720
721 def timeFlag(self):
721 def timeFlag(self):
722 currentTime = self.dataOut.utctime
722 currentTime = self.dataOut.utctime
723 if self.localtime:
723 if self.localtime:
724 timeTuple = time.localtime(currentTime)
724 timeTuple = time.localtime(currentTime)
725 else:
725 else:
726 timeTuple = time.gmtime(currentTime)
726 timeTuple = time.gmtime(currentTime)
727
727
728 dataDay = timeTuple.tm_yday
728 dataDay = timeTuple.tm_yday
729
729
730 if self.lastTime is None:
730 if self.lastTime is None:
731 self.lastTime = currentTime
731 self.lastTime = currentTime
732 self.currentDay = dataDay
732 self.currentDay = dataDay
733 return False
733 return False
734
734
735 timeDiff = currentTime - self.lastTime
735 timeDiff = currentTime - self.lastTime
736
736
737 # Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
737 # Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
738 if dataDay != self.currentDay:
738 if dataDay != self.currentDay:
739 self.currentDay = dataDay
739 self.currentDay = dataDay
740 return True
740 return True
741 elif timeDiff > 3 * 60 * 60:
741 elif timeDiff > 3 * 60 * 60:
742 self.lastTime = currentTime
742 self.lastTime = currentTime
743 return True
743 return True
744 else:
744 else:
745 self.lastTime = currentTime
745 self.lastTime = currentTime
746 return False
746 return False
747
747
748 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
748 def run(self, dataOut, path, blocksPerFile=10, metadataList=None,
749 dataDict={}, setType=None, localtime=True):
749 dataDict={}, setType=None, localtime=True):
750
750
751 self.dataOut = dataOut
751 self.dataOut = dataOut
752 if not(self.isConfig):
752 if not(self.isConfig):
753 self.setup(path=path, blocksPerFile=blocksPerFile,
753 self.setup(path=path, blocksPerFile=blocksPerFile,
754 metadataList=metadataList, dataDict=dataDict,
754 metadataList=metadataList, dataDict=dataDict,
755 setType=setType, localtime=localtime)
755 setType=setType, localtime=localtime)
756
756
757 self.isConfig = True
757 self.isConfig = True
758 self.setNextFile()
758 self.setNextFile()
759
759
760 self.putData()
760 self.putData()
761 return
761 return
762
762
763 def setNextFile(self):
763 def setNextFile(self):
764
764
765 ext = self.ext
765 ext = self.ext
766 path = self.path
766 path = self.path
767 setFile = self.setFile
767 setFile = self.setFile
768 if self.localtime:
768 if self.localtime:
769 timeTuple = time.localtime(self.dataOut.utctime)
769 timeTuple = time.localtime(self.dataOut.utctime)
770 else:
770 else:
771 timeTuple = time.gmtime(self.dataOut.utctime)
771 timeTuple = time.gmtime(self.dataOut.utctime)
772 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
772 subfolder = 'd%4.4d%3.3d' % (timeTuple.tm_year, timeTuple.tm_yday)
773 fullpath = os.path.join(path, subfolder)
773 fullpath = os.path.join(path, subfolder)
774
774
775 if os.path.exists(fullpath):
775 if os.path.exists(fullpath):
776 filesList = os.listdir(fullpath)
776 filesList = os.listdir(fullpath)
777 filesList = [k for k in filesList if k.startswith(self.optchar)]
777 filesList = [k for k in filesList if k.startswith(self.optchar)]
778 if len(filesList) > 0:
778 if len(filesList) > 0:
779 filesList = sorted(filesList, key=str.lower)
779 filesList = sorted(filesList, key=str.lower)
780 filen = filesList[-1]
780 filen = filesList[-1]
781 # el filename debera tener el siguiente formato
781 # el filename debera tener el siguiente formato
782 # 0 1234 567 89A BCDE (hex)
782 # 0 1234 567 89A BCDE (hex)
783 # x YYYY DDD SSS .ext
783 # x YYYY DDD SSS .ext
784 if isNumber(filen[8:11]):
784 if isNumber(filen[8:11]):
785 setFile = int(filen[8:11]) # inicializo mi contador de seteo al seteo del ultimo file
785 setFile = int(filen[8:11]) # inicializo mi contador de seteo al seteo del ultimo file
786 else:
786 else:
787 setFile = -1
787 setFile = -1
788 else:
788 else:
789 setFile = -1 # inicializo mi contador de seteo
789 setFile = -1 # inicializo mi contador de seteo
790 else:
790 else:
791 os.makedirs(fullpath)
791 os.makedirs(fullpath)
792 setFile = -1 # inicializo mi contador de seteo
792 setFile = -1 # inicializo mi contador de seteo
793
793
794 if self.setType is None:
794 if self.setType is None:
795 setFile += 1
795 setFile += 1
796 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
796 file = '%s%4.4d%3.3d%03d%s' % (self.optchar,
797 timeTuple.tm_year,
797 timeTuple.tm_year,
798 timeTuple.tm_yday,
798 timeTuple.tm_yday,
799 setFile,
799 setFile,
800 ext)
800 ext)
801 else:
801 else:
802 setFile = timeTuple.tm_hour * 60 + timeTuple.tm_min
802 setFile = timeTuple.tm_hour * 60 + timeTuple.tm_min
803 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
803 file = '%s%4.4d%3.3d%04d%s' % (self.optchar,
804 timeTuple.tm_year,
804 timeTuple.tm_year,
805 timeTuple.tm_yday,
805 timeTuple.tm_yday,
806 setFile,
806 setFile,
807 ext)
807 ext)
808
808
809 self.filename = os.path.join(path, subfolder, file)
809 self.filename = os.path.join(path, subfolder, file)
810
810
811 # Setting HDF5 File
811 # Setting HDF5 File
812 self.fp = open(self.filename, 'w')
812 self.fp = open(self.filename, 'w')
813 # write metadata
813 # write metadata
814 self.writeMetadata(self.fp)
814 self.writeMetadata(self.fp)
815 # Write data
815 # Write data
816 self.writeData(self.fp)
816 self.writeData(self.fp)
817
817
818 def writeMetadata(self, fp):
818 def writeMetadata(self, fp):
819
819
820 line = ''
820 line = ''
821 for d in self.dsList:
821 for d in self.dsList:
822 par = self.dataDict[d['variable']]
822 par = self.dataDict[d['variable']]
823 if isinstance(par, (list,tuple)):
823 if isinstance(par, (list,tuple)):
824 for p in par:
824 for p in par:
825 line += '{:>16}'.format(p)
825 line += '{:>16}'.format(p)
826 else:
826 else:
827 line += '{:>16}'.format(par)
827 line += '{:>16}'.format(par)
828
828
829 line += '\n'
829 line += '\n'
830 fp.write(line)
830 fp.write(line)
831
831
832 def writeData(self, fp):
832 def writeData(self, fp):
833
833
834 log.log('Creating file: {}'.format(self.filename), self.name)
834 log.log('Creating file: {}'.format(self.filename), self.name)
835
835
836 self.firsttime = True
836 self.firsttime = True
837 self.blockIndex = 0
837 self.blockIndex = 0
838 return
838 return
839
839
840 def putData(self):
840 def putData(self):
841
841
842 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
842 if (self.blockIndex == self.blocksPerFile) or self.timeFlag():
843 self.closeFile()
843 self.closeFile()
844 self.setNextFile()
844 self.setNextFile()
845
845
846 line = ''
846 line = ''
847 for j in range(len(self.dataOut.heightList)):
847 for j in range(len(self.dataOut.heightList)):
848 for ds in self.dsList:
848 for ds in self.dsList:
849 par = self.dataDict[ds['variable']]
849 par = self.dataDict[ds['variable']]
850 if ds['nDim'] == 2:
850 if ds['nDim'] == 2:
851 for i in range(len(par)):
851 for i in range(len(par)):
852 line += '{:>16}'.format('%8.2f' % getattr(self.dataOut, ds['variable'])[i][j])
852 line += '{:>16}'.format('%8.2f' % getattr(self.dataOut, ds['variable'])[i][j])
853 elif ds['nDim'] == 1:
853 elif ds['nDim'] == 1:
854 line += '{:>16}'.format('%8.2f' % getattr(self.dataOut, ds['variable'])[j])
854 line += '{:>16}'.format('%8.2f' % getattr(self.dataOut, ds['variable'])[j])
855 else:
855 else:
856 line += '{:>16}'.format('%8.2f' % getattr(self.dataOut, ds['variable']))
856 line += '{:>16}'.format('%8.2f' % getattr(self.dataOut, ds['variable']))
857
857
858 line += '\n'
858 line += '\n'
859 self.fp.write(line)
859 self.fp.write(line)
860
860
861 self.blockIndex += 1
861 self.blockIndex += 1
862 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
862 log.log('Block No. {}/{}'.format(self.blockIndex, self.blocksPerFile), self.name)
863
863
864 return
864 return
865
865
866 def closeFile(self):
866 def closeFile(self):
867
867
868 if self.fp:
868 if self.fp:
869 self.fp.close()
869 self.fp.close()
870
870
871 def close(self):
871 def close(self):
872
872
873 self.closeFile()
873 self.closeFile()
General Comments 0
You need to be logged in to leave comments. Login now