##// END OF EJS Templates
Modificación a kmamisr para ejecutarse en la versión 3, creación de scripts con terminación v3 para difereciarlos, se comentó la linea #720 de JroIO_param.py debido a que reiniciaba la lista de archivos, ocasionando la reescritura del archivo hdf5. Alguna otra modificación aparente es producto de algunas variaciones en espacios al usar la función print()
joabAM -
r1279:c53fe2a4a291
parent child
Show More
@@ -57,7 +57,7 def MPProject(project, n=cpu_count()):
57 57 nFiles = len(files)
58 58 if nFiles == 0:
59 59 continue
60 skip = int(math.ceil(nFiles / n))
60 skip = int(math.ceil(nFiles / n))
61 61 while nFiles > cursor * skip:
62 62 rconf.update(startDate=dt_str, endDate=dt_str, cursor=cursor,
63 63 skip=skip)
@@ -81,11 +81,11 def MPProject(project, n=cpu_count()):
81 81 time.sleep(3)
82 82
83 83 def wait(context):
84
84
85 85 time.sleep(1)
86 86 c = zmq.Context()
87 87 receiver = c.socket(zmq.SUB)
88 receiver.connect('ipc:///tmp/schain_{}_pub'.format(self.id))
88 receiver.connect('ipc:///tmp/schain_{}_pub'.format(self.id))
89 89 receiver.setsockopt(zmq.SUBSCRIBE, self.id.encode())
90 90 msg = receiver.recv_multipart()[1]
91 91 context.terminate()
@@ -262,7 +262,7 class ParameterConf():
262 262 parmElement.set('name', self.name)
263 263 parmElement.set('value', self.value)
264 264 parmElement.set('format', self.format)
265
265
266 266 def readXml(self, parmElement):
267 267
268 268 self.id = parmElement.get('id')
@@ -417,7 +417,7 class OperationConf():
417 417 self.name = opElement.get('name')
418 418 self.type = opElement.get('type')
419 419 self.priority = opElement.get('priority')
420 self.project_id = str(project_id)
420 self.project_id = str(project_id)
421 421
422 422 # Compatible with old signal chain version
423 423 # Use of 'run' method instead 'init'
@@ -476,7 +476,7 class ProcUnitConf():
476 476 self.id = None
477 477 self.datatype = None
478 478 self.name = None
479 self.inputId = None
479 self.inputId = None
480 480 self.opConfObjList = []
481 481 self.procUnitObj = None
482 482 self.opObjDict = {}
@@ -497,7 +497,7 class ProcUnitConf():
497 497
498 498 return self.id
499 499
500 def updateId(self, new_id):
500 def updateId(self, new_id):
501 501 '''
502 502 new_id = int(parentId) * 10 + (int(self.id) % 10)
503 503 new_inputId = int(parentId) * 10 + (int(self.inputId) % 10)
@@ -556,7 +556,7 class ProcUnitConf():
556 556 id sera el topico a publicar
557 557 inputId sera el topico a subscribirse
558 558 '''
559
559
560 560 # Compatible with old signal chain version
561 561 if datatype == None and name == None:
562 562 raise ValueError('datatype or name should be defined')
@@ -581,7 +581,7 class ProcUnitConf():
581 581 self.lock = lock
582 582 self.opConfObjList = []
583 583
584 self.addOperation(name='run', optype='self')
584 self.addOperation(name='run', optype='self')
585 585
586 586 def removeOperations(self):
587 587
@@ -679,28 +679,32 class ProcUnitConf():
679 679 '''
680 680
681 681 className = eval(self.name)
682 #print(self.name)
682 683 kwargs = self.getKwargs()
684 #print(kwargs)
685 #print("mark_a")
683 686 procUnitObj = className(self.id, self.inputId, self.project_id, self.err_queue, self.lock, 'ProcUnit', **kwargs)
687 #print("mark_b")
684 688 log.success('creating process...', self.name)
685 689
686 690 for opConfObj in self.opConfObjList:
687
691
688 692 if opConfObj.type == 'self' and opConfObj.name == 'run':
689 693 continue
690 694 elif opConfObj.type == 'self':
691 695 opObj = getattr(procUnitObj, opConfObj.name)
692 696 else:
693 697 opObj = opConfObj.createObject()
694
698
695 699 log.success('adding operation: {}, type:{}'.format(
696 700 opConfObj.name,
697 701 opConfObj.type), self.name)
698
702
699 703 procUnitObj.addOperation(opConfObj, opObj)
700
704
701 705 procUnitObj.start()
702 706 self.procUnitObj = procUnitObj
703
707
704 708 def close(self):
705 709
706 710 for opConfObj in self.opConfObjList:
@@ -732,8 +736,8 class ReadUnitConf(ProcUnitConf):
732 736
733 737 def getElementName(self):
734 738
735 return self.ELEMENTNAME
736
739 return self.ELEMENTNAME
740
737 741 def setup(self, project_id, id, name, datatype, err_queue, path='', startDate='', endDate='',
738 742 startTime='', endTime='', server=None, **kwargs):
739 743
@@ -745,7 +749,7 class ReadUnitConf(ProcUnitConf):
745 749 kwargs deben ser trasmitidos en la instanciacion
746 750
747 751 '''
748
752
749 753 # Compatible with old signal chain version
750 754 if datatype == None and name == None:
751 755 raise ValueError('datatype or name should be defined')
@@ -768,12 +772,13 class ReadUnitConf(ProcUnitConf):
768 772 self.datatype = datatype
769 773 if path != '':
770 774 self.path = os.path.abspath(path)
775 print (self.path)
771 776 self.startDate = startDate
772 777 self.endDate = endDate
773 778 self.startTime = startTime
774 779 self.endTime = endTime
775 780 self.server = server
776 self.err_queue = err_queue
781 self.err_queue = err_queue
777 782 self.addRunOperation(**kwargs)
778 783
779 784 def update(self, **kwargs):
@@ -804,7 +809,7 class ReadUnitConf(ProcUnitConf):
804 809
805 810 def addRunOperation(self, **kwargs):
806 811
807 opObj = self.addOperation(name='run', optype='self')
812 opObj = self.addOperation(name='run', optype='self')
808 813
809 814 if self.server is None:
810 815 opObj.addParameter(
@@ -942,7 +947,7 class Project(Process):
942 947 print('*' * 19)
943 948 print(' ')
944 949 self.id = str(id)
945 self.description = description
950 self.description = description
946 951 self.email = email
947 952 self.alarm = alarm
948 953 if name:
@@ -977,7 +982,7 class Project(Process):
977 982 readUnitConfObj = ReadUnitConf()
978 983 readUnitConfObj.setup(self.id, idReadUnit, name, datatype, self.err_queue, **kwargs)
979 984 self.procUnitConfObjDict[readUnitConfObj.getId()] = readUnitConfObj
980
985
981 986 return readUnitConfObj
982 987
983 988 def addProcUnit(self, inputId='0', datatype=None, name=None):
@@ -994,7 +999,7 class Project(Process):
994 999
995 1000 idProcUnit = self.__getNewId()
996 1001 procUnitConfObj = ProcUnitConf()
997 input_proc = self.procUnitConfObjDict[inputId]
1002 input_proc = self.procUnitConfObjDict[inputId]
998 1003 procUnitConfObj.setup(self.id, idProcUnit, name, datatype, inputId, self.err_queue, input_proc.lock)
999 1004 self.procUnitConfObjDict[procUnitConfObj.getId()] = procUnitConfObj
1000 1005
@@ -1152,14 +1157,14 class Project(Process):
1152 1157
1153 1158 t = Thread(target=self.__monitor, args=(self.err_queue, self.ctx))
1154 1159 t.start()
1155
1160
1156 1161 def __monitor(self, queue, ctx):
1157 1162
1158 1163 import socket
1159
1164
1160 1165 procs = 0
1161 1166 err_msg = ''
1162
1167
1163 1168 while True:
1164 1169 msg = queue.get()
1165 1170 if '#_start_#' in msg:
@@ -1168,11 +1173,11 class Project(Process):
1168 1173 procs -=1
1169 1174 else:
1170 1175 err_msg = msg
1171
1172 if procs == 0 or 'Traceback' in err_msg:
1176
1177 if procs == 0 or 'Traceback' in err_msg:
1173 1178 break
1174 1179 time.sleep(0.1)
1175
1180
1176 1181 if '|' in err_msg:
1177 1182 name, err = err_msg.split('|')
1178 1183 if 'SchainWarning' in err:
@@ -1181,9 +1186,9 class Project(Process):
1181 1186 log.error(err.split('SchainError:')[-1].split('\n')[0].strip(), name)
1182 1187 else:
1183 1188 log.error(err, name)
1184 else:
1189 else:
1185 1190 name, err = self.name, err_msg
1186
1191
1187 1192 time.sleep(2)
1188 1193
1189 1194 for conf in self.procUnitConfObjDict.values():
@@ -1191,7 +1196,7 class Project(Process):
1191 1196 if confop.type == 'external':
1192 1197 confop.opObj.terminate()
1193 1198 conf.procUnitObj.terminate()
1194
1199
1195 1200 ctx.term()
1196 1201
1197 1202 message = ''.join(err)
@@ -1217,7 +1222,7 class Project(Process):
1217 1222 subtitle += '[End time = %s]\n' % readUnitConfObj.endTime
1218 1223
1219 1224 a = Alarm(
1220 modes=self.alarm,
1225 modes=self.alarm,
1221 1226 email=self.email,
1222 1227 message=message,
1223 1228 subject=subject,
@@ -1266,7 +1271,7 class Project(Process):
1266 1271
1267 1272 if not os.path.exists('/tmp/schain'):
1268 1273 os.mkdir('/tmp/schain')
1269
1274
1270 1275 self.ctx = zmq.Context()
1271 1276 xpub = self.ctx.socket(zmq.XPUB)
1272 1277 xpub.bind('ipc:///tmp/schain/{}_pub'.format(self.id))
@@ -1282,9 +1287,9 class Project(Process):
1282 1287 def run(self):
1283 1288
1284 1289 log.success('Starting {}: {}'.format(self.name, self.id), tag='')
1285 self.start_time = time.time()
1286 self.createObjects()
1287 self.setProxy()
1290 self.start_time = time.time()
1291 self.createObjects()
1292 self.setProxy()
1288 1293 log.success('{} Done (Time: {}s)'.format(
1289 1294 self.name,
1290 1295 time.time()-self.start_time), '')
@@ -114,7 +114,7 class GenericData(object):
114 114 flagNoData = True
115 115
116 116 def copy(self, inputObj=None):
117
117
118 118 if inputObj == None:
119 119 return copy.deepcopy(self)
120 120
@@ -548,7 +548,7 class Spectra(JROData):
548 548
549 549 deltav = self.getVmax() / (self.nFFTPoints * self.ippFactor)
550 550 velrange = deltav * (numpy.arange(self.nFFTPoints + extrapoints) - self.nFFTPoints / 2.)
551
551
552 552 if self.nmodes:
553 553 return velrange/self.nmodes
554 554 else:
@@ -1104,7 +1104,7 class PlotterData(object):
1104 1104 MAXNUMY = 100
1105 1105
1106 1106 def __init__(self, code, throttle_value, exp_code, buffering=True, snr=False):
1107
1107
1108 1108 self.key = code
1109 1109 self.throttle = throttle_value
1110 1110 self.exp_code = exp_code
@@ -1139,7 +1139,7 class PlotterData(object):
1139 1139 return len(self.__times)
1140 1140
1141 1141 def __getitem__(self, key):
1142
1142
1143 1143 if key not in self.data:
1144 1144 raise KeyError(log.error('Missing key: {}'.format(key)))
1145 1145 if 'spc' in key or not self.buffering:
@@ -1172,7 +1172,7 class PlotterData(object):
1172 1172 elif 'spc_moments' == plot:
1173 1173 plot = 'moments'
1174 1174 self.data[plot] = {}
1175
1175
1176 1176 if 'spc' in self.data or 'rti' in self.data or 'cspc' in self.data or 'moments' in self.data:
1177 1177 self.data['noise'] = {}
1178 1178 self.data['rti'] = {}
@@ -1180,7 +1180,7 class PlotterData(object):
1180 1180 self.plottypes.append('noise')
1181 1181 if 'rti' not in self.plottypes:
1182 1182 self.plottypes.append('rti')
1183
1183
1184 1184 def shape(self, key):
1185 1185 '''
1186 1186 Get the shape of the one-element data for the given key
@@ -1196,17 +1196,17 class PlotterData(object):
1196 1196 '''
1197 1197 Update data object with new dataOut
1198 1198 '''
1199
1199
1200 1200 if tm in self.__times:
1201 1201 return
1202 1202 self.profileIndex = dataOut.profileIndex
1203 1203 self.tm = tm
1204 1204 self.type = dataOut.type
1205 1205 self.parameters = getattr(dataOut, 'parameters', [])
1206
1206
1207 1207 if hasattr(dataOut, 'meta'):
1208 1208 self.meta.update(dataOut.meta)
1209
1209
1210 1210 self.pairs = dataOut.pairsList
1211 1211 self.interval = dataOut.getTimeInterval()
1212 1212 self.localtime = dataOut.useLocalTime
@@ -1217,7 +1217,7 class PlotterData(object):
1217 1217 self.__heights.append(dataOut.heightList)
1218 1218 self.__all_heights.update(dataOut.heightList)
1219 1219 self.__times.append(tm)
1220
1220
1221 1221 for plot in self.plottypes:
1222 1222 if plot in ('spc', 'spc_moments'):
1223 1223 z = dataOut.data_spc/dataOut.normFactor
@@ -1250,8 +1250,8 class PlotterData(object):
1250 1250 if plot == 'scope':
1251 1251 buffer = dataOut.data
1252 1252 self.flagDataAsBlock = dataOut.flagDataAsBlock
1253 self.nProfiles = dataOut.nProfiles
1254
1253 self.nProfiles = dataOut.nProfiles
1254
1255 1255 if plot == 'spc':
1256 1256 self.data['spc'] = buffer
1257 1257 elif plot == 'cspc':
@@ -1326,7 +1326,7 class PlotterData(object):
1326 1326 else:
1327 1327 meta['xrange'] = []
1328 1328
1329 meta.update(self.meta)
1329 meta.update(self.meta)
1330 1330 ret['metadata'] = meta
1331 1331 return json.dumps(ret)
1332 1332
@@ -218,7 +218,7 class SystemHeader(Header):
218 218 structure = SYSTEM_STRUCTURE
219 219
220 220 def __init__(self, nSamples=0, nProfiles=0, nChannels=0, adcResolution=14, pciDioBusWidth=0):
221
221
222 222 self.size = 24
223 223 self.nSamples = nSamples
224 224 self.nProfiles = nProfiles
@@ -903,4 +903,4 def get_procflag_dtype(index):
903 903
904 904 def get_dtype_width(index):
905 905
906 return DTYPE_WIDTH[index] No newline at end of file
906 return DTYPE_WIDTH[index]
@@ -228,7 +228,7 class Plot(Operation):
228 228 self.__throttle_plot = apply_throttle(self.throttle)
229 229 self.data = PlotterData(
230 230 self.CODE, self.throttle, self.exp_code, self.buffering, snr=self.showSNR)
231
231
232 232 if self.plot_server:
233 233 if not self.plot_server.startswith('tcp://'):
234 234 self.plot_server = 'tcp://{}'.format(self.plot_server)
@@ -246,7 +246,7 class Plot(Operation):
246 246
247 247 self.setup()
248 248
249 self.time_label = 'LT' if self.localtime else 'UTC'
249 self.time_label = 'LT' if self.localtime else 'UTC'
250 250
251 251 if self.width is None:
252 252 self.width = 8
@@ -305,7 +305,7 class Plot(Operation):
305 305 cmap = plt.get_cmap(self.colormap)
306 306 cmap.set_bad(self.bgcolor, 1.)
307 307 self.cmaps.append(cmap)
308
308
309 309 for fig in self.figures:
310 310 fig.canvas.mpl_connect('key_press_event', self.OnKeyPress)
311 311 fig.canvas.mpl_connect('scroll_event', self.OnBtnScroll)
@@ -474,11 +474,11 class Plot(Operation):
474 474 xmax += time.timezone
475 475 else:
476 476 xmax = self.xmax
477
477
478 478 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
479 479 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
480 480 #Y = numpy.array([1, 2, 5, 10, 20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000])
481
481
482 482 #i = 1 if numpy.where(
483 483 # abs(ymax-ymin) <= Y)[0][0] < 0 else numpy.where(abs(ymax-ymin) <= Y)[0][0]
484 484 #ystep = Y[i] / 10.
@@ -492,14 +492,14 class Plot(Operation):
492 492 ystep = ystep/5
493 493 ystep = ystep/(10**digD)
494 494
495 else:
495 else:
496 496 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
497 497 ystep = ystep/5
498
498
499 499 if self.xaxis is not 'time':
500
500
501 501 dig = int(numpy.log10(xmax))
502
502
503 503 if dig <= 0:
504 504 digD = len(str(xmax)) - 2
505 505 xdec = xmax*(10**digD)
@@ -508,11 +508,11 class Plot(Operation):
508 508 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
509 509 xstep = xstep*0.5
510 510 xstep = xstep/(10**digD)
511
512 else:
511
512 else:
513 513 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
514 514 xstep = xstep/5
515
515
516 516 for n, ax in enumerate(self.axes):
517 517 if ax.firsttime:
518 518 ax.set_facecolor(self.bgcolor)
@@ -610,7 +610,7 class Plot(Operation):
610 610
611 611 if self.save:
612 612 self.save_figure(n)
613
613
614 614 if self.plot_server:
615 615 self.send_to_server()
616 616 # t = Thread(target=self.send_to_server)
@@ -643,11 +643,10 class Plot(Operation):
643 643 '{}{}_{}.png'.format(
644 644 self.CODE,
645 645 label,
646 self.getDateTime(self.data.max_time).strftime(
647 '%Y%m%d_%H%M%S'
648 ),
646 self.getDateTime(self.data.max_time).strftime('%Y%m%d_%H%M%S'),
649 647 )
650 648 )
649
651 650 log.log('Saving figure: {}'.format(figname), self.name)
652 651 if not os.path.isdir(os.path.dirname(figname)):
653 652 os.makedirs(os.path.dirname(figname))
@@ -718,7 +717,7 class Plot(Operation):
718 717 self.ncols: number of cols
719 718 self.nplots: number of plots (channels or pairs)
720 719 self.ylabel: label for Y axes
721 self.titles: list of axes title
720 self.titles: list of axes title
722 721
723 722 '''
724 723 raise NotImplementedError
@@ -728,18 +727,18 class Plot(Operation):
728 727 Must be defined in the child class
729 728 '''
730 729 raise NotImplementedError
731
730
732 731 def run(self, dataOut, **kwargs):
733 732 '''
734 733 Main plotting routine
735 734 '''
736
735
737 736 if self.isConfig is False:
738 737 self.__setup(**kwargs)
739 738 if dataOut.type == 'Parameters':
740 739 t = dataOut.utctimeInit
741 740 else:
742 t = dataOut.utctime
741 t = dataOut.utctime
743 742
744 743 if dataOut.useLocalTime:
745 744 self.getDateTime = datetime.datetime.fromtimestamp
@@ -749,15 +748,15 class Plot(Operation):
749 748 self.getDateTime = datetime.datetime.utcfromtimestamp
750 749 if self.localtime:
751 750 t -= time.timezone
752
751
753 752 if 'buffer' in self.plot_type:
754 753 if self.xmin is None:
755 754 self.tmin = t
756 755 else:
757 756 self.tmin = (
758 757 self.getDateTime(t).replace(
759 hour=self.xmin,
760 minute=0,
758 hour=self.xmin,
759 minute=0,
761 760 second=0) - self.getDateTime(0)).total_seconds()
762 761
763 762 self.data.setup()
@@ -779,7 +778,7 class Plot(Operation):
779 778 if dataOut.useLocalTime and not self.localtime:
780 779 tm += time.timezone
781 780
782 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
781 if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60:
783 782 self.save_counter = self.save_period
784 783 self.__plot()
785 784 self.xmin += self.xrange
@@ -807,4 +806,3 class Plot(Operation):
807 806 self.__plot()
808 807 if self.data and self.pause:
809 808 figpause(10)
810
@@ -21,9 +21,10 except:
21 21
22 22 from schainpy.model.data.jroheaderIO import RadarControllerHeader, SystemHeader
23 23 from schainpy.model.data.jrodata import Voltage
24 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation
24 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
25 25 from numpy import imag
26 26
27 @MPDecorator
27 28 class AMISRReader(ProcessingUnit):
28 29 '''
29 30 classdocs
@@ -33,9 +34,9 class AMISRReader(ProcessingUnit):
33 34 '''
34 35 Constructor
35 36 '''
36
37
37 38 ProcessingUnit.__init__(self)
38
39
39 40 self.set = None
40 41 self.subset = None
41 42 self.extension_file = '.h5'
@@ -50,40 +51,41 class AMISRReader(ProcessingUnit):
50 51 self.flagIsNewFile = 0
51 52 self.filename = ''
52 53 self.amisrFilePointer = None
53
54
55 self.dataset = None
56
57
58
54
55
56 #self.dataset = None
57
58
59
59 60
60 61 self.profileIndex = 0
61
62
62
63
63 64 self.beamCodeByFrame = None
64 65 self.radacTimeByFrame = None
65
66
66 67 self.dataset = None
67
68
69
70
68
69
70
71
71 72 self.__firstFile = True
72
73
73 74 self.buffer = None
74
75
75
76
76 77 self.timezone = 'ut'
77
78
78 79 self.__waitForNewFile = 20
79 self.__filename_online = None
80 self.__filename_online = None
80 81 #Is really necessary create the output object in the initializer
81 82 self.dataOut = Voltage()
82
83 self.dataOut.error=False
84
83 85 def setup(self,path=None,
84 startDate=None,
85 endDate=None,
86 startTime=None,
86 startDate=None,
87 endDate=None,
88 startTime=None,
87 89 endTime=None,
88 90 walk=True,
89 91 timezone='ut',
@@ -92,41 +94,42 class AMISRReader(ProcessingUnit):
92 94 nCode = 0,
93 95 nBaud = 0,
94 96 online=False):
95
97
98 #print ("T",path)
99
96 100 self.timezone = timezone
97 101 self.all = all
98 102 self.online = online
99
103
100 104 self.code = code
101 105 self.nCode = int(nCode)
102 106 self.nBaud = int(nBaud)
103
104
105
107
108
109
106 110 #self.findFiles()
107 111 if not(online):
108 112 #Busqueda de archivos offline
109 113 self.searchFilesOffLine(path, startDate, endDate, startTime, endTime, walk)
110 114 else:
111 115 self.searchFilesOnLine(path, startDate, endDate, startTime,endTime,walk)
112
116
113 117 if not(self.filenameList):
114 118 print("There is no files into the folder: %s"%(path))
115
116 119 sys.exit(-1)
117
120
118 121 self.fileIndex = -1
119
120 self.readNextFile(online)
121
122
123 self.readNextFile(online)
124
122 125 '''
123 126 Add code
124 '''
127 '''
125 128 self.isConfig = True
126
129
127 130 pass
128
129
131
132
130 133 def readAMISRHeader(self,fp):
131 134 header = 'Raw11/Data/RadacHeader'
132 135 self.beamCodeByPulse = fp.get(header+'/BeamCode') # LIST OF BEAMS PER PROFILE, TO BE USED ON REARRANGE
@@ -142,26 +145,26 class AMISRReader(ProcessingUnit):
142 145 self.rangeFromFile = fp.get('Raw11/Data/Samples/Range')
143 146 self.frequency = fp.get('Rx/Frequency')
144 147 txAus = fp.get('Raw11/Data/Pulsewidth')
145
146
148
149
147 150 self.nblocks = self.pulseCount.shape[0] #nblocks
148
151
149 152 self.nprofiles = self.pulseCount.shape[1] #nprofile
150 153 self.nsa = self.nsamplesPulse[0,0] #ngates
151 154 self.nchannels = self.beamCode.shape[1]
152 155 self.ippSeconds = (self.radacTime[0][1] -self.radacTime[0][0]) #Ipp in seconds
153 156 #self.__waitForNewFile = self.nblocks # wait depending on the number of blocks since each block is 1 sec
154 157 self.__waitForNewFile = self.nblocks * self.nprofiles * self.ippSeconds # wait until new file is created
155
158
156 159 #filling radar controller header parameters
157 160 self.__ippKm = self.ippSeconds *.15*1e6 # in km
158 161 self.__txA = (txAus.value)*.15 #(ipp[us]*.15km/1us) in km
159 162 self.__txB = 0
160 163 nWindows=1
161 self.__nSamples = self.nsa
164 self.__nSamples = self.nsa
162 165 self.__firstHeight = self.rangeFromFile[0][0]/1000 #in km
163 self.__deltaHeight = (self.rangeFromFile[0][1] - self.rangeFromFile[0][0])/1000
164
166 self.__deltaHeight = (self.rangeFromFile[0][1] - self.rangeFromFile[0][0])/1000
167
165 168 #for now until understand why the code saved is different (code included even though code not in tuf file)
166 169 #self.__codeType = 0
167 170 # self.__nCode = None
@@ -173,20 +176,20 class AMISRReader(ProcessingUnit):
173 176 self.__nCode = self.nCode
174 177 self.__nBaud = self.nBaud
175 178 #self.__code = 0
176
179
177 180 #filling system header parameters
178 181 self.__nSamples = self.nsa
179 self.newProfiles = self.nprofiles/self.nchannels
182 self.newProfiles = self.nprofiles/self.nchannels
180 183 self.__channelList = list(range(self.nchannels))
181
184
182 185 self.__frequency = self.frequency[0][0]
183
184 186
185
187
188
186 189 def createBuffers(self):
187
188 pass
189
190
191 pass
192
190 193 def __setParameters(self,path='', startDate='',endDate='',startTime='', endTime='', walk=''):
191 194 self.path = path
192 195 self.startDate = startDate
@@ -194,35 +197,35 class AMISRReader(ProcessingUnit):
194 197 self.startTime = startTime
195 198 self.endTime = endTime
196 199 self.walk = walk
197
200
198 201 def __checkPath(self):
199 202 if os.path.exists(self.path):
200 203 self.status = 1
201 204 else:
202 205 self.status = 0
203 206 print('Path:%s does not exists'%self.path)
204
207
205 208 return
206
207
209
210
208 211 def __selDates(self, amisr_dirname_format):
209 212 try:
210 213 year = int(amisr_dirname_format[0:4])
211 214 month = int(amisr_dirname_format[4:6])
212 215 dom = int(amisr_dirname_format[6:8])
213 216 thisDate = datetime.date(year,month,dom)
214
217
215 218 if (thisDate>=self.startDate and thisDate <= self.endDate):
216 219 return amisr_dirname_format
217 220 except:
218 221 return None
219
220
222
223
221 224 def __findDataForDates(self,online=False):
222
225
223 226 if not(self.status):
224 227 return None
225
228
226 229 pat = '\d+.\d+'
227 230 dirnameList = [re.search(pat,x) for x in os.listdir(self.path)]
228 231 dirnameList = [x for x in dirnameList if x!=None]
@@ -237,7 +240,7 class AMISRReader(ProcessingUnit):
237 240 else:
238 241 self.status = 0
239 242 return None
240
243
241 244 def __getTimeFromData(self):
242 245 startDateTime_Reader = datetime.datetime.combine(self.startDate,self.startTime)
243 246 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
@@ -251,33 +254,35 class AMISRReader(ProcessingUnit):
251 254 filename = self.filenameList[i]
252 255 fp = h5py.File(filename,'r')
253 256 time_str = fp.get('Time/RadacTimeString')
254
255 startDateTimeStr_File = time_str[0][0].split('.')[0]
257
258 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
259 #startDateTimeStr_File = "2019-12-16 09:21:11"
256 260 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
257 261 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
258
259 endDateTimeStr_File = time_str[-1][-1].split('.')[0]
262
263 #endDateTimeStr_File = "2019-12-16 11:10:11"
264 endDateTimeStr_File = time_str[-1][-1].decode('UTF-8').split('.')[0]
260 265 junk = time.strptime(endDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
261 266 endDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
262
267
263 268 fp.close()
264
269
270 #print("check time", startDateTime_File)
265 271 if self.timezone == 'lt':
266 272 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
267 273 endDateTime_File = endDateTime_File - datetime.timedelta(minutes = 300)
268
269 274 if (endDateTime_File>=startDateTime_Reader and endDateTime_File<endDateTime_Reader):
270 275 #self.filenameList.remove(filename)
271 276 filter_filenameList.append(filename)
272
277
273 278 if (endDateTime_File>=endDateTime_Reader):
274 279 break
275
276
280
281
277 282 filter_filenameList.sort()
278 283 self.filenameList = filter_filenameList
279 284 return 1
280
285
281 286 def __filterByGlob1(self, dirName):
282 287 filter_files = glob.glob1(dirName, '*.*%s'%self.extension_file)
283 288 filter_files.sort()
@@ -285,24 +290,24 class AMISRReader(ProcessingUnit):
285 290 filterDict.setdefault(dirName)
286 291 filterDict[dirName] = filter_files
287 292 return filterDict
288
293
289 294 def __getFilenameList(self, fileListInKeys, dirList):
290 295 for value in fileListInKeys:
291 296 dirName = list(value.keys())[0]
292 297 for file in value[dirName]:
293 298 filename = os.path.join(dirName, file)
294 299 self.filenameList.append(filename)
295
296
300
301
297 302 def __selectDataForTimes(self, online=False):
298 303 #aun no esta implementado el filtro for tiempo
299 304 if not(self.status):
300 305 return None
301
306
302 307 dirList = [os.path.join(self.path,x) for x in self.dirnameList]
303
308
304 309 fileListInKeys = [self.__filterByGlob1(x) for x in dirList]
305
310
306 311 self.__getFilenameList(fileListInKeys, dirList)
307 312 if not(online):
308 313 #filtro por tiempo
@@ -315,11 +320,11 class AMISRReader(ProcessingUnit):
315 320 else:
316 321 self.status = 0
317 322 return None
318
323
319 324 else:
320 325 #get the last file - 1
321 326 self.filenameList = [self.filenameList[-2]]
322
327
323 328 new_dirnameList = []
324 329 for dirname in self.dirnameList:
325 330 junk = numpy.array([dirname in x for x in self.filenameList])
@@ -328,27 +333,27 class AMISRReader(ProcessingUnit):
328 333 new_dirnameList.append(dirname)
329 334 self.dirnameList = new_dirnameList
330 335 return 1
331
336
332 337 def searchFilesOnLine(self, path, startDate, endDate, startTime=datetime.time(0,0,0),
333 338 endTime=datetime.time(23,59,59),walk=True):
334
339
335 340 if endDate ==None:
336 341 startDate = datetime.datetime.utcnow().date()
337 342 endDate = datetime.datetime.utcnow().date()
338
343
339 344 self.__setParameters(path=path, startDate=startDate, endDate=endDate,startTime = startTime,endTime=endTime, walk=walk)
340
345
341 346 self.__checkPath()
342
347
343 348 self.__findDataForDates(online=True)
344
349
345 350 self.dirnameList = [self.dirnameList[-1]]
346
351
347 352 self.__selectDataForTimes(online=True)
348
353
349 354 return
350
351
355
356
352 357 def searchFilesOffLine(self,
353 358 path,
354 359 startDate,
@@ -356,20 +361,20 class AMISRReader(ProcessingUnit):
356 361 startTime=datetime.time(0,0,0),
357 362 endTime=datetime.time(23,59,59),
358 363 walk=True):
359
364
360 365 self.__setParameters(path, startDate, endDate, startTime, endTime, walk)
361
366
362 367 self.__checkPath()
363
368
364 369 self.__findDataForDates()
365
370
366 371 self.__selectDataForTimes()
367
372
368 373 for i in range(len(self.filenameList)):
369 374 print("%s" %(self.filenameList[i]))
370
371 return
372
375
376 return
377
373 378 def __setNextFileOffline(self):
374 379 idFile = self.fileIndex
375 380
@@ -378,12 +383,13 class AMISRReader(ProcessingUnit):
378 383 if not(idFile < len(self.filenameList)):
379 384 self.flagNoMoreFiles = 1
380 385 print("No more Files")
386 self.dataOut.error = True
381 387 return 0
382 388
383 389 filename = self.filenameList[idFile]
384 390
385 391 amisrFilePointer = h5py.File(filename,'r')
386
392
387 393 break
388 394
389 395 self.flagIsNewFile = 1
@@ -395,8 +401,8 class AMISRReader(ProcessingUnit):
395 401 print("Setting the file: %s"%self.filename)
396 402
397 403 return 1
398
399
404
405
400 406 def __setNextFileOnline(self):
401 407 filename = self.filenameList[0]
402 408 if self.__filename_online != None:
@@ -411,54 +417,56 class AMISRReader(ProcessingUnit):
411 417 self.__selectDataForTimes(online=True)
412 418 filename = self.filenameList[0]
413 419 wait += 1
414
420
415 421 self.__filename_online = filename
416
422
417 423 self.amisrFilePointer = h5py.File(filename,'r')
418 424 self.flagIsNewFile = 1
419 425 self.filename = filename
420 426 print("Setting the file: %s"%self.filename)
421 427 return 1
422
423
428
429
424 430 def readData(self):
425 431 buffer = self.amisrFilePointer.get('Raw11/Data/Samples/Data')
426 432 re = buffer[:,:,:,0]
427 433 im = buffer[:,:,:,1]
428 434 dataset = re + im*1j
435
429 436 self.radacTime = self.amisrFilePointer.get('Raw11/Data/RadacHeader/RadacTime')
430 437 timeset = self.radacTime[:,0]
438
431 439 return dataset,timeset
432
440
433 441 def reshapeData(self):
434 #self.beamCodeByPulse, self.beamCode, self.nblocks, self.nprofiles, self.nsa,
442 #self.beamCodeByPulse, self.beamCode, self.nblocks, self.nprofiles, self.nsa,
435 443 channels = self.beamCodeByPulse[0,:]
436 444 nchan = self.nchannels
437 445 #self.newProfiles = self.nprofiles/nchan #must be defined on filljroheader
438 446 nblocks = self.nblocks
439 447 nsamples = self.nsa
440
448
441 449 #Dimensions : nChannels, nProfiles, nSamples
442 new_block = numpy.empty((nblocks, nchan, self.newProfiles, nsamples), dtype="complex64")
450 new_block = numpy.empty((nblocks, nchan, numpy.int_(self.newProfiles), nsamples), dtype="complex64")
443 451 ############################################
444
452
445 453 for thisChannel in range(nchan):
446 454 new_block[:,thisChannel,:,:] = self.dataset[:,numpy.where(channels==self.beamCode[0][thisChannel])[0],:]
447 455
448
456
449 457 new_block = numpy.transpose(new_block, (1,0,2,3))
450 458 new_block = numpy.reshape(new_block, (nchan,-1, nsamples))
451
452 return new_block
453
459
460 return new_block
461
454 462 def updateIndexes(self):
455
463
456 464 pass
457
465
458 466 def fillJROHeader(self):
459
467
460 468 #fill radar controller header
461 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(ippKm=self.__ippKm,
469 self.dataOut.radarControllerHeaderObj = RadarControllerHeader(ipp=self.__ippKm,
462 470 txA=self.__txA,
463 471 txB=0,
464 472 nWindows=1,
@@ -469,161 +477,173 class AMISRReader(ProcessingUnit):
469 477 nCode=self.__nCode, nBaud=self.__nBaud,
470 478 code = self.__code,
471 479 fClock=1)
472
473
474
480
475 481 #fill system header
476 482 self.dataOut.systemHeaderObj = SystemHeader(nSamples=self.__nSamples,
477 483 nProfiles=self.newProfiles,
478 484 nChannels=len(self.__channelList),
479 485 adcResolution=14,
480 pciDioBusWith=32)
481
486 pciDioBusWidth=32)
487
482 488 self.dataOut.type = "Voltage"
483
489
484 490 self.dataOut.data = None
485
491
486 492 self.dataOut.dtype = numpy.dtype([('real','<i8'),('imag','<i8')])
487
493
488 494 # self.dataOut.nChannels = 0
489
495
490 496 # self.dataOut.nHeights = 0
491
497
492 498 self.dataOut.nProfiles = self.newProfiles*self.nblocks
493
499
494 500 #self.dataOut.heightList = self.__firstHeigth + numpy.arange(self.__nSamples, dtype = numpy.float)*self.__deltaHeigth
495 501 ranges = numpy.reshape(self.rangeFromFile.value,(-1))
496 502 self.dataOut.heightList = ranges/1000.0 #km
497
498
503
504
499 505 self.dataOut.channelList = self.__channelList
500
506
501 507 self.dataOut.blocksize = self.dataOut.getNChannels() * self.dataOut.getNHeights()
502
508
503 509 # self.dataOut.channelIndexList = None
504
510
505 511 self.dataOut.flagNoData = True
506
507 #Set to TRUE if the data is discontinuous
512
513 #Set to TRUE if the data is discontinuous
508 514 self.dataOut.flagDiscontinuousBlock = False
509
515
510 516 self.dataOut.utctime = None
511
517
512 518 #self.dataOut.timeZone = -5 #self.__timezone/60 #timezone like jroheader, difference in minutes between UTC and localtime
513 519 if self.timezone == 'lt':
514 520 self.dataOut.timeZone = time.timezone / 60. #get the timezone in minutes
515 else:
521 else:
516 522 self.dataOut.timeZone = 0 #by default time is UTC
517 523
518 524 self.dataOut.dstFlag = 0
519
525
520 526 self.dataOut.errorCount = 0
521
527
522 528 self.dataOut.nCohInt = 1
523
529
524 530 self.dataOut.flagDecodeData = False #asumo que la data esta decodificada
525
531
526 532 self.dataOut.flagDeflipData = False #asumo que la data esta sin flip
527
533
528 534 self.dataOut.flagShiftFFT = False
529
535
530 536 self.dataOut.ippSeconds = self.ippSeconds
531
532 #Time interval between profiles
537
538 #Time interval between profiles
533 539 #self.dataOut.timeInterval = self.dataOut.ippSeconds * self.dataOut.nCohInt
534
540
535 541 self.dataOut.frequency = self.__frequency
536
537 542 self.dataOut.realtime = self.online
538 543 pass
539
544
540 545 def readNextFile(self,online=False):
541
546
542 547 if not(online):
543 548 newFile = self.__setNextFileOffline()
544 549 else:
545 newFile = self.__setNextFileOnline()
546
550 newFile = self.__setNextFileOnline()
551
547 552 if not(newFile):
548 553 return 0
549
550 554 #if self.__firstFile:
551 555 self.readAMISRHeader(self.amisrFilePointer)
556
552 557 self.createBuffers()
558
553 559 self.fillJROHeader()
560
554 561 #self.__firstFile = False
555
556
557
562
563
564
558 565 self.dataset,self.timeset = self.readData()
559
566
560 567 if self.endDate!=None:
561 568 endDateTime_Reader = datetime.datetime.combine(self.endDate,self.endTime)
562 569 time_str = self.amisrFilePointer.get('Time/RadacTimeString')
563 startDateTimeStr_File = time_str[0][0].split('.')[0]
570 startDateTimeStr_File = time_str[0][0].decode('UTF-8').split('.')[0]
564 571 junk = time.strptime(startDateTimeStr_File, '%Y-%m-%d %H:%M:%S')
565 572 startDateTime_File = datetime.datetime(junk.tm_year,junk.tm_mon,junk.tm_mday,junk.tm_hour, junk.tm_min, junk.tm_sec)
566 573 if self.timezone == 'lt':
567 574 startDateTime_File = startDateTime_File - datetime.timedelta(minutes = 300)
568 575 if (startDateTime_File>endDateTime_Reader):
569 576 return 0
570
577
571 578 self.jrodataset = self.reshapeData()
572 579 #----self.updateIndexes()
573 580 self.profileIndex = 0
574
581
575 582 return 1
576
577
583
584
578 585 def __hasNotDataInBuffer(self):
579 586 if self.profileIndex >= (self.newProfiles*self.nblocks):
580 587 return 1
581 588 return 0
582
583
589
590
584 591 def getData(self):
585
592
586 593 if self.flagNoMoreFiles:
587 594 self.dataOut.flagNoData = True
588 595 return 0
589
596
590 597 if self.__hasNotDataInBuffer():
591 598 if not (self.readNextFile(self.online)):
592 599 return 0
593 600
594
595 if self.dataset is None: # setear esta condicion cuando no hayan datos por leers
596 self.dataOut.flagNoData = True
601
602 if self.dataset is None: # setear esta condicion cuando no hayan datos por leer
603 self.dataOut.flagNoData = True
597 604 return 0
598
605
599 606 #self.dataOut.data = numpy.reshape(self.jrodataset[self.profileIndex,:],(1,-1))
600
607
601 608 self.dataOut.data = self.jrodataset[:,self.profileIndex,:]
602
609
610 #print("R_t",self.timeset)
611
603 612 #self.dataOut.utctime = self.jrotimeset[self.profileIndex]
604 613 #verificar basic header de jro data y ver si es compatible con este valor
605 614 #self.dataOut.utctime = self.timeset + (self.profileIndex * self.ippSeconds * self.nchannels)
606 615 indexprof = numpy.mod(self.profileIndex, self.newProfiles)
607 616 indexblock = self.profileIndex/self.newProfiles
608 #print indexblock, indexprof
609 self.dataOut.utctime = self.timeset[indexblock] + (indexprof * self.ippSeconds * self.nchannels)
617 #print (indexblock, indexprof)
618 diffUTC = 1.8e4 #UTC diference from peru in seconds --Joab
619 diffUTC = 0
620 t_comp = (indexprof * self.ippSeconds * self.nchannels) + diffUTC #
621 #cambio posible 18/02/2020
622
623
624
625 #print("utc :",indexblock," __ ",t_comp)
626 #print(numpy.shape(self.timeset))
627 self.dataOut.utctime = self.timeset[numpy.int_(indexblock)] + t_comp
628 #self.dataOut.utctime = self.timeset[self.profileIndex] + t_comp
629 #print(self.dataOut.utctime)
610 630 self.dataOut.profileIndex = self.profileIndex
611 631 self.dataOut.flagNoData = False
612 632 # if indexprof == 0:
613 633 # print self.dataOut.utctime
614
634
615 635 self.profileIndex += 1
616
636
617 637 return self.dataOut.data
618
619
638
639
620 640 def run(self, **kwargs):
621 641 '''
622 642 This method will be called many times so here you should put all your code
623 643 '''
624
644
625 645 if not self.isConfig:
626 646 self.setup(**kwargs)
627 647 self.isConfig = True
628
648
629 649 self.getData()
@@ -183,7 +183,7 class ParamReader(JRODataReader,ProcessingUnit):
183 183 except IOError:
184 184 traceback.print_exc()
185 185 raise IOError("The file %s can't be opened" %(filename))
186
186
187 187 #In case has utctime attribute
188 188 grp2 = grp1['utctime']
189 189 # thisUtcTime = grp2.value[0] - 5*3600 #To convert to local time
@@ -497,7 +497,7 class ParamWriter(Operation):
497 497 setType = None
498 498
499 499 def __init__(self):
500
500
501 501 Operation.__init__(self)
502 502 return
503 503
@@ -530,9 +530,9 class ParamWriter(Operation):
530 530 dsDict['variable'] = self.dataList[i]
531 531 #--------------------- Conditionals ------------------------
532 532 #There is no data
533
533
534 534 if dataAux is None:
535
535
536 536 return 0
537 537
538 538 if isinstance(dataAux, (int, float, numpy.integer, numpy.float)):
@@ -704,7 +704,7 class ParamWriter(Operation):
704 704 return False
705 705
706 706 def setNextFile(self):
707
707
708 708 ext = self.ext
709 709 path = self.path
710 710 setFile = self.setFile
@@ -717,7 +717,7 class ParamWriter(Operation):
717 717
718 718 if os.path.exists(fullpath):
719 719 filesList = os.listdir( fullpath )
720 filesList = [k for k in filesList if 'M' in k]
720 ##filesList = [k for k in filesList if 'M' in k]
721 721 if len( filesList ) > 0:
722 722 filesList = sorted( filesList, key=str.lower )
723 723 filen = filesList[-1]
@@ -785,7 +785,7 class ParamWriter(Operation):
785 785 for j in range(dsInfo['dsNumber']):
786 786 dsInfo = dsList[i]
787 787 tableName = dsInfo['dsName']
788
788
789 789
790 790 if dsInfo['nDim'] == 3:
791 791 shape = dsInfo['shape'].astype(int)
@@ -954,7 +954,7 class ParamWriter(Operation):
954 954
955 955 self.dataOut = dataOut
956 956 if not(self.isConfig):
957 self.setup(dataOut, path=path, blocksPerFile=blocksPerFile,
957 self.setup(dataOut, path=path, blocksPerFile=blocksPerFile,
958 958 metadataList=metadataList, dataList=dataList, mode=mode,
959 959 setType=setType)
960 960
@@ -963,7 +963,7 class ParamWriter(Operation):
963 963
964 964 self.putData()
965 965 return
966
966
967 967
968 968 @MPDecorator
969 969 class ParameterReader(Reader, ProcessingUnit):
@@ -992,43 +992,43 class ParameterReader(Reader, ProcessingUnit):
992 992
993 993 self.set_kwargs(**kwargs)
994 994 if not self.ext.startswith('.'):
995 self.ext = '.{}'.format(self.ext)
995 self.ext = '.{}'.format(self.ext)
996 996
997 997 if self.online:
998 998 log.log("Searching files in online mode...", self.name)
999 999
1000 1000 for nTries in range(self.nTries):
1001 1001 fullpath = self.searchFilesOnLine(self.path, self.startDate,
1002 self.endDate, self.expLabel, self.ext, self.walk,
1002 self.endDate, self.expLabel, self.ext, self.walk,
1003 1003 self.filefmt, self.folderfmt)
1004 1004
1005 1005 try:
1006 1006 fullpath = next(fullpath)
1007 1007 except:
1008 1008 fullpath = None
1009
1009
1010 1010 if fullpath:
1011 1011 break
1012 1012
1013 1013 log.warning(
1014 1014 'Waiting {} sec for a valid file in {}: try {} ...'.format(
1015 self.delay, self.path, nTries + 1),
1015 self.delay, self.path, nTries + 1),
1016 1016 self.name)
1017 1017 time.sleep(self.delay)
1018 1018
1019 1019 if not(fullpath):
1020 1020 raise schainpy.admin.SchainError(
1021 'There isn\'t any valid file in {}'.format(self.path))
1021 'There isn\'t any valid file in {}'.format(self.path))
1022 1022
1023 1023 pathname, filename = os.path.split(fullpath)
1024 1024 self.year = int(filename[1:5])
1025 1025 self.doy = int(filename[5:8])
1026 self.set = int(filename[8:11]) - 1
1026 self.set = int(filename[8:11]) - 1
1027 1027 else:
1028 1028 log.log("Searching files in {}".format(self.path), self.name)
1029 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1029 self.filenameList = self.searchFilesOffLine(self.path, self.startDate,
1030 1030 self.endDate, self.expLabel, self.ext, self.walk, self.filefmt, self.folderfmt)
1031
1031
1032 1032 self.setNextFile()
1033 1033
1034 1034 return
@@ -1036,11 +1036,11 class ParameterReader(Reader, ProcessingUnit):
1036 1036 def readFirstHeader(self):
1037 1037 '''Read metadata and data'''
1038 1038
1039 self.__readMetadata()
1039 self.__readMetadata()
1040 1040 self.__readData()
1041 1041 self.__setBlockList()
1042 1042 self.blockIndex = 0
1043
1043
1044 1044 return
1045 1045
1046 1046 def __setBlockList(self):
@@ -1099,7 +1099,7 class ParameterReader(Reader, ProcessingUnit):
1099 1099 else:
1100 1100 data = gp[name].value
1101 1101 listMetaname.append(name)
1102 listMetadata.append(data)
1102 listMetadata.append(data)
1103 1103 elif self.metadata:
1104 1104 metadata = json.loads(self.metadata)
1105 1105 listShapes = {}
@@ -1115,7 +1115,7 class ParameterReader(Reader, ProcessingUnit):
1115 1115
1116 1116 self.listShapes = listShapes
1117 1117 self.listMetaname = listMetaname
1118 self.listMeta = listMetadata
1118 self.listMeta = listMetadata
1119 1119
1120 1120 return
1121 1121
@@ -1123,7 +1123,7 class ParameterReader(Reader, ProcessingUnit):
1123 1123
1124 1124 listdataname = []
1125 1125 listdata = []
1126
1126
1127 1127 if 'Data' in self.fp:
1128 1128 grp = self.fp['Data']
1129 1129 for item in list(grp.items()):
@@ -1137,7 +1137,7 class ParameterReader(Reader, ProcessingUnit):
1137 1137 for i in range(dim):
1138 1138 array.append(grp[name]['table{:02d}'.format(i)].value)
1139 1139 array = numpy.array(array)
1140
1140
1141 1141 listdata.append(array)
1142 1142 elif self.metadata:
1143 1143 metadata = json.loads(self.metadata)
@@ -1160,7 +1160,7 class ParameterReader(Reader, ProcessingUnit):
1160 1160 self.listDataname = listdataname
1161 1161 self.listData = listdata
1162 1162 return
1163
1163
1164 1164 def getData(self):
1165 1165
1166 1166 for i in range(len(self.listMeta)):
@@ -1230,7 +1230,7 class ParameterWriter(Operation):
1230 1230 lastTime = None
1231 1231
1232 1232 def __init__(self):
1233
1233
1234 1234 Operation.__init__(self)
1235 1235 return
1236 1236
@@ -1257,7 +1257,7 class ParameterWriter(Operation):
1257 1257 dsDict['nDim'] = len(dataAux.shape)
1258 1258 dsDict['shape'] = dataAux.shape
1259 1259 dsDict['dsNumber'] = dataAux.shape[0]
1260
1260
1261 1261 dsList.append(dsDict)
1262 1262 tableList.append((self.dataList[i], dsDict['nDim']))
1263 1263
@@ -1274,7 +1274,7 class ParameterWriter(Operation):
1274 1274 self.lastTime = currentTime
1275 1275 self.currentDay = dataDay
1276 1276 return False
1277
1277
1278 1278 timeDiff = currentTime - self.lastTime
1279 1279
1280 1280 #Si el dia es diferente o si la diferencia entre un dato y otro supera la hora
@@ -1292,7 +1292,7 class ParameterWriter(Operation):
1292 1292
1293 1293 self.dataOut = dataOut
1294 1294 if not(self.isConfig):
1295 self.setup(path=path, blocksPerFile=blocksPerFile,
1295 self.setup(path=path, blocksPerFile=blocksPerFile,
1296 1296 metadataList=metadataList, dataList=dataList,
1297 1297 setType=setType)
1298 1298
@@ -1301,9 +1301,9 class ParameterWriter(Operation):
1301 1301
1302 1302 self.putData()
1303 1303 return
1304
1304
1305 1305 def setNextFile(self):
1306
1306
1307 1307 ext = self.ext
1308 1308 path = self.path
1309 1309 setFile = self.setFile
@@ -1369,17 +1369,17 class ParameterWriter(Operation):
1369 1369 return
1370 1370
1371 1371 def writeData(self, fp):
1372
1372
1373 1373 grp = fp.create_group("Data")
1374 1374 dtsets = []
1375 1375 data = []
1376
1376
1377 1377 for dsInfo in self.dsList:
1378 1378 if dsInfo['nDim'] == 0:
1379 1379 ds = grp.create_dataset(
1380 dsInfo['variable'],
1380 dsInfo['variable'],
1381 1381 (self.blocksPerFile, ),
1382 chunks=True,
1382 chunks=True,
1383 1383 dtype=numpy.float64)
1384 1384 dtsets.append(ds)
1385 1385 data.append((dsInfo['variable'], -1))
@@ -1387,7 +1387,7 class ParameterWriter(Operation):
1387 1387 sgrp = grp.create_group(dsInfo['variable'])
1388 1388 for i in range(dsInfo['dsNumber']):
1389 1389 ds = sgrp.create_dataset(
1390 'table{:02d}'.format(i),
1390 'table{:02d}'.format(i),
1391 1391 (self.blocksPerFile, ) + dsInfo['shape'][1:],
1392 1392 chunks=True)
1393 1393 dtsets.append(ds)
@@ -1395,7 +1395,7 class ParameterWriter(Operation):
1395 1395 fp.flush()
1396 1396
1397 1397 log.log('Creating file: {}'.format(fp.filename), self.name)
1398
1398
1399 1399 self.ds = dtsets
1400 1400 self.data = data
1401 1401 self.firsttime = True
@@ -4,8 +4,8 Author : Sergio Cortez
4 4 Jan 2018
5 5 Abstract:
6 6 Base class for processing units and operations. A decorator provides multiprocessing features and interconnect the processes created.
7 The argument (kwargs) sent from the controller is parsed and filtered via the decorator for each processing unit or operation instantiated.
8 The decorator handle also the methods inside the processing unit to be called from the main script (not as operations) (OPERATION -> type ='self').
7 The argument (kwargs) sent from the controller is parsed and filtered via the decorator for each processing unit or operation instantiated.
8 The decorator handle also the methods inside the processing unit to be called from the main script (not as operations) (OPERATION -> type ='self').
9 9
10 10 Based on:
11 11 $Author: murco $
@@ -33,14 +33,14 class ProcessingUnit(object):
33 33
34 34 """
35 35 Update - Jan 2018 - MULTIPROCESSING
36 All the "call" methods present in the previous base were removed.
36 All the "call" methods present in the previous base were removed.
37 37 The majority of operations are independant processes, thus
38 the decorator is in charge of communicate the operation processes
38 the decorator is in charge of communicate the operation processes
39 39 with the proccessing unit via IPC.
40 40
41 41 The constructor does not receive any argument. The remaining methods
42 42 are related with the operations to execute.
43
43
44 44
45 45 """
46 46 proc_type = 'processing'
@@ -62,7 +62,7 class ProcessingUnit(object):
62 62
63 63 def addOperation(self, conf, operation):
64 64 """
65 This method is used in the controller, and update the dictionary containing the operations to execute. The dict
65 This method is used in the controller, and update the dictionary containing the operations to execute. The dict
66 66 posses the id of the operation process (IPC purposes)
67 67
68 68 Agrega un objeto del tipo "Operation" (opObj) a la lista de objetos "self.objectList" y retorna el
@@ -79,7 +79,7 class ProcessingUnit(object):
79 79
80 80 self.operations.append(
81 81 (operation, conf.type, conf.id, conf.getKwargs()))
82
82
83 83 if 'plot' in self.name.lower():
84 84 self.plots.append(operation.CODE)
85 85
@@ -181,7 +181,7 class Operation(object):
181 181 return
182 182
183 183 class InputQueue(Thread):
184
184
185 185 '''
186 186 Class to hold input data for Proccessing Units and external Operations,
187 187 '''
@@ -212,26 +212,26 class InputQueue(Thread):
212 212 def get(self):
213 213
214 214 if not self.islocked and self.size/1000000 > 512:
215 self.lock.n.value += 1
215 self.lock.n.value += 1
216 216 self.islocked = True
217 217 self.lock.clear()
218 218 elif self.islocked and self.size/1000000 <= 512:
219 219 self.islocked = False
220 220 self.lock.n.value -= 1
221 221 if self.lock.n.value == 0:
222 self.lock.set()
223
222 self.lock.set()
223
224 224 obj = self.queue.get()
225 225 self.size -= sys.getsizeof(obj)
226 226 return pickle.loads(obj)
227 227
228
228
229 229 def MPDecorator(BaseClass):
230 230 """
231 231 Multiprocessing class decorator
232 232
233 233 This function add multiprocessing features to a BaseClass. Also, it handle
234 the communication beetween processes (readers, procUnits and operations).
234 the communication beetween processes (readers, procUnits and operations).
235 235 """
236 236
237 237 class MPClass(BaseClass, Process):
@@ -248,11 +248,11 def MPDecorator(BaseClass):
248 248 self.t = time.time()
249 249 self.name = BaseClass.__name__
250 250 self.__doc__ = BaseClass.__doc__
251
251
252 252 if 'plot' in self.name.lower() and not self.name.endswith('_'):
253 253 self.name = '{}{}'.format(self.CODE.upper(), 'Plot')
254
255 self.start_time = time.time()
254
255 self.start_time = time.time()
256 256 self.id = args[0]
257 257 self.inputId = args[1]
258 258 self.project_id = args[2]
@@ -269,21 +269,21 def MPDecorator(BaseClass):
269 269 '''
270 270
271 271 self.queue.start()
272
272
273 273 def listen(self):
274 274 '''
275 275 This function waits for objects
276 276 '''
277
278 return self.queue.get()
277
278 return self.queue.get()
279 279
280 280 def set_publisher(self):
281 281 '''
282 This function create a zmq socket for publishing objects.
282 This function create a zmq socket for publishing objects.
283 283 '''
284 284
285 285 time.sleep(0.5)
286
286
287 287 c = zmq.Context()
288 288 self.sender = c.socket(zmq.PUB)
289 289 self.sender.connect(
@@ -293,12 +293,11 def MPDecorator(BaseClass):
293 293 '''
294 294 This function publish an object, to an specific topic.
295 295 It blocks publishing when receiver queue is full to avoid data loss
296 '''
297
296 '''
297
298 298 if self.inputId is None:
299 299 self.lock.wait()
300 300 self.sender.send_multipart([str(id).encode(), pickle.dumps(data)])
301
302 301 def runReader(self):
303 302 '''
304 303 Run fuction for read units
@@ -308,13 +307,13 def MPDecorator(BaseClass):
308 307 try:
309 308 BaseClass.run(self, **self.kwargs)
310 309 except:
311 err = traceback.format_exc()
310 err = traceback.format_exc()
312 311 if 'No more files' in err:
313 312 log.warning('No more files to read', self.name)
314 313 else:
315 314 self.err_queue.put('{}|{}'.format(self.name, err))
316 self.dataOut.error = True
317
315 self.dataOut.error = True
316
318 317 for op, optype, opId, kwargs in self.operations:
319 318 if optype == 'self' and not self.dataOut.flagNoData:
320 319 op(**kwargs)
@@ -327,8 +326,7 def MPDecorator(BaseClass):
327 326 continue
328 327
329 328 self.publish(self.dataOut, self.id)
330
331 if self.dataOut.error:
329 if self.dataOut.error:
332 330 break
333 331
334 332 time.sleep(0.5)
@@ -339,7 +337,7 def MPDecorator(BaseClass):
339 337 '''
340 338
341 339 while True:
342 self.dataIn = self.listen()
340 self.dataIn = self.listen()
343 341
344 342 if self.dataIn.flagNoData and self.dataIn.error is None:
345 343 continue
@@ -352,23 +350,23 def MPDecorator(BaseClass):
352 350 elif self.dataIn.error:
353 351 self.dataOut.error = self.dataIn.error
354 352 self.dataOut.flagNoData = True
355
353
356 354 for op, optype, opId, kwargs in self.operations:
357 355 if optype == 'self' and not self.dataOut.flagNoData:
358 356 op(**kwargs)
359 357 elif optype == 'other' and not self.dataOut.flagNoData:
360 358 self.dataOut = op.run(self.dataOut, **kwargs)
361 elif optype == 'external' and not self.dataOut.flagNoData:
359 elif optype == 'external' and not self.dataOut.flagNoData:
362 360 self.publish(self.dataOut, opId)
363
361
364 362 self.publish(self.dataOut, self.id)
365 363 for op, optype, opId, kwargs in self.operations:
366 if optype == 'external' and self.dataOut.error:
364 if optype == 'external' and self.dataOut.error:
367 365 self.publish(self.dataOut, opId)
368
366
369 367 if self.dataOut.error:
370 368 break
371
369
372 370 time.sleep(0.5)
373 371
374 372 def runOp(self):
@@ -376,7 +374,7 def MPDecorator(BaseClass):
376 374 Run function for external operations (this operations just receive data
377 375 ex: plots, writers, publishers)
378 376 '''
379
377
380 378 while True:
381 379
382 380 dataOut = self.listen()
@@ -388,21 +386,20 def MPDecorator(BaseClass):
388 386 self.err_queue.put('{}|{}'.format(self.name, traceback.format_exc()))
389 387 dataOut.error = True
390 388 else:
391 break
389 break
392 390
393 391 def run(self):
394 392 if self.typeProc is "ProcUnit":
395 393
396 394 if self.inputId is not None:
397 395 self.subscribe()
398
396
399 397 self.set_publisher()
400 398
401 399 if 'Reader' not in BaseClass.__name__:
402 400 self.runProc()
403 401 else:
404 402 self.runReader()
405
406 403 elif self.typeProc is "Operation":
407 404
408 405 self.subscribe()
This diff has been collapsed as it changes many lines, (2152 lines changed) Show them Hide them
@@ -8,12 +8,12 import copy
8 8 import sys
9 9 import importlib
10 10 import itertools
11 from multiprocessing import Pool, TimeoutError
11 from multiprocessing import Pool, TimeoutError
12 12 from multiprocessing.pool import ThreadPool
13 13 import time
14 14
15 15 from scipy.optimize import fmin_l_bfgs_b #optimize with bounds on state papameters
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
16 from .jroproc_base import ProcessingUnit, Operation, MPDecorator
17 17 from schainpy.model.data.jrodata import Parameters, hildebrand_sekhon
18 18 from scipy import asarray as ar,exp
19 19 from scipy.optimize import curve_fit
@@ -47,13 +47,13 def _unpickle_method(func_name, obj, cls):
47 47
48 48 @MPDecorator
49 49 class ParametersProc(ProcessingUnit):
50
50
51 51 METHODS = {}
52 52 nSeconds = None
53 53
54 54 def __init__(self):
55 55 ProcessingUnit.__init__(self)
56
56
57 57 # self.objectDict = {}
58 58 self.buffer = None
59 59 self.firstdatatime = None
@@ -62,14 +62,14 class ParametersProc(ProcessingUnit):
62 62 self.setupReq = False #Agregar a todas las unidades de proc
63 63
64 64 def __updateObjFromInput(self):
65
65
66 66 self.dataOut.inputUnit = self.dataIn.type
67
67
68 68 self.dataOut.timeZone = self.dataIn.timeZone
69 69 self.dataOut.dstFlag = self.dataIn.dstFlag
70 70 self.dataOut.errorCount = self.dataIn.errorCount
71 71 self.dataOut.useLocalTime = self.dataIn.useLocalTime
72
72
73 73 self.dataOut.radarControllerHeaderObj = self.dataIn.radarControllerHeaderObj.copy()
74 74 self.dataOut.systemHeaderObj = self.dataIn.systemHeaderObj.copy()
75 75 self.dataOut.channelList = self.dataIn.channelList
@@ -91,27 +91,27 class ParametersProc(ProcessingUnit):
91 91 self.dataOut.ippSeconds = self.dataIn.ippSeconds
92 92 # self.dataOut.windowOfFilter = self.dataIn.windowOfFilter
93 93 self.dataOut.timeInterval1 = self.dataIn.timeInterval
94 self.dataOut.heightList = self.dataIn.getHeiRange()
94 self.dataOut.heightList = self.dataIn.getHeiRange()
95 95 self.dataOut.frequency = self.dataIn.frequency
96 96 # self.dataOut.noise = self.dataIn.noise
97
97
98 98 def run(self):
99 99
100 100
101 101
102 102 #---------------------- Voltage Data ---------------------------
103
103
104 104 if self.dataIn.type == "Voltage":
105 105
106 106 self.__updateObjFromInput()
107 107 self.dataOut.data_pre = self.dataIn.data.copy()
108 108 self.dataOut.flagNoData = False
109 109 self.dataOut.utctimeInit = self.dataIn.utctime
110 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
110 self.dataOut.paramInterval = self.dataIn.nProfiles*self.dataIn.nCohInt*self.dataIn.ippSeconds
111 111 return
112
112
113 113 #---------------------- Spectra Data ---------------------------
114
114
115 115 if self.dataIn.type == "Spectra":
116 116
117 117 self.dataOut.data_pre = (self.dataIn.data_spc, self.dataIn.data_cspc)
@@ -125,243 +125,244 class ParametersProc(ProcessingUnit):
125 125 self.dataOut.spc_noise = self.dataIn.getNoise()
126 126 self.dataOut.spc_range = (self.dataIn.getFreqRange(1) , self.dataIn.getAcfRange(1) , self.dataIn.getVelRange(1))
127 127 # self.dataOut.normFactor = self.dataIn.normFactor
128 self.dataOut.pairsList = self.dataIn.pairsList
128 self.dataOut.pairsList = self.dataIn.pairsList
129 129 self.dataOut.groupList = self.dataIn.pairsList
130 self.dataOut.flagNoData = False
131
130 self.dataOut.flagNoData = False
131
132 132 if hasattr(self.dataIn, 'ChanDist'): #Distances of receiver channels
133 133 self.dataOut.ChanDist = self.dataIn.ChanDist
134 else: self.dataOut.ChanDist = None
135
134 else: self.dataOut.ChanDist = None
135
136 136 #if hasattr(self.dataIn, 'VelRange'): #Velocities range
137 137 # self.dataOut.VelRange = self.dataIn.VelRange
138 138 #else: self.dataOut.VelRange = None
139
139
140 140 if hasattr(self.dataIn, 'RadarConst'): #Radar Constant
141 141 self.dataOut.RadarConst = self.dataIn.RadarConst
142
142
143 143 if hasattr(self.dataIn, 'NPW'): #NPW
144 144 self.dataOut.NPW = self.dataIn.NPW
145
145
146 146 if hasattr(self.dataIn, 'COFA'): #COFA
147 147 self.dataOut.COFA = self.dataIn.COFA
148
149
150
148
149
150
151 151 #---------------------- Correlation Data ---------------------------
152
152
153 153 if self.dataIn.type == "Correlation":
154 154 acf_ind, ccf_ind, acf_pairs, ccf_pairs, data_acf, data_ccf = self.dataIn.splitFunctions()
155
155
156 156 self.dataOut.data_pre = (self.dataIn.data_cf[acf_ind,:], self.dataIn.data_cf[ccf_ind,:,:])
157 157 self.dataOut.normFactor = (self.dataIn.normFactor[acf_ind,:], self.dataIn.normFactor[ccf_ind,:])
158 158 self.dataOut.groupList = (acf_pairs, ccf_pairs)
159
159
160 160 self.dataOut.abscissaList = self.dataIn.lagRange
161 161 self.dataOut.noise = self.dataIn.noise
162 162 self.dataOut.data_SNR = self.dataIn.SNR
163 163 self.dataOut.flagNoData = False
164 164 self.dataOut.nAvg = self.dataIn.nAvg
165
165
166 166 #---------------------- Parameters Data ---------------------------
167
167
168 168 if self.dataIn.type == "Parameters":
169 169 self.dataOut.copy(self.dataIn)
170 170 self.dataOut.flagNoData = False
171
171
172 172 return True
173
173
174 174 self.__updateObjFromInput()
175 175 self.dataOut.utctimeInit = self.dataIn.utctime
176 176 self.dataOut.paramInterval = self.dataIn.timeInterval
177
177
178
178 179 return
179 180
180 181
181 182 def target(tups):
182
183
183 184 obj, args = tups
184
185
185 186 return obj.FitGau(args)
186
187
187
188
188 189 class SpectralFilters(Operation):
189
190
190 191 '''This class allows the Rainfall / Wind Selection for CLAIRE RADAR
191
192
192 193 LimitR : It is the limit in m/s of Rainfall
193 194 LimitW : It is the limit in m/s for Winds
194
195
195 196 Input:
196
197
197 198 self.dataOut.data_pre : SPC and CSPC
198 199 self.dataOut.spc_range : To select wind and rainfall velocities
199
200
200 201 Affected:
201
202
202 203 self.dataOut.data_pre : It is used for the new SPC and CSPC ranges of wind
203 self.dataOut.spcparam_range : Used in SpcParamPlot
204 self.dataOut.spcparam_range : Used in SpcParamPlot
204 205 self.dataOut.SPCparam : Used in PrecipitationProc
205
206
206
207
207 208 '''
208
209
209 210 def __init__(self):
210 211 Operation.__init__(self)
211 212 self.i=0
212
213 def run(self, dataOut, PositiveLimit=1.5, NegativeLimit=2.5):
214
215
216 #Limite de vientos
213
214 def run(self, dataOut, PositiveLimit=1.5, NegativeLimit=2.5):
215
216
217 #Limite de vientos
217 218 LimitR = PositiveLimit
218 219 LimitN = NegativeLimit
219
220
220 221 self.spc = dataOut.data_pre[0].copy()
221 222 self.cspc = dataOut.data_pre[1].copy()
222
223
223 224 self.Num_Hei = self.spc.shape[2]
224 225 self.Num_Bin = self.spc.shape[1]
225 226 self.Num_Chn = self.spc.shape[0]
226
227
227 228 VelRange = dataOut.spc_range[2]
228 229 TimeRange = dataOut.spc_range[1]
229 230 FrecRange = dataOut.spc_range[0]
230
231
231 232 Vmax= 2*numpy.max(dataOut.spc_range[2])
232 233 Tmax= 2*numpy.max(dataOut.spc_range[1])
233 234 Fmax= 2*numpy.max(dataOut.spc_range[0])
234
235
235 236 Breaker1R=VelRange[numpy.abs(VelRange-(-LimitN)).argmin()]
236 237 Breaker1R=numpy.where(VelRange == Breaker1R)
237
238 Delta = self.Num_Bin/2 - Breaker1R[0]
239
240
238
239 Delta = self.Num_Bin/2 - Breaker1R[0]
240
241
241 242 '''Reacomodando SPCrange'''
242 243
243 244 VelRange=numpy.roll(VelRange,-(int(self.Num_Bin/2)) ,axis=0)
244
245
245 246 VelRange[-(int(self.Num_Bin/2)):]+= Vmax
246
247
247 248 FrecRange=numpy.roll(FrecRange,-(int(self.Num_Bin/2)),axis=0)
248
249
249 250 FrecRange[-(int(self.Num_Bin/2)):]+= Fmax
250
251
251 252 TimeRange=numpy.roll(TimeRange,-(int(self.Num_Bin/2)),axis=0)
252
253
253 254 TimeRange[-(int(self.Num_Bin/2)):]+= Tmax
254
255
255 256 ''' ------------------ '''
256
257
257 258 Breaker2R=VelRange[numpy.abs(VelRange-(LimitR)).argmin()]
258 259 Breaker2R=numpy.where(VelRange == Breaker2R)
259
260
260
261
261 262 SPCroll = numpy.roll(self.spc,-(int(self.Num_Bin/2)) ,axis=1)
262
263
263 264 SPCcut = SPCroll.copy()
264 265 for i in range(self.Num_Chn):
265
266
266 267 SPCcut[i,0:int(Breaker2R[0]),:] = dataOut.noise[i]
267 268 SPCcut[i,-int(Delta):,:] = dataOut.noise[i]
268
269
269 270 SPCcut[i]=SPCcut[i]- dataOut.noise[i]
270 271 SPCcut[ numpy.where( SPCcut<0 ) ] = 1e-20
271
272
272 273 SPCroll[i]=SPCroll[i]-dataOut.noise[i]
273 274 SPCroll[ numpy.where( SPCroll<0 ) ] = 1e-20
274
275
275 276 SPC_ch1 = SPCroll
276
277
277 278 SPC_ch2 = SPCcut
278
279
279 280 SPCparam = (SPC_ch1, SPC_ch2, self.spc)
280 dataOut.SPCparam = numpy.asarray(SPCparam)
281
282
281 dataOut.SPCparam = numpy.asarray(SPCparam)
282
283
283 284 dataOut.spcparam_range=numpy.zeros([self.Num_Chn,self.Num_Bin+1])
284
285
285 286 dataOut.spcparam_range[2]=VelRange
286 287 dataOut.spcparam_range[1]=TimeRange
287 288 dataOut.spcparam_range[0]=FrecRange
288 289 return dataOut
289
290
290 291 class GaussianFit(Operation):
291
292
292 293 '''
293 Function that fit of one and two generalized gaussians (gg) based
294 on the PSD shape across an "power band" identified from a cumsum of
294 Function that fit of one and two generalized gaussians (gg) based
295 on the PSD shape across an "power band" identified from a cumsum of
295 296 the measured spectrum - noise.
296
297
297 298 Input:
298 299 self.dataOut.data_pre : SelfSpectra
299
300
300 301 Output:
301 302 self.dataOut.SPCparam : SPC_ch1, SPC_ch2
302
303
303 304 '''
304 305 def __init__(self):
305 306 Operation.__init__(self)
306 307 self.i=0
307
308
308
309
309 310 def run(self, dataOut, num_intg=7, pnoise=1., SNRlimit=-9): #num_intg: Incoherent integrations, pnoise: Noise, vel_arr: range of velocities, similar to the ftt points
310 311 """This routine will find a couple of generalized Gaussians to a power spectrum
311 312 input: spc
312 313 output:
313 314 Amplitude0,shift0,width0,p0,Amplitude1,shift1,width1,p1,noise
314 315 """
315
316
316 317 self.spc = dataOut.data_pre[0].copy()
317 318 self.Num_Hei = self.spc.shape[2]
318 319 self.Num_Bin = self.spc.shape[1]
319 320 self.Num_Chn = self.spc.shape[0]
320 321 Vrange = dataOut.abscissaList
321
322
322 323 GauSPC = numpy.empty([self.Num_Chn,self.Num_Bin,self.Num_Hei])
323 324 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
324 325 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
325 326 SPC_ch1[:] = numpy.NaN
326 327 SPC_ch2[:] = numpy.NaN
327 328
328
329
329 330 start_time = time.time()
330
331
331 332 noise_ = dataOut.spc_noise[0].copy()
332
333
334 pool = Pool(processes=self.Num_Chn)
333
334
335 pool = Pool(processes=self.Num_Chn)
335 336 args = [(Vrange, Ch, pnoise, noise_, num_intg, SNRlimit) for Ch in range(self.Num_Chn)]
336 objs = [self for __ in range(self.Num_Chn)]
337 attrs = list(zip(objs, args))
337 objs = [self for __ in range(self.Num_Chn)]
338 attrs = list(zip(objs, args))
338 339 gauSPC = pool.map(target, attrs)
339 340 dataOut.SPCparam = numpy.asarray(SPCparam)
340
341
341 342 ''' Parameters:
342 343 1. Amplitude
343 344 2. Shift
344 345 3. Width
345 346 4. Power
346 347 '''
347
348
348 349 def FitGau(self, X):
349
350
350 351 Vrange, ch, pnoise, noise_, num_intg, SNRlimit = X
351
352
352 353 SPCparam = []
353 354 SPC_ch1 = numpy.empty([self.Num_Bin,self.Num_Hei])
354 355 SPC_ch2 = numpy.empty([self.Num_Bin,self.Num_Hei])
355 356 SPC_ch1[:] = 0#numpy.NaN
356 357 SPC_ch2[:] = 0#numpy.NaN
357
358
359
358
359
360
360 361 for ht in range(self.Num_Hei):
361
362
362
363
363 364 spc = numpy.asarray(self.spc)[ch,:,ht]
364
365
365 366 #############################################
366 367 # normalizing spc and noise
367 368 # This part differs from gg1
@@ -369,60 +370,60 class GaussianFit(Operation):
369 370 #spc = spc / spc_norm_max
370 371 pnoise = pnoise #/ spc_norm_max
371 372 #############################################
372
373
373 374 fatspectra=1.0
374
375
375 376 wnoise = noise_ #/ spc_norm_max
376 377 #wnoise,stdv,i_max,index =enoise(spc,num_intg) #noise estimate using Hildebrand Sekhon, only wnoise is used
377 #if wnoise>1.1*pnoise: # to be tested later
378 #if wnoise>1.1*pnoise: # to be tested later
378 379 # wnoise=pnoise
379 noisebl=wnoise*0.9;
380 noisebl=wnoise*0.9;
380 381 noisebh=wnoise*1.1
381 382 spc=spc-wnoise
382
383
383 384 minx=numpy.argmin(spc)
384 #spcs=spc.copy()
385 #spcs=spc.copy()
385 386 spcs=numpy.roll(spc,-minx)
386 387 cum=numpy.cumsum(spcs)
387 388 tot_noise=wnoise * self.Num_Bin #64;
388
389
389 390 snr = sum(spcs)/tot_noise
390 391 snrdB=10.*numpy.log10(snr)
391
392
392 393 if snrdB < SNRlimit :
393 394 snr = numpy.NaN
394 395 SPC_ch1[:,ht] = 0#numpy.NaN
395 396 SPC_ch1[:,ht] = 0#numpy.NaN
396 397 SPCparam = (SPC_ch1,SPC_ch2)
397 398 continue
398
399
399
400
400 401 #if snrdB<-18 or numpy.isnan(snrdB) or num_intg<4:
401 402 # return [None,]*4,[None,]*4,None,snrdB,None,None,[None,]*5,[None,]*9,None
402
403 cummax=max(cum);
403
404 cummax=max(cum);
404 405 epsi=0.08*fatspectra # cumsum to narrow down the energy region
405 cumlo=cummax*epsi;
406 cumlo=cummax*epsi;
406 407 cumhi=cummax*(1-epsi)
407 408 powerindex=numpy.array(numpy.where(numpy.logical_and(cum>cumlo, cum<cumhi))[0])
408
409
409
410
410 411 if len(powerindex) < 1:# case for powerindex 0
411 412 continue
412 413 powerlo=powerindex[0]
413 414 powerhi=powerindex[-1]
414 415 powerwidth=powerhi-powerlo
415
416
416 417 firstpeak=powerlo+powerwidth/10.# first gaussian energy location
417 418 secondpeak=powerhi-powerwidth/10.#second gaussian energy location
418 419 midpeak=(firstpeak+secondpeak)/2.
419 420 firstamp=spcs[int(firstpeak)]
420 421 secondamp=spcs[int(secondpeak)]
421 422 midamp=spcs[int(midpeak)]
422
423
423 424 x=numpy.arange( self.Num_Bin )
424 425 y_data=spc+wnoise
425
426
426 427 ''' single Gaussian '''
427 428 shift0=numpy.mod(midpeak+minx, self.Num_Bin )
428 429 width0=powerwidth/4.#Initialization entire power of spectrum divided by 4
@@ -431,10 +432,10 class GaussianFit(Operation):
431 432 state0=[shift0,width0,amplitude0,power0,wnoise]
432 433 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth),(0,None),(0.5,3.),(noisebl,noisebh))
433 434 lsq1=fmin_l_bfgs_b(self.misfit1,state0,args=(y_data,x,num_intg),bounds=bnds,approx_grad=True)
434
435 chiSq1=lsq1[1];
436 435
437
436 chiSq1=lsq1[1];
437
438
438 439 if fatspectra<1.0 and powerwidth<4:
439 440 choice=0
440 441 Amplitude0=lsq1[0][2]
@@ -448,31 +449,31 class GaussianFit(Operation):
448 449 noise=lsq1[0][4]
449 450 #return (numpy.array([shift0,width0,Amplitude0,p0]),
450 451 # numpy.array([shift1,width1,Amplitude1,p1]),noise,snrdB,chiSq1,6.,sigmas1,[None,]*9,choice)
451
452
452 453 ''' two gaussians '''
453 454 #shift0=numpy.mod(firstpeak+minx,64); shift1=numpy.mod(secondpeak+minx,64)
454 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
455 shift0=numpy.mod(firstpeak+minx, self.Num_Bin );
455 456 shift1=numpy.mod(secondpeak+minx, self.Num_Bin )
456 width0=powerwidth/6.;
457 width0=powerwidth/6.;
457 458 width1=width0
458 power0=2.;
459 power0=2.;
459 460 power1=power0
460 amplitude0=firstamp;
461 amplitude0=firstamp;
461 462 amplitude1=secondamp
462 463 state0=[shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,wnoise]
463 464 #bnds=((0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(0,63),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
464 465 bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(noisebl,noisebh))
465 466 #bnds=(( 0,(self.Num_Bin-1) ),(1,powerwidth/2.),(0,None),(0.5,3.),( 0,(self.Num_Bin-1)),(1,powerwidth/2.),(0,None),(0.5,3.),(0.1,0.5))
466
467
467 468 lsq2 = fmin_l_bfgs_b( self.misfit2 , state0 , args=(y_data,x,num_intg) , bounds=bnds , approx_grad=True )
468
469
470 chiSq2=lsq2[1];
471
472
473
469
470
471 chiSq2=lsq2[1];
472
473
474
474 475 oneG=(chiSq1<5 and chiSq1/chiSq2<2.0) and (abs(lsq2[0][0]-lsq2[0][4])<(lsq2[0][1]+lsq2[0][5])/3. or abs(lsq2[0][0]-lsq2[0][4])<10)
475
476
476 477 if snrdB>-12: # when SNR is strong pick the peak with least shift (LOS velocity) error
477 478 if oneG:
478 479 choice=0
@@ -480,10 +481,10 class GaussianFit(Operation):
480 481 w1=lsq2[0][1]; w2=lsq2[0][5]
481 482 a1=lsq2[0][2]; a2=lsq2[0][6]
482 483 p1=lsq2[0][3]; p2=lsq2[0][7]
483 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
484 s1=(2**(1+1./p1))*scipy.special.gamma(1./p1)/p1;
484 485 s2=(2**(1+1./p2))*scipy.special.gamma(1./p2)/p2;
485 486 gp1=a1*w1*s1; gp2=a2*w2*s2 # power content of each ggaussian with proper p scaling
486
487
487 488 if gp1>gp2:
488 489 if a1>0.7*a2:
489 490 choice=1
@@ -498,157 +499,157 class GaussianFit(Operation):
498 499 choice=numpy.argmax([a1,a2])+1
499 500 #else:
500 501 #choice=argmin([std2a,std2b])+1
501
502
502 503 else: # with low SNR go to the most energetic peak
503 504 choice=numpy.argmax([lsq1[0][2]*lsq1[0][1],lsq2[0][2]*lsq2[0][1],lsq2[0][6]*lsq2[0][5]])
504
505
506 shift0=lsq2[0][0];
505
506
507 shift0=lsq2[0][0];
507 508 vel0=Vrange[0] + shift0*(Vrange[1]-Vrange[0])
508 shift1=lsq2[0][4];
509 shift1=lsq2[0][4];
509 510 vel1=Vrange[0] + shift1*(Vrange[1]-Vrange[0])
510
511
511 512 max_vel = 1.0
512
513
513 514 #first peak will be 0, second peak will be 1
514 515 if vel0 > -1.0 and vel0 < max_vel : #first peak is in the correct range
515 516 shift0=lsq2[0][0]
516 517 width0=lsq2[0][1]
517 518 Amplitude0=lsq2[0][2]
518 519 p0=lsq2[0][3]
519
520
520 521 shift1=lsq2[0][4]
521 522 width1=lsq2[0][5]
522 523 Amplitude1=lsq2[0][6]
523 524 p1=lsq2[0][7]
524 noise=lsq2[0][8]
525 noise=lsq2[0][8]
525 526 else:
526 527 shift1=lsq2[0][0]
527 528 width1=lsq2[0][1]
528 529 Amplitude1=lsq2[0][2]
529 530 p1=lsq2[0][3]
530
531
531 532 shift0=lsq2[0][4]
532 533 width0=lsq2[0][5]
533 534 Amplitude0=lsq2[0][6]
534 p0=lsq2[0][7]
535 noise=lsq2[0][8]
536
535 p0=lsq2[0][7]
536 noise=lsq2[0][8]
537
537 538 if Amplitude0<0.05: # in case the peak is noise
538 shift0,width0,Amplitude0,p0 = [0,0,0,0]#4*[numpy.NaN]
539 shift0,width0,Amplitude0,p0 = [0,0,0,0]#4*[numpy.NaN]
539 540 if Amplitude1<0.05:
540 shift1,width1,Amplitude1,p1 = [0,0,0,0]#4*[numpy.NaN]
541
542
541 shift1,width1,Amplitude1,p1 = [0,0,0,0]#4*[numpy.NaN]
542
543
543 544 SPC_ch1[:,ht] = noise + Amplitude0*numpy.exp(-0.5*(abs(x-shift0))/width0)**p0
544 545 SPC_ch2[:,ht] = noise + Amplitude1*numpy.exp(-0.5*(abs(x-shift1))/width1)**p1
545 546 SPCparam = (SPC_ch1,SPC_ch2)
546
547
547
548
548 549 return GauSPC
549
550
550 551 def y_model1(self,x,state):
551 552 shift0,width0,amplitude0,power0,noise=state
552 553 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
553
554
554 555 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
555
556
556 557 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
557 558 return model0+model0u+model0d+noise
558
559 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
559
560 def y_model2(self,x,state): #Equation for two generalized Gaussians with Nyquist
560 561 shift0,width0,amplitude0,power0,shift1,width1,amplitude1,power1,noise=state
561 562 model0=amplitude0*numpy.exp(-0.5*abs((x-shift0)/width0)**power0)
562
563
563 564 model0u=amplitude0*numpy.exp(-0.5*abs((x-shift0- self.Num_Bin )/width0)**power0)
564
565
565 566 model0d=amplitude0*numpy.exp(-0.5*abs((x-shift0+ self.Num_Bin )/width0)**power0)
566 567 model1=amplitude1*numpy.exp(-0.5*abs((x-shift1)/width1)**power1)
567
568
568 569 model1u=amplitude1*numpy.exp(-0.5*abs((x-shift1- self.Num_Bin )/width1)**power1)
569
570
570 571 model1d=amplitude1*numpy.exp(-0.5*abs((x-shift1+ self.Num_Bin )/width1)**power1)
571 572 return model0+model0u+model0d+model1+model1u+model1d+noise
572
573 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
573
574 def misfit1(self,state,y_data,x,num_intg): # This function compares how close real data is with the model data, the close it is, the better it is.
574 575
575 576 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model1(x,state)))**2)#/(64-5.) # /(64-5.) can be commented
576
577
577 578 def misfit2(self,state,y_data,x,num_intg):
578 579 return num_intg*sum((numpy.log(y_data)-numpy.log(self.y_model2(x,state)))**2)#/(64-9.)
579
580
580
581
581 582
582 583 class PrecipitationProc(Operation):
583
584
584 585 '''
585 586 Operator that estimates Reflectivity factor (Z), and estimates rainfall Rate (R)
586
587 Input:
587
588 Input:
588 589 self.dataOut.data_pre : SelfSpectra
589
590 Output:
591
592 self.dataOut.data_output : Reflectivity factor, rainfall Rate
593
594
595 Parameters affected:
590
591 Output:
592
593 self.dataOut.data_output : Reflectivity factor, rainfall Rate
594
595
596 Parameters affected:
596 597 '''
597
598
598 599 def __init__(self):
599 600 Operation.__init__(self)
600 601 self.i=0
601
602
602
603
603 604 def gaus(self,xSamples,Amp,Mu,Sigma):
604 605 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
605
606
607
606
607
608
608 609 def Moments(self, ySamples, xSamples):
609 610 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
610 611 yNorm = ySamples / Pot
611
612
612 613 Vr = numpy.nansum( yNorm * xSamples ) # Velocidad radial, mu, corrimiento doppler, primer momento
613 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
614 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
614 615 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
615
616 return numpy.array([Pot, Vr, Desv])
617
618 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
616
617 return numpy.array([Pot, Vr, Desv])
618
619 def run(self, dataOut, radar=None, Pt=5000, Gt=295.1209, Gr=70.7945, Lambda=0.6741, aL=2.5118,
619 620 tauW=4e-06, ThetaT=0.1656317, ThetaR=0.36774087, Km = 0.93, Altitude=3350):
620
621
621
622
622 623 Velrange = dataOut.spcparam_range[2]
623 624 FrecRange = dataOut.spcparam_range[0]
624
625
625 626 dV= Velrange[1]-Velrange[0]
626 627 dF= FrecRange[1]-FrecRange[0]
627
628
628 629 if radar == "MIRA35C" :
629
630
630 631 self.spc = dataOut.data_pre[0].copy()
631 632 self.Num_Hei = self.spc.shape[2]
632 633 self.Num_Bin = self.spc.shape[1]
633 634 self.Num_Chn = self.spc.shape[0]
634 635 Ze = self.dBZeMODE2(dataOut)
635
636
636 637 else:
637
638
638 639 self.spc = dataOut.SPCparam[1].copy() #dataOut.data_pre[0].copy() #
639
640
640 641 """NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX"""
641
642 self.spc[:,:,0:7]= numpy.NaN
643
642
643 self.spc[:,:,0:7]= numpy.NaN
644
644 645 """##########################################"""
645
646
646 647 self.Num_Hei = self.spc.shape[2]
647 648 self.Num_Bin = self.spc.shape[1]
648 649 self.Num_Chn = self.spc.shape[0]
649
650
650 651 ''' Se obtiene la constante del RADAR '''
651
652
652 653 self.Pt = Pt
653 654 self.Gt = Gt
654 655 self.Gr = Gr
@@ -657,30 +658,30 class PrecipitationProc(Operation):
657 658 self.tauW = tauW
658 659 self.ThetaT = ThetaT
659 660 self.ThetaR = ThetaR
660
661
661 662 Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
662 663 Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * tauW * numpy.pi * ThetaT * ThetaR)
663 664 RadarConstant = 10e-26 * Numerator / Denominator #
664
665
665 666 ''' ============================= '''
666
667 self.spc[0] = (self.spc[0]-dataOut.noise[0])
668 self.spc[1] = (self.spc[1]-dataOut.noise[1])
669 self.spc[2] = (self.spc[2]-dataOut.noise[2])
670
667
668 self.spc[0] = (self.spc[0]-dataOut.noise[0])
669 self.spc[1] = (self.spc[1]-dataOut.noise[1])
670 self.spc[2] = (self.spc[2]-dataOut.noise[2])
671
671 672 self.spc[ numpy.where(self.spc < 0)] = 0
672
673 SPCmean = (numpy.mean(self.spc,0) - numpy.mean(dataOut.noise))
673
674 SPCmean = (numpy.mean(self.spc,0) - numpy.mean(dataOut.noise))
674 675 SPCmean[ numpy.where(SPCmean < 0)] = 0
675
676
676 677 ETAn = numpy.zeros([self.Num_Bin,self.Num_Hei])
677 678 ETAv = numpy.zeros([self.Num_Bin,self.Num_Hei])
678 679 ETAd = numpy.zeros([self.Num_Bin,self.Num_Hei])
679
680
680 681 Pr = SPCmean[:,:]
681
682
682 683 VelMeteoro = numpy.mean(SPCmean,axis=0)
683
684
684 685 D_range = numpy.zeros([self.Num_Bin,self.Num_Hei])
685 686 SIGMA = numpy.zeros([self.Num_Bin,self.Num_Hei])
686 687 N_dist = numpy.zeros([self.Num_Bin,self.Num_Hei])
@@ -689,102 +690,102 class PrecipitationProc(Operation):
689 690 Z = numpy.zeros(self.Num_Hei)
690 691 Ze = numpy.zeros(self.Num_Hei)
691 692 RR = numpy.zeros(self.Num_Hei)
692
693
693 694 Range = dataOut.heightList*1000.
694
695
695 696 for R in range(self.Num_Hei):
696
697
697 698 h = Range[R] + Altitude #Range from ground to radar pulse altitude
698 699 del_V[R] = 1 + 3.68 * 10**-5 * h + 1.71 * 10**-9 * h**2 #Density change correction for velocity
699
700
700 701 D_range[:,R] = numpy.log( (9.65 - (Velrange[0:self.Num_Bin] / del_V[R])) / 10.3 ) / -0.6 #Diameter range [m]x10**-3
701
702
702 703 '''NOTA: ETA(n) dn = ETA(f) df
703
704
704 705 dn = 1 Diferencial de muestreo
705 706 df = ETA(n) / ETA(f)
706
707
707 708 '''
708
709
709 710 ETAn[:,R] = RadarConstant * Pr[:,R] * (Range[R] )**2 #Reflectivity (ETA)
710
711
711 712 ETAv[:,R]=ETAn[:,R]/dV
712
713
713 714 ETAd[:,R]=ETAv[:,R]*6.18*exp(-0.6*D_range[:,R])
714
715
715 716 SIGMA[:,R] = Km * (D_range[:,R] * 1e-3 )**6 * numpy.pi**5 / Lambda**4 #Equivalent Section of drops (sigma)
716
717 N_dist[:,R] = ETAn[:,R] / SIGMA[:,R]
718
717
718 N_dist[:,R] = ETAn[:,R] / SIGMA[:,R]
719
719 720 DMoments = self.Moments(Pr[:,R], Velrange[0:self.Num_Bin])
720
721
721 722 try:
722 723 popt01,pcov = curve_fit(self.gaus, Velrange[0:self.Num_Bin] , Pr[:,R] , p0=DMoments)
723 except:
724 except:
724 725 popt01=numpy.zeros(3)
725 726 popt01[1]= DMoments[1]
726
727
727 728 if popt01[1]<0 or popt01[1]>20:
728 729 popt01[1]=numpy.NaN
729
730
730
731
731 732 V_mean[R]=popt01[1]
732
733
733 734 Z[R] = numpy.nansum( N_dist[:,R] * (D_range[:,R])**6 )#*10**-18
734
735
735 736 RR[R] = 0.0006*numpy.pi * numpy.nansum( D_range[:,R]**3 * N_dist[:,R] * Velrange[0:self.Num_Bin] ) #Rainfall rate
736
737
737 738 Ze[R] = (numpy.nansum( ETAn[:,R]) * Lambda**4) / ( 10**-18*numpy.pi**5 * Km)
738
739
740
739
740
741
741 742 RR2 = (Z/200)**(1/1.6)
742 743 dBRR = 10*numpy.log10(RR)
743 744 dBRR2 = 10*numpy.log10(RR2)
744
745
745 746 dBZe = 10*numpy.log10(Ze)
746 747 dBZ = 10*numpy.log10(Z)
747
748
748 749 dataOut.data_output = RR[8]
749 750 dataOut.data_param = numpy.ones([3,self.Num_Hei])
750 751 dataOut.channelList = [0,1,2]
751
752
752 753 dataOut.data_param[0]=dBZ
753 754 dataOut.data_param[1]=V_mean
754 755 dataOut.data_param[2]=RR
755 756
756 757 return dataOut
757
758
758 759 def dBZeMODE2(self, dataOut): # Processing for MIRA35C
759
760
760 761 NPW = dataOut.NPW
761 762 COFA = dataOut.COFA
762
763
763 764 SNR = numpy.array([self.spc[0,:,:] / NPW[0]]) #, self.spc[1,:,:] / NPW[1]])
764 765 RadarConst = dataOut.RadarConst
765 766 #frequency = 34.85*10**9
766
767
767 768 ETA = numpy.zeros(([self.Num_Chn ,self.Num_Hei]))
768 769 data_output = numpy.ones([self.Num_Chn , self.Num_Hei])*numpy.NaN
769
770
770 771 ETA = numpy.sum(SNR,1)
771
772
772 773 ETA = numpy.where(ETA is not 0. , ETA, numpy.NaN)
773
774
774 775 Ze = numpy.ones([self.Num_Chn, self.Num_Hei] )
775
776
776 777 for r in range(self.Num_Hei):
777
778
778 779 Ze[0,r] = ( ETA[0,r] ) * COFA[0,r][0] * RadarConst * ((r/5000.)**2)
779 780 #Ze[1,r] = ( ETA[1,r] ) * COFA[1,r][0] * RadarConst * ((r/5000.)**2)
780
781
781 782 return Ze
782
783
783 784 # def GetRadarConstant(self):
784 #
785 # """
785 #
786 # """
786 787 # Constants:
787 #
788 #
788 789 # Pt: Transmission Power dB 5kW 5000
789 790 # Gt: Transmission Gain dB 24.7 dB 295.1209
790 791 # Gr: Reception Gain dB 18.5 dB 70.7945
@@ -793,63 +794,63 class PrecipitationProc(Operation):
793 794 # tauW: Width of transmission pulse s 4us 4e-6
794 795 # ThetaT: Transmission antenna bean angle rad 0.1656317 rad 0.1656317
795 796 # ThetaR: Reception antenna beam angle rad 0.36774087 rad 0.36774087
796 #
797 #
797 798 # """
798 #
799 #
799 800 # Numerator = ( (4*numpy.pi)**3 * aL**2 * 16 * numpy.log(2) )
800 801 # Denominator = ( Pt * Gt * Gr * Lambda**2 * SPEED_OF_LIGHT * TauW * numpy.pi * ThetaT * TheraR)
801 802 # RadarConstant = Numerator / Denominator
802 #
803 #
803 804 # return RadarConstant
804
805
806
807 class FullSpectralAnalysis(Operation):
808
805
806
807
808 class FullSpectralAnalysis(Operation):
809
809 810 """
810 811 Function that implements Full Spectral Analisys technique.
811
812 Input:
812
813 Input:
813 814 self.dataOut.data_pre : SelfSpectra and CrossSPectra data
814 815 self.dataOut.groupList : Pairlist of channels
815 816 self.dataOut.ChanDist : Physical distance between receivers
816
817
818 Output:
819
820 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
821
822
817
818
819 Output:
820
821 self.dataOut.data_output : Zonal wind, Meridional wind and Vertical wind
822
823
823 824 Parameters affected: Winds, height range, SNR
824
825
825 826 """
826 827 def run(self, dataOut, Xi01=None, Xi02=None, Xi12=None, Eta01=None, Eta02=None, Eta12=None, SNRlimit=7):
827
828 self.indice=int(numpy.random.rand()*1000)
829
828
829 self.indice=int(numpy.random.rand()*1000)
830
830 831 spc = dataOut.data_pre[0].copy()
831 832 cspc = dataOut.data_pre[1]
832
833
833 834 """NOTA SE DEBE REMOVER EL RANGO DEL PULSO TX"""
834
835
835 836 SNRspc = spc.copy()
836 837 SNRspc[:,:,0:7]= numpy.NaN
837
838
838 839 """##########################################"""
839
840
840
841
841 842 nChannel = spc.shape[0]
842 843 nProfiles = spc.shape[1]
843 844 nHeights = spc.shape[2]
844
845
845 846 pairsList = dataOut.groupList
846 847 if dataOut.ChanDist is not None :
847 848 ChanDist = dataOut.ChanDist
848 849 else:
849 850 ChanDist = numpy.array([[Xi01, Eta01],[Xi02,Eta02],[Xi12,Eta12]])
850
851
851 852 FrecRange = dataOut.spc_range[0]
852
853
853 854 ySamples=numpy.ones([nChannel,nProfiles])
854 855 phase=numpy.ones([nChannel,nProfiles])
855 856 CSPCSamples=numpy.ones([nChannel,nProfiles],dtype=numpy.complex_)
@@ -857,82 +858,82 class FullSpectralAnalysis(Operation):
857 858 PhaseSlope=numpy.ones(nChannel)
858 859 PhaseInter=numpy.ones(nChannel)
859 860 data_SNR=numpy.zeros([nProfiles])
860
861
861 862 data = dataOut.data_pre
862 863 noise = dataOut.noise
863
864
864 865 dataOut.data_SNR = (numpy.mean(SNRspc,axis=1)- noise[0]) / noise[0]
865
866
866 867 dataOut.data_SNR[numpy.where( dataOut.data_SNR <0 )] = 1e-20
867
868
868
869
869 870 data_output=numpy.ones([spc.shape[0],spc.shape[2]])*numpy.NaN
870
871
871 872 velocityX=[]
872 873 velocityY=[]
873 874 velocityV=[]
874 875 PhaseLine=[]
875
876
876 877 dbSNR = 10*numpy.log10(dataOut.data_SNR)
877 878 dbSNR = numpy.average(dbSNR,0)
878
879
879 880 for Height in range(nHeights):
880
881
881 882 [Vzon,Vmer,Vver, GaussCenter, PhaseSlope, FitGaussCSPC]= self.WindEstimation(spc, cspc, pairsList, ChanDist, Height, noise, dataOut.spc_range, dbSNR[Height], SNRlimit)
882 883 PhaseLine = numpy.append(PhaseLine, PhaseSlope)
883
884
884 885 if abs(Vzon)<100. and abs(Vzon)> 0.:
885 886 velocityX=numpy.append(velocityX, Vzon)#Vmag
886
887
887 888 else:
888 889 velocityX=numpy.append(velocityX, numpy.NaN)
889
890
890 891 if abs(Vmer)<100. and abs(Vmer) > 0.:
891 892 velocityY=numpy.append(velocityY, -Vmer)#Vang
892
893
893 894 else:
894 895 velocityY=numpy.append(velocityY, numpy.NaN)
895
896
896 897 if dbSNR[Height] > SNRlimit:
897 898 velocityV=numpy.append(velocityV, -Vver)#FirstMoment[Height])
898 899 else:
899 900 velocityV=numpy.append(velocityV, numpy.NaN)
900 901
901
902
902
903
903 904 '''Nota: Cambiar el signo de numpy.array(velocityX) cuando se intente procesar datos de BLTR'''
904 905 data_output[0] = numpy.array(velocityX) #self.moving_average(numpy.array(velocityX) , N=1)
905 906 data_output[1] = numpy.array(velocityY) #self.moving_average(numpy.array(velocityY) , N=1)
906 907 data_output[2] = velocityV#FirstMoment
907
908
908 909 xFrec=FrecRange[0:spc.shape[1]]
909
910
910 911 dataOut.data_output=data_output
911
912
912 913 return dataOut
913
914
914
915
915 916 def moving_average(self,x, N=2):
916 917 return numpy.convolve(x, numpy.ones((N,))/N)[(N-1):]
917
918
918 919 def gaus(self,xSamples,Amp,Mu,Sigma):
919 920 return ( Amp / ((2*numpy.pi)**0.5 * Sigma) ) * numpy.exp( -( xSamples - Mu )**2 / ( 2 * (Sigma**2) ))
920
921
922
921
922
923
923 924 def Moments(self, ySamples, xSamples):
924 925 Pot = numpy.nansum( ySamples ) # Potencia, momento 0
925 926 yNorm = ySamples / Pot
926 927 Vr = numpy.nansum( yNorm * xSamples ) # Velocidad radial, mu, corrimiento doppler, primer momento
927 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
928 Sigma2 = abs(numpy.nansum( yNorm * ( xSamples - Vr )**2 )) # Segundo Momento
928 929 Desv = Sigma2**0.5 # Desv. Estandar, Ancho espectral
929
930
930 931 return numpy.array([Pot, Vr, Desv])
931
932
932 933 def WindEstimation(self, spc, cspc, pairsList, ChanDist, Height, noise, AbbsisaRange, dbSNR, SNRlimit):
933
934 934
935
935
936
936 937 ySamples=numpy.ones([spc.shape[0],spc.shape[1]])
937 938 phase=numpy.ones([spc.shape[0],spc.shape[1]])
938 939 CSPCSamples=numpy.ones([spc.shape[0],spc.shape[1]],dtype=numpy.complex_)
@@ -943,84 +944,84 class FullSpectralAnalysis(Operation):
943 944 xVel =AbbsisaRange[2][0:spc.shape[1]]
944 945 Vv=numpy.empty(spc.shape[2])*0
945 946 SPCav = numpy.average(spc, axis=0)-numpy.average(noise) #spc[0]-noise[0]#
946
947 SPCmoments = self.Moments(SPCav[:,Height], xVel )
947
948 SPCmoments = self.Moments(SPCav[:,Height], xVel )
948 949 CSPCmoments = []
949 950 cspcNoise = numpy.empty(3)
950
951
951 952 '''Getting Eij and Nij'''
952
953
953 954 Xi01=ChanDist[0][0]
954 955 Eta01=ChanDist[0][1]
955
956
956 957 Xi02=ChanDist[1][0]
957 958 Eta02=ChanDist[1][1]
958
959
959 960 Xi12=ChanDist[2][0]
960 961 Eta12=ChanDist[2][1]
961
962
962 963 z = spc.copy()
963 964 z = numpy.where(numpy.isfinite(z), z, numpy.NAN)
964
965 for i in range(spc.shape[0]):
966
965
966 for i in range(spc.shape[0]):
967
967 968 '''****** Line of Data SPC ******'''
968 969 zline=z[i,:,Height].copy() - noise[i] # Se resta ruido
969
970
970 971 '''****** SPC is normalized ******'''
971 972 SmoothSPC =self.moving_average(zline.copy(),N=1) # Se suaviza el ruido
972 FactNorm = SmoothSPC/numpy.nansum(SmoothSPC) # SPC Normalizado y suavizado
973
973 FactNorm = SmoothSPC/numpy.nansum(SmoothSPC) # SPC Normalizado y suavizado
974
974 975 xSamples = xFrec # Se toma el rango de frecuncias
975 976 ySamples[i] = FactNorm # Se toman los valores de SPC normalizado
976
977
977 978 for i in range(spc.shape[0]):
978
979
979 980 '''****** Line of Data CSPC ******'''
980 981 cspcLine = ( cspc[i,:,Height].copy())# - noise[i] ) # no! Se resta el ruido
981 982 SmoothCSPC =self.moving_average(cspcLine,N=1) # Se suaviza el ruido
982 983 cspcNorm = SmoothCSPC/numpy.nansum(SmoothCSPC) # CSPC normalizado y suavizado
983
984
984 985 '''****** CSPC is normalized with respect to Briggs and Vincent ******'''
985 986 chan_index0 = pairsList[i][0]
986 987 chan_index1 = pairsList[i][1]
987
988 CSPCFactor= numpy.abs(numpy.nansum(ySamples[chan_index0]))**2 * numpy.abs(numpy.nansum(ySamples[chan_index1]))**2
988
989 CSPCFactor= numpy.abs(numpy.nansum(ySamples[chan_index0]))**2 * numpy.abs(numpy.nansum(ySamples[chan_index1]))**2
989 990 CSPCNorm = cspcNorm / numpy.sqrt(CSPCFactor)
990
991
991 992 CSPCSamples[i] = CSPCNorm
992
993
993 994 coherence[i] = numpy.abs(CSPCSamples[i]) / numpy.sqrt(CSPCFactor)
994
995
995 996 #coherence[i]= self.moving_average(coherence[i],N=1)
996
997
997 998 phase[i] = self.moving_average( numpy.arctan2(CSPCSamples[i].imag, CSPCSamples[i].real),N=1)#*180/numpy.pi
998
999
999 1000 CSPCmoments = numpy.vstack([self.Moments(numpy.abs(CSPCSamples[0]), xSamples),
1000 1001 self.Moments(numpy.abs(CSPCSamples[1]), xSamples),
1001 self.Moments(numpy.abs(CSPCSamples[2]), xSamples)])
1002
1003
1002 self.Moments(numpy.abs(CSPCSamples[2]), xSamples)])
1003
1004
1004 1005 popt=[1e-10,0,1e-10]
1005 popt01, popt02, popt12 = [1e-10,1e-10,1e-10], [1e-10,1e-10,1e-10] ,[1e-10,1e-10,1e-10]
1006 popt01, popt02, popt12 = [1e-10,1e-10,1e-10], [1e-10,1e-10,1e-10] ,[1e-10,1e-10,1e-10]
1006 1007 FitGauss01, FitGauss02, FitGauss12 = numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0, numpy.empty(len(xSamples))*0
1007
1008
1008 1009 CSPCMask01 = numpy.abs(CSPCSamples[0])
1009 1010 CSPCMask02 = numpy.abs(CSPCSamples[1])
1010 1011 CSPCMask12 = numpy.abs(CSPCSamples[2])
1011
1012
1012 1013 mask01 = ~numpy.isnan(CSPCMask01)
1013 1014 mask02 = ~numpy.isnan(CSPCMask02)
1014 1015 mask12 = ~numpy.isnan(CSPCMask12)
1015
1016
1016 1017 #mask = ~numpy.isnan(CSPCMask01)
1017 1018 CSPCMask01 = CSPCMask01[mask01]
1018 1019 CSPCMask02 = CSPCMask02[mask02]
1019 1020 CSPCMask12 = CSPCMask12[mask12]
1020 1021 #CSPCMask01 = numpy.ma.masked_invalid(CSPCMask01)
1021
1022
1023
1022
1023
1024
1024 1025 '''***Fit Gauss CSPC01***'''
1025 1026 if dbSNR > SNRlimit and numpy.abs(SPCmoments[1])<3 :
1026 1027 try:
@@ -1034,87 +1035,87 class FullSpectralAnalysis(Operation):
1034 1035 FitGauss01=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[0]))
1035 1036 FitGauss02=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[1]))
1036 1037 FitGauss12=numpy.ones(len(xSamples))*numpy.mean(numpy.abs(CSPCSamples[2]))
1037
1038
1038
1039
1039 1040 CSPCopt = numpy.vstack([popt01,popt02,popt12])
1040
1041
1041 1042 '''****** Getting fij width ******'''
1042
1043 yMean = numpy.average(ySamples, axis=0) # ySamples[0]
1044
1043
1044 yMean = numpy.average(ySamples, axis=0) # ySamples[0]
1045
1045 1046 '''******* Getting fitting Gaussian *******'''
1046 meanGauss = sum(xSamples*yMean) / len(xSamples) # Mu, velocidad radial (frecuencia)
1047 sigma2 = sum(yMean*(xSamples-meanGauss)**2) / len(xSamples) # Varianza, Ancho espectral (frecuencia)
1048
1047 meanGauss = sum(xSamples*yMean) / len(xSamples) # Mu, velocidad radial (frecuencia)
1048 sigma2 = sum(yMean*(xSamples-meanGauss)**2) / len(xSamples) # Varianza, Ancho espectral (frecuencia)
1049
1049 1050 yMoments = self.Moments(yMean, xSamples)
1050
1051
1051 1052 if dbSNR > SNRlimit and numpy.abs(SPCmoments[1])<3: # and abs(meanGauss/sigma2) > 0.00001:
1052 1053 try:
1053 1054 popt,pcov = curve_fit(self.gaus,xSamples,yMean,p0=yMoments)
1054 1055 FitGauss=self.gaus(xSamples,*popt)
1055
1056
1056 1057 except :#RuntimeError:
1057 1058 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1058
1059
1059
1060
1060 1061 else:
1061 1062 FitGauss=numpy.ones(len(xSamples))*numpy.mean(yMean)
1062
1063
1064
1063
1064
1065
1065 1066 '''****** Getting Fij ******'''
1066 1067 Fijcspc = CSPCopt[:,2]/2*3
1067
1068
1068
1069
1069 1070 GaussCenter = popt[1] #xFrec[GCpos]
1070 1071 #Punto en Eje X de la Gaussiana donde se encuentra el centro
1071 1072 ClosestCenter = xSamples[numpy.abs(xSamples-GaussCenter).argmin()]
1072 1073 PointGauCenter = numpy.where(xSamples==ClosestCenter)[0][0]
1073
1074 #Punto e^-1 hubicado en la Gaussiana
1074
1075 #Punto e^-1 hubicado en la Gaussiana
1075 1076 PeMinus1 = numpy.max(FitGauss)* numpy.exp(-1)
1076 1077 FijClosest = FitGauss[numpy.abs(FitGauss-PeMinus1).argmin()] # El punto mas cercano a "Peminus1" dentro de "FitGauss"
1077 1078 PointFij = numpy.where(FitGauss==FijClosest)[0][0]
1078
1079
1079 1080 if xSamples[PointFij] > xSamples[PointGauCenter]:
1080 1081 Fij = xSamples[PointFij] - xSamples[PointGauCenter]
1081
1082
1082 1083 else:
1083 1084 Fij = xSamples[PointGauCenter] - xSamples[PointFij]
1084
1085
1085
1086
1086 1087 '''****** Taking frequency ranges from SPCs ******'''
1087
1088
1088
1089
1089 1090 #GaussCenter = popt[1] #Primer momento 01
1090 1091 GauWidth = popt[2] *3/2 #Ancho de banda de Gau01
1091 1092 Range = numpy.empty(2)
1092 1093 Range[0] = GaussCenter - GauWidth
1093 Range[1] = GaussCenter + GauWidth
1094 #Punto en Eje X de la Gaussiana donde se encuentra ancho de banda (min:max)
1094 Range[1] = GaussCenter + GauWidth
1095 #Punto en Eje X de la Gaussiana donde se encuentra ancho de banda (min:max)
1095 1096 ClosRangeMin = xSamples[numpy.abs(xSamples-Range[0]).argmin()]
1096 1097 ClosRangeMax = xSamples[numpy.abs(xSamples-Range[1]).argmin()]
1097
1098
1098 1099 PointRangeMin = numpy.where(xSamples==ClosRangeMin)[0][0]
1099 1100 PointRangeMax = numpy.where(xSamples==ClosRangeMax)[0][0]
1100
1101
1101 1102 Range=numpy.array([ PointRangeMin, PointRangeMax ])
1102
1103
1103 1104 FrecRange = xFrec[ Range[0] : Range[1] ]
1104 1105 VelRange = xVel[ Range[0] : Range[1] ]
1105
1106
1106
1107
1107 1108 '''****** Getting SCPC Slope ******'''
1108
1109
1109 1110 for i in range(spc.shape[0]):
1110
1111
1111 1112 if len(FrecRange)>5 and len(FrecRange)<spc.shape[1]*0.3:
1112 PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=3)
1113
1113 PhaseRange=self.moving_average(phase[i,Range[0]:Range[1]],N=3)
1114
1114 1115 '''***********************VelRange******************'''
1115
1116
1116 1117 mask = ~numpy.isnan(FrecRange) & ~numpy.isnan(PhaseRange)
1117
1118
1118 1119 if len(FrecRange) == len(PhaseRange):
1119 1120 try:
1120 1121 slope, intercept, r_value, p_value, std_err = stats.linregress(FrecRange[mask], PhaseRange[mask])
@@ -1129,36 +1130,36 class FullSpectralAnalysis(Operation):
1129 1130 else:
1130 1131 PhaseSlope[i]=0
1131 1132 PhaseInter[i]=0
1132
1133
1133
1134
1134 1135 '''Getting constant C'''
1135 1136 cC=(Fij*numpy.pi)**2
1136
1137
1137 1138 '''****** Getting constants F and G ******'''
1138 1139 MijEijNij=numpy.array([[Xi02,Eta02], [Xi12,Eta12]])
1139 1140 MijResult0=(-PhaseSlope[1]*cC) / (2*numpy.pi)
1140 MijResult1=(-PhaseSlope[2]*cC) / (2*numpy.pi)
1141 MijResult1=(-PhaseSlope[2]*cC) / (2*numpy.pi)
1141 1142 MijResults=numpy.array([MijResult0,MijResult1])
1142 1143 (cF,cG) = numpy.linalg.solve(MijEijNij, MijResults)
1143
1144
1144 1145 '''****** Getting constants A, B and H ******'''
1145 1146 W01=numpy.nanmax( FitGauss01 ) #numpy.abs(CSPCSamples[0]))
1146 1147 W02=numpy.nanmax( FitGauss02 ) #numpy.abs(CSPCSamples[1]))
1147 1148 W12=numpy.nanmax( FitGauss12 ) #numpy.abs(CSPCSamples[2]))
1148
1149
1149 1150 WijResult0=((cF*Xi01+cG*Eta01)**2)/cC - numpy.log(W01 / numpy.sqrt(numpy.pi/cC))
1150 1151 WijResult1=((cF*Xi02+cG*Eta02)**2)/cC - numpy.log(W02 / numpy.sqrt(numpy.pi/cC))
1151 1152 WijResult2=((cF*Xi12+cG*Eta12)**2)/cC - numpy.log(W12 / numpy.sqrt(numpy.pi/cC))
1152
1153
1153 1154 WijResults=numpy.array([WijResult0, WijResult1, WijResult2])
1154
1155 WijEijNij=numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1155
1156 WijEijNij=numpy.array([ [Xi01**2, Eta01**2, 2*Xi01*Eta01] , [Xi02**2, Eta02**2, 2*Xi02*Eta02] , [Xi12**2, Eta12**2, 2*Xi12*Eta12] ])
1156 1157 (cA,cB,cH) = numpy.linalg.solve(WijEijNij, WijResults)
1157
1158
1158 1159 VxVy=numpy.array([[cA,cH],[cH,cB]])
1159 1160 VxVyResults=numpy.array([-cF,-cG])
1160 1161 (Vx,Vy) = numpy.linalg.solve(VxVy, VxVyResults)
1161
1162
1162 1163 Vzon = Vy
1163 1164 Vmer = Vx
1164 1165 Vmag=numpy.sqrt(Vzon**2+Vmer**2)
@@ -1168,63 +1169,63 class FullSpectralAnalysis(Operation):
1168 1169 else:
1169 1170 Vver=numpy.NaN
1170 1171 FitGaussCSPC = numpy.array([FitGauss01,FitGauss02,FitGauss12])
1171
1172
1172
1173
1173 1174 return Vzon, Vmer, Vver, GaussCenter, PhaseSlope, FitGaussCSPC
1174
1175
1175 1176 class SpectralMoments(Operation):
1176
1177
1177 1178 '''
1178 1179 Function SpectralMoments()
1179
1180
1180 1181 Calculates moments (power, mean, standard deviation) and SNR of the signal
1181
1182
1182 1183 Type of dataIn: Spectra
1183
1184
1184 1185 Configuration Parameters:
1185
1186
1186 1187 dirCosx : Cosine director in X axis
1187 1188 dirCosy : Cosine director in Y axis
1188
1189
1189 1190 elevation :
1190 1191 azimuth :
1191
1192
1192 1193 Input:
1193 channelList : simple channel list to select e.g. [2,3,7]
1194 channelList : simple channel list to select e.g. [2,3,7]
1194 1195 self.dataOut.data_pre : Spectral data
1195 1196 self.dataOut.abscissaList : List of frequencies
1196 1197 self.dataOut.noise : Noise level per channel
1197
1198
1198 1199 Affected:
1199 1200 self.dataOut.moments : Parameters per channel
1200 1201 self.dataOut.data_SNR : SNR per channel
1201
1202
1202 1203 '''
1203
1204
1204 1205 def run(self, dataOut):
1205
1206
1206 1207 #dataOut.data_pre = dataOut.data_pre[0]
1207 1208 data = dataOut.data_pre[0]
1208 1209 absc = dataOut.abscissaList[:-1]
1209 1210 noise = dataOut.noise
1210 1211 nChannel = data.shape[0]
1211 1212 data_param = numpy.zeros((nChannel, 4, data.shape[2]))
1212
1213
1213 1214 for ind in range(nChannel):
1214 1215 data_param[ind,:,:] = self.__calculateMoments( data[ind,:,:] , absc , noise[ind] )
1215
1216
1216 1217 dataOut.moments = data_param[:,1:,:]
1217 1218 dataOut.data_SNR = data_param[:,0]
1218 1219 dataOut.data_POW = data_param[:,1]
1219 1220 dataOut.data_DOP = data_param[:,2]
1220 1221 dataOut.data_WIDTH = data_param[:,3]
1221 1222 return dataOut
1222
1223 def __calculateMoments(self, oldspec, oldfreq, n0,
1223
1224 def __calculateMoments(self, oldspec, oldfreq, n0,
1224 1225 nicoh = None, graph = None, smooth = None, type1 = None, fwindow = None, snrth = None, dc = None, aliasing = None, oldfd = None, wwauto = None):
1225
1226
1226 1227 if (nicoh is None): nicoh = 1
1227 if (graph is None): graph = 0
1228 if (graph is None): graph = 0
1228 1229 if (smooth is None): smooth = 0
1229 1230 elif (self.smooth < 3): smooth = 0
1230 1231
@@ -1235,98 +1236,98 class SpectralMoments(Operation):
1235 1236 if (aliasing is None): aliasing = 0
1236 1237 if (oldfd is None): oldfd = 0
1237 1238 if (wwauto is None): wwauto = 0
1238
1239
1239 1240 if (n0 < 1.e-20): n0 = 1.e-20
1240
1241
1241 1242 freq = oldfreq
1242 1243 vec_power = numpy.zeros(oldspec.shape[1])
1243 1244 vec_fd = numpy.zeros(oldspec.shape[1])
1244 1245 vec_w = numpy.zeros(oldspec.shape[1])
1245 1246 vec_snr = numpy.zeros(oldspec.shape[1])
1246
1247
1247 1248 oldspec = numpy.ma.masked_invalid(oldspec)
1248 1249
1249 1250 for ind in range(oldspec.shape[1]):
1250
1251
1251 1252 spec = oldspec[:,ind]
1252 1253 aux = spec*fwindow
1253 1254 max_spec = aux.max()
1254 1255 m = list(aux).index(max_spec)
1255
1256 #Smooth
1256
1257 #Smooth
1257 1258 if (smooth == 0): spec2 = spec
1258 1259 else: spec2 = scipy.ndimage.filters.uniform_filter1d(spec,size=smooth)
1259
1260
1260 1261 # Calculo de Momentos
1261 1262 bb = spec2[list(range(m,spec2.size))]
1262 1263 bb = (bb<n0).nonzero()
1263 1264 bb = bb[0]
1264
1265
1265 1266 ss = spec2[list(range(0,m + 1))]
1266 1267 ss = (ss<n0).nonzero()
1267 1268 ss = ss[0]
1268
1269
1269 1270 if (bb.size == 0):
1270 1271 bb0 = spec.size - 1 - m
1271 else:
1272 else:
1272 1273 bb0 = bb[0] - 1
1273 1274 if (bb0 < 0):
1274 1275 bb0 = 0
1275
1276
1276 1277 if (ss.size == 0): ss1 = 1
1277 1278 else: ss1 = max(ss) + 1
1278
1279
1279 1280 if (ss1 > m): ss1 = m
1280
1281 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
1281
1282 valid = numpy.asarray(list(range(int(m + bb0 - ss1 + 1)))) + ss1
1282 1283 power = ((spec2[valid] - n0)*fwindow[valid]).sum()
1283 1284 fd = ((spec2[valid]- n0)*freq[valid]*fwindow[valid]).sum()/power
1284 1285 w = math.sqrt(((spec2[valid] - n0)*fwindow[valid]*(freq[valid]- fd)**2).sum()/power)
1285 snr = (spec2.mean()-n0)/n0
1286
1287 if (snr < 1.e-20) :
1286 snr = (spec2.mean()-n0)/n0
1287
1288 if (snr < 1.e-20) :
1288 1289 snr = 1.e-20
1289
1290
1290 1291 vec_power[ind] = power
1291 1292 vec_fd[ind] = fd
1292 1293 vec_w[ind] = w
1293 1294 vec_snr[ind] = snr
1294
1295
1295 1296 moments = numpy.vstack((vec_snr, vec_power, vec_fd, vec_w))
1296 1297 return moments
1297
1298
1298 1299 #------------------ Get SA Parameters --------------------------
1299
1300
1300 1301 def GetSAParameters(self):
1301 1302 #SA en frecuencia
1302 1303 pairslist = self.dataOut.groupList
1303 1304 num_pairs = len(pairslist)
1304
1305
1305 1306 vel = self.dataOut.abscissaList
1306 1307 spectra = self.dataOut.data_pre
1307 1308 cspectra = self.dataIn.data_cspc
1308 delta_v = vel[1] - vel[0]
1309
1309 delta_v = vel[1] - vel[0]
1310
1310 1311 #Calculating the power spectrum
1311 1312 spc_pow = numpy.sum(spectra, 3)*delta_v
1312 1313 #Normalizing Spectra
1313 1314 norm_spectra = spectra/spc_pow
1314 1315 #Calculating the norm_spectra at peak
1315 max_spectra = numpy.max(norm_spectra, 3)
1316
1316 max_spectra = numpy.max(norm_spectra, 3)
1317
1317 1318 #Normalizing Cross Spectra
1318 1319 norm_cspectra = numpy.zeros(cspectra.shape)
1319
1320
1320 1321 for i in range(num_chan):
1321 1322 norm_cspectra[i,:,:] = cspectra[i,:,:]/numpy.sqrt(spc_pow[pairslist[i][0],:]*spc_pow[pairslist[i][1],:])
1322
1323
1323 1324 max_cspectra = numpy.max(norm_cspectra,2)
1324 1325 max_cspectra_index = numpy.argmax(norm_cspectra, 2)
1325
1326
1326 1327 for i in range(num_pairs):
1327 1328 cspc_par[i,:,:] = __calculateMoments(norm_cspectra)
1328 1329 #------------------- Get Lags ----------------------------------
1329
1330
1330 1331 class SALags(Operation):
1331 1332 '''
1332 1333 Function GetMoments()
@@ -1339,19 +1340,19 class SALags(Operation):
1339 1340 self.dataOut.data_SNR
1340 1341 self.dataOut.groupList
1341 1342 self.dataOut.nChannels
1342
1343
1343 1344 Affected:
1344 1345 self.dataOut.data_param
1345
1346
1346 1347 '''
1347 def run(self, dataOut):
1348 def run(self, dataOut):
1348 1349 data_acf = dataOut.data_pre[0]
1349 1350 data_ccf = dataOut.data_pre[1]
1350 1351 normFactor_acf = dataOut.normFactor[0]
1351 1352 normFactor_ccf = dataOut.normFactor[1]
1352 1353 pairs_acf = dataOut.groupList[0]
1353 1354 pairs_ccf = dataOut.groupList[1]
1354
1355
1355 1356 nHeights = dataOut.nHeights
1356 1357 absc = dataOut.abscissaList
1357 1358 noise = dataOut.noise
@@ -1362,97 +1363,97 class SALags(Operation):
1362 1363
1363 1364 for l in range(len(pairs_acf)):
1364 1365 data_acf[l,:,:] = data_acf[l,:,:]/normFactor_acf[l,:]
1365
1366
1366 1367 for l in range(len(pairs_ccf)):
1367 1368 data_ccf[l,:,:] = data_ccf[l,:,:]/normFactor_ccf[l,:]
1368
1369
1369 1370 dataOut.data_param = numpy.zeros((len(pairs_ccf)*2 + 1, nHeights))
1370 1371 dataOut.data_param[:-1,:] = self.__calculateTaus(data_acf, data_ccf, absc)
1371 1372 dataOut.data_param[-1,:] = self.__calculateLag1Phase(data_acf, absc)
1372 1373 return
1373
1374
1374 1375 # def __getPairsAutoCorr(self, pairsList, nChannels):
1375 #
1376 #
1376 1377 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1377 #
1378 # for l in range(len(pairsList)):
1378 #
1379 # for l in range(len(pairsList)):
1379 1380 # firstChannel = pairsList[l][0]
1380 1381 # secondChannel = pairsList[l][1]
1381 #
1382 # #Obteniendo pares de Autocorrelacion
1382 #
1383 # #Obteniendo pares de Autocorrelacion
1383 1384 # if firstChannel == secondChannel:
1384 1385 # pairsAutoCorr[firstChannel] = int(l)
1385 #
1386 #
1386 1387 # pairsAutoCorr = pairsAutoCorr.astype(int)
1387 #
1388 #
1388 1389 # pairsCrossCorr = range(len(pairsList))
1389 1390 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1390 #
1391 #
1391 1392 # return pairsAutoCorr, pairsCrossCorr
1392
1393
1393 1394 def __calculateTaus(self, data_acf, data_ccf, lagRange):
1394
1395
1395 1396 lag0 = data_acf.shape[1]/2
1396 1397 #Funcion de Autocorrelacion
1397 1398 mean_acf = stats.nanmean(data_acf, axis = 0)
1398
1399
1399 1400 #Obtencion Indice de TauCross
1400 1401 ind_ccf = data_ccf.argmax(axis = 1)
1401 1402 #Obtencion Indice de TauAuto
1402 1403 ind_acf = numpy.zeros(ind_ccf.shape,dtype = 'int')
1403 1404 ccf_lag0 = data_ccf[:,lag0,:]
1404
1405
1405 1406 for i in range(ccf_lag0.shape[0]):
1406 1407 ind_acf[i,:] = numpy.abs(mean_acf - ccf_lag0[i,:]).argmin(axis = 0)
1407
1408
1408 1409 #Obtencion de TauCross y TauAuto
1409 1410 tau_ccf = lagRange[ind_ccf]
1410 1411 tau_acf = lagRange[ind_acf]
1411
1412
1412 1413 Nan1, Nan2 = numpy.where(tau_ccf == lagRange[0])
1413
1414
1414 1415 tau_ccf[Nan1,Nan2] = numpy.nan
1415 1416 tau_acf[Nan1,Nan2] = numpy.nan
1416 1417 tau = numpy.vstack((tau_ccf,tau_acf))
1417
1418
1418 1419 return tau
1419
1420
1420 1421 def __calculateLag1Phase(self, data, lagTRange):
1421 1422 data1 = stats.nanmean(data, axis = 0)
1422 1423 lag1 = numpy.where(lagTRange == 0)[0][0] + 1
1423 1424
1424 1425 phase = numpy.angle(data1[lag1,:])
1425
1426
1426 1427 return phase
1427
1428
1428 1429 class SpectralFitting(Operation):
1429 1430 '''
1430 1431 Function GetMoments()
1431
1432
1432 1433 Input:
1433 1434 Output:
1434 1435 Variables modified:
1435 1436 '''
1436
1437 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1438
1439
1437
1438 def run(self, dataOut, getSNR = True, path=None, file=None, groupList=None):
1439
1440
1440 1441 if path != None:
1441 1442 sys.path.append(path)
1442 1443 self.dataOut.library = importlib.import_module(file)
1443
1444
1444 1445 #To be inserted as a parameter
1445 1446 groupArray = numpy.array(groupList)
1446 # groupArray = numpy.array([[0,1],[2,3]])
1447 # groupArray = numpy.array([[0,1],[2,3]])
1447 1448 self.dataOut.groupList = groupArray
1448
1449
1449 1450 nGroups = groupArray.shape[0]
1450 1451 nChannels = self.dataIn.nChannels
1451 1452 nHeights=self.dataIn.heightList.size
1452
1453
1453 1454 #Parameters Array
1454 1455 self.dataOut.data_param = None
1455
1456
1456 1457 #Set constants
1457 1458 constants = self.dataOut.library.setConstants(self.dataIn)
1458 1459 self.dataOut.constants = constants
@@ -1461,24 +1462,24 class SpectralFitting(Operation):
1461 1462 ippSeconds = self.dataIn.ippSeconds
1462 1463 K = self.dataIn.nIncohInt
1463 1464 pairsArray = numpy.array(self.dataIn.pairsList)
1464
1465
1465 1466 #List of possible combinations
1466 1467 listComb = itertools.combinations(numpy.arange(groupArray.shape[1]),2)
1467 1468 indCross = numpy.zeros(len(list(listComb)), dtype = 'int')
1468
1469
1469 1470 if getSNR:
1470 1471 listChannels = groupArray.reshape((groupArray.size))
1471 1472 listChannels.sort()
1472 1473 noise = self.dataIn.getNoise()
1473 1474 self.dataOut.data_SNR = self.__getSNR(self.dataIn.data_spc[listChannels,:,:], noise[listChannels])
1474
1475 for i in range(nGroups):
1475
1476 for i in range(nGroups):
1476 1477 coord = groupArray[i,:]
1477
1478
1478 1479 #Input data array
1479 1480 data = self.dataIn.data_spc[coord,:,:]/(M*N)
1480 1481 data = data.reshape((data.shape[0]*data.shape[1],data.shape[2]))
1481
1482
1482 1483 #Cross Spectra data array for Covariance Matrixes
1483 1484 ind = 0
1484 1485 for pairs in listComb:
@@ -1487,9 +1488,9 class SpectralFitting(Operation):
1487 1488 ind += 1
1488 1489 dataCross = self.dataIn.data_cspc[indCross,:,:]/(M*N)
1489 1490 dataCross = dataCross**2/K
1490
1491
1491 1492 for h in range(nHeights):
1492
1493
1493 1494 #Input
1494 1495 d = data[:,h]
1495 1496
@@ -1498,7 +1499,7 class SpectralFitting(Operation):
1498 1499 ind = 0
1499 1500 for pairs in listComb:
1500 1501 #Coordinates in Covariance Matrix
1501 x = pairs[0]
1502 x = pairs[0]
1502 1503 y = pairs[1]
1503 1504 #Channel Index
1504 1505 S12 = dataCross[ind,:,h]
@@ -1512,15 +1513,15 class SpectralFitting(Operation):
1512 1513 LT=L.T
1513 1514
1514 1515 dp = numpy.dot(LT,d)
1515
1516
1516 1517 #Initial values
1517 1518 data_spc = self.dataIn.data_spc[coord,:,h]
1518
1519
1519 1520 if (h>0)and(error1[3]<5):
1520 1521 p0 = self.dataOut.data_param[i,:,h-1]
1521 1522 else:
1522 1523 p0 = numpy.array(self.dataOut.library.initialValuesFunction(data_spc, constants, i))
1523
1524
1524 1525 try:
1525 1526 #Least Squares
1526 1527 minp,covp,infodict,mesg,ier = optimize.leastsq(self.__residFunction,p0,args=(dp,LT,constants),full_output=True)
@@ -1533,30 +1534,30 class SpectralFitting(Operation):
1533 1534 minp = p0*numpy.nan
1534 1535 error0 = numpy.nan
1535 1536 error1 = p0*numpy.nan
1536
1537
1537 1538 #Save
1538 1539 if self.dataOut.data_param is None:
1539 1540 self.dataOut.data_param = numpy.zeros((nGroups, p0.size, nHeights))*numpy.nan
1540 1541 self.dataOut.data_error = numpy.zeros((nGroups, p0.size + 1, nHeights))*numpy.nan
1541
1542
1542 1543 self.dataOut.data_error[i,:,h] = numpy.hstack((error0,error1))
1543 1544 self.dataOut.data_param[i,:,h] = minp
1544 1545 return
1545
1546
1546 1547 def __residFunction(self, p, dp, LT, constants):
1547 1548
1548 1549 fm = self.dataOut.library.modelFunction(p, constants)
1549 1550 fmp=numpy.dot(LT,fm)
1550
1551
1551 1552 return dp-fmp
1552 1553
1553 1554 def __getSNR(self, z, noise):
1554
1555
1555 1556 avg = numpy.average(z, axis=1)
1556 1557 SNR = (avg.T-noise)/noise
1557 1558 SNR = SNR.T
1558 1559 return SNR
1559
1560
1560 1561 def __chisq(p,chindex,hindex):
1561 1562 #similar to Resid but calculates CHI**2
1562 1563 [LT,d,fm]=setupLTdfm(p,chindex,hindex)
@@ -1564,53 +1565,53 class SpectralFitting(Operation):
1564 1565 fmp=numpy.dot(LT,fm)
1565 1566 chisq=numpy.dot((dp-fmp).T,(dp-fmp))
1566 1567 return chisq
1567
1568
1568 1569 class WindProfiler(Operation):
1569
1570
1570 1571 __isConfig = False
1571
1572
1572 1573 __initime = None
1573 1574 __lastdatatime = None
1574 1575 __integrationtime = None
1575
1576
1576 1577 __buffer = None
1577
1578
1578 1579 __dataReady = False
1579
1580
1580 1581 __firstdata = None
1581
1582
1582 1583 n = None
1583
1584 def __init__(self):
1584
1585 def __init__(self):
1585 1586 Operation.__init__(self)
1586
1587
1587 1588 def __calculateCosDir(self, elev, azim):
1588 1589 zen = (90 - elev)*numpy.pi/180
1589 1590 azim = azim*numpy.pi/180
1590 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1591 cosDirX = numpy.sqrt((1-numpy.cos(zen)**2)/((1+numpy.tan(azim)**2)))
1591 1592 cosDirY = numpy.sqrt(1-numpy.cos(zen)**2-cosDirX**2)
1592
1593
1593 1594 signX = numpy.sign(numpy.cos(azim))
1594 1595 signY = numpy.sign(numpy.sin(azim))
1595
1596
1596 1597 cosDirX = numpy.copysign(cosDirX, signX)
1597 1598 cosDirY = numpy.copysign(cosDirY, signY)
1598 1599 return cosDirX, cosDirY
1599
1600
1600 1601 def __calculateAngles(self, theta_x, theta_y, azimuth):
1601
1602
1602 1603 dir_cosw = numpy.sqrt(1-theta_x**2-theta_y**2)
1603 1604 zenith_arr = numpy.arccos(dir_cosw)
1604 1605 azimuth_arr = numpy.arctan2(theta_x,theta_y) + azimuth*math.pi/180
1605
1606
1606 1607 dir_cosu = numpy.sin(azimuth_arr)*numpy.sin(zenith_arr)
1607 1608 dir_cosv = numpy.cos(azimuth_arr)*numpy.sin(zenith_arr)
1608
1609
1609 1610 return azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw
1610 1611
1611 1612 def __calculateMatA(self, dir_cosu, dir_cosv, dir_cosw, horOnly):
1612
1613 #
1613
1614 #
1614 1615 if horOnly:
1615 1616 A = numpy.c_[dir_cosu,dir_cosv]
1616 1617 else:
@@ -1624,37 +1625,37 class WindProfiler(Operation):
1624 1625 listPhi = phi.tolist()
1625 1626 maxid = listPhi.index(max(listPhi))
1626 1627 minid = listPhi.index(min(listPhi))
1627
1628 rango = list(range(len(phi)))
1628
1629 rango = list(range(len(phi)))
1629 1630 # rango = numpy.delete(rango,maxid)
1630
1631
1631 1632 heiRang1 = heiRang*math.cos(phi[maxid])
1632 1633 heiRangAux = heiRang*math.cos(phi[minid])
1633 1634 indOut = (heiRang1 < heiRangAux[0]).nonzero()
1634 1635 heiRang1 = numpy.delete(heiRang1,indOut)
1635
1636
1636 1637 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
1637 1638 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
1638
1639
1639 1640 for i in rango:
1640 1641 x = heiRang*math.cos(phi[i])
1641 1642 y1 = velRadial[i,:]
1642 1643 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
1643
1644
1644 1645 x1 = heiRang1
1645 1646 y11 = f1(x1)
1646
1647
1647 1648 y2 = SNR[i,:]
1648 1649 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
1649 1650 y21 = f2(x1)
1650
1651
1651 1652 velRadial1[i,:] = y11
1652 1653 SNR1[i,:] = y21
1653
1654
1654 1655 return heiRang1, velRadial1, SNR1
1655 1656
1656 1657 def __calculateVelUVW(self, A, velRadial):
1657
1658
1658 1659 #Operacion Matricial
1659 1660 # velUVW = numpy.zeros((velRadial.shape[1],3))
1660 1661 # for ind in range(velRadial.shape[1]):
@@ -1662,27 +1663,27 class WindProfiler(Operation):
1662 1663 # velUVW = velUVW.transpose()
1663 1664 velUVW = numpy.zeros((A.shape[0],velRadial.shape[1]))
1664 1665 velUVW[:,:] = numpy.dot(A,velRadial)
1665
1666
1666
1667
1667 1668 return velUVW
1668
1669
1669 1670 # def techniqueDBS(self, velRadial0, dirCosx, disrCosy, azimuth, correct, horizontalOnly, heiRang, SNR0):
1670
1671
1671 1672 def techniqueDBS(self, kwargs):
1672 1673 """
1673 1674 Function that implements Doppler Beam Swinging (DBS) technique.
1674
1675
1675 1676 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1676 1677 Direction correction (if necessary), Ranges and SNR
1677
1678
1678 1679 Output: Winds estimation (Zonal, Meridional and Vertical)
1679
1680
1680 1681 Parameters affected: Winds, height range, SNR
1681 1682 """
1682 1683 velRadial0 = kwargs['velRadial']
1683 1684 heiRang = kwargs['heightList']
1684 1685 SNR0 = kwargs['SNR']
1685
1686
1686 1687 if 'dirCosx' in kwargs and 'dirCosy' in kwargs:
1687 1688 theta_x = numpy.array(kwargs['dirCosx'])
1688 1689 theta_y = numpy.array(kwargs['dirCosy'])
@@ -1690,7 +1691,7 class WindProfiler(Operation):
1690 1691 elev = numpy.array(kwargs['elevation'])
1691 1692 azim = numpy.array(kwargs['azimuth'])
1692 1693 theta_x, theta_y = self.__calculateCosDir(elev, azim)
1693 azimuth = kwargs['correctAzimuth']
1694 azimuth = kwargs['correctAzimuth']
1694 1695 if 'horizontalOnly' in kwargs:
1695 1696 horizontalOnly = kwargs['horizontalOnly']
1696 1697 else: horizontalOnly = False
@@ -1705,22 +1706,22 class WindProfiler(Operation):
1705 1706 param = param[arrayChannel,:,:]
1706 1707 theta_x = theta_x[arrayChannel]
1707 1708 theta_y = theta_y[arrayChannel]
1708
1709 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1710 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1709
1710 azimuth_arr, zenith_arr, dir_cosu, dir_cosv, dir_cosw = self.__calculateAngles(theta_x, theta_y, azimuth)
1711 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, zenith_arr, correctFactor*velRadial0, SNR0)
1711 1712 A = self.__calculateMatA(dir_cosu, dir_cosv, dir_cosw, horizontalOnly)
1712
1713
1713 1714 #Calculo de Componentes de la velocidad con DBS
1714 1715 winds = self.__calculateVelUVW(A,velRadial1)
1715
1716
1716 1717 return winds, heiRang1, SNR1
1717
1718
1718 1719 def __calculateDistance(self, posx, posy, pairs_ccf, azimuth = None):
1719
1720
1720 1721 nPairs = len(pairs_ccf)
1721 1722 posx = numpy.asarray(posx)
1722 1723 posy = numpy.asarray(posy)
1723
1724
1724 1725 #Rotacion Inversa para alinear con el azimuth
1725 1726 if azimuth!= None:
1726 1727 azimuth = azimuth*math.pi/180
@@ -1729,126 +1730,126 class WindProfiler(Operation):
1729 1730 else:
1730 1731 posx1 = posx
1731 1732 posy1 = posy
1732
1733
1733 1734 #Calculo de Distancias
1734 1735 distx = numpy.zeros(nPairs)
1735 1736 disty = numpy.zeros(nPairs)
1736 1737 dist = numpy.zeros(nPairs)
1737 1738 ang = numpy.zeros(nPairs)
1738
1739
1739 1740 for i in range(nPairs):
1740 1741 distx[i] = posx1[pairs_ccf[i][1]] - posx1[pairs_ccf[i][0]]
1741 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1742 disty[i] = posy1[pairs_ccf[i][1]] - posy1[pairs_ccf[i][0]]
1742 1743 dist[i] = numpy.sqrt(distx[i]**2 + disty[i]**2)
1743 1744 ang[i] = numpy.arctan2(disty[i],distx[i])
1744
1745
1745 1746 return distx, disty, dist, ang
1746 #Calculo de Matrices
1747 #Calculo de Matrices
1747 1748 # nPairs = len(pairs)
1748 1749 # ang1 = numpy.zeros((nPairs, 2, 1))
1749 1750 # dist1 = numpy.zeros((nPairs, 2, 1))
1750 #
1751 #
1751 1752 # for j in range(nPairs):
1752 1753 # dist1[j,0,0] = dist[pairs[j][0]]
1753 1754 # dist1[j,1,0] = dist[pairs[j][1]]
1754 1755 # ang1[j,0,0] = ang[pairs[j][0]]
1755 1756 # ang1[j,1,0] = ang[pairs[j][1]]
1756 #
1757 #
1757 1758 # return distx,disty, dist1,ang1
1758 1759
1759
1760
1760 1761 def __calculateVelVer(self, phase, lagTRange, _lambda):
1761 1762
1762 1763 Ts = lagTRange[1] - lagTRange[0]
1763 1764 velW = -_lambda*phase/(4*math.pi*Ts)
1764
1765
1765 1766 return velW
1766
1767
1767 1768 def __calculateVelHorDir(self, dist, tau1, tau2, ang):
1768 1769 nPairs = tau1.shape[0]
1769 1770 nHeights = tau1.shape[1]
1770 vel = numpy.zeros((nPairs,3,nHeights))
1771 vel = numpy.zeros((nPairs,3,nHeights))
1771 1772 dist1 = numpy.reshape(dist, (dist.size,1))
1772
1773
1773 1774 angCos = numpy.cos(ang)
1774 1775 angSin = numpy.sin(ang)
1775
1776 vel0 = dist1*tau1/(2*tau2**2)
1776
1777 vel0 = dist1*tau1/(2*tau2**2)
1777 1778 vel[:,0,:] = (vel0*angCos).sum(axis = 1)
1778 1779 vel[:,1,:] = (vel0*angSin).sum(axis = 1)
1779
1780
1780 1781 ind = numpy.where(numpy.isinf(vel))
1781 1782 vel[ind] = numpy.nan
1782
1783
1783 1784 return vel
1784
1785
1785 1786 # def __getPairsAutoCorr(self, pairsList, nChannels):
1786 #
1787 #
1787 1788 # pairsAutoCorr = numpy.zeros(nChannels, dtype = 'int')*numpy.nan
1788 #
1789 # for l in range(len(pairsList)):
1789 #
1790 # for l in range(len(pairsList)):
1790 1791 # firstChannel = pairsList[l][0]
1791 1792 # secondChannel = pairsList[l][1]
1792 #
1793 # #Obteniendo pares de Autocorrelacion
1793 #
1794 # #Obteniendo pares de Autocorrelacion
1794 1795 # if firstChannel == secondChannel:
1795 1796 # pairsAutoCorr[firstChannel] = int(l)
1796 #
1797 #
1797 1798 # pairsAutoCorr = pairsAutoCorr.astype(int)
1798 #
1799 #
1799 1800 # pairsCrossCorr = range(len(pairsList))
1800 1801 # pairsCrossCorr = numpy.delete(pairsCrossCorr,pairsAutoCorr)
1801 #
1802 #
1802 1803 # return pairsAutoCorr, pairsCrossCorr
1803
1804
1804 1805 # def techniqueSA(self, pairsSelected, pairsList, nChannels, tau, azimuth, _lambda, position_x, position_y, lagTRange, correctFactor):
1805 1806 def techniqueSA(self, kwargs):
1806
1807 """
1807
1808 """
1808 1809 Function that implements Spaced Antenna (SA) technique.
1809
1810
1810 1811 Input: Radial velocities, Direction cosines (x and y) of the Beam, Antenna azimuth,
1811 1812 Direction correction (if necessary), Ranges and SNR
1812
1813
1813 1814 Output: Winds estimation (Zonal, Meridional and Vertical)
1814
1815
1815 1816 Parameters affected: Winds
1816 1817 """
1817 1818 position_x = kwargs['positionX']
1818 1819 position_y = kwargs['positionY']
1819 1820 azimuth = kwargs['azimuth']
1820
1821
1821 1822 if 'correctFactor' in kwargs:
1822 1823 correctFactor = kwargs['correctFactor']
1823 1824 else:
1824 1825 correctFactor = 1
1825
1826
1826 1827 groupList = kwargs['groupList']
1827 1828 pairs_ccf = groupList[1]
1828 1829 tau = kwargs['tau']
1829 1830 _lambda = kwargs['_lambda']
1830
1831
1831 1832 #Cross Correlation pairs obtained
1832 1833 # pairsAutoCorr, pairsCrossCorr = self.__getPairsAutoCorr(pairssList, nChannels)
1833 1834 # pairsArray = numpy.array(pairsList)[pairsCrossCorr]
1834 1835 # pairsSelArray = numpy.array(pairsSelected)
1835 1836 # pairs = []
1836 #
1837 #
1837 1838 # #Wind estimation pairs obtained
1838 1839 # for i in range(pairsSelArray.shape[0]/2):
1839 1840 # ind1 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i], axis = 1))[0][0]
1840 1841 # ind2 = numpy.where(numpy.all(pairsArray == pairsSelArray[2*i + 1], axis = 1))[0][0]
1841 1842 # pairs.append((ind1,ind2))
1842
1843
1843 1844 indtau = tau.shape[0]/2
1844 1845 tau1 = tau[:indtau,:]
1845 1846 tau2 = tau[indtau:-1,:]
1846 1847 # tau1 = tau1[pairs,:]
1847 1848 # tau2 = tau2[pairs,:]
1848 1849 phase1 = tau[-1,:]
1849
1850
1850 1851 #---------------------------------------------------------------------
1851 #Metodo Directo
1852 #Metodo Directo
1852 1853 distx, disty, dist, ang = self.__calculateDistance(position_x, position_y, pairs_ccf,azimuth)
1853 1854 winds = self.__calculateVelHorDir(dist, tau1, tau2, ang)
1854 1855 winds = stats.nanmean(winds, axis=0)
@@ -1864,97 +1865,97 class WindProfiler(Operation):
1864 1865 winds[2,:] = self.__calculateVelVer(phase1, lagTRange, _lambda)
1865 1866 winds = correctFactor*winds
1866 1867 return winds
1867
1868
1868 1869 def __checkTime(self, currentTime, paramInterval, outputInterval):
1869
1870
1870 1871 dataTime = currentTime + paramInterval
1871 1872 deltaTime = dataTime - self.__initime
1872
1873
1873 1874 if deltaTime >= outputInterval or deltaTime < 0:
1874 1875 self.__dataReady = True
1875 return
1876
1876 return
1877
1877 1878 def techniqueMeteors(self, arrayMeteor, meteorThresh, heightMin, heightMax):
1878 1879 '''
1879 1880 Function that implements winds estimation technique with detected meteors.
1880
1881
1881 1882 Input: Detected meteors, Minimum meteor quantity to wind estimation
1882
1883
1883 1884 Output: Winds estimation (Zonal and Meridional)
1884
1885
1885 1886 Parameters affected: Winds
1886 '''
1887 '''
1887 1888 #Settings
1888 1889 nInt = (heightMax - heightMin)/2
1889 1890 nInt = int(nInt)
1890 winds = numpy.zeros((2,nInt))*numpy.nan
1891
1891 winds = numpy.zeros((2,nInt))*numpy.nan
1892
1892 1893 #Filter errors
1893 1894 error = numpy.where(arrayMeteor[:,-1] == 0)[0]
1894 1895 finalMeteor = arrayMeteor[error,:]
1895
1896
1896 1897 #Meteor Histogram
1897 1898 finalHeights = finalMeteor[:,2]
1898 1899 hist = numpy.histogram(finalHeights, bins = nInt, range = (heightMin,heightMax))
1899 1900 nMeteorsPerI = hist[0]
1900 1901 heightPerI = hist[1]
1901
1902
1902 1903 #Sort of meteors
1903 1904 indSort = finalHeights.argsort()
1904 1905 finalMeteor2 = finalMeteor[indSort,:]
1905
1906
1906 1907 # Calculating winds
1907 1908 ind1 = 0
1908 ind2 = 0
1909
1909 ind2 = 0
1910
1910 1911 for i in range(nInt):
1911 1912 nMet = nMeteorsPerI[i]
1912 1913 ind1 = ind2
1913 1914 ind2 = ind1 + nMet
1914
1915
1915 1916 meteorAux = finalMeteor2[ind1:ind2,:]
1916
1917
1917 1918 if meteorAux.shape[0] >= meteorThresh:
1918 1919 vel = meteorAux[:, 6]
1919 1920 zen = meteorAux[:, 4]*numpy.pi/180
1920 1921 azim = meteorAux[:, 3]*numpy.pi/180
1921
1922
1922 1923 n = numpy.cos(zen)
1923 1924 # m = (1 - n**2)/(1 - numpy.tan(azim)**2)
1924 1925 # l = m*numpy.tan(azim)
1925 1926 l = numpy.sin(zen)*numpy.sin(azim)
1926 1927 m = numpy.sin(zen)*numpy.cos(azim)
1927
1928
1928 1929 A = numpy.vstack((l, m)).transpose()
1929 1930 A1 = numpy.dot(numpy.linalg.inv( numpy.dot(A.transpose(),A) ),A.transpose())
1930 1931 windsAux = numpy.dot(A1, vel)
1931
1932
1932 1933 winds[0,i] = windsAux[0]
1933 1934 winds[1,i] = windsAux[1]
1934
1935
1935 1936 return winds, heightPerI[:-1]
1936
1937
1937 1938 def techniqueNSM_SA(self, **kwargs):
1938 1939 metArray = kwargs['metArray']
1939 1940 heightList = kwargs['heightList']
1940 1941 timeList = kwargs['timeList']
1941
1942
1942 1943 rx_location = kwargs['rx_location']
1943 1944 groupList = kwargs['groupList']
1944 1945 azimuth = kwargs['azimuth']
1945 1946 dfactor = kwargs['dfactor']
1946 1947 k = kwargs['k']
1947
1948
1948 1949 azimuth1, dist = self.__calculateAzimuth1(rx_location, groupList, azimuth)
1949 1950 d = dist*dfactor
1950 1951 #Phase calculation
1951 1952 metArray1 = self.__getPhaseSlope(metArray, heightList, timeList)
1952
1953
1953 1954 metArray1[:,-2] = metArray1[:,-2]*metArray1[:,2]*1000/(k*d[metArray1[:,1].astype(int)]) #angles into velocities
1954
1955
1955 1956 velEst = numpy.zeros((heightList.size,2))*numpy.nan
1956 1957 azimuth1 = azimuth1*numpy.pi/180
1957
1958
1958 1959 for i in range(heightList.size):
1959 1960 h = heightList[i]
1960 1961 indH = numpy.where((metArray1[:,2] == h)&(numpy.abs(metArray1[:,-2]) < 100))[0]
@@ -1967,71 +1968,71 class WindProfiler(Operation):
1967 1968 A = numpy.asmatrix(A)
1968 1969 A1 = numpy.linalg.pinv(A.transpose()*A)*A.transpose()
1969 1970 velHor = numpy.dot(A1,velAux)
1970
1971
1971 1972 velEst[i,:] = numpy.squeeze(velHor)
1972 1973 return velEst
1973
1974
1974 1975 def __getPhaseSlope(self, metArray, heightList, timeList):
1975 1976 meteorList = []
1976 1977 #utctime sec1 height SNR velRad ph0 ph1 ph2 coh0 coh1 coh2
1977 1978 #Putting back together the meteor matrix
1978 1979 utctime = metArray[:,0]
1979 1980 uniqueTime = numpy.unique(utctime)
1980
1981
1981 1982 phaseDerThresh = 0.5
1982 1983 ippSeconds = timeList[1] - timeList[0]
1983 1984 sec = numpy.where(timeList>1)[0][0]
1984 1985 nPairs = metArray.shape[1] - 6
1985 1986 nHeights = len(heightList)
1986
1987
1987 1988 for t in uniqueTime:
1988 1989 metArray1 = metArray[utctime==t,:]
1989 1990 # phaseDerThresh = numpy.pi/4 #reducir Phase thresh
1990 1991 tmet = metArray1[:,1].astype(int)
1991 1992 hmet = metArray1[:,2].astype(int)
1992
1993
1993 1994 metPhase = numpy.zeros((nPairs, heightList.size, timeList.size - 1))
1994 1995 metPhase[:,:] = numpy.nan
1995 1996 metPhase[:,hmet,tmet] = metArray1[:,6:].T
1996
1997
1997 1998 #Delete short trails
1998 1999 metBool = ~numpy.isnan(metPhase[0,:,:])
1999 2000 heightVect = numpy.sum(metBool, axis = 1)
2000 2001 metBool[heightVect<sec,:] = False
2001 2002 metPhase[:,heightVect<sec,:] = numpy.nan
2002
2003
2003 2004 #Derivative
2004 2005 metDer = numpy.abs(metPhase[:,:,1:] - metPhase[:,:,:-1])
2005 2006 phDerAux = numpy.dstack((numpy.full((nPairs,nHeights,1), False, dtype=bool),metDer > phaseDerThresh))
2006 2007 metPhase[phDerAux] = numpy.nan
2007
2008
2008 2009 #--------------------------METEOR DETECTION -----------------------------------------
2009 2010 indMet = numpy.where(numpy.any(metBool,axis=1))[0]
2010
2011
2011 2012 for p in numpy.arange(nPairs):
2012 2013 phase = metPhase[p,:,:]
2013 2014 phDer = metDer[p,:,:]
2014
2015
2015 2016 for h in indMet:
2016 2017 height = heightList[h]
2017 2018 phase1 = phase[h,:] #82
2018 2019 phDer1 = phDer[h,:]
2019
2020
2020 2021 phase1[~numpy.isnan(phase1)] = numpy.unwrap(phase1[~numpy.isnan(phase1)]) #Unwrap
2021
2022
2022 2023 indValid = numpy.where(~numpy.isnan(phase1))[0]
2023 2024 initMet = indValid[0]
2024 2025 endMet = 0
2025
2026
2026 2027 for i in range(len(indValid)-1):
2027
2028
2028 2029 #Time difference
2029 2030 inow = indValid[i]
2030 2031 inext = indValid[i+1]
2031 2032 idiff = inext - inow
2032 2033 #Phase difference
2033 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2034
2034 phDiff = numpy.abs(phase1[inext] - phase1[inow])
2035
2035 2036 if idiff>sec or phDiff>numpy.pi/4 or inext==indValid[-1]: #End of Meteor
2036 2037 sizeTrail = inow - initMet + 1
2037 2038 if sizeTrail>3*sec: #Too short meteors
@@ -2047,43 +2048,43 class WindProfiler(Operation):
2047 2048 vel = slope#*height*1000/(k*d)
2048 2049 estAux = numpy.array([utctime,p,height, vel, rsq])
2049 2050 meteorList.append(estAux)
2050 initMet = inext
2051 initMet = inext
2051 2052 metArray2 = numpy.array(meteorList)
2052
2053
2053 2054 return metArray2
2054
2055
2055 2056 def __calculateAzimuth1(self, rx_location, pairslist, azimuth0):
2056
2057
2057 2058 azimuth1 = numpy.zeros(len(pairslist))
2058 2059 dist = numpy.zeros(len(pairslist))
2059
2060
2060 2061 for i in range(len(rx_location)):
2061 2062 ch0 = pairslist[i][0]
2062 2063 ch1 = pairslist[i][1]
2063
2064
2064 2065 diffX = rx_location[ch0][0] - rx_location[ch1][0]
2065 2066 diffY = rx_location[ch0][1] - rx_location[ch1][1]
2066 2067 azimuth1[i] = numpy.arctan2(diffY,diffX)*180/numpy.pi
2067 2068 dist[i] = numpy.sqrt(diffX**2 + diffY**2)
2068
2069
2069 2070 azimuth1 -= azimuth0
2070 2071 return azimuth1, dist
2071
2072
2072 2073 def techniqueNSM_DBS(self, **kwargs):
2073 2074 metArray = kwargs['metArray']
2074 2075 heightList = kwargs['heightList']
2075 timeList = kwargs['timeList']
2076 timeList = kwargs['timeList']
2076 2077 azimuth = kwargs['azimuth']
2077 2078 theta_x = numpy.array(kwargs['theta_x'])
2078 2079 theta_y = numpy.array(kwargs['theta_y'])
2079
2080
2080 2081 utctime = metArray[:,0]
2081 2082 cmet = metArray[:,1].astype(int)
2082 2083 hmet = metArray[:,3].astype(int)
2083 2084 SNRmet = metArray[:,4]
2084 2085 vmet = metArray[:,5]
2085 2086 spcmet = metArray[:,6]
2086
2087
2087 2088 nChan = numpy.max(cmet) + 1
2088 2089 nHeights = len(heightList)
2089 2090
@@ -2099,20 +2100,20 class WindProfiler(Operation):
2099 2100
2100 2101 thisH = (h1met>=hmin) & (h1met<hmax) & (cmet!=2) & (SNRmet>8) & (vmet<50) & (spcmet<10)
2101 2102 indthisH = numpy.where(thisH)
2102
2103
2103 2104 if numpy.size(indthisH) > 3:
2104
2105
2105 2106 vel_aux = vmet[thisH]
2106 2107 chan_aux = cmet[thisH]
2107 2108 cosu_aux = dir_cosu[chan_aux]
2108 2109 cosv_aux = dir_cosv[chan_aux]
2109 2110 cosw_aux = dir_cosw[chan_aux]
2110
2111 nch = numpy.size(numpy.unique(chan_aux))
2111
2112 nch = numpy.size(numpy.unique(chan_aux))
2112 2113 if nch > 1:
2113 2114 A = self.__calculateMatA(cosu_aux, cosv_aux, cosw_aux, True)
2114 2115 velEst[i,:] = numpy.dot(A,vel_aux)
2115
2116
2116 2117 return velEst
2117 2118
2118 2119 def run(self, dataOut, technique, nHours=1, hmin=70, hmax=110, **kwargs):
@@ -2123,39 +2124,39 class WindProfiler(Operation):
2123 2124 # noise = dataOut.noise
2124 2125 heightList = dataOut.heightList
2125 2126 SNR = dataOut.data_SNR
2126
2127
2127 2128 if technique == 'DBS':
2128
2129 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2129
2130 kwargs['velRadial'] = param[:,1,:] #Radial velocity
2130 2131 kwargs['heightList'] = heightList
2131 2132 kwargs['SNR'] = SNR
2132
2133
2133 2134 dataOut.data_output, dataOut.heightList, dataOut.data_SNR = self.techniqueDBS(kwargs) #DBS Function
2134 2135 dataOut.utctimeInit = dataOut.utctime
2135 2136 dataOut.outputInterval = dataOut.paramInterval
2136
2137
2137 2138 elif technique == 'SA':
2138
2139
2139 2140 #Parameters
2140 2141 # position_x = kwargs['positionX']
2141 2142 # position_y = kwargs['positionY']
2142 2143 # azimuth = kwargs['azimuth']
2143 #
2144 #
2144 2145 # if kwargs.has_key('crosspairsList'):
2145 2146 # pairs = kwargs['crosspairsList']
2146 2147 # else:
2147 # pairs = None
2148 #
2148 # pairs = None
2149 #
2149 2150 # if kwargs.has_key('correctFactor'):
2150 2151 # correctFactor = kwargs['correctFactor']
2151 2152 # else:
2152 2153 # correctFactor = 1
2153
2154
2154 2155 # tau = dataOut.data_param
2155 2156 # _lambda = dataOut.C/dataOut.frequency
2156 2157 # pairsList = dataOut.groupList
2157 2158 # nChannels = dataOut.nChannels
2158
2159
2159 2160 kwargs['groupList'] = dataOut.groupList
2160 2161 kwargs['tau'] = dataOut.data_param
2161 2162 kwargs['_lambda'] = dataOut.C/dataOut.frequency
@@ -2163,30 +2164,30 class WindProfiler(Operation):
2163 2164 dataOut.data_output = self.techniqueSA(kwargs)
2164 2165 dataOut.utctimeInit = dataOut.utctime
2165 2166 dataOut.outputInterval = dataOut.timeInterval
2166
2167 elif technique == 'Meteors':
2167
2168 elif technique == 'Meteors':
2168 2169 dataOut.flagNoData = True
2169 2170 self.__dataReady = False
2170
2171
2171 2172 if 'nHours' in kwargs:
2172 2173 nHours = kwargs['nHours']
2173 else:
2174 else:
2174 2175 nHours = 1
2175
2176
2176 2177 if 'meteorsPerBin' in kwargs:
2177 2178 meteorThresh = kwargs['meteorsPerBin']
2178 2179 else:
2179 2180 meteorThresh = 6
2180
2181
2181 2182 if 'hmin' in kwargs:
2182 2183 hmin = kwargs['hmin']
2183 2184 else: hmin = 70
2184 2185 if 'hmax' in kwargs:
2185 2186 hmax = kwargs['hmax']
2186 2187 else: hmax = 110
2187
2188
2188 2189 dataOut.outputInterval = nHours*3600
2189
2190
2190 2191 if self.__isConfig == False:
2191 2192 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
2192 2193 #Get Initial LTC time
@@ -2194,29 +2195,29 class WindProfiler(Operation):
2194 2195 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2195 2196
2196 2197 self.__isConfig = True
2197
2198
2198 2199 if self.__buffer is None:
2199 2200 self.__buffer = dataOut.data_param
2200 2201 self.__firstdata = copy.copy(dataOut)
2201 2202
2202 2203 else:
2203 2204 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2204
2205
2205 2206 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2206
2207
2207 2208 if self.__dataReady:
2208 2209 dataOut.utctimeInit = self.__initime
2209
2210
2210 2211 self.__initime += dataOut.outputInterval #to erase time offset
2211
2212
2212 2213 dataOut.data_output, dataOut.heightList = self.techniqueMeteors(self.__buffer, meteorThresh, hmin, hmax)
2213 2214 dataOut.flagNoData = False
2214 2215 self.__buffer = None
2215
2216
2216 2217 elif technique == 'Meteors1':
2217 2218 dataOut.flagNoData = True
2218 2219 self.__dataReady = False
2219
2220
2220 2221 if 'nMins' in kwargs:
2221 2222 nMins = kwargs['nMins']
2222 2223 else: nMins = 20
@@ -2231,7 +2232,7 class WindProfiler(Operation):
2231 2232 if 'mode' in kwargs:
2232 2233 mode = kwargs['mode']
2233 2234 if 'theta_x' in kwargs:
2234 theta_x = kwargs['theta_x']
2235 theta_x = kwargs['theta_x']
2235 2236 if 'theta_y' in kwargs:
2236 2237 theta_y = kwargs['theta_y']
2237 2238 else: mode = 'SA'
@@ -2244,10 +2245,10 class WindProfiler(Operation):
2244 2245 freq = 50e6
2245 2246 lamb = C/freq
2246 2247 k = 2*numpy.pi/lamb
2247
2248
2248 2249 timeList = dataOut.abscissaList
2249 2250 heightList = dataOut.heightList
2250
2251
2251 2252 if self.__isConfig == False:
2252 2253 dataOut.outputInterval = nMins*60
2253 2254 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
@@ -2258,20 +2259,20 class WindProfiler(Operation):
2258 2259 self.__initime = (initime.replace(minute = minuteNew, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
2259 2260
2260 2261 self.__isConfig = True
2261
2262
2262 2263 if self.__buffer is None:
2263 2264 self.__buffer = dataOut.data_param
2264 2265 self.__firstdata = copy.copy(dataOut)
2265 2266
2266 2267 else:
2267 2268 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
2268
2269
2269 2270 self.__checkTime(dataOut.utctime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
2270
2271
2271 2272 if self.__dataReady:
2272 2273 dataOut.utctimeInit = self.__initime
2273 2274 self.__initime += dataOut.outputInterval #to erase time offset
2274
2275
2275 2276 metArray = self.__buffer
2276 2277 if mode == 'SA':
2277 2278 dataOut.data_output = self.techniqueNSM_SA(rx_location=rx_location, groupList=groupList, azimuth=azimuth, dfactor=dfactor, k=k,metArray=metArray, heightList=heightList,timeList=timeList)
@@ -2282,71 +2283,71 class WindProfiler(Operation):
2282 2283 self.__buffer = None
2283 2284
2284 2285 return
2285
2286
2286 2287 class EWDriftsEstimation(Operation):
2287
2288 def __init__(self):
2289 Operation.__init__(self)
2290
2288
2289 def __init__(self):
2290 Operation.__init__(self)
2291
2291 2292 def __correctValues(self, heiRang, phi, velRadial, SNR):
2292 2293 listPhi = phi.tolist()
2293 2294 maxid = listPhi.index(max(listPhi))
2294 2295 minid = listPhi.index(min(listPhi))
2295
2296 rango = list(range(len(phi)))
2296
2297 rango = list(range(len(phi)))
2297 2298 # rango = numpy.delete(rango,maxid)
2298
2299
2299 2300 heiRang1 = heiRang*math.cos(phi[maxid])
2300 2301 heiRangAux = heiRang*math.cos(phi[minid])
2301 2302 indOut = (heiRang1 < heiRangAux[0]).nonzero()
2302 2303 heiRang1 = numpy.delete(heiRang1,indOut)
2303
2304
2304 2305 velRadial1 = numpy.zeros([len(phi),len(heiRang1)])
2305 2306 SNR1 = numpy.zeros([len(phi),len(heiRang1)])
2306
2307
2307 2308 for i in rango:
2308 2309 x = heiRang*math.cos(phi[i])
2309 2310 y1 = velRadial[i,:]
2310 2311 f1 = interpolate.interp1d(x,y1,kind = 'cubic')
2311
2312
2312 2313 x1 = heiRang1
2313 2314 y11 = f1(x1)
2314
2315
2315 2316 y2 = SNR[i,:]
2316 2317 f2 = interpolate.interp1d(x,y2,kind = 'cubic')
2317 2318 y21 = f2(x1)
2318
2319
2319 2320 velRadial1[i,:] = y11
2320 2321 SNR1[i,:] = y21
2321
2322
2322 2323 return heiRang1, velRadial1, SNR1
2323 2324
2324 2325 def run(self, dataOut, zenith, zenithCorrection):
2325 2326 heiRang = dataOut.heightList
2326 2327 velRadial = dataOut.data_param[:,3,:]
2327 2328 SNR = dataOut.data_SNR
2328
2329
2329 2330 zenith = numpy.array(zenith)
2330 zenith -= zenithCorrection
2331 zenith -= zenithCorrection
2331 2332 zenith *= numpy.pi/180
2332
2333
2333 2334 heiRang1, velRadial1, SNR1 = self.__correctValues(heiRang, numpy.abs(zenith), velRadial, SNR)
2334
2335
2335 2336 alp = zenith[0]
2336 2337 bet = zenith[1]
2337
2338
2338 2339 w_w = velRadial1[0,:]
2339 2340 w_e = velRadial1[1,:]
2340
2341 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2342 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2343
2341
2342 w = (w_w*numpy.sin(bet) - w_e*numpy.sin(alp))/(numpy.cos(alp)*numpy.sin(bet) - numpy.cos(bet)*numpy.sin(alp))
2343 u = (w_w*numpy.cos(bet) - w_e*numpy.cos(alp))/(numpy.sin(alp)*numpy.cos(bet) - numpy.sin(bet)*numpy.cos(alp))
2344
2344 2345 winds = numpy.vstack((u,w))
2345
2346
2346 2347 dataOut.heightList = heiRang1
2347 2348 dataOut.data_output = winds
2348 2349 dataOut.data_SNR = SNR1
2349
2350
2350 2351 dataOut.utctimeInit = dataOut.utctime
2351 2352 dataOut.outputInterval = dataOut.timeInterval
2352 2353 return
@@ -2359,11 +2360,11 class NonSpecularMeteorDetection(Operation):
2359 2360 data_acf = dataOut.data_pre[0]
2360 2361 data_ccf = dataOut.data_pre[1]
2361 2362 pairsList = dataOut.groupList[1]
2362
2363
2363 2364 lamb = dataOut.C/dataOut.frequency
2364 2365 tSamp = dataOut.ippSeconds*dataOut.nCohInt
2365 2366 paramInterval = dataOut.paramInterval
2366
2367
2367 2368 nChannels = data_acf.shape[0]
2368 2369 nLags = data_acf.shape[1]
2369 2370 nProfiles = data_acf.shape[2]
@@ -2373,7 +2374,7 class NonSpecularMeteorDetection(Operation):
2373 2374 heightList = dataOut.heightList
2374 2375 ippSeconds = dataOut.ippSeconds*dataOut.nCohInt*dataOut.nAvg
2375 2376 utctime = dataOut.utctime
2376
2377
2377 2378 dataOut.abscissaList = numpy.arange(0,paramInterval+ippSeconds,ippSeconds)
2378 2379
2379 2380 #------------------------ SNR --------------------------------------
@@ -2385,7 +2386,7 class NonSpecularMeteorDetection(Operation):
2385 2386 SNR[i] = (power[i]-noise[i])/noise[i]
2386 2387 SNRm = numpy.nanmean(SNR, axis = 0)
2387 2388 SNRdB = 10*numpy.log10(SNR)
2388
2389
2389 2390 if mode == 'SA':
2390 2391 dataOut.groupList = dataOut.groupList[1]
2391 2392 nPairs = data_ccf.shape[0]
@@ -2393,22 +2394,22 class NonSpecularMeteorDetection(Operation):
2393 2394 phase = numpy.zeros(data_ccf[:,0,:,:].shape)
2394 2395 # phase1 = numpy.copy(phase)
2395 2396 coh1 = numpy.zeros(data_ccf[:,0,:,:].shape)
2396
2397
2397 2398 for p in range(nPairs):
2398 2399 ch0 = pairsList[p][0]
2399 2400 ch1 = pairsList[p][1]
2400 2401 ccf = data_ccf[p,0,:,:]/numpy.sqrt(data_acf[ch0,0,:,:]*data_acf[ch1,0,:,:])
2401 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2402 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2403 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2404 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2402 phase[p,:,:] = ndimage.median_filter(numpy.angle(ccf), size = (5,1)) #median filter
2403 # phase1[p,:,:] = numpy.angle(ccf) #median filter
2404 coh1[p,:,:] = ndimage.median_filter(numpy.abs(ccf), 5) #median filter
2405 # coh1[p,:,:] = numpy.abs(ccf) #median filter
2405 2406 coh = numpy.nanmax(coh1, axis = 0)
2406 2407 # struc = numpy.ones((5,1))
2407 2408 # coh = ndimage.morphology.grey_dilation(coh, size=(10,1))
2408 2409 #---------------------- Radial Velocity ----------------------------
2409 2410 phaseAux = numpy.mean(numpy.angle(data_acf[:,1,:,:]), axis = 0)
2410 2411 velRad = phaseAux*lamb/(4*numpy.pi*tSamp)
2411
2412
2412 2413 if allData:
2413 2414 boolMetFin = ~numpy.isnan(SNRm)
2414 2415 # coh[:-1,:] = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
@@ -2416,31 +2417,31 class NonSpecularMeteorDetection(Operation):
2416 2417 #------------------------ Meteor mask ---------------------------------
2417 2418 # #SNR mask
2418 2419 # boolMet = (SNRdB>SNRthresh)#|(~numpy.isnan(SNRdB))
2419 #
2420 #
2420 2421 # #Erase small objects
2421 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2422 #
2422 # boolMet1 = self.__erase_small(boolMet, 2*sec, 5)
2423 #
2423 2424 # auxEEJ = numpy.sum(boolMet1,axis=0)
2424 2425 # indOver = auxEEJ>nProfiles*0.8 #Use this later
2425 2426 # indEEJ = numpy.where(indOver)[0]
2426 2427 # indNEEJ = numpy.where(~indOver)[0]
2427 #
2428 #
2428 2429 # boolMetFin = boolMet1
2429 #
2430 #
2430 2431 # if indEEJ.size > 0:
2431 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2432 #
2432 # boolMet1[:,indEEJ] = False #Erase heights with EEJ
2433 #
2433 2434 # boolMet2 = coh > cohThresh
2434 2435 # boolMet2 = self.__erase_small(boolMet2, 2*sec,5)
2435 #
2436 #
2436 2437 # #Final Meteor mask
2437 2438 # boolMetFin = boolMet1|boolMet2
2438
2439
2439 2440 #Coherence mask
2440 2441 boolMet1 = coh > 0.75
2441 2442 struc = numpy.ones((30,1))
2442 2443 boolMet1 = ndimage.morphology.binary_dilation(boolMet1, structure=struc)
2443
2444
2444 2445 #Derivative mask
2445 2446 derPhase = numpy.nanmean(numpy.abs(phase[:,1:,:] - phase[:,:-1,:]),axis=0)
2446 2447 boolMet2 = derPhase < 0.2
@@ -2457,7 +2458,7 class NonSpecularMeteorDetection(Operation):
2457 2458
2458 2459 tmet = coordMet[0]
2459 2460 hmet = coordMet[1]
2460
2461
2461 2462 data_param = numpy.zeros((tmet.size, 6 + nPairs))
2462 2463 data_param[:,0] = utctime
2463 2464 data_param[:,1] = tmet
@@ -2466,7 +2467,7 class NonSpecularMeteorDetection(Operation):
2466 2467 data_param[:,4] = velRad[tmet,hmet]
2467 2468 data_param[:,5] = coh[tmet,hmet]
2468 2469 data_param[:,6:] = phase[:,tmet,hmet].T
2469
2470
2470 2471 elif mode == 'DBS':
2471 2472 dataOut.groupList = numpy.arange(nChannels)
2472 2473
@@ -2474,7 +2475,7 class NonSpecularMeteorDetection(Operation):
2474 2475 phase = numpy.angle(data_acf[:,1,:,:])
2475 2476 # phase = ndimage.median_filter(numpy.angle(data_acf[:,1,:,:]), size = (1,5,1))
2476 2477 velRad = phase*lamb/(4*numpy.pi*tSamp)
2477
2478
2478 2479 #Spectral width
2479 2480 # acf1 = ndimage.median_filter(numpy.abs(data_acf[:,1,:,:]), size = (1,5,1))
2480 2481 # acf2 = ndimage.median_filter(numpy.abs(data_acf[:,2,:,:]), size = (1,5,1))
@@ -2489,24 +2490,24 class NonSpecularMeteorDetection(Operation):
2489 2490 #SNR
2490 2491 boolMet1 = (SNRdB>SNRthresh) #SNR mask
2491 2492 boolMet1 = ndimage.median_filter(boolMet1, size=(1,5,5))
2492
2493
2493 2494 #Radial velocity
2494 2495 boolMet2 = numpy.abs(velRad) < 20
2495 2496 boolMet2 = ndimage.median_filter(boolMet2, (1,5,5))
2496
2497
2497 2498 #Spectral Width
2498 2499 boolMet3 = spcWidth < 30
2499 2500 boolMet3 = ndimage.median_filter(boolMet3, (1,5,5))
2500 2501 # boolMetFin = self.__erase_small(boolMet1, 10,5)
2501 2502 boolMetFin = boolMet1&boolMet2&boolMet3
2502
2503
2503 2504 #Creating data_param
2504 2505 coordMet = numpy.where(boolMetFin)
2505 2506
2506 2507 cmet = coordMet[0]
2507 2508 tmet = coordMet[1]
2508 2509 hmet = coordMet[2]
2509
2510
2510 2511 data_param = numpy.zeros((tmet.size, 7))
2511 2512 data_param[:,0] = utctime
2512 2513 data_param[:,1] = cmet
@@ -2515,7 +2516,7 class NonSpecularMeteorDetection(Operation):
2515 2516 data_param[:,4] = SNR[cmet,tmet,hmet].T
2516 2517 data_param[:,5] = velRad[cmet,tmet,hmet].T
2517 2518 data_param[:,6] = spcWidth[cmet,tmet,hmet].T
2518
2519
2519 2520 # self.dataOut.data_param = data_int
2520 2521 if len(data_param) == 0:
2521 2522 dataOut.flagNoData = True
@@ -2525,21 +2526,21 class NonSpecularMeteorDetection(Operation):
2525 2526 def __erase_small(self, binArray, threshX, threshY):
2526 2527 labarray, numfeat = ndimage.measurements.label(binArray)
2527 2528 binArray1 = numpy.copy(binArray)
2528
2529
2529 2530 for i in range(1,numfeat + 1):
2530 2531 auxBin = (labarray==i)
2531 2532 auxSize = auxBin.sum()
2532
2533
2533 2534 x,y = numpy.where(auxBin)
2534 2535 widthX = x.max() - x.min()
2535 2536 widthY = y.max() - y.min()
2536
2537
2537 2538 #width X: 3 seg -> 12.5*3
2538 #width Y:
2539
2539 #width Y:
2540
2540 2541 if (auxSize < 50) or (widthX < threshX) or (widthY < threshY):
2541 2542 binArray1[auxBin] = False
2542
2543
2543 2544 return binArray1
2544 2545
2545 2546 #--------------- Specular Meteor ----------------
@@ -2549,36 +2550,36 class SMDetection(Operation):
2549 2550 Function DetectMeteors()
2550 2551 Project developed with paper:
2551 2552 HOLDSWORTH ET AL. 2004
2552
2553
2553 2554 Input:
2554 2555 self.dataOut.data_pre
2555
2556
2556 2557 centerReceiverIndex: From the channels, which is the center receiver
2557
2558
2558 2559 hei_ref: Height reference for the Beacon signal extraction
2559 2560 tauindex:
2560 2561 predefinedPhaseShifts: Predefined phase offset for the voltge signals
2561
2562
2562 2563 cohDetection: Whether to user Coherent detection or not
2563 2564 cohDet_timeStep: Coherent Detection calculation time step
2564 2565 cohDet_thresh: Coherent Detection phase threshold to correct phases
2565
2566
2566 2567 noise_timeStep: Noise calculation time step
2567 2568 noise_multiple: Noise multiple to define signal threshold
2568
2569
2569 2570 multDet_timeLimit: Multiple Detection Removal time limit in seconds
2570 2571 multDet_rangeLimit: Multiple Detection Removal range limit in km
2571
2572
2572 2573 phaseThresh: Maximum phase difference between receiver to be consider a meteor
2573 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2574
2574 SNRThresh: Minimum SNR threshold of the meteor signal to be consider a meteor
2575
2575 2576 hmin: Minimum Height of the meteor to use it in the further wind estimations
2576 2577 hmax: Maximum Height of the meteor to use it in the further wind estimations
2577 2578 azimuth: Azimuth angle correction
2578
2579
2579 2580 Affected:
2580 2581 self.dataOut.data_param
2581
2582
2582 2583 Rejection Criteria (Errors):
2583 2584 0: No error; analysis OK
2584 2585 1: SNR < SNR threshold
@@ -2597,9 +2598,9 class SMDetection(Operation):
2597 2598 14: height ambiguous echo: more then one possible height within 70 to 110 km
2598 2599 15: radial drift velocity or projected horizontal velocity exceeds 200 m/s
2599 2600 16: oscilatory echo, indicating event most likely not an underdense echo
2600
2601
2601 2602 17: phase difference in meteor Reestimation
2602
2603
2603 2604 Data Storage:
2604 2605 Meteors for Wind Estimation (8):
2605 2606 Utc Time | Range Height
@@ -2607,19 +2608,19 class SMDetection(Operation):
2607 2608 VelRad errorVelRad
2608 2609 Phase0 Phase1 Phase2 Phase3
2609 2610 TypeError
2610
2611 '''
2612
2611
2612 '''
2613
2613 2614 def run(self, dataOut, hei_ref = None, tauindex = 0,
2614 2615 phaseOffsets = None,
2615 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2616 cohDetection = False, cohDet_timeStep = 1, cohDet_thresh = 25,
2616 2617 noise_timeStep = 4, noise_multiple = 4,
2617 2618 multDet_timeLimit = 1, multDet_rangeLimit = 3,
2618 2619 phaseThresh = 20, SNRThresh = 5,
2619 2620 hmin = 50, hmax=150, azimuth = 0,
2620 2621 channelPositions = None) :
2621
2622
2622
2623
2623 2624 #Getting Pairslist
2624 2625 if channelPositions is None:
2625 2626 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
@@ -2629,53 +2630,53 class SMDetection(Operation):
2629 2630 heiRang = dataOut.getHeiRange()
2630 2631 #Get Beacon signal - No Beacon signal anymore
2631 2632 # newheis = numpy.where(self.dataOut.heightList>self.dataOut.radarControllerHeaderObj.Taus[tauindex])
2632 #
2633 #
2633 2634 # if hei_ref != None:
2634 2635 # newheis = numpy.where(self.dataOut.heightList>hei_ref)
2635 #
2636
2637
2636 #
2637
2638
2638 2639 #****************REMOVING HARDWARE PHASE DIFFERENCES***************
2639 2640 # see if the user put in pre defined phase shifts
2640 2641 voltsPShift = dataOut.data_pre.copy()
2641
2642
2642 2643 # if predefinedPhaseShifts != None:
2643 2644 # hardwarePhaseShifts = numpy.array(predefinedPhaseShifts)*numpy.pi/180
2644 #
2645 #
2645 2646 # # elif beaconPhaseShifts:
2646 2647 # # #get hardware phase shifts using beacon signal
2647 2648 # # hardwarePhaseShifts = self.__getHardwarePhaseDiff(self.dataOut.data_pre, pairslist, newheis, 10)
2648 2649 # # hardwarePhaseShifts = numpy.insert(hardwarePhaseShifts,centerReceiverIndex,0)
2649 #
2650 #
2650 2651 # else:
2651 # hardwarePhaseShifts = numpy.zeros(5)
2652 #
2652 # hardwarePhaseShifts = numpy.zeros(5)
2653 #
2653 2654 # voltsPShift = numpy.zeros((self.dataOut.data_pre.shape[0],self.dataOut.data_pre.shape[1],self.dataOut.data_pre.shape[2]), dtype = 'complex')
2654 2655 # for i in range(self.dataOut.data_pre.shape[0]):
2655 2656 # voltsPShift[i,:,:] = self.__shiftPhase(self.dataOut.data_pre[i,:,:], hardwarePhaseShifts[i])
2656 2657
2657 2658 #******************END OF REMOVING HARDWARE PHASE DIFFERENCES*********
2658
2659
2659 2660 #Remove DC
2660 2661 voltsDC = numpy.mean(voltsPShift,1)
2661 2662 voltsDC = numpy.mean(voltsDC,1)
2662 2663 for i in range(voltsDC.shape[0]):
2663 2664 voltsPShift[i] = voltsPShift[i] - voltsDC[i]
2664
2665 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2665
2666 #Don't considerate last heights, theyre used to calculate Hardware Phase Shift
2666 2667 # voltsPShift = voltsPShift[:,:,:newheis[0][0]]
2667
2668
2668 2669 #************ FIND POWER OF DATA W/COH OR NON COH DETECTION (3.4) **********
2669 2670 #Coherent Detection
2670 2671 if cohDetection:
2671 2672 #use coherent detection to get the net power
2672 2673 cohDet_thresh = cohDet_thresh*numpy.pi/180
2673 2674 voltsPShift = self.__coherentDetection(voltsPShift, cohDet_timeStep, dataOut.timeInterval, pairslist0, cohDet_thresh)
2674
2675
2675 2676 #Non-coherent detection!
2676 2677 powerNet = numpy.nansum(numpy.abs(voltsPShift[:,:,:])**2,0)
2677 2678 #********** END OF COH/NON-COH POWER CALCULATION**********************
2678
2679
2679 2680 #********** FIND THE NOISE LEVEL AND POSSIBLE METEORS ****************
2680 2681 #Get noise
2681 2682 noise, noise1 = self.__getNoise(powerNet, noise_timeStep, dataOut.timeInterval)
@@ -2685,7 +2686,7 class SMDetection(Operation):
2685 2686 #Meteor echoes detection
2686 2687 listMeteors = self.__findMeteors(powerNet, signalThresh)
2687 2688 #******* END OF NOISE LEVEL AND POSSIBLE METEORS CACULATION **********
2688
2689
2689 2690 #************** REMOVE MULTIPLE DETECTIONS (3.5) ***************************
2690 2691 #Parameters
2691 2692 heiRange = dataOut.getHeiRange()
@@ -2695,7 +2696,7 class SMDetection(Operation):
2695 2696 #Multiple detection removals
2696 2697 listMeteors1 = self.__removeMultipleDetections(listMeteors, rangeLimit, timeLimit)
2697 2698 #************ END OF REMOVE MULTIPLE DETECTIONS **********************
2698
2699
2699 2700 #********************* METEOR REESTIMATION (3.7, 3.8, 3.9, 3.10) ********************
2700 2701 #Parameters
2701 2702 phaseThresh = phaseThresh*numpy.pi/180
@@ -2706,40 +2707,40 class SMDetection(Operation):
2706 2707 #Estimation of decay times (Errors N 7, 8, 11)
2707 2708 listMeteors3 = self.__estimateDecayTime(listMeteors2, listMeteorsPower, dataOut.timeInterval, dataOut.frequency)
2708 2709 #******************* END OF METEOR REESTIMATION *******************
2709
2710
2710 2711 #********************* METEOR PARAMETERS CALCULATION (3.11, 3.12, 3.13) **************************
2711 2712 #Calculating Radial Velocity (Error N 15)
2712 2713 radialStdThresh = 10
2713 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2714 listMeteors4 = self.__getRadialVelocity(listMeteors3, listMeteorsVolts, radialStdThresh, pairslist0, dataOut.timeInterval)
2714 2715
2715 2716 if len(listMeteors4) > 0:
2716 2717 #Setting New Array
2717 2718 date = dataOut.utctime
2718 2719 arrayParameters = self.__setNewArrays(listMeteors4, date, heiRang)
2719
2720
2720 2721 #Correcting phase offset
2721 2722 if phaseOffsets != None:
2722 2723 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
2723 2724 arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
2724
2725
2725 2726 #Second Pairslist
2726 2727 pairsList = []
2727 2728 pairx = (0,1)
2728 2729 pairy = (2,3)
2729 2730 pairsList.append(pairx)
2730 2731 pairsList.append(pairy)
2731
2732
2732 2733 jph = numpy.array([0,0,0,0])
2733 2734 h = (hmin,hmax)
2734 2735 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
2735
2736
2736 2737 # #Calculate AOA (Error N 3, 4)
2737 2738 # #JONES ET AL. 1998
2738 2739 # error = arrayParameters[:,-1]
2739 2740 # AOAthresh = numpy.pi/8
2740 2741 # phases = -arrayParameters[:,9:13]
2741 2742 # arrayParameters[:,4:7], arrayParameters[:,-1] = meteorOps.getAOA(phases, pairsList, error, AOAthresh, azimuth)
2742 #
2743 #
2743 2744 # #Calculate Heights (Error N 13 and 14)
2744 2745 # error = arrayParameters[:,-1]
2745 2746 # Ranges = arrayParameters[:,2]
@@ -2747,73 +2748,73 class SMDetection(Operation):
2747 2748 # arrayParameters[:,3], arrayParameters[:,-1] = meteorOps.getHeights(Ranges, zenith, error, hmin, hmax)
2748 2749 # error = arrayParameters[:,-1]
2749 2750 #********************* END OF PARAMETERS CALCULATION **************************
2750
2751 #***************************+ PASS DATA TO NEXT STEP **********************
2751
2752 #***************************+ PASS DATA TO NEXT STEP **********************
2752 2753 # arrayFinal = arrayParameters.reshape((1,arrayParameters.shape[0],arrayParameters.shape[1]))
2753 2754 dataOut.data_param = arrayParameters
2754
2755
2755 2756 if arrayParameters is None:
2756 2757 dataOut.flagNoData = True
2757 2758 else:
2758 2759 dataOut.flagNoData = True
2759
2760
2760 2761 return
2761
2762
2762 2763 def __getHardwarePhaseDiff(self, voltage0, pairslist, newheis, n):
2763
2764
2764 2765 minIndex = min(newheis[0])
2765 2766 maxIndex = max(newheis[0])
2766
2767
2767 2768 voltage = voltage0[:,:,minIndex:maxIndex+1]
2768 2769 nLength = voltage.shape[1]/n
2769 2770 nMin = 0
2770 2771 nMax = 0
2771 2772 phaseOffset = numpy.zeros((len(pairslist),n))
2772
2773
2773 2774 for i in range(n):
2774 2775 nMax += nLength
2775 2776 phaseCCF = -numpy.angle(self.__calculateCCF(voltage[:,nMin:nMax,:], pairslist, [0]))
2776 2777 phaseCCF = numpy.mean(phaseCCF, axis = 2)
2777 phaseOffset[:,i] = phaseCCF.transpose()
2778 phaseOffset[:,i] = phaseCCF.transpose()
2778 2779 nMin = nMax
2779 2780 # phaseDiff, phaseArrival = self.estimatePhaseDifference(voltage, pairslist)
2780
2781
2781 2782 #Remove Outliers
2782 2783 factor = 2
2783 2784 wt = phaseOffset - signal.medfilt(phaseOffset,(1,5))
2784 2785 dw = numpy.std(wt,axis = 1)
2785 2786 dw = dw.reshape((dw.size,1))
2786 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2787 ind = numpy.where(numpy.logical_or(wt>dw*factor,wt<-dw*factor))
2787 2788 phaseOffset[ind] = numpy.nan
2788 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2789
2789 phaseOffset = stats.nanmean(phaseOffset, axis=1)
2790
2790 2791 return phaseOffset
2791
2792
2792 2793 def __shiftPhase(self, data, phaseShift):
2793 2794 #this will shift the phase of a complex number
2794 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2795 dataShifted = numpy.abs(data) * numpy.exp((numpy.angle(data)+phaseShift)*1j)
2795 2796 return dataShifted
2796
2797
2797 2798 def __estimatePhaseDifference(self, array, pairslist):
2798 2799 nChannel = array.shape[0]
2799 2800 nHeights = array.shape[2]
2800 2801 numPairs = len(pairslist)
2801 2802 # phaseCCF = numpy.zeros((nChannel, 5, nHeights))
2802 2803 phaseCCF = numpy.angle(self.__calculateCCF(array, pairslist, [-2,-1,0,1,2]))
2803
2804
2804 2805 #Correct phases
2805 2806 derPhaseCCF = phaseCCF[:,1:,:] - phaseCCF[:,0:-1,:]
2806 2807 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
2807
2808 if indDer[0].shape[0] > 0:
2808
2809 if indDer[0].shape[0] > 0:
2809 2810 for i in range(indDer[0].shape[0]):
2810 2811 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i],indDer[2][i]])
2811 2812 phaseCCF[indDer[0][i],indDer[1][i]+1:,:] += signo*2*numpy.pi
2812
2813
2813 2814 # for j in range(numSides):
2814 2815 # phaseCCFAux = self.calculateCCF(arrayCenter, arraySides[j,:,:], [-2,1,0,1,2])
2815 2816 # phaseCCF[j,:,:] = numpy.angle(phaseCCFAux)
2816 #
2817 #
2817 2818 #Linear
2818 2819 phaseInt = numpy.zeros((numPairs,1))
2819 2820 angAllCCF = phaseCCF[:,[0,1,3,4],0]
@@ -2823,16 +2824,16 class SMDetection(Operation):
2823 2824 #Phase Differences
2824 2825 phaseDiff = phaseInt - phaseCCF[:,2,:]
2825 2826 phaseArrival = phaseInt.reshape(phaseInt.size)
2826
2827
2827 2828 #Dealias
2828 2829 phaseArrival = numpy.angle(numpy.exp(1j*phaseArrival))
2829 2830 # indAlias = numpy.where(phaseArrival > numpy.pi)
2830 2831 # phaseArrival[indAlias] -= 2*numpy.pi
2831 2832 # indAlias = numpy.where(phaseArrival < -numpy.pi)
2832 2833 # phaseArrival[indAlias] += 2*numpy.pi
2833
2834
2834 2835 return phaseDiff, phaseArrival
2835
2836
2836 2837 def __coherentDetection(self, volts, timeSegment, timeInterval, pairslist, thresh):
2837 2838 #this function will run the coherent detection used in Holdworth et al. 2004 and return the net power
2838 2839 #find the phase shifts of each channel over 1 second intervals
@@ -2842,25 +2843,25 class SMDetection(Operation):
2842 2843 numHeights = volts.shape[2]
2843 2844 nChannel = volts.shape[0]
2844 2845 voltsCohDet = volts.copy()
2845
2846
2846 2847 pairsarray = numpy.array(pairslist)
2847 2848 indSides = pairsarray[:,1]
2848 2849 # indSides = numpy.array(range(nChannel))
2849 2850 # indSides = numpy.delete(indSides, indCenter)
2850 #
2851 #
2851 2852 # listCenter = numpy.array_split(volts[indCenter,:,:], numBlocks, 0)
2852 2853 listBlocks = numpy.array_split(volts, numBlocks, 1)
2853
2854
2854 2855 startInd = 0
2855 2856 endInd = 0
2856
2857
2857 2858 for i in range(numBlocks):
2858 2859 startInd = endInd
2859 endInd = endInd + listBlocks[i].shape[1]
2860
2860 endInd = endInd + listBlocks[i].shape[1]
2861
2861 2862 arrayBlock = listBlocks[i]
2862 2863 # arrayBlockCenter = listCenter[i]
2863
2864
2864 2865 #Estimate the Phase Difference
2865 2866 phaseDiff, aux = self.__estimatePhaseDifference(arrayBlock, pairslist)
2866 2867 #Phase Difference RMS
@@ -2872,21 +2873,21 class SMDetection(Operation):
2872 2873 for j in range(indSides.size):
2873 2874 arrayBlock[indSides[j],:,indPhase] = self.__shiftPhase(arrayBlock[indSides[j],:,indPhase], phaseDiff[j,indPhase].transpose())
2874 2875 voltsCohDet[:,startInd:endInd,:] = arrayBlock
2875
2876
2876 2877 return voltsCohDet
2877
2878
2878 2879 def __calculateCCF(self, volts, pairslist ,laglist):
2879
2880
2880 2881 nHeights = volts.shape[2]
2881 nPoints = volts.shape[1]
2882 nPoints = volts.shape[1]
2882 2883 voltsCCF = numpy.zeros((len(pairslist), len(laglist), nHeights),dtype = 'complex')
2883
2884
2884 2885 for i in range(len(pairslist)):
2885 2886 volts1 = volts[pairslist[i][0]]
2886 volts2 = volts[pairslist[i][1]]
2887
2887 volts2 = volts[pairslist[i][1]]
2888
2888 2889 for t in range(len(laglist)):
2889 idxT = laglist[t]
2890 idxT = laglist[t]
2890 2891 if idxT >= 0:
2891 2892 vStacked = numpy.vstack((volts2[idxT:,:],
2892 2893 numpy.zeros((idxT, nHeights),dtype='complex')))
@@ -2894,10 +2895,10 class SMDetection(Operation):
2894 2895 vStacked = numpy.vstack((numpy.zeros((-idxT, nHeights),dtype='complex'),
2895 2896 volts2[:(nPoints + idxT),:]))
2896 2897 voltsCCF[i,t,:] = numpy.sum((numpy.conjugate(volts1)*vStacked),axis=0)
2897
2898
2898 2899 vStacked = None
2899 2900 return voltsCCF
2900
2901
2901 2902 def __getNoise(self, power, timeSegment, timeInterval):
2902 2903 numProfPerBlock = numpy.ceil(timeSegment/timeInterval)
2903 2904 numBlocks = int(power.shape[0]/numProfPerBlock)
@@ -2906,100 +2907,100 class SMDetection(Operation):
2906 2907 listPower = numpy.array_split(power, numBlocks, 0)
2907 2908 noise = numpy.zeros((power.shape[0], power.shape[1]))
2908 2909 noise1 = numpy.zeros((power.shape[0], power.shape[1]))
2909
2910
2910 2911 startInd = 0
2911 2912 endInd = 0
2912
2913
2913 2914 for i in range(numBlocks): #split por canal
2914 2915 startInd = endInd
2915 endInd = endInd + listPower[i].shape[0]
2916
2916 endInd = endInd + listPower[i].shape[0]
2917
2917 2918 arrayBlock = listPower[i]
2918 2919 noiseAux = numpy.mean(arrayBlock, 0)
2919 2920 # noiseAux = numpy.median(noiseAux)
2920 2921 # noiseAux = numpy.mean(arrayBlock)
2921 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2922
2922 noise[startInd:endInd,:] = noise[startInd:endInd,:] + noiseAux
2923
2923 2924 noiseAux1 = numpy.mean(arrayBlock)
2924 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2925
2925 noise1[startInd:endInd,:] = noise1[startInd:endInd,:] + noiseAux1
2926
2926 2927 return noise, noise1
2927
2928
2928 2929 def __findMeteors(self, power, thresh):
2929 2930 nProf = power.shape[0]
2930 2931 nHeights = power.shape[1]
2931 2932 listMeteors = []
2932
2933
2933 2934 for i in range(nHeights):
2934 2935 powerAux = power[:,i]
2935 2936 threshAux = thresh[:,i]
2936
2937
2937 2938 indUPthresh = numpy.where(powerAux > threshAux)[0]
2938 2939 indDNthresh = numpy.where(powerAux <= threshAux)[0]
2939
2940
2940 2941 j = 0
2941
2942
2942 2943 while (j < indUPthresh.size - 2):
2943 2944 if (indUPthresh[j + 2] == indUPthresh[j] + 2):
2944 2945 indDNAux = numpy.where(indDNthresh > indUPthresh[j])
2945 2946 indDNthresh = indDNthresh[indDNAux]
2946
2947
2947 2948 if (indDNthresh.size > 0):
2948 2949 indEnd = indDNthresh[0] - 1
2949 2950 indInit = indUPthresh[j]
2950
2951
2951 2952 meteor = powerAux[indInit:indEnd + 1]
2952 2953 indPeak = meteor.argmax() + indInit
2953 2954 FLA = sum(numpy.conj(meteor)*numpy.hstack((meteor[1:],0)))
2954
2955
2955 2956 listMeteors.append(numpy.array([i,indInit,indPeak,indEnd,FLA])) #CHEQUEAR!!!!!
2956 2957 j = numpy.where(indUPthresh == indEnd)[0] + 1
2957 2958 else: j+=1
2958 2959 else: j+=1
2959
2960
2960 2961 return listMeteors
2961
2962
2962 2963 def __removeMultipleDetections(self,listMeteors, rangeLimit, timeLimit):
2963
2964 arrayMeteors = numpy.asarray(listMeteors)
2964
2965 arrayMeteors = numpy.asarray(listMeteors)
2965 2966 listMeteors1 = []
2966
2967
2967 2968 while arrayMeteors.shape[0] > 0:
2968 2969 FLAs = arrayMeteors[:,4]
2969 2970 maxFLA = FLAs.argmax()
2970 2971 listMeteors1.append(arrayMeteors[maxFLA,:])
2971
2972
2972 2973 MeteorInitTime = arrayMeteors[maxFLA,1]
2973 2974 MeteorEndTime = arrayMeteors[maxFLA,3]
2974 2975 MeteorHeight = arrayMeteors[maxFLA,0]
2975
2976
2976 2977 #Check neighborhood
2977 2978 maxHeightIndex = MeteorHeight + rangeLimit
2978 2979 minHeightIndex = MeteorHeight - rangeLimit
2979 2980 minTimeIndex = MeteorInitTime - timeLimit
2980 2981 maxTimeIndex = MeteorEndTime + timeLimit
2981
2982
2982 2983 #Check Heights
2983 2984 indHeight = numpy.logical_and(arrayMeteors[:,0] >= minHeightIndex, arrayMeteors[:,0] <= maxHeightIndex)
2984 2985 indTime = numpy.logical_and(arrayMeteors[:,3] >= minTimeIndex, arrayMeteors[:,1] <= maxTimeIndex)
2985 2986 indBoth = numpy.where(numpy.logical_and(indTime,indHeight))
2986
2987
2987 2988 arrayMeteors = numpy.delete(arrayMeteors, indBoth, axis = 0)
2988
2989
2989 2990 return listMeteors1
2990
2991
2991 2992 def __meteorReestimation(self, listMeteors, volts, pairslist, thresh, noise, timeInterval,frequency):
2992 2993 numHeights = volts.shape[2]
2993 2994 nChannel = volts.shape[0]
2994
2995
2995 2996 thresholdPhase = thresh[0]
2996 2997 thresholdNoise = thresh[1]
2997 2998 thresholdDB = float(thresh[2])
2998
2999
2999 3000 thresholdDB1 = 10**(thresholdDB/10)
3000 3001 pairsarray = numpy.array(pairslist)
3001 3002 indSides = pairsarray[:,1]
3002
3003
3003 3004 pairslist1 = list(pairslist)
3004 3005 pairslist1.append((0,1))
3005 3006 pairslist1.append((3,4))
@@ -3008,31 +3009,31 class SMDetection(Operation):
3008 3009 listPowerSeries = []
3009 3010 listVoltageSeries = []
3010 3011 #volts has the war data
3011
3012
3012 3013 if frequency == 30e6:
3013 3014 timeLag = 45*10**-3
3014 3015 else:
3015 3016 timeLag = 15*10**-3
3016 3017 lag = numpy.ceil(timeLag/timeInterval)
3017
3018
3018 3019 for i in range(len(listMeteors)):
3019
3020
3020 3021 ###################### 3.6 - 3.7 PARAMETERS REESTIMATION #########################
3021 3022 meteorAux = numpy.zeros(16)
3022
3023
3023 3024 #Loading meteor Data (mHeight, mStart, mPeak, mEnd)
3024 3025 mHeight = listMeteors[i][0]
3025 3026 mStart = listMeteors[i][1]
3026 3027 mPeak = listMeteors[i][2]
3027 3028 mEnd = listMeteors[i][3]
3028
3029
3029 3030 #get the volt data between the start and end times of the meteor
3030 3031 meteorVolts = volts[:,mStart:mEnd+1,mHeight]
3031 3032 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3032
3033
3033 3034 #3.6. Phase Difference estimation
3034 3035 phaseDiff, aux = self.__estimatePhaseDifference(meteorVolts, pairslist)
3035
3036
3036 3037 #3.7. Phase difference removal & meteor start, peak and end times reestimated
3037 3038 #meteorVolts0.- all Channels, all Profiles
3038 3039 meteorVolts0 = volts[:,:,mHeight]
@@ -3040,15 +3041,15 class SMDetection(Operation):
3040 3041 meteorNoise = noise[:,mHeight]
3041 3042 meteorVolts0[indSides,:] = self.__shiftPhase(meteorVolts0[indSides,:], phaseDiff) #Phase Shifting
3042 3043 powerNet0 = numpy.nansum(numpy.abs(meteorVolts0)**2, axis = 0) #Power
3043
3044
3044 3045 #Times reestimation
3045 3046 mStart1 = numpy.where(powerNet0[:mPeak] < meteorThresh[:mPeak])[0]
3046 3047 if mStart1.size > 0:
3047 3048 mStart1 = mStart1[-1] + 1
3048
3049 else:
3049
3050 else:
3050 3051 mStart1 = mPeak
3051
3052
3052 3053 mEnd1 = numpy.where(powerNet0[mPeak:] < meteorThresh[mPeak:])[0][0] + mPeak - 1
3053 3054 mEndDecayTime1 = numpy.where(powerNet0[mPeak:] < meteorNoise[mPeak:])[0]
3054 3055 if mEndDecayTime1.size == 0:
@@ -3056,7 +3057,7 class SMDetection(Operation):
3056 3057 else:
3057 3058 mEndDecayTime1 = mEndDecayTime1[0] + mPeak - 1
3058 3059 # mPeak1 = meteorVolts0[mStart1:mEnd1 + 1].argmax()
3059
3060
3060 3061 #meteorVolts1.- all Channels, from start to end
3061 3062 meteorVolts1 = meteorVolts0[:,mStart1:mEnd1 + 1]
3062 3063 meteorVolts2 = meteorVolts0[:,mPeak + lag:mEnd1 + 1]
@@ -3065,17 +3066,17 class SMDetection(Operation):
3065 3066 meteorVolts1 = meteorVolts1.reshape(meteorVolts1.shape[0], meteorVolts1.shape[1], 1)
3066 3067 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1], 1)
3067 3068 ##################### END PARAMETERS REESTIMATION #########################
3068
3069
3069 3070 ##################### 3.8 PHASE DIFFERENCE REESTIMATION ########################
3070 3071 # if mEnd1 - mStart1 > 4: #Error Number 6: echo less than 5 samples long; too short for analysis
3071 if meteorVolts2.shape[1] > 0:
3072 if meteorVolts2.shape[1] > 0:
3072 3073 #Phase Difference re-estimation
3073 3074 phaseDiff1, phaseDiffint = self.__estimatePhaseDifference(meteorVolts2, pairslist1) #Phase Difference Estimation
3074 3075 # phaseDiff1, phaseDiffint = self.estimatePhaseDifference(meteorVolts2, pairslist)
3075 3076 meteorVolts2 = meteorVolts2.reshape(meteorVolts2.shape[0], meteorVolts2.shape[1])
3076 3077 phaseDiff11 = numpy.reshape(phaseDiff1, (phaseDiff1.shape[0],1))
3077 3078 meteorVolts2[indSides,:] = self.__shiftPhase(meteorVolts2[indSides,:], phaseDiff11[0:4]) #Phase Shifting
3078
3079
3079 3080 #Phase Difference RMS
3080 3081 phaseRMS1 = numpy.sqrt(numpy.mean(numpy.square(phaseDiff1)))
3081 3082 powerNet1 = numpy.nansum(numpy.abs(meteorVolts1[:,:])**2,0)
@@ -3090,27 +3091,27 class SMDetection(Operation):
3090 3091 #Vectorize
3091 3092 meteorAux[0:7] = [mHeight, mStart1, mPeak1, mEnd1, mPeakPower1, mSNR1, phaseRMS1]
3092 3093 meteorAux[7:11] = phaseDiffint[0:4]
3093
3094
3094 3095 #Rejection Criterions
3095 3096 if phaseRMS1 > thresholdPhase: #Error Number 17: Phase variation
3096 3097 meteorAux[-1] = 17
3097 3098 elif mSNR1 < thresholdDB1: #Error Number 1: SNR < threshold dB
3098 3099 meteorAux[-1] = 1
3099
3100
3101 else:
3100
3101
3102 else:
3102 3103 meteorAux[0:4] = [mHeight, mStart, mPeak, mEnd]
3103 3104 meteorAux[-1] = 6 #Error Number 6: echo less than 5 samples long; too short for analysis
3104 3105 PowerSeries = 0
3105
3106
3106 3107 listMeteors1.append(meteorAux)
3107 3108 listPowerSeries.append(PowerSeries)
3108 3109 listVoltageSeries.append(meteorVolts1)
3109
3110 return listMeteors1, listPowerSeries, listVoltageSeries
3111
3110
3111 return listMeteors1, listPowerSeries, listVoltageSeries
3112
3112 3113 def __estimateDecayTime(self, listMeteors, listPower, timeInterval, frequency):
3113
3114
3114 3115 threshError = 10
3115 3116 #Depending if it is 30 or 50 MHz
3116 3117 if frequency == 30e6:
@@ -3118,22 +3119,22 class SMDetection(Operation):
3118 3119 else:
3119 3120 timeLag = 15*10**-3
3120 3121 lag = numpy.ceil(timeLag/timeInterval)
3121
3122
3122 3123 listMeteors1 = []
3123
3124
3124 3125 for i in range(len(listMeteors)):
3125 3126 meteorPower = listPower[i]
3126 3127 meteorAux = listMeteors[i]
3127
3128
3128 3129 if meteorAux[-1] == 0:
3129 3130
3130 try:
3131 try:
3131 3132 indmax = meteorPower.argmax()
3132 3133 indlag = indmax + lag
3133
3134
3134 3135 y = meteorPower[indlag:]
3135 3136 x = numpy.arange(0, y.size)*timeLag
3136
3137
3137 3138 #first guess
3138 3139 a = y[0]
3139 3140 tau = timeLag
@@ -3142,26 +3143,26 class SMDetection(Operation):
3142 3143 y1 = self.__exponential_function(x, *popt)
3143 3144 #error estimation
3144 3145 error = sum((y - y1)**2)/(numpy.var(y)*(y.size - popt.size))
3145
3146
3146 3147 decayTime = popt[1]
3147 3148 riseTime = indmax*timeInterval
3148 3149 meteorAux[11:13] = [decayTime, error]
3149
3150
3150 3151 #Table items 7, 8 and 11
3151 3152 if (riseTime > 0.3): #Number 7: Echo rise exceeds 0.3s
3152 meteorAux[-1] = 7
3153 meteorAux[-1] = 7
3153 3154 elif (decayTime < 2*riseTime) : #Number 8: Echo decay time less than than twice rise time
3154 3155 meteorAux[-1] = 8
3155 3156 if (error > threshError): #Number 11: Poor fit to amplitude for estimation of decay time
3156 meteorAux[-1] = 11
3157
3158
3157 meteorAux[-1] = 11
3158
3159
3159 3160 except:
3160 meteorAux[-1] = 11
3161
3162
3161 meteorAux[-1] = 11
3162
3163
3163 3164 listMeteors1.append(meteorAux)
3164
3165
3165 3166 return listMeteors1
3166 3167
3167 3168 #Exponential Function
@@ -3169,9 +3170,9 class SMDetection(Operation):
3169 3170 def __exponential_function(self, x, a, tau):
3170 3171 y = a*numpy.exp(-x/tau)
3171 3172 return y
3172
3173
3173 3174 def __getRadialVelocity(self, listMeteors, listVolts, radialStdThresh, pairslist, timeInterval):
3174
3175
3175 3176 pairslist1 = list(pairslist)
3176 3177 pairslist1.append((0,1))
3177 3178 pairslist1.append((3,4))
@@ -3181,33 +3182,33 class SMDetection(Operation):
3181 3182 c = 3e8
3182 3183 lag = numpy.ceil(timeLag/timeInterval)
3183 3184 freq = 30e6
3184
3185
3185 3186 listMeteors1 = []
3186
3187
3187 3188 for i in range(len(listMeteors)):
3188 3189 meteorAux = listMeteors[i]
3189 3190 if meteorAux[-1] == 0:
3190 3191 mStart = listMeteors[i][1]
3191 mPeak = listMeteors[i][2]
3192 mPeak = listMeteors[i][2]
3192 3193 mLag = mPeak - mStart + lag
3193
3194
3194 3195 #get the volt data between the start and end times of the meteor
3195 3196 meteorVolts = listVolts[i]
3196 3197 meteorVolts = meteorVolts.reshape(meteorVolts.shape[0], meteorVolts.shape[1], 1)
3197 3198
3198 3199 #Get CCF
3199 3200 allCCFs = self.__calculateCCF(meteorVolts, pairslist1, [-2,-1,0,1,2])
3200
3201
3201 3202 #Method 2
3202 3203 slopes = numpy.zeros(numPairs)
3203 3204 time = numpy.array([-2,-1,1,2])*timeInterval
3204 3205 angAllCCF = numpy.angle(allCCFs[:,[0,1,3,4],0])
3205
3206
3206 3207 #Correct phases
3207 3208 derPhaseCCF = angAllCCF[:,1:] - angAllCCF[:,0:-1]
3208 3209 indDer = numpy.where(numpy.abs(derPhaseCCF) > numpy.pi)
3209
3210 if indDer[0].shape[0] > 0:
3210
3211 if indDer[0].shape[0] > 0:
3211 3212 for i in range(indDer[0].shape[0]):
3212 3213 signo = -numpy.sign(derPhaseCCF[indDer[0][i],indDer[1][i]])
3213 3214 angAllCCF[indDer[0][i],indDer[1][i]+1:] += signo*2*numpy.pi
@@ -3216,51 +3217,51 class SMDetection(Operation):
3216 3217 for j in range(numPairs):
3217 3218 fit = stats.linregress(time, angAllCCF[j,:])
3218 3219 slopes[j] = fit[0]
3219
3220
3220 3221 #Remove Outlier
3221 3222 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3222 3223 # slopes = numpy.delete(slopes,indOut)
3223 3224 # indOut = numpy.argmax(numpy.abs(slopes - numpy.mean(slopes)))
3224 3225 # slopes = numpy.delete(slopes,indOut)
3225
3226
3226 3227 radialVelocity = -numpy.mean(slopes)*(0.25/numpy.pi)*(c/freq)
3227 3228 radialError = numpy.std(slopes)*(0.25/numpy.pi)*(c/freq)
3228 3229 meteorAux[-2] = radialError
3229 3230 meteorAux[-3] = radialVelocity
3230
3231
3231 3232 #Setting Error
3232 3233 #Number 15: Radial Drift velocity or projected horizontal velocity exceeds 200 m/s
3233 if numpy.abs(radialVelocity) > 200:
3234 if numpy.abs(radialVelocity) > 200:
3234 3235 meteorAux[-1] = 15
3235 3236 #Number 12: Poor fit to CCF variation for estimation of radial drift velocity
3236 3237 elif radialError > radialStdThresh:
3237 3238 meteorAux[-1] = 12
3238
3239
3239 3240 listMeteors1.append(meteorAux)
3240 3241 return listMeteors1
3241
3242
3242 3243 def __setNewArrays(self, listMeteors, date, heiRang):
3243
3244
3244 3245 #New arrays
3245 3246 arrayMeteors = numpy.array(listMeteors)
3246 3247 arrayParameters = numpy.zeros((len(listMeteors), 13))
3247
3248
3248 3249 #Date inclusion
3249 3250 # date = re.findall(r'\((.*?)\)', date)
3250 3251 # date = date[0].split(',')
3251 3252 # date = map(int, date)
3252 #
3253 #
3253 3254 # if len(date)<6:
3254 3255 # date.append(0)
3255 #
3256 #
3256 3257 # date = [date[0]*10000 + date[1]*100 + date[2], date[3]*10000 + date[4]*100 + date[5]]
3257 3258 # arrayDate = numpy.tile(date, (len(listMeteors), 1))
3258 3259 arrayDate = numpy.tile(date, (len(listMeteors)))
3259
3260
3260 3261 #Meteor array
3261 3262 # arrayMeteors[:,0] = heiRang[arrayMeteors[:,0].astype(int)]
3262 3263 # arrayMeteors = numpy.hstack((arrayDate, arrayMeteors))
3263
3264
3264 3265 #Parameters Array
3265 3266 arrayParameters[:,0] = arrayDate #Date
3266 3267 arrayParameters[:,1] = heiRang[arrayMeteors[:,0].astype(int)] #Range
@@ -3268,13 +3269,13 class SMDetection(Operation):
3268 3269 arrayParameters[:,8:12] = arrayMeteors[:,7:11] #Phases
3269 3270 arrayParameters[:,-1] = arrayMeteors[:,-1] #Error
3270 3271
3271
3272
3272 3273 return arrayParameters
3273
3274
3274 3275 class CorrectSMPhases(Operation):
3275
3276
3276 3277 def run(self, dataOut, phaseOffsets, hmin = 50, hmax = 150, azimuth = 45, channelPositions = None):
3277
3278
3278 3279 arrayParameters = dataOut.data_param
3279 3280 pairsList = []
3280 3281 pairx = (0,1)
@@ -3282,49 +3283,49 class CorrectSMPhases(Operation):
3282 3283 pairsList.append(pairx)
3283 3284 pairsList.append(pairy)
3284 3285 jph = numpy.zeros(4)
3285
3286
3286 3287 phaseOffsets = numpy.array(phaseOffsets)*numpy.pi/180
3287 3288 # arrayParameters[:,8:12] = numpy.unwrap(arrayParameters[:,8:12] + phaseOffsets)
3288 3289 arrayParameters[:,8:12] = numpy.angle(numpy.exp(1j*(arrayParameters[:,8:12] + phaseOffsets)))
3289
3290
3290 3291 meteorOps = SMOperations()
3291 3292 if channelPositions is None:
3292 3293 # channelPositions = [(2.5,0), (0,2.5), (0,0), (0,4.5), (-2,0)] #T
3293 3294 channelPositions = [(4.5,2), (2,4.5), (2,2), (2,0), (0,2)] #Estrella
3294
3295
3295 3296 pairslist0, distances = meteorOps.getPhasePairs(channelPositions)
3296 3297 h = (hmin,hmax)
3297
3298
3298 3299 arrayParameters = meteorOps.getMeteorParams(arrayParameters, azimuth, h, pairsList, distances, jph)
3299
3300
3300 3301 dataOut.data_param = arrayParameters
3301 3302 return
3302 3303
3303 3304 class SMPhaseCalibration(Operation):
3304
3305
3305 3306 __buffer = None
3306 3307
3307 3308 __initime = None
3308 3309
3309 3310 __dataReady = False
3310
3311
3311 3312 __isConfig = False
3312
3313
3313 3314 def __checkTime(self, currentTime, initTime, paramInterval, outputInterval):
3314
3315
3315 3316 dataTime = currentTime + paramInterval
3316 3317 deltaTime = dataTime - initTime
3317
3318
3318 3319 if deltaTime >= outputInterval or deltaTime < 0:
3319 3320 return True
3320
3321
3321 3322 return False
3322
3323
3323 3324 def __getGammas(self, pairs, d, phases):
3324 3325 gammas = numpy.zeros(2)
3325
3326
3326 3327 for i in range(len(pairs)):
3327
3328
3328 3329 pairi = pairs[i]
3329 3330
3330 3331 phip3 = phases[:,pairi[0]]
@@ -3338,7 +3339,7 class SMPhaseCalibration(Operation):
3338 3339 jgamma = numpy.angle(numpy.exp(1j*jgamma))
3339 3340 # jgamma[jgamma>numpy.pi] -= 2*numpy.pi
3340 3341 # jgamma[jgamma<-numpy.pi] += 2*numpy.pi
3341
3342
3342 3343 #Revised distribution
3343 3344 jgammaArray = numpy.hstack((jgamma,jgamma+0.5*numpy.pi,jgamma-0.5*numpy.pi))
3344 3345
@@ -3347,39 +3348,39 class SMPhaseCalibration(Operation):
3347 3348 rmin = -0.5*numpy.pi
3348 3349 rmax = 0.5*numpy.pi
3349 3350 phaseHisto = numpy.histogram(jgammaArray, bins=nBins, range=(rmin,rmax))
3350
3351
3351 3352 meteorsY = phaseHisto[0]
3352 3353 phasesX = phaseHisto[1][:-1]
3353 3354 width = phasesX[1] - phasesX[0]
3354 3355 phasesX += width/2
3355
3356
3356 3357 #Gaussian aproximation
3357 3358 bpeak = meteorsY.argmax()
3358 3359 peak = meteorsY.max()
3359 3360 jmin = bpeak - 5
3360 3361 jmax = bpeak + 5 + 1
3361
3362
3362 3363 if jmin<0:
3363 3364 jmin = 0
3364 3365 jmax = 6
3365 3366 elif jmax > meteorsY.size:
3366 3367 jmin = meteorsY.size - 6
3367 3368 jmax = meteorsY.size
3368
3369
3369 3370 x0 = numpy.array([peak,bpeak,50])
3370 3371 coeff = optimize.leastsq(self.__residualFunction, x0, args=(meteorsY[jmin:jmax], phasesX[jmin:jmax]))
3371
3372
3372 3373 #Gammas
3373 3374 gammas[i] = coeff[0][1]
3374
3375
3375 3376 return gammas
3376
3377
3377 3378 def __residualFunction(self, coeffs, y, t):
3378
3379
3379 3380 return y - self.__gauss_function(t, coeffs)
3380 3381
3381 3382 def __gauss_function(self, t, coeffs):
3382
3383
3383 3384 return coeffs[0]*numpy.exp(-0.5*((t - coeffs[1]) / coeffs[2])**2)
3384 3385
3385 3386 def __getPhases(self, azimuth, h, pairsList, d, gammas, meteorsArray):
@@ -3400,16 +3401,16 class SMPhaseCalibration(Operation):
3400 3401 max_xangle = range_angle[iz]/2 + center_xangle
3401 3402 min_yangle = -range_angle[iz]/2 + center_yangle
3402 3403 max_yangle = range_angle[iz]/2 + center_yangle
3403
3404
3404 3405 inc_x = (max_xangle-min_xangle)/nstepsx
3405 3406 inc_y = (max_yangle-min_yangle)/nstepsy
3406
3407
3407 3408 alpha_y = numpy.arange(nstepsy)*inc_y + min_yangle
3408 3409 alpha_x = numpy.arange(nstepsx)*inc_x + min_xangle
3409 3410 penalty = numpy.zeros((nstepsx,nstepsy))
3410 3411 jph_array = numpy.zeros((nchan,nstepsx,nstepsy))
3411 3412 jph = numpy.zeros(nchan)
3412
3413
3413 3414 # Iterations looking for the offset
3414 3415 for iy in range(int(nstepsy)):
3415 3416 for ix in range(int(nstepsx)):
@@ -3417,46 +3418,46 class SMPhaseCalibration(Operation):
3417 3418 d2 = d[pairsList[1][1]]
3418 3419 d5 = d[pairsList[0][0]]
3419 3420 d4 = d[pairsList[0][1]]
3420
3421
3421 3422 alp2 = alpha_y[iy] #gamma 1
3422 alp4 = alpha_x[ix] #gamma 0
3423
3423 alp4 = alpha_x[ix] #gamma 0
3424
3424 3425 alp3 = -alp2*d3/d2 - gammas[1]
3425 3426 alp5 = -alp4*d5/d4 - gammas[0]
3426 3427 # jph[pairy[1]] = alpha_y[iy]
3427 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3428
3428 # jph[pairy[0]] = -gammas[1] - alpha_y[iy]*d[pairy[1]]/d[pairy[0]]
3429
3429 3430 # jph[pairx[1]] = alpha_x[ix]
3430 3431 # jph[pairx[0]] = -gammas[0] - alpha_x[ix]*d[pairx[1]]/d[pairx[0]]
3431 3432 jph[pairsList[0][1]] = alp4
3432 3433 jph[pairsList[0][0]] = alp5
3433 3434 jph[pairsList[1][0]] = alp3
3434 jph[pairsList[1][1]] = alp2
3435 jph[pairsList[1][1]] = alp2
3435 3436 jph_array[:,ix,iy] = jph
3436 3437 # d = [2.0,2.5,2.5,2.0]
3437 #falta chequear si va a leer bien los meteoros
3438 #falta chequear si va a leer bien los meteoros
3438 3439 meteorsArray1 = meteorOps.getMeteorParams(meteorsArray, azimuth, h, pairsList, d, jph)
3439 3440 error = meteorsArray1[:,-1]
3440 3441 ind1 = numpy.where(error==0)[0]
3441 3442 penalty[ix,iy] = ind1.size
3442
3443
3443 3444 i,j = numpy.unravel_index(penalty.argmax(), penalty.shape)
3444 3445 phOffset = jph_array[:,i,j]
3445
3446
3446 3447 center_xangle = phOffset[pairx[1]]
3447 3448 center_yangle = phOffset[pairy[1]]
3448
3449
3449 3450 phOffset = numpy.angle(numpy.exp(1j*jph_array[:,i,j]))
3450 phOffset = phOffset*180/numpy.pi
3451 phOffset = phOffset*180/numpy.pi
3451 3452 return phOffset
3452
3453
3453
3454
3454 3455 def run(self, dataOut, hmin, hmax, channelPositions=None, nHours = 1):
3455
3456
3456 3457 dataOut.flagNoData = True
3457 self.__dataReady = False
3458 self.__dataReady = False
3458 3459 dataOut.outputInterval = nHours*3600
3459
3460
3460 3461 if self.__isConfig == False:
3461 3462 # self.__initime = dataOut.datatime.replace(minute = 0, second = 0, microsecond = 03)
3462 3463 #Get Initial LTC time
@@ -3464,19 +3465,19 class SMPhaseCalibration(Operation):
3464 3465 self.__initime = (self.__initime.replace(minute = 0, second = 0, microsecond = 0) - datetime.datetime(1970, 1, 1)).total_seconds()
3465 3466
3466 3467 self.__isConfig = True
3467
3468
3468 3469 if self.__buffer is None:
3469 3470 self.__buffer = dataOut.data_param.copy()
3470 3471
3471 3472 else:
3472 3473 self.__buffer = numpy.vstack((self.__buffer, dataOut.data_param))
3473
3474
3474 3475 self.__dataReady = self.__checkTime(dataOut.utctime, self.__initime, dataOut.paramInterval, dataOut.outputInterval) #Check if the buffer is ready
3475
3476
3476 3477 if self.__dataReady:
3477 3478 dataOut.utctimeInit = self.__initime
3478 3479 self.__initime += dataOut.outputInterval #to erase time offset
3479
3480
3480 3481 freq = dataOut.frequency
3481 3482 c = dataOut.C #m/s
3482 3483 lamb = c/freq
@@ -3498,13 +3499,13 class SMPhaseCalibration(Operation):
3498 3499 pairs.append((1,0))
3499 3500 else:
3500 3501 pairs.append((0,1))
3501
3502
3502 3503 if distances[3] > distances[2]:
3503 3504 pairs.append((3,2))
3504 3505 else:
3505 3506 pairs.append((2,3))
3506 3507 # distances1 = [-distances[0]*lamb, distances[1]*lamb, -distances[2]*lamb, distances[3]*lamb]
3507
3508
3508 3509 meteorsArray = self.__buffer
3509 3510 error = meteorsArray[:,-1]
3510 3511 boolError = (error==0)|(error==3)|(error==4)|(error==13)|(error==14)
@@ -3512,7 +3513,7 class SMPhaseCalibration(Operation):
3512 3513 meteorsArray = meteorsArray[ind1,:]
3513 3514 meteorsArray[:,-1] = 0
3514 3515 phases = meteorsArray[:,8:12]
3515
3516
3516 3517 #Calculate Gammas
3517 3518 gammas = self.__getGammas(pairs, distances, phases)
3518 3519 # gammas = numpy.array([-21.70409463,45.76935864])*numpy.pi/180
@@ -3522,22 +3523,22 class SMPhaseCalibration(Operation):
3522 3523 dataOut.data_output = -phasesOff
3523 3524 dataOut.flagNoData = False
3524 3525 self.__buffer = None
3525
3526
3526
3527
3527 3528 return
3528
3529
3529 3530 class SMOperations():
3530
3531
3531 3532 def __init__(self):
3532
3533
3533 3534 return
3534
3535
3535 3536 def getMeteorParams(self, arrayParameters0, azimuth, h, pairsList, distances, jph):
3536
3537
3537 3538 arrayParameters = arrayParameters0.copy()
3538 3539 hmin = h[0]
3539 3540 hmax = h[1]
3540
3541
3541 3542 #Calculate AOA (Error N 3, 4)
3542 3543 #JONES ET AL. 1998
3543 3544 AOAthresh = numpy.pi/8
@@ -3545,72 +3546,72 class SMOperations():
3545 3546 phases = -arrayParameters[:,8:12] + jph
3546 3547 # phases = numpy.unwrap(phases)
3547 3548 arrayParameters[:,3:6], arrayParameters[:,-1] = self.__getAOA(phases, pairsList, distances, error, AOAthresh, azimuth)
3548
3549
3549 3550 #Calculate Heights (Error N 13 and 14)
3550 3551 error = arrayParameters[:,-1]
3551 3552 Ranges = arrayParameters[:,1]
3552 3553 zenith = arrayParameters[:,4]
3553 3554 arrayParameters[:,2], arrayParameters[:,-1] = self.__getHeights(Ranges, zenith, error, hmin, hmax)
3554
3555
3555 3556 #----------------------- Get Final data ------------------------------------
3556 3557 # error = arrayParameters[:,-1]
3557 3558 # ind1 = numpy.where(error==0)[0]
3558 3559 # arrayParameters = arrayParameters[ind1,:]
3559
3560
3560 3561 return arrayParameters
3561
3562
3562 3563 def __getAOA(self, phases, pairsList, directions, error, AOAthresh, azimuth):
3563
3564
3564 3565 arrayAOA = numpy.zeros((phases.shape[0],3))
3565 3566 cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList,directions)
3566
3567
3567 3568 arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3568 3569 cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3569 3570 arrayAOA[:,2] = cosDirError
3570
3571
3571 3572 azimuthAngle = arrayAOA[:,0]
3572 3573 zenithAngle = arrayAOA[:,1]
3573
3574
3574 3575 #Setting Error
3575 3576 indError = numpy.where(numpy.logical_or(error == 3, error == 4))[0]
3576 3577 error[indError] = 0
3577 3578 #Number 3: AOA not fesible
3578 3579 indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3579 error[indInvalid] = 3
3580 error[indInvalid] = 3
3580 3581 #Number 4: Large difference in AOAs obtained from different antenna baselines
3581 3582 indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3582 error[indInvalid] = 4
3583 error[indInvalid] = 4
3583 3584 return arrayAOA, error
3584
3585
3585 3586 def __getDirectionCosines(self, arrayPhase, pairsList, distances):
3586
3587
3587 3588 #Initializing some variables
3588 3589 ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3589 3590 ang_aux = ang_aux.reshape(1,ang_aux.size)
3590
3591
3591 3592 cosdir = numpy.zeros((arrayPhase.shape[0],2))
3592 3593 cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3593
3594
3594
3595
3595 3596 for i in range(2):
3596 3597 ph0 = arrayPhase[:,pairsList[i][0]]
3597 3598 ph1 = arrayPhase[:,pairsList[i][1]]
3598 3599 d0 = distances[pairsList[i][0]]
3599 3600 d1 = distances[pairsList[i][1]]
3600
3601 ph0_aux = ph0 + ph1
3601
3602 ph0_aux = ph0 + ph1
3602 3603 ph0_aux = numpy.angle(numpy.exp(1j*ph0_aux))
3603 3604 # ph0_aux[ph0_aux > numpy.pi] -= 2*numpy.pi
3604 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3605 # ph0_aux[ph0_aux < -numpy.pi] += 2*numpy.pi
3605 3606 #First Estimation
3606 3607 cosdir0[:,i] = (ph0_aux)/(2*numpy.pi*(d0 - d1))
3607
3608
3608 3609 #Most-Accurate Second Estimation
3609 3610 phi1_aux = ph0 - ph1
3610 3611 phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3611 3612 #Direction Cosine 1
3612 3613 cosdir1 = (phi1_aux + ang_aux)/(2*numpy.pi*(d0 + d1))
3613
3614
3614 3615 #Searching the correct Direction Cosine
3615 3616 cosdir0_aux = cosdir0[:,i]
3616 3617 cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
@@ -3619,59 +3620,59 class SMOperations():
3619 3620 indcos = cosDiff.argmin(axis = 1)
3620 3621 #Saving Value obtained
3621 3622 cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3622
3623
3623 3624 return cosdir0, cosdir
3624
3625
3625 3626 def __calculateAOA(self, cosdir, azimuth):
3626 3627 cosdirX = cosdir[:,0]
3627 3628 cosdirY = cosdir[:,1]
3628
3629
3629 3630 zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3630 3631 azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth#0 deg north, 90 deg east
3631 3632 angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3632
3633
3633 3634 return angles
3634
3635
3635 3636 def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3636
3637
3637 3638 Ramb = 375 #Ramb = c/(2*PRF)
3638 3639 Re = 6371 #Earth Radius
3639 3640 heights = numpy.zeros(Ranges.shape)
3640
3641
3641 3642 R_aux = numpy.array([0,1,2])*Ramb
3642 3643 R_aux = R_aux.reshape(1,R_aux.size)
3643 3644
3644 3645 Ranges = Ranges.reshape(Ranges.size,1)
3645
3646
3646 3647 Ri = Ranges + R_aux
3647 3648 hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3648
3649
3649 3650 #Check if there is a height between 70 and 110 km
3650 3651 h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3651 3652 ind_h = numpy.where(h_bool == 1)[0]
3652
3653
3653 3654 hCorr = hi[ind_h, :]
3654 3655 ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3655
3656
3656 3657 hCorr = hi[ind_hCorr][:len(ind_h)]
3657 3658 heights[ind_h] = hCorr
3658
3659
3659 3660 #Setting Error
3660 3661 #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3661 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3662 #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3662 3663 indError = numpy.where(numpy.logical_or(error == 13, error == 14))[0]
3663 3664 error[indError] = 0
3664 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3665 indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3665 3666 error[indInvalid2] = 14
3666 3667 indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3667 error[indInvalid1] = 13
3668
3668 error[indInvalid1] = 13
3669
3669 3670 return heights, error
3670
3671
3671 3672 def getPhasePairs(self, channelPositions):
3672 3673 chanPos = numpy.array(channelPositions)
3673 3674 listOper = list(itertools.combinations(list(range(5)),2))
3674
3675
3675 3676 distances = numpy.zeros(4)
3676 3677 axisX = []
3677 3678 axisY = []
@@ -3679,15 +3680,15 class SMOperations():
3679 3680 distY = numpy.zeros(3)
3680 3681 ix = 0
3681 3682 iy = 0
3682
3683
3683 3684 pairX = numpy.zeros((2,2))
3684 3685 pairY = numpy.zeros((2,2))
3685
3686
3686 3687 for i in range(len(listOper)):
3687 3688 pairi = listOper[i]
3688
3689
3689 3690 posDif = numpy.abs(chanPos[pairi[0],:] - chanPos[pairi[1],:])
3690
3691
3691 3692 if posDif[0] == 0:
3692 3693 axisY.append(pairi)
3693 3694 distY[iy] = posDif[1]
@@ -3696,7 +3697,7 class SMOperations():
3696 3697 axisX.append(pairi)
3697 3698 distX[ix] = posDif[0]
3698 3699 ix += 1
3699
3700
3700 3701 for i in range(2):
3701 3702 if i==0:
3702 3703 dist0 = distX
@@ -3704,7 +3705,7 class SMOperations():
3704 3705 else:
3705 3706 dist0 = distY
3706 3707 axis0 = axisY
3707
3708
3708 3709 side = numpy.argsort(dist0)[:-1]
3709 3710 axis0 = numpy.array(axis0)[side,:]
3710 3711 chanC = int(numpy.intersect1d(axis0[0,:], axis0[1,:])[0])
@@ -3712,7 +3713,7 class SMOperations():
3712 3713 side = axis1[axis1 != chanC]
3713 3714 diff1 = chanPos[chanC,i] - chanPos[side[0],i]
3714 3715 diff2 = chanPos[chanC,i] - chanPos[side[1],i]
3715 if diff1<0:
3716 if diff1<0:
3716 3717 chan2 = side[0]
3717 3718 d2 = numpy.abs(diff1)
3718 3719 chan1 = side[1]
@@ -3722,7 +3723,7 class SMOperations():
3722 3723 d2 = numpy.abs(diff2)
3723 3724 chan1 = side[0]
3724 3725 d1 = numpy.abs(diff1)
3725
3726
3726 3727 if i==0:
3727 3728 chanCX = chanC
3728 3729 chan1X = chan1
@@ -3734,10 +3735,10 class SMOperations():
3734 3735 chan2Y = chan2
3735 3736 distances[2:4] = numpy.array([d1,d2])
3736 3737 # axisXsides = numpy.reshape(axisX[ix,:],4)
3737 #
3738 #
3738 3739 # channelCentX = int(numpy.intersect1d(pairX[0,:], pairX[1,:])[0])
3739 3740 # channelCentY = int(numpy.intersect1d(pairY[0,:], pairY[1,:])[0])
3740 #
3741 #
3741 3742 # ind25X = numpy.where(pairX[0,:] != channelCentX)[0][0]
3742 3743 # ind20X = numpy.where(pairX[1,:] != channelCentX)[0][0]
3743 3744 # channel25X = int(pairX[0,ind25X])
@@ -3746,59 +3747,59 class SMOperations():
3746 3747 # ind20Y = numpy.where(pairY[1,:] != channelCentY)[0][0]
3747 3748 # channel25Y = int(pairY[0,ind25Y])
3748 3749 # channel20Y = int(pairY[1,ind20Y])
3749
3750
3750 3751 # pairslist = [(channelCentX, channel25X),(channelCentX, channel20X),(channelCentY,channel25Y),(channelCentY, channel20Y)]
3751 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3752
3752 pairslist = [(chanCX, chan1X),(chanCX, chan2X),(chanCY,chan1Y),(chanCY, chan2Y)]
3753
3753 3754 return pairslist, distances
3754 3755 # def __getAOA(self, phases, pairsList, error, AOAthresh, azimuth):
3755 #
3756 #
3756 3757 # arrayAOA = numpy.zeros((phases.shape[0],3))
3757 3758 # cosdir0, cosdir = self.__getDirectionCosines(phases, pairsList)
3758 #
3759 #
3759 3760 # arrayAOA[:,:2] = self.__calculateAOA(cosdir, azimuth)
3760 3761 # cosDirError = numpy.sum(numpy.abs(cosdir0 - cosdir), axis = 1)
3761 3762 # arrayAOA[:,2] = cosDirError
3762 #
3763 #
3763 3764 # azimuthAngle = arrayAOA[:,0]
3764 3765 # zenithAngle = arrayAOA[:,1]
3765 #
3766 #
3766 3767 # #Setting Error
3767 3768 # #Number 3: AOA not fesible
3768 3769 # indInvalid = numpy.where(numpy.logical_and((numpy.logical_or(numpy.isnan(zenithAngle), numpy.isnan(azimuthAngle))),error == 0))[0]
3769 # error[indInvalid] = 3
3770 # error[indInvalid] = 3
3770 3771 # #Number 4: Large difference in AOAs obtained from different antenna baselines
3771 3772 # indInvalid = numpy.where(numpy.logical_and(cosDirError > AOAthresh,error == 0))[0]
3772 # error[indInvalid] = 4
3773 # error[indInvalid] = 4
3773 3774 # return arrayAOA, error
3774 #
3775 #
3775 3776 # def __getDirectionCosines(self, arrayPhase, pairsList):
3776 #
3777 #
3777 3778 # #Initializing some variables
3778 3779 # ang_aux = numpy.array([-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8])*2*numpy.pi
3779 3780 # ang_aux = ang_aux.reshape(1,ang_aux.size)
3780 #
3781 #
3781 3782 # cosdir = numpy.zeros((arrayPhase.shape[0],2))
3782 3783 # cosdir0 = numpy.zeros((arrayPhase.shape[0],2))
3783 #
3784 #
3784 #
3785 #
3785 3786 # for i in range(2):
3786 3787 # #First Estimation
3787 3788 # phi0_aux = arrayPhase[:,pairsList[i][0]] + arrayPhase[:,pairsList[i][1]]
3788 3789 # #Dealias
3789 3790 # indcsi = numpy.where(phi0_aux > numpy.pi)
3790 # phi0_aux[indcsi] -= 2*numpy.pi
3791 # phi0_aux[indcsi] -= 2*numpy.pi
3791 3792 # indcsi = numpy.where(phi0_aux < -numpy.pi)
3792 # phi0_aux[indcsi] += 2*numpy.pi
3793 # phi0_aux[indcsi] += 2*numpy.pi
3793 3794 # #Direction Cosine 0
3794 3795 # cosdir0[:,i] = -(phi0_aux)/(2*numpy.pi*0.5)
3795 #
3796 #
3796 3797 # #Most-Accurate Second Estimation
3797 3798 # phi1_aux = arrayPhase[:,pairsList[i][0]] - arrayPhase[:,pairsList[i][1]]
3798 3799 # phi1_aux = phi1_aux.reshape(phi1_aux.size,1)
3799 3800 # #Direction Cosine 1
3800 3801 # cosdir1 = -(phi1_aux + ang_aux)/(2*numpy.pi*4.5)
3801 #
3802 #
3802 3803 # #Searching the correct Direction Cosine
3803 3804 # cosdir0_aux = cosdir0[:,i]
3804 3805 # cosdir0_aux = cosdir0_aux.reshape(cosdir0_aux.size,1)
@@ -3807,51 +3808,50 class SMOperations():
3807 3808 # indcos = cosDiff.argmin(axis = 1)
3808 3809 # #Saving Value obtained
3809 3810 # cosdir[:,i] = cosdir1[numpy.arange(len(indcos)),indcos]
3810 #
3811 #
3811 3812 # return cosdir0, cosdir
3812 #
3813 #
3813 3814 # def __calculateAOA(self, cosdir, azimuth):
3814 3815 # cosdirX = cosdir[:,0]
3815 3816 # cosdirY = cosdir[:,1]
3816 #
3817 #
3817 3818 # zenithAngle = numpy.arccos(numpy.sqrt(1 - cosdirX**2 - cosdirY**2))*180/numpy.pi
3818 3819 # azimuthAngle = numpy.arctan2(cosdirX,cosdirY)*180/numpy.pi + azimuth #0 deg north, 90 deg east
3819 3820 # angles = numpy.vstack((azimuthAngle, zenithAngle)).transpose()
3820 #
3821 #
3821 3822 # return angles
3822 #
3823 #
3823 3824 # def __getHeights(self, Ranges, zenith, error, minHeight, maxHeight):
3824 #
3825 #
3825 3826 # Ramb = 375 #Ramb = c/(2*PRF)
3826 3827 # Re = 6371 #Earth Radius
3827 3828 # heights = numpy.zeros(Ranges.shape)
3828 #
3829 #
3829 3830 # R_aux = numpy.array([0,1,2])*Ramb
3830 3831 # R_aux = R_aux.reshape(1,R_aux.size)
3831 #
3832 #
3832 3833 # Ranges = Ranges.reshape(Ranges.size,1)
3833 #
3834 #
3834 3835 # Ri = Ranges + R_aux
3835 3836 # hi = numpy.sqrt(Re**2 + Ri**2 + (2*Re*numpy.cos(zenith*numpy.pi/180)*Ri.transpose()).transpose()) - Re
3836 #
3837 #
3837 3838 # #Check if there is a height between 70 and 110 km
3838 3839 # h_bool = numpy.sum(numpy.logical_and(hi > minHeight, hi < maxHeight), axis = 1)
3839 3840 # ind_h = numpy.where(h_bool == 1)[0]
3840 #
3841 #
3841 3842 # hCorr = hi[ind_h, :]
3842 3843 # ind_hCorr = numpy.where(numpy.logical_and(hi > minHeight, hi < maxHeight))
3843 #
3844 # hCorr = hi[ind_hCorr]
3844 #
3845 # hCorr = hi[ind_hCorr]
3845 3846 # heights[ind_h] = hCorr
3846 #
3847 #
3847 3848 # #Setting Error
3848 3849 # #Number 13: Height unresolvable echo: not valid height within 70 to 110 km
3849 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3850 #
3851 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3850 # #Number 14: Height ambiguous echo: more than one possible height within 70 to 110 km
3851 #
3852 # indInvalid2 = numpy.where(numpy.logical_and(h_bool > 1, error == 0))[0]
3852 3853 # error[indInvalid2] = 14
3853 3854 # indInvalid1 = numpy.where(numpy.logical_and(h_bool == 0, error == 0))[0]
3854 # error[indInvalid1] = 13
3855 #
3856 # return heights, error
3857 No newline at end of file
3855 # error[indInvalid1] = 13
3856 #
3857 # return heights, error
@@ -291,16 +291,16 class SpectraProc(ProcessingUnit):
291 291 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
292 292 self.dataOut.channelList = range(len(channelIndexList))
293 293 self.__selectPairsByChannel(channelIndexList)
294
294
295 295 return 1
296
297
296
297
298 298 def selectFFTs(self, minFFT, maxFFT ):
299 299 """
300 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
300 Selecciona un bloque de datos en base a un grupo de valores de puntos FFTs segun el rango
301 301 minFFT<= FFT <= maxFFT
302 302 """
303
303
304 304 if (minFFT > maxFFT):
305 305 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minFFT, maxFFT))
306 306
@@ -330,20 +330,20 class SpectraProc(ProcessingUnit):
330 330 self.selectFFTsByIndex(minIndex, maxIndex)
331 331
332 332 return 1
333
334
333
334
335 335 def setH0(self, h0, deltaHeight = None):
336
336
337 337 if not deltaHeight:
338 338 deltaHeight = self.dataOut.heightList[1] - self.dataOut.heightList[0]
339
339
340 340 nHeights = self.dataOut.nHeights
341
341
342 342 newHeiRange = h0 + numpy.arange(nHeights)*deltaHeight
343
343
344 344 self.dataOut.heightList = newHeiRange
345
346
345
346
347 347 def selectHeights(self, minHei, maxHei):
348 348 """
349 349 Selecciona un bloque de datos en base a un grupo de valores de alturas segun el rango
@@ -360,7 +360,7 class SpectraProc(ProcessingUnit):
360 360 1 si el metodo se ejecuto con exito caso contrario devuelve 0
361 361 """
362 362
363
363
364 364 if (minHei > maxHei):
365 365 raise ValueError("Error selecting heights: Height range (%d,%d) is not valid" % (minHei, maxHei))
366 366
@@ -388,7 +388,7 class SpectraProc(ProcessingUnit):
388 388 maxIndex = len(heights)
389 389
390 390 self.selectHeightsByIndex(minIndex, maxIndex)
391
391
392 392
393 393 return 1
394 394
@@ -436,7 +436,7 class SpectraProc(ProcessingUnit):
436 436
437 437 def selectFFTsByIndex(self, minIndex, maxIndex):
438 438 """
439
439
440 440 """
441 441
442 442 if (minIndex < 0) or (minIndex > maxIndex):
@@ -459,7 +459,7 class SpectraProc(ProcessingUnit):
459 459 self.dataOut.data_spc = data_spc
460 460 self.dataOut.data_cspc = data_cspc
461 461 self.dataOut.data_dc = data_dc
462
462
463 463 self.dataOut.ippSeconds = self.dataOut.ippSeconds*(self.dataOut.nFFTPoints / numpy.shape(data_cspc)[1])
464 464 self.dataOut.nFFTPoints = numpy.shape(data_cspc)[1]
465 465 self.dataOut.profilesPerBlock = numpy.shape(data_cspc)[1]
@@ -552,7 +552,7 class SpectraProc(ProcessingUnit):
552 552 xx_inv = numpy.linalg.inv(xx)
553 553 xx_aux = xx_inv[0, :]
554 554
555 for ich in range(num_chan):
555 for ich in range(num_chan):
556 556 yy = jspectra[ich, ind_vel, :]
557 557 jspectra[ich, freq_dc, :] = numpy.dot(xx_aux, yy)
558 558
@@ -574,12 +574,12 class SpectraProc(ProcessingUnit):
574 574 return 1
575 575
576 576 def removeInterference2(self):
577
577
578 578 cspc = self.dataOut.data_cspc
579 579 spc = self.dataOut.data_spc
580 Heights = numpy.arange(cspc.shape[2])
580 Heights = numpy.arange(cspc.shape[2])
581 581 realCspc = numpy.abs(cspc)
582
582
583 583 for i in range(cspc.shape[0]):
584 584 LinePower= numpy.sum(realCspc[i], axis=0)
585 585 Threshold = numpy.amax(LinePower)-numpy.sort(LinePower)[len(Heights)-int(len(Heights)*0.1)]
@@ -587,17 +587,17 class SpectraProc(ProcessingUnit):
587 587 InterferenceSum = numpy.sum( realCspc[i,:,SelectedHeights], axis=0 )
588 588 InterferenceThresholdMin = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.98)]
589 589 InterferenceThresholdMax = numpy.sort(InterferenceSum)[int(len(InterferenceSum)*0.99)]
590
591
590
591
592 592 InterferenceRange = numpy.where( ([InterferenceSum > InterferenceThresholdMin]))# , InterferenceSum < InterferenceThresholdMax]) )
593 593 #InterferenceRange = numpy.where( ([InterferenceRange < InterferenceThresholdMax]))
594 594 if len(InterferenceRange)<int(cspc.shape[1]*0.3):
595 595 cspc[i,InterferenceRange,:] = numpy.NaN
596
597
598
596
597
598
599 599 self.dataOut.data_cspc = cspc
600
600
601 601 def removeInterference(self, interf = 2,hei_interf = None, nhei_interf = None, offhei_interf = None):
602 602
603 603 jspectra = self.dataOut.data_spc
@@ -931,7 +931,7 class IncohInt(Operation):
931 931 if n is not None:
932 932 self.n = int(n)
933 933 else:
934
934
935 935 self.__integrationtime = int(timeInterval)
936 936 self.n = None
937 937 self.__byTime = True
@@ -1032,7 +1032,7 class IncohInt(Operation):
1032 1032 def run(self, dataOut, n=None, timeInterval=None, overlapping=False):
1033 1033 if n == 1:
1034 1034 return
1035
1035
1036 1036 dataOut.flagNoData = True
1037 1037
1038 1038 if not self.isConfig:
@@ -1048,9 +1048,9 class IncohInt(Operation):
1048 1048
1049 1049 dataOut.data_spc = avgdata_spc
1050 1050 dataOut.data_cspc = avgdata_cspc
1051 dataOut.data_dc = avgdata_dc
1051 dataOut.data_dc = avgdata_dc
1052 1052 dataOut.nIncohInt *= self.n
1053 1053 dataOut.utctime = avgdatatime
1054 1054 dataOut.flagNoData = False
1055 1055
1056 return dataOut No newline at end of file
1056 return dataOut
@@ -8,8 +8,8 from time import time
8 8
9 9
10 10 @MPDecorator
11 class VoltageProc(ProcessingUnit):
12
11 class VoltageProc(ProcessingUnit):
12
13 13 def __init__(self):
14 14
15 15 ProcessingUnit.__init__(self)
@@ -115,7 +115,7 class VoltageProc(ProcessingUnit):
115 115 self.dataOut.data = data
116 116 # self.dataOut.channelList = [self.dataOut.channelList[i] for i in channelIndexList]
117 117 self.dataOut.channelList = range(len(channelIndexList))
118
118
119 119 return 1
120 120
121 121 def selectHeights(self, minHei=None, maxHei=None):
@@ -229,7 +229,7 class VoltageProc(ProcessingUnit):
229 229 """
230 230 Si la data es obtenida por bloques, dimension = [nChannels, nProfiles, nHeis]
231 231 """
232 buffer = self.dataOut.data[:, :, 0:int(self.dataOut.nHeights-r)]
232 buffer = self.dataOut.data[:, :, 0:int(self.dataOut.nHeights-r)]
233 233 buffer = buffer.reshape(self.dataOut.nChannels, self.dataOut.nProfiles, int(self.dataOut.nHeights/window), window)
234 234 buffer = numpy.sum(buffer,3)
235 235
@@ -497,8 +497,8 class CohInt(Operation):
497 497 # print self.__bufferStride[self.__profIndexStride - 1]
498 498 # raise
499 499 return self.__bufferStride[self.__profIndexStride - 1]
500
501
500
501
502 502 return None, None
503 503
504 504 def integrate(self, data, datatime=None):
@@ -520,7 +520,7 class CohInt(Operation):
520 520 avgdatatime = self.__initime
521 521
522 522 deltatime = datatime - self.__lastdatatime
523
523
524 524 if not self.__withOverlapping:
525 525 self.__initime = datatime
526 526 else:
@@ -546,7 +546,7 class CohInt(Operation):
546 546 avgdatatime = (times - 1) * timeInterval + dataOut.utctime
547 547 self.__dataReady = True
548 548 return avgdata, avgdatatime
549
549
550 550 def run(self, dataOut, n=None, timeInterval=None, stride=None, overlapping=False, byblock=False, **kwargs):
551 551
552 552 if not self.isConfig:
@@ -560,12 +560,12 class CohInt(Operation):
560 560 avgdata, avgdatatime = self.integrateByBlock(dataOut)
561 561 dataOut.nProfiles /= self.n
562 562 else:
563 if stride is None:
563 if stride is None:
564 564 avgdata, avgdatatime = self.integrate(dataOut.data, dataOut.utctime)
565 565 else:
566 566 avgdata, avgdatatime = self.integrateByStride(dataOut.data, dataOut.utctime)
567 567
568
568
569 569 # dataOut.timeInterval *= n
570 570 dataOut.flagNoData = True
571 571
@@ -606,7 +606,6 class Decoder(Operation):
606 606
607 607 self.nCode = len(code)
608 608 self.nBaud = len(code[0])
609
610 609 if (osamp != None) and (osamp >1):
611 610 self.osamp = osamp
612 611 self.code = numpy.repeat(code, repeats=self.osamp, axis=1)
@@ -621,7 +620,7 class Decoder(Operation):
621 620
622 621 #Frequency
623 622 __codeBuffer = numpy.zeros((self.nCode, self.__nHeis), dtype=numpy.complex)
624
623
625 624 __codeBuffer[:,0:self.nBaud] = self.code
626 625
627 626 self.fft_code = numpy.conj(numpy.fft.fft(__codeBuffer, axis=1))
@@ -670,11 +669,11 class Decoder(Operation):
670 669 junk = junk.flatten()
671 670 code_block = numpy.reshape(junk, (self.nCode*repetitions, self.nBaud))
672 671 profilesList = range(self.__nProfiles)
673
674 for i in range(self.__nChannels):
675 for j in profilesList:
676 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
677 return self.datadecTime
672
673 for i in range(self.__nChannels):
674 for j in profilesList:
675 self.datadecTime[i,j,:] = numpy.correlate(data[i,j,:], code_block[j,:], mode='full')[self.nBaud-1:]
676 return self.datadecTime
678 677
679 678 def __convolutionByBlockInFreq(self, data):
680 679
@@ -691,7 +690,7 class Decoder(Operation):
691 690
692 691 return data
693 692
694
693
695 694 def run(self, dataOut, code=None, nCode=None, nBaud=None, mode = 0, osamp=None, times=None):
696 695
697 696 if dataOut.flagDecodeData:
@@ -722,7 +721,7 class Decoder(Operation):
722 721
723 722 self.__nProfiles = dataOut.nProfiles
724 723 datadec = None
725
724
726 725 if mode == 3:
727 726 mode = 0
728 727
@@ -1105,9 +1104,9 class SplitProfiles(Operation):
1105 1104
1106 1105 if shape[2] % n != 0:
1107 1106 raise ValueError("Could not split the data, n=%d has to be multiple of %d" %(n, shape[2]))
1108
1107
1109 1108 new_shape = shape[0], shape[1]*n, int(shape[2]/n)
1110
1109
1111 1110 dataOut.data = numpy.reshape(dataOut.data, new_shape)
1112 1111 dataOut.flagNoData = False
1113 1112
@@ -167,12 +167,12 class Remote(Thread):
167 167
168 168 self.mutex.acquire()
169 169 # init = time.time()
170 #
170 #
171 171 # while(self.bussy):
172 172 # sleep(0.1)
173 173 # if time.time() - init > 2*self.period:
174 174 # return 0
175
175
176 176 self.fileList = fileList
177 177 self.mutex.release()
178 178 return 1
@@ -195,7 +195,7 class Remote(Thread):
195 195
196 196 if self.stopFlag:
197 197 break
198
198
199 199 # self.bussy = True
200 200 self.mutex.acquire()
201 201
@@ -399,19 +399,19 class SSHClient(Remote):
399 399
400 400 """
401 401 This method is used to set SSH parameters and establish a connection to a remote server
402
402
403 403 Inputs:
404 server - remote server IP Address
405
406 username - remote server Username
407
404 server - remote server IP Address
405
406 username - remote server Username
407
408 408 password - remote server password
409
409
410 410 remotefolder - remote server current working directory
411
411
412 412 Return: void
413
414 Affects:
413
414 Affects:
415 415 self.status - in case of error or fail connection this parameter is set to 0 else 1
416 416
417 417 """
@@ -483,10 +483,10 class SSHClient(Remote):
483 483 def __execute(self, command):
484 484 """
485 485 __execute a command on remote server
486
486
487 487 Input:
488 488 command - Exmaple 'ls -l'
489
489
490 490 Return:
491 491 0 in error case else 1
492 492 """
@@ -508,10 +508,10 class SSHClient(Remote):
508 508 def mkdir(self, remotefolder):
509 509 """
510 510 mkdir is used to make a new directory in remote server
511
511
512 512 Input:
513 513 remotefolder - directory name
514
514
515 515 Return:
516 516 0 in error case else 1
517 517 """
@@ -529,14 +529,14 class SSHClient(Remote):
529 529 def cd(self, remotefolder):
530 530 """
531 531 cd is used to change remote working directory on server
532
532
533 533 Input:
534 534 remotefolder - current working directory
535
535
536 536 Affects:
537 537 self.remotefolder
538
539 Return:
538
539 Return:
540 540 0 in case of error else 1
541 541 """
542 542 if not self.status:
@@ -580,8 +580,8 class SendToServer(ProcessingUnit):
580 580 ProcessingUnit.__init__(self, **kwargs)
581 581
582 582 self.isConfig = False
583 self.clientObj = None
584
583 self.clientObj = None
584
585 585 def setup(self, server, username, password, remotefolder, localfolder, ext='.png', period=60, protocol='ftp', **kwargs):
586 586
587 587 self.clientObj = None
@@ -641,11 +641,11 class SendToServer(ProcessingUnit):
641 641 self.init = time.time()
642 642 self.setup(**kwargs)
643 643 self.isConfig = True
644
644
645 645 if not self.clientObj.is_alive():
646 646 print("[Remote Server]: Restarting connection ")
647 647 self.setup(**kwargs)
648
648
649 649 if time.time() - self.init >= self.period:
650 650 fullfilenameList = self.findFiles()
651 651
@@ -706,9 +706,9 class FTP(object):
706 706 try:
707 707 self.ftp = ftplib.FTP(self.server)
708 708 self.ftp.login(self.username,self.password)
709 self.ftp.cwd(self.remotefolder)
709 self.ftp.cwd(self.remotefolder)
710 710 # print 'Connect to FTP Server: Successfully'
711
711
712 712 except ftplib.all_errors:
713 713 print('Error FTP Service')
714 714 self.status = 1
@@ -1005,4 +1005,4 class SendByFTP(Operation):
1005 1005
1006 1006 self.counter = 0
1007 1007
1008 self.status = 1 No newline at end of file
1008 self.status = 1
@@ -47,7 +47,7 PLOT_CODES = {
47 47 def get_plot_code(s):
48 48 label = s.split('_')[0]
49 49 codes = [key for key in PLOT_CODES if key in label]
50 if codes:
50 if codes:
51 51 return PLOT_CODES[codes[0]]
52 52 else:
53 53 return 24
@@ -69,7 +69,7 class PublishData(Operation):
69 69 self.counter = 0
70 70 self.delay = kwargs.get('delay', 0)
71 71 self.cnt = 0
72 self.verbose = verbose
72 self.verbose = verbose
73 73 context = zmq.Context()
74 74 self.zmq_socket = context.socket(zmq.PUSH)
75 75 server = kwargs.get('server', 'zmq.pipe')
@@ -85,7 +85,7 class PublishData(Operation):
85 85
86 86 def publish_data(self):
87 87 self.dataOut.finished = False
88
88
89 89 if self.verbose:
90 90 log.log(
91 91 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
@@ -103,12 +103,12 class PublishData(Operation):
103 103 time.sleep(self.delay)
104 104
105 105 def close(self):
106
106
107 107 self.dataOut.finished = True
108 108 self.zmq_socket.send_pyobj(self.dataOut)
109 109 time.sleep(0.1)
110 110 self.zmq_socket.close()
111
111
112 112
113 113 class ReceiverData(ProcessingUnit):
114 114
@@ -195,7 +195,7 class SendToFTP(Operation):
195 195 self.ftp.close()
196 196 self.ftp = None
197 197 self.ready = False
198 return
198 return
199 199
200 200 try:
201 201 self.ftp.login(self.username, self.password)
@@ -244,8 +244,8 class SendToFTP(Operation):
244 244 def upload(self, src, dst):
245 245
246 246 log.log('Uploading {} -> {} '.format(
247 src.split('/')[-1], dst.split('/')[-1]),
248 self.name,
247 src.split('/')[-1], dst.split('/')[-1]),
248 self.name,
249 249 nl=False
250 250 )
251 251
@@ -273,7 +273,7 class SendToFTP(Operation):
273 273 fp.close()
274 274 log.success('OK', tag='')
275 275 return 1
276
276
277 277 def send_files(self):
278 278
279 279 for x, pattern in enumerate(self.patterns):
@@ -282,35 +282,35 class SendToFTP(Operation):
282 282 srcname = self.find_files(local, ext)
283 283 src = os.path.join(local, srcname)
284 284 if os.path.getmtime(src) < time.time() - 30*60:
285 log.warning('Skipping old file {}'.format(srcname))
285 log.warning('Skipping old file {}'.format(srcname))
286 286 continue
287 287
288 288 if srcname is None or srcname == self.latest[x]:
289 log.warning('File alreday uploaded {}'.format(srcname))
289 log.warning('File alreday uploaded {}'.format(srcname))
290 290 continue
291
291
292 292 if 'png' in ext:
293 293 dstname = self.getftpname(srcname, int(exp_code), int(sub_exp_code))
294 294 else:
295 dstname = srcname
296
295 dstname = srcname
296
297 297 dst = os.path.join(remote, dstname)
298 298
299 299 if self.upload(src, dst):
300 300 self.times[x] = time.time()
301 301 self.latest[x] = srcname
302 else:
302 else:
303 303 self.ready = False
304 break
304 break
305 305
306 306 def run(self, dataOut, server, username, password, timeout=10, **kwargs):
307 307
308 308 if not self.isConfig:
309 309 self.setup(
310 server=server,
311 username=username,
312 password=password,
313 timeout=timeout,
310 server=server,
311 username=username,
312 password=password,
313 timeout=timeout,
314 314 **kwargs
315 315 )
316 316 self.isConfig = True
General Comments 0
You need to be logged in to leave comments. Login now