##// END OF EJS Templates
Fix xmin & xmax in plots, fix SendToFTP
jespinoza -
r1334:96199ee477a0
parent child
Show More
@@ -1,102 +1,102
1 # Signal Chain
1 # Signal Chain
2
2
3 Signal Chain is a radar data processing library wich includes modules to read,
3 Signal Chain is a radar data processing library wich includes modules to read,
4 and write different files formats, besides modules to process and visualize the
4 and write different files formats, besides modules to process and visualize the
5 data.
5 data.
6
6
7 ## Dependencies
7 ## Dependencies
8
8
9 - GCC (gcc or gfortran)
9 - GCC (gcc or gfortran)
10 - Python.h (python-dev or python-devel)
10 - Python.h (python-dev or python-devel)
11 - Python-TK (python-tk)
11 - Python-TK (python-tk)
12 - HDF5 libraries (libhdf5-dev)
12 - HDF5 libraries (libhdf5-dev)
13
13
14 ## Installation
14 ## Installation
15
15
16 To get started the easiest way to install it is through [PyPI](https://pypi.org/project/schainpy/) with pip:
16 To get started the easiest way to install it is through [PyPI](https://pypi.org/project/schainpy/) with pip:
17
17
18 ```bash
18 ```bash
19 pip install schainpy
19 pip install schainpy
20 ```
20 ```
21
21
22 ### From source
22 ### From source
23
23
24 First, ensure that you have the above-listed dependencies installed, then clone
24 First, ensure that you have the above-listed dependencies installed, then clone
25 the repository and install as normal python package:
25 the repository and install as normal python package:
26
26
27 ```bash
27 ```bash
28 git clone https://github.com/JRO-Peru/schain.git
28 git clone https://github.com/JRO-Peru/schain.git
29 cd schain
29 cd schain
30 git checkout `branch-name` (optional)
30 git checkout `branch-name` (optional)
31 sudo pip install ./
31 sudo pip install ./
32 ```
32 ```
33
33
34 ### Using Docker
34 ### Using Docker
35
35
36 Download Dockerfile from the repository, and create a docker image:
36 Download Dockerfile from the repository, and create a docker image:
37
37
38 ```bash
38 ```bash
39 docker build -t schain .
39 docker build -t schain .
40 ```
40 ```
41
41
42 You can run a container using an xml file or a schain script also you need to
42 You can run a container using an xml file or a schain script also you need to
43 mount a volume for the data input and for the output files/plots:
43 mount a volume for the data input and for the output files/plots:
44
44
45 ```bash
45 ```bash
46 docker run -it --rm --volume /path/to/host/data:/data schain xml /data/test.xml
46 docker run -it --rm --volume /path/to/host/data:/data schain xml /data/test.xml
47 docker run -it --rm --volume /path/to/host/data:/data --entrypoint /urs/local/bin/python schain /data/test.py
47 docker run -it --rm --volume /path/to/host/data:/data --entrypoint /urs/local/bin/python schain /data/test.py
48 ```
48 ```
49
49
50 ## CLI (command line interface)
50 ## CLI (command line interface)
51
51
52 Signal Chain provides the following commands:
52 Signal Chain provides the following commands:
53
53
54 - schainGUI: Open the GUI
54 - schainGUI: Open the GUI
55 - schain: Signal chain command line
55 - schain: Signal chain command line
56
56
57 ## Example
57 ## Example
58
58
59 Here you can find an script to read Spectra data (.pdata), remove dc and plot
59 Here you can find an script to read Spectra data (.pdata), remove dc and plot
60 self-spectra & RTI:
60 self-spectra & RTI:
61
61
62 ```python
62 ```python
63 #!/usr/bin/python
63 #!/usr/bin/python
64
64
65 from schainpy.controller import Project
65 from schainpy.controller import Project
66
66
67 prj = Project()
67 prj = Project()
68
68
69 read_unit = prj.addReadUnit(
69 read_unit = prj.addReadUnit(
70 datatype='Spectra',
70 datatype='Spectra',
71 path='/path/to/pdata/',
71 path='/path/to/pdata/',
72 startDate='2014/01/31',
72 startDate='2014/01/31',
73 endDate='2014/03/31',
73 endDate='2014/03/31',
74 startTime='00:00:00',
74 startTime='00:00:00',
75 endTime='23:59:59',
75 endTime='23:59:59',
76 online=0,
76 online=0,
77 walk=0
77 walk=0
78 )
78 )
79
79
80 proc_unit = prj.addProcUnit(
80 proc_unit = prj.addProcUnit(
81 datatype='Spectra',
81 datatype='Spectra',
82 inputId=read_unit.getId()
82 inputId=read_unit.getId()
83 )
83 )
84
84
85 op = proc_unit.addOperation(name='selectChannels')
85 op = proc_unit.addOperation(name='selectChannels')
86 op.addParameter(name='channelList', value='0,1')
86 op.addParameter(name='channelList', value='0,1')
87
87
88 op = proc_unit.addOperation(name='selectHeights')
88 op = proc_unit.addOperation(name='selectHeights')
89 op.addParameter(name='minHei', value='80')
89 op.addParameter(name='minHei', value='80')
90 op.addParameter(name='maxHei', value='200')
90 op.addParameter(name='maxHei', value='200')
91
91
92 op = proc_unit.addOperation(name='removeDC')
92 op = proc_unit.addOperation(name='removeDC')
93
93
94 op = proc_unit.addOperation(name='SpectraPlot')
94 op = proc_unit.addOperation(name='SpectraPlot')
95 op.addParameter(name='wintitle', value='Spectra', format='str')
95 op.addParameter(name='wintitle', value='Spectra', format='str')
96
96
97 op = procUnitConfObj1.addOperation(name='RTIPlot')
97 op = proc_unit.addOperation(name='RTIPlot')
98 op.addParameter(name='wintitle', value='RTI', format='str')
98 op.addParameter(name='wintitle', value='RTI', format='str')
99
99
100 prj.start()
100 prj.start()
101
101
102 ```
102 ```
@@ -1,716 +1,665
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 # All rights reserved.
3 #
4 # Distributed under the terms of the BSD 3-clause license.
5 """Base class to create plot operations
6
7 """
1
8
2 import os
9 import os
3 import sys
10 import sys
4 import zmq
11 import zmq
5 import time
12 import time
6 import numpy
13 import numpy
7 import datetime
14 import datetime
8 try:
15 from multiprocessing import Queue
9 from queue import Queue
10 except:
11 from Queue import Queue
12 from functools import wraps
16 from functools import wraps
13 from threading import Thread
17 from threading import Thread
14 import matplotlib
18 import matplotlib
15
19
16 if 'BACKEND' in os.environ:
20 if 'BACKEND' in os.environ:
17 matplotlib.use(os.environ['BACKEND'])
21 matplotlib.use(os.environ['BACKEND'])
18 elif 'linux' in sys.platform:
22 elif 'linux' in sys.platform:
19 matplotlib.use("TkAgg")
23 matplotlib.use("TkAgg")
20 elif 'darwin' in sys.platform:
24 elif 'darwin' in sys.platform:
21 matplotlib.use('WxAgg')
25 matplotlib.use('WxAgg')
22 else:
26 else:
23 from schainpy.utils import log
27 from schainpy.utils import log
24 log.warning('Using default Backend="Agg"', 'INFO')
28 log.warning('Using default Backend="Agg"', 'INFO')
25 matplotlib.use('Agg')
29 matplotlib.use('Agg')
26
30
27 import matplotlib.pyplot as plt
31 import matplotlib.pyplot as plt
28 from matplotlib.patches import Polygon
32 from matplotlib.patches import Polygon
29 from mpl_toolkits.axes_grid1 import make_axes_locatable
33 from mpl_toolkits.axes_grid1 import make_axes_locatable
30 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
34 from matplotlib.ticker import FuncFormatter, LinearLocator, MultipleLocator
31
35
32 from schainpy.model.data.jrodata import PlotterData
36 from schainpy.model.data.jrodata import PlotterData
33 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
37 from schainpy.model.proc.jroproc_base import ProcessingUnit, Operation, MPDecorator
34 from schainpy.utils import log
38 from schainpy.utils import log
35
39
36 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
40 jet_values = matplotlib.pyplot.get_cmap('jet', 100)(numpy.arange(100))[10:90]
37 blu_values = matplotlib.pyplot.get_cmap(
41 blu_values = matplotlib.pyplot.get_cmap(
38 'seismic_r', 20)(numpy.arange(20))[10:15]
42 'seismic_r', 20)(numpy.arange(20))[10:15]
39 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
43 ncmap = matplotlib.colors.LinearSegmentedColormap.from_list(
40 'jro', numpy.vstack((blu_values, jet_values)))
44 'jro', numpy.vstack((blu_values, jet_values)))
41 matplotlib.pyplot.register_cmap(cmap=ncmap)
45 matplotlib.pyplot.register_cmap(cmap=ncmap)
42
46
43 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
47 CMAPS = [plt.get_cmap(s) for s in ('jro', 'jet', 'viridis',
44 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
48 'plasma', 'inferno', 'Greys', 'seismic', 'bwr', 'coolwarm')]
45
49
46 EARTH_RADIUS = 6.3710e3
50 EARTH_RADIUS = 6.3710e3
47
51
48 def ll2xy(lat1, lon1, lat2, lon2):
52 def ll2xy(lat1, lon1, lat2, lon2):
49
53
50 p = 0.017453292519943295
54 p = 0.017453292519943295
51 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
55 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
52 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
56 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
53 r = 12742 * numpy.arcsin(numpy.sqrt(a))
57 r = 12742 * numpy.arcsin(numpy.sqrt(a))
54 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
58 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
55 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
59 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
56 theta = -theta + numpy.pi/2
60 theta = -theta + numpy.pi/2
57 return r*numpy.cos(theta), r*numpy.sin(theta)
61 return r*numpy.cos(theta), r*numpy.sin(theta)
58
62
59
63
60 def km2deg(km):
64 def km2deg(km):
61 '''
65 '''
62 Convert distance in km to degrees
66 Convert distance in km to degrees
63 '''
67 '''
64
68
65 return numpy.rad2deg(km/EARTH_RADIUS)
69 return numpy.rad2deg(km/EARTH_RADIUS)
66
70
67
71
68 def figpause(interval):
72 def figpause(interval):
69 backend = plt.rcParams['backend']
73 backend = plt.rcParams['backend']
70 if backend in matplotlib.rcsetup.interactive_bk:
74 if backend in matplotlib.rcsetup.interactive_bk:
71 figManager = matplotlib._pylab_helpers.Gcf.get_active()
75 figManager = matplotlib._pylab_helpers.Gcf.get_active()
72 if figManager is not None:
76 if figManager is not None:
73 canvas = figManager.canvas
77 canvas = figManager.canvas
74 if canvas.figure.stale:
78 if canvas.figure.stale:
75 canvas.draw()
79 canvas.draw()
76 try:
80 try:
77 canvas.start_event_loop(interval)
81 canvas.start_event_loop(interval)
78 except:
82 except:
79 pass
83 pass
80 return
84 return
81
85
82
86
83 def popup(message):
87 def popup(message):
84 '''
88 '''
85 '''
89 '''
86
90
87 fig = plt.figure(figsize=(12, 8), facecolor='r')
91 fig = plt.figure(figsize=(12, 8), facecolor='r')
88 text = '\n'.join([s.strip() for s in message.split(':')])
92 text = '\n'.join([s.strip() for s in message.split(':')])
89 fig.text(0.01, 0.5, text, ha='left', va='center',
93 fig.text(0.01, 0.5, text, ha='left', va='center',
90 size='20', weight='heavy', color='w')
94 size='20', weight='heavy', color='w')
91 fig.show()
95 fig.show()
92 figpause(1000)
96 figpause(1000)
93
97
94
98
95 class Throttle(object):
99 class Throttle(object):
96 '''
100 '''
97 Decorator that prevents a function from being called more than once every
101 Decorator that prevents a function from being called more than once every
98 time period.
102 time period.
99 To create a function that cannot be called more than once a minute, but
103 To create a function that cannot be called more than once a minute, but
100 will sleep until it can be called:
104 will sleep until it can be called:
101 @Throttle(minutes=1)
105 @Throttle(minutes=1)
102 def foo():
106 def foo():
103 pass
107 pass
104
108
105 for i in range(10):
109 for i in range(10):
106 foo()
110 foo()
107 print "This function has run %s times." % i
111 print "This function has run %s times." % i
108 '''
112 '''
109
113
110 def __init__(self, seconds=0, minutes=0, hours=0):
114 def __init__(self, seconds=0, minutes=0, hours=0):
111 self.throttle_period = datetime.timedelta(
115 self.throttle_period = datetime.timedelta(
112 seconds=seconds, minutes=minutes, hours=hours
116 seconds=seconds, minutes=minutes, hours=hours
113 )
117 )
114
118
115 self.time_of_last_call = datetime.datetime.min
119 self.time_of_last_call = datetime.datetime.min
116
120
117 def __call__(self, fn):
121 def __call__(self, fn):
118 @wraps(fn)
122 @wraps(fn)
119 def wrapper(*args, **kwargs):
123 def wrapper(*args, **kwargs):
120 coerce = kwargs.pop('coerce', None)
124 coerce = kwargs.pop('coerce', None)
121 if coerce:
125 if coerce:
122 self.time_of_last_call = datetime.datetime.now()
126 self.time_of_last_call = datetime.datetime.now()
123 return fn(*args, **kwargs)
127 return fn(*args, **kwargs)
124 else:
128 else:
125 now = datetime.datetime.now()
129 now = datetime.datetime.now()
126 time_since_last_call = now - self.time_of_last_call
130 time_since_last_call = now - self.time_of_last_call
127 time_left = self.throttle_period - time_since_last_call
131 time_left = self.throttle_period - time_since_last_call
128
132
129 if time_left > datetime.timedelta(seconds=0):
133 if time_left > datetime.timedelta(seconds=0):
130 return
134 return
131
135
132 self.time_of_last_call = datetime.datetime.now()
136 self.time_of_last_call = datetime.datetime.now()
133 return fn(*args, **kwargs)
137 return fn(*args, **kwargs)
134
138
135 return wrapper
139 return wrapper
136
140
137 def apply_throttle(value):
141 def apply_throttle(value):
138
142
139 @Throttle(seconds=value)
143 @Throttle(seconds=value)
140 def fnThrottled(fn):
144 def fnThrottled(fn):
141 fn()
145 fn()
142
146
143 return fnThrottled
147 return fnThrottled
144
148
145
149
146 @MPDecorator
150 @MPDecorator
147 class Plot(Operation):
151 class Plot(Operation):
148 '''
152 """Base class for Schain plotting operations
149 Base class for Schain plotting operations
153
150 '''
154 This class should never be use directtly you must subclass a new operation,
155 children classes must be defined as follow:
156
157 ExamplePlot(Plot):
158
159 CODE = 'code'
160 colormap = 'jet'
161 plot_type = 'pcolor' # options are ('pcolor', 'pcolorbuffer', 'scatter', 'scatterbuffer')
162
163 def setup(self):
164 pass
165
166 def plot(self):
167 pass
168
169 """
151
170
152 CODE = 'Figure'
171 CODE = 'Figure'
153 colormap = 'jet'
172 colormap = 'jet'
154 bgcolor = 'white'
173 bgcolor = 'white'
155 buffering = True
174 buffering = True
156 __missing = 1E30
175 __missing = 1E30
157
176
158 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
177 __attrs__ = ['show', 'save', 'ymin', 'ymax', 'zmin', 'zmax', 'title',
159 'showprofile']
178 'showprofile']
160
179
161 def __init__(self):
180 def __init__(self):
162
181
163 Operation.__init__(self)
182 Operation.__init__(self)
164 self.isConfig = False
183 self.isConfig = False
165 self.isPlotConfig = False
184 self.isPlotConfig = False
166 self.save_counter = 1
185 self.save_time = 0
167 self.sender_time = 0
186 self.sender_time = 0
168 self.data = None
187 self.data = None
169 self.firsttime = True
188 self.firsttime = True
170 self.sender_queue = Queue(maxsize=60)
189 self.sender_queue = Queue(maxsize=60)
171 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
190 self.plots_adjust = {'left': 0.125, 'right': 0.9, 'bottom': 0.15, 'top': 0.9, 'wspace': 0.2, 'hspace': 0.2}
172
191
173 def __fmtTime(self, x, pos):
192 def __fmtTime(self, x, pos):
174 '''
193 '''
175 '''
194 '''
176
195
177 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
196 return '{}'.format(self.getDateTime(x).strftime('%H:%M'))
178
197
179 def __setup(self, **kwargs):
198 def __setup(self, **kwargs):
180 '''
199 '''
181 Initialize variables
200 Initialize variables
182 '''
201 '''
183
202
184 self.figures = []
203 self.figures = []
185 self.axes = []
204 self.axes = []
186 self.cb_axes = []
205 self.cb_axes = []
187 self.localtime = kwargs.pop('localtime', True)
206 self.localtime = kwargs.pop('localtime', True)
188 self.show = kwargs.get('show', True)
207 self.show = kwargs.get('show', True)
189 self.save = kwargs.get('save', False)
208 self.save = kwargs.get('save', False)
190 self.save_period = kwargs.get('save_period', 1)
209 self.save_period = kwargs.get('save_period', 60)
191 self.colormap = kwargs.get('colormap', self.colormap)
210 self.colormap = kwargs.get('colormap', self.colormap)
192 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
211 self.colormap_coh = kwargs.get('colormap_coh', 'jet')
193 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
212 self.colormap_phase = kwargs.get('colormap_phase', 'RdBu_r')
194 self.colormaps = kwargs.get('colormaps', None)
213 self.colormaps = kwargs.get('colormaps', None)
195 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
214 self.bgcolor = kwargs.get('bgcolor', self.bgcolor)
196 self.showprofile = kwargs.get('showprofile', False)
215 self.showprofile = kwargs.get('showprofile', False)
197 self.title = kwargs.get('wintitle', self.CODE.upper())
216 self.title = kwargs.get('wintitle', self.CODE.upper())
198 self.cb_label = kwargs.get('cb_label', None)
217 self.cb_label = kwargs.get('cb_label', None)
199 self.cb_labels = kwargs.get('cb_labels', None)
218 self.cb_labels = kwargs.get('cb_labels', None)
200 self.labels = kwargs.get('labels', None)
219 self.labels = kwargs.get('labels', None)
201 self.xaxis = kwargs.get('xaxis', 'frequency')
220 self.xaxis = kwargs.get('xaxis', 'frequency')
202 self.zmin = kwargs.get('zmin', None)
221 self.zmin = kwargs.get('zmin', None)
203 self.zmax = kwargs.get('zmax', None)
222 self.zmax = kwargs.get('zmax', None)
204 self.zlimits = kwargs.get('zlimits', None)
223 self.zlimits = kwargs.get('zlimits', None)
205 self.xmin = kwargs.get('xmin', None)
224 self.xmin = kwargs.get('xmin', None)
206 self.xmax = kwargs.get('xmax', None)
225 self.xmax = kwargs.get('xmax', None)
207 self.xrange = kwargs.get('xrange', 12)
226 self.xrange = kwargs.get('xrange', 12)
208 self.xscale = kwargs.get('xscale', None)
227 self.xscale = kwargs.get('xscale', None)
209 self.ymin = kwargs.get('ymin', None)
228 self.ymin = kwargs.get('ymin', None)
210 self.ymax = kwargs.get('ymax', None)
229 self.ymax = kwargs.get('ymax', None)
211 self.yscale = kwargs.get('yscale', None)
230 self.yscale = kwargs.get('yscale', None)
212 self.xlabel = kwargs.get('xlabel', None)
231 self.xlabel = kwargs.get('xlabel', None)
213 self.attr_time = kwargs.get('attr_time', 'utctime')
232 self.attr_time = kwargs.get('attr_time', 'utctime')
214 self.decimation = kwargs.get('decimation', None)
233 self.decimation = kwargs.get('decimation', None)
215 self.showSNR = kwargs.get('showSNR', False)
234 self.showSNR = kwargs.get('showSNR', False)
216 self.oneFigure = kwargs.get('oneFigure', True)
235 self.oneFigure = kwargs.get('oneFigure', True)
217 self.width = kwargs.get('width', None)
236 self.width = kwargs.get('width', None)
218 self.height = kwargs.get('height', None)
237 self.height = kwargs.get('height', None)
219 self.colorbar = kwargs.get('colorbar', True)
238 self.colorbar = kwargs.get('colorbar', True)
220 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
239 self.factors = kwargs.get('factors', [1, 1, 1, 1, 1, 1, 1, 1])
221 self.channels = kwargs.get('channels', None)
240 self.channels = kwargs.get('channels', None)
222 self.titles = kwargs.get('titles', [])
241 self.titles = kwargs.get('titles', [])
223 self.polar = False
242 self.polar = False
224 self.type = kwargs.get('type', 'iq')
243 self.type = kwargs.get('type', 'iq')
225 self.grid = kwargs.get('grid', False)
244 self.grid = kwargs.get('grid', False)
226 self.pause = kwargs.get('pause', False)
245 self.pause = kwargs.get('pause', False)
227 self.save_code = kwargs.get('save_code', None)
246 self.save_code = kwargs.get('save_code', self.CODE)
228 self.throttle = kwargs.get('throttle', 0)
247 self.throttle = kwargs.get('throttle', 0)
229 self.exp_code = kwargs.get('exp_code', None)
248 self.exp_code = kwargs.get('exp_code', None)
230 self.plot_server = kwargs.get('plot_server', False)
249 self.plot_server = kwargs.get('plot_server', False)
231 self.sender_period = kwargs.get('sender_period', 60)
250 self.sender_period = kwargs.get('sender_period', 60)
232 self.tag = kwargs.get('tag', '')
251 self.tag = kwargs.get('tag', '')
233 self.height_index = kwargs.get('height_index', None)
252 self.height_index = kwargs.get('height_index', None)
234 self.__throttle_plot = apply_throttle(self.throttle)
253 self.__throttle_plot = apply_throttle(self.throttle)
235 self.data = PlotterData(
254 self.data = PlotterData(
236 self.CODE, self.throttle, self.exp_code, self.localtime, self.buffering, snr=self.showSNR)
255 self.CODE, self.throttle, self.exp_code, self.localtime, self.buffering, snr=self.showSNR)
237
256
238 if self.plot_server:
257 if self.plot_server:
239 if not self.plot_server.startswith('tcp://'):
258 if not self.plot_server.startswith('tcp://'):
240 self.plot_server = 'tcp://{}'.format(self.plot_server)
259 self.plot_server = 'tcp://{}'.format(self.plot_server)
241 log.success(
260 log.success(
242 'Sending to server: {}'.format(self.plot_server),
261 'Sending to server: {}'.format(self.plot_server),
243 self.name
262 self.name
244 )
263 )
245 if 'plot_name' in kwargs:
246 self.plot_name = kwargs['plot_name']
247
264
248 def __setup_plot(self):
265 def __setup_plot(self):
249 '''
266 '''
250 Common setup for all figures, here figures and axes are created
267 Common setup for all figures, here figures and axes are created
251 '''
268 '''
252
269
253 self.setup()
270 self.setup()
254
271
255 self.time_label = 'LT' if self.localtime else 'UTC'
272 self.time_label = 'LT' if self.localtime else 'UTC'
256
273
257 if self.width is None:
274 if self.width is None:
258 self.width = 8
275 self.width = 8
259
276
260 self.figures = []
277 self.figures = []
261 self.axes = []
278 self.axes = []
262 self.cb_axes = []
279 self.cb_axes = []
263 self.pf_axes = []
280 self.pf_axes = []
264 self.cmaps = []
281 self.cmaps = []
265
282
266 size = '15%' if self.ncols == 1 else '30%'
283 size = '15%' if self.ncols == 1 else '30%'
267 pad = '4%' if self.ncols == 1 else '8%'
284 pad = '4%' if self.ncols == 1 else '8%'
268
285
269 if self.oneFigure:
286 if self.oneFigure:
270 if self.height is None:
287 if self.height is None:
271 self.height = 1.4 * self.nrows + 1
288 self.height = 1.4 * self.nrows + 1
272 fig = plt.figure(figsize=(self.width, self.height),
289 fig = plt.figure(figsize=(self.width, self.height),
273 edgecolor='k',
290 edgecolor='k',
274 facecolor='w')
291 facecolor='w')
275 self.figures.append(fig)
292 self.figures.append(fig)
276 for n in range(self.nplots):
293 for n in range(self.nplots):
277 ax = fig.add_subplot(self.nrows, self.ncols,
294 ax = fig.add_subplot(self.nrows, self.ncols,
278 n + 1, polar=self.polar)
295 n + 1, polar=self.polar)
279 ax.tick_params(labelsize=8)
296 ax.tick_params(labelsize=8)
280 ax.firsttime = True
297 ax.firsttime = True
281 ax.index = 0
298 ax.index = 0
282 ax.press = None
299 ax.press = None
283 self.axes.append(ax)
300 self.axes.append(ax)
284 if self.showprofile:
301 if self.showprofile:
285 cax = self.__add_axes(ax, size=size, pad=pad)
302 cax = self.__add_axes(ax, size=size, pad=pad)
286 cax.tick_params(labelsize=8)
303 cax.tick_params(labelsize=8)
287 self.pf_axes.append(cax)
304 self.pf_axes.append(cax)
288 else:
305 else:
289 if self.height is None:
306 if self.height is None:
290 self.height = 3
307 self.height = 3
291 for n in range(self.nplots):
308 for n in range(self.nplots):
292 fig = plt.figure(figsize=(self.width, self.height),
309 fig = plt.figure(figsize=(self.width, self.height),
293 edgecolor='k',
310 edgecolor='k',
294 facecolor='w')
311 facecolor='w')
295 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
312 ax = fig.add_subplot(1, 1, 1, polar=self.polar)
296 ax.tick_params(labelsize=8)
313 ax.tick_params(labelsize=8)
297 ax.firsttime = True
314 ax.firsttime = True
298 ax.index = 0
315 ax.index = 0
299 ax.press = None
316 ax.press = None
300 self.figures.append(fig)
317 self.figures.append(fig)
301 self.axes.append(ax)
318 self.axes.append(ax)
302 if self.showprofile:
319 if self.showprofile:
303 cax = self.__add_axes(ax, size=size, pad=pad)
320 cax = self.__add_axes(ax, size=size, pad=pad)
304 cax.tick_params(labelsize=8)
321 cax.tick_params(labelsize=8)
305 self.pf_axes.append(cax)
322 self.pf_axes.append(cax)
306
323
307 for n in range(self.nrows):
324 for n in range(self.nrows):
308 if self.colormaps is not None:
325 if self.colormaps is not None:
309 cmap = plt.get_cmap(self.colormaps[n])
326 cmap = plt.get_cmap(self.colormaps[n])
310 else:
327 else:
311 cmap = plt.get_cmap(self.colormap)
328 cmap = plt.get_cmap(self.colormap)
312 cmap.set_bad(self.bgcolor, 1.)
329 cmap.set_bad(self.bgcolor, 1.)
313 self.cmaps.append(cmap)
330 self.cmaps.append(cmap)
314
331
315 def __add_axes(self, ax, size='30%', pad='8%'):
332 def __add_axes(self, ax, size='30%', pad='8%'):
316 '''
333 '''
317 Add new axes to the given figure
334 Add new axes to the given figure
318 '''
335 '''
319 divider = make_axes_locatable(ax)
336 divider = make_axes_locatable(ax)
320 nax = divider.new_horizontal(size=size, pad=pad)
337 nax = divider.new_horizontal(size=size, pad=pad)
321 ax.figure.add_axes(nax)
338 ax.figure.add_axes(nax)
322 return nax
339 return nax
323
340
324 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
341 def fill_gaps(self, x_buffer, y_buffer, z_buffer):
325 '''
342 '''
326 Create a masked array for missing data
343 Create a masked array for missing data
327 '''
344 '''
328 if x_buffer.shape[0] < 2:
345 if x_buffer.shape[0] < 2:
329 return x_buffer, y_buffer, z_buffer
346 return x_buffer, y_buffer, z_buffer
330
347
331 deltas = x_buffer[1:] - x_buffer[0:-1]
348 deltas = x_buffer[1:] - x_buffer[0:-1]
332 x_median = numpy.median(deltas)
349 x_median = numpy.median(deltas)
333
350
334 index = numpy.where(deltas > 5 * x_median)
351 index = numpy.where(deltas > 5 * x_median)
335
352
336 if len(index[0]) != 0:
353 if len(index[0]) != 0:
337 z_buffer[::, index[0], ::] = self.__missing
354 z_buffer[::, index[0], ::] = self.__missing
338 z_buffer = numpy.ma.masked_inside(z_buffer,
355 z_buffer = numpy.ma.masked_inside(z_buffer,
339 0.99 * self.__missing,
356 0.99 * self.__missing,
340 1.01 * self.__missing)
357 1.01 * self.__missing)
341
358
342 return x_buffer, y_buffer, z_buffer
359 return x_buffer, y_buffer, z_buffer
343
360
344 def decimate(self):
361 def decimate(self):
345
362
346 # dx = int(len(self.x)/self.__MAXNUMX) + 1
363 # dx = int(len(self.x)/self.__MAXNUMX) + 1
347 dy = int(len(self.y) / self.decimation) + 1
364 dy = int(len(self.y) / self.decimation) + 1
348
365
349 # x = self.x[::dx]
366 # x = self.x[::dx]
350 x = self.x
367 x = self.x
351 y = self.y[::dy]
368 y = self.y[::dy]
352 z = self.z[::, ::, ::dy]
369 z = self.z[::, ::, ::dy]
353
370
354 return x, y, z
371 return x, y, z
355
372
356 def format(self):
373 def format(self):
357 '''
374 '''
358 Set min and max values, labels, ticks and titles
375 Set min and max values, labels, ticks and titles
359 '''
376 '''
360
377
361 if self.xmin is None:
378 for n, ax in enumerate(self.axes):
362 xmin = self.data.min_time
379 if ax.firsttime:
363 else:
380 if self.xaxis != 'time':
364 if self.xaxis is 'time':
365 dt = self.getDateTime(self.data.min_time)
366 xmin = (dt.replace(hour=int(self.xmin), minute=0, second=0) -
367 datetime.datetime(1970, 1, 1)).total_seconds()
368 if self.data.localtime:
369 xmin += time.timezone
370 else:
371 xmin = self.xmin
381 xmin = self.xmin
372
373 if self.xmax is None:
374 xmax = xmin + self.xrange * 60 * 60
375 else:
376 if self.xaxis is 'time':
377 dt = self.getDateTime(self.data.max_time)
378 xmax = self.xmax - 1
379 xmax = (dt.replace(hour=int(xmax), minute=59, second=59) -
380 datetime.datetime(1970, 1, 1) + datetime.timedelta(seconds=1)).total_seconds()
381 if self.data.localtime:
382 xmax += time.timezone
383 else:
384 xmax = self.xmax
382 xmax = self.xmax
385
383 else:
384 xmin = self.tmin
385 xmax = self.tmin + self.xrange*60*60
386 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
387 ax.xaxis.set_major_locator(LinearLocator(9))
386 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
388 ymin = self.ymin if self.ymin else numpy.nanmin(self.y)
387 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
389 ymax = self.ymax if self.ymax else numpy.nanmax(self.y)
388
389 for n, ax in enumerate(self.axes):
390 if ax.firsttime:
391
392 dig = int(numpy.log10(ymax))
393 if dig == 0:
394 digD = len(str(ymax)) - 2
395 ydec = ymax*(10**digD)
396
397 dig = int(numpy.log10(ydec))
398 ystep = ((ydec + (10**(dig)))//10**(dig))*(10**(dig))
399 ystep = ystep/5
400 ystep = ystep/(10**digD)
401
402 else:
403 ystep = ((ymax + (10**(dig)))//10**(dig))*(10**(dig))
404 ystep = ystep/5
405
406 if self.xaxis is not 'time':
407
408 dig = int(numpy.log10(xmax))
409
410 if dig <= 0:
411 digD = len(str(xmax)) - 2
412 xdec = xmax*(10**digD)
413
414 dig = int(numpy.log10(xdec))
415 xstep = ((xdec + (10**(dig)))//10**(dig))*(10**(dig))
416 xstep = xstep*0.5
417 xstep = xstep/(10**digD)
418
419 else:
420 xstep = ((xmax + (10**(dig)))//10**(dig))*(10**(dig))
421 xstep = xstep/5
422
423 ax.set_facecolor(self.bgcolor)
390 ax.set_facecolor(self.bgcolor)
424 ax.yaxis.set_major_locator(MultipleLocator(ystep))
425 if self.xscale:
391 if self.xscale:
426 ax.xaxis.set_major_formatter(FuncFormatter(
392 ax.xaxis.set_major_formatter(FuncFormatter(
427 lambda x, pos: '{0:g}'.format(x*self.xscale)))
393 lambda x, pos: '{0:g}'.format(x*self.xscale)))
428 if self.xscale:
394 if self.yscale:
429 ax.yaxis.set_major_formatter(FuncFormatter(
395 ax.yaxis.set_major_formatter(FuncFormatter(
430 lambda x, pos: '{0:g}'.format(x*self.yscale)))
396 lambda x, pos: '{0:g}'.format(x*self.yscale)))
431 if self.xaxis is 'time':
432 ax.xaxis.set_major_formatter(FuncFormatter(self.__fmtTime))
433 ax.xaxis.set_major_locator(LinearLocator(9))
434 else:
435 ax.xaxis.set_major_locator(MultipleLocator(xstep))
436 if self.xlabel is not None:
397 if self.xlabel is not None:
437 ax.set_xlabel(self.xlabel)
398 ax.set_xlabel(self.xlabel)
399 if self.ylabel is not None:
438 ax.set_ylabel(self.ylabel)
400 ax.set_ylabel(self.ylabel)
439 ax.firsttime = False
440 if self.showprofile:
401 if self.showprofile:
441 self.pf_axes[n].set_ylim(ymin, ymax)
402 self.pf_axes[n].set_ylim(ymin, ymax)
442 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
403 self.pf_axes[n].set_xlim(self.zmin, self.zmax)
443 self.pf_axes[n].set_xlabel('dB')
404 self.pf_axes[n].set_xlabel('dB')
444 self.pf_axes[n].grid(b=True, axis='x')
405 self.pf_axes[n].grid(b=True, axis='x')
445 [tick.set_visible(False)
406 [tick.set_visible(False)
446 for tick in self.pf_axes[n].get_yticklabels()]
407 for tick in self.pf_axes[n].get_yticklabels()]
447 if self.colorbar:
408 if self.colorbar:
448 ax.cbar = plt.colorbar(
409 ax.cbar = plt.colorbar(
449 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
410 ax.plt, ax=ax, fraction=0.05, pad=0.02, aspect=10)
450 ax.cbar.ax.tick_params(labelsize=8)
411 ax.cbar.ax.tick_params(labelsize=8)
451 ax.cbar.ax.press = None
412 ax.cbar.ax.press = None
452 if self.cb_label:
413 if self.cb_label:
453 ax.cbar.set_label(self.cb_label, size=8)
414 ax.cbar.set_label(self.cb_label, size=8)
454 elif self.cb_labels:
415 elif self.cb_labels:
455 ax.cbar.set_label(self.cb_labels[n], size=8)
416 ax.cbar.set_label(self.cb_labels[n], size=8)
456 else:
417 else:
457 ax.cbar = None
418 ax.cbar = None
419 ax.set_xlim(xmin, xmax)
420 ax.set_ylim(ymin, ymax)
421 ax.firsttime = False
458 if self.grid:
422 if self.grid:
459 ax.grid(True)
423 ax.grid(True)
460
461 if not self.polar:
424 if not self.polar:
462 ax.set_xlim(xmin, xmax)
463 ax.set_ylim(ymin, ymax)
464 ax.set_title('{} {} {}'.format(
425 ax.set_title('{} {} {}'.format(
465 self.titles[n],
426 self.titles[n],
466 self.getDateTime(self.data.max_time).strftime(
427 self.getDateTime(self.data.max_time).strftime(
467 '%Y-%m-%d %H:%M:%S'),
428 '%Y-%m-%d %H:%M:%S'),
468 self.time_label),
429 self.time_label),
469 size=8)
430 size=8)
470 else:
431 else:
471 ax.set_title('{}'.format(self.titles[n]), size=8)
432 ax.set_title('{}'.format(self.titles[n]), size=8)
472 ax.set_ylim(0, 90)
433 ax.set_ylim(0, 90)
473 ax.set_yticks(numpy.arange(0, 90, 20))
434 ax.set_yticks(numpy.arange(0, 90, 20))
474 ax.yaxis.labelpad = 40
435 ax.yaxis.labelpad = 40
475
436
476 if self.firsttime:
437 if self.firsttime:
477 for n, fig in enumerate(self.figures):
438 for n, fig in enumerate(self.figures):
478 fig.subplots_adjust(**self.plots_adjust)
439 fig.subplots_adjust(**self.plots_adjust)
479 self.firsttime = False
440 self.firsttime = False
480
441
481 def clear_figures(self):
442 def clear_figures(self):
482 '''
443 '''
483 Reset axes for redraw plots
444 Reset axes for redraw plots
484 '''
445 '''
485
446
486 for ax in self.axes+self.pf_axes+self.cb_axes:
447 for ax in self.axes+self.pf_axes+self.cb_axes:
487 ax.clear()
448 ax.clear()
488 ax.firsttime = True
449 ax.firsttime = True
489 if hasattr(ax, 'cbar') and ax.cbar:
450 if hasattr(ax, 'cbar') and ax.cbar:
490 ax.cbar.remove()
451 ax.cbar.remove()
491
452
492 def __plot(self):
453 def __plot(self):
493 '''
454 '''
494 Main function to plot, format and save figures
455 Main function to plot, format and save figures
495 '''
456 '''
496
457
497 self.plot()
458 self.plot()
498 self.format()
459 self.format()
499
460
500 for n, fig in enumerate(self.figures):
461 for n, fig in enumerate(self.figures):
501 if self.nrows == 0 or self.nplots == 0:
462 if self.nrows == 0 or self.nplots == 0:
502 log.warning('No data', self.name)
463 log.warning('No data', self.name)
503 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
464 fig.text(0.5, 0.5, 'No Data', fontsize='large', ha='center')
504 fig.canvas.manager.set_window_title(self.CODE)
465 fig.canvas.manager.set_window_title(self.CODE)
505 continue
466 continue
506
467
507 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
468 fig.canvas.manager.set_window_title('{} - {}'.format(self.title,
508 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
469 self.getDateTime(self.data.max_time).strftime('%Y/%m/%d')))
509 fig.canvas.draw()
470 fig.canvas.draw()
510 if self.show:
471 if self.show:
511 fig.show()
472 fig.show()
512 figpause(0.01)
473 figpause(0.01)
513
474
514 if self.save:
475 if self.save:
515 self.save_figure(n)
476 self.save_figure(n)
516
477
517 if self.plot_server:
478 if self.plot_server:
518 self.send_to_server()
479 self.send_to_server()
519
480
520 def save_figure(self, n):
481 def save_figure(self, n):
521 '''
482 '''
522 '''
483 '''
523
484
524 if self.save_counter < self.save_period:
485 if (self.data.tm - self.save_time) < self.sender_period:
525 self.save_counter += 1
526 return
486 return
527
487
528 self.save_counter = 1
488 self.save_time = self.data.tm
529
489
530 fig = self.figures[n]
490 fig = self.figures[n]
531
491
532 if self.save_code:
533 if isinstance(self.save_code, str):
534 labels = [self.save_code for x in self.figures]
535 else:
536 labels = self.save_code
537 else:
538 labels = [self.CODE for x in self.figures]
539
540 figname = os.path.join(
492 figname = os.path.join(
541 self.save,
493 self.save,
542 labels[n],
494 self.save_code,
543 '{}_{}.png'.format(
495 '{}_{}.png'.format(
544 labels[n],
496 self.save_code,
545 self.getDateTime(self.data.max_time).strftime(
497 self.getDateTime(self.data.max_time).strftime(
546 '%Y%m%d_%H%M%S'
498 '%Y%m%d_%H%M%S'
547 ),
499 ),
548 )
500 )
549 )
501 )
550 log.log('Saving figure: {}'.format(figname), self.name)
502 log.log('Saving figure: {}'.format(figname), self.name)
551 if not os.path.isdir(os.path.dirname(figname)):
503 if not os.path.isdir(os.path.dirname(figname)):
552 os.makedirs(os.path.dirname(figname))
504 os.makedirs(os.path.dirname(figname))
553 fig.savefig(figname)
505 fig.savefig(figname)
554
506
555 if self.throttle == 0:
507 if self.throttle == 0:
556 figname = os.path.join(
508 figname = os.path.join(
557 self.save,
509 self.save,
558 '{}_{}.png'.format(
510 '{}_{}.png'.format(
559 labels[n],
511 self.save_code,
560 self.getDateTime(self.data.min_time).strftime(
512 self.getDateTime(self.data.min_time).strftime(
561 '%Y%m%d'
513 '%Y%m%d'
562 ),
514 ),
563 )
515 )
564 )
516 )
565 fig.savefig(figname)
517 fig.savefig(figname)
566
518
567 def send_to_server(self):
519 def send_to_server(self):
568 '''
520 '''
569 '''
521 '''
570
522
571 interval = self.data.tm - self.sender_time
523 interval = self.data.tm - self.sender_time
572 if interval < self.sender_period:
524 if interval < self.sender_period:
573 return
525 return
574
526
575 self.sender_time = self.data.tm
527 self.sender_time = self.data.tm
576
528
577 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
529 attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax']
578 for attr in attrs:
530 for attr in attrs:
579 value = getattr(self, attr)
531 value = getattr(self, attr)
580 if value:
532 if value:
581 if isinstance(value, (numpy.float32, numpy.float64)):
533 if isinstance(value, (numpy.float32, numpy.float64)):
582 value = round(float(value), 2)
534 value = round(float(value), 2)
583 self.data.meta[attr] = value
535 self.data.meta[attr] = value
584 if self.colormap == 'jet':
536 if self.colormap == 'jet':
585 self.data.meta['colormap'] = 'Jet'
537 self.data.meta['colormap'] = 'Jet'
586 elif 'RdBu' in self.colormap:
538 elif 'RdBu' in self.colormap:
587 self.data.meta['colormap'] = 'RdBu'
539 self.data.meta['colormap'] = 'RdBu'
588 else:
540 else:
589 self.data.meta['colormap'] = 'Viridis'
541 self.data.meta['colormap'] = 'Viridis'
590 self.data.meta['interval'] = int(interval)
542 self.data.meta['interval'] = int(interval)
591 # msg = self.data.jsonify(self.data.tm, self.plot_name, self.plot_type)
543
592 try:
544 try:
593 self.sender_queue.put(self.data.tm, block=False)
545 self.sender_queue.put(self.data.tm, block=False)
594 except:
546 except:
595 tm = self.sender_queue.get()
547 tm = self.sender_queue.get()
596 self.sender_queue.put(self.data.tm)
548 self.sender_queue.put(self.data.tm)
597
549
598 while True:
550 while True:
599 if self.sender_queue.empty():
551 if self.sender_queue.empty():
600 break
552 break
601 tm = self.sender_queue.get()
553 tm = self.sender_queue.get()
602 try:
554 try:
603 msg = self.data.jsonify(tm, self.plot_name, self.plot_type)
555 msg = self.data.jsonify(tm, self.save_code, self.plot_type)
604 except:
556 except:
605 continue
557 continue
606 self.socket.send_string(msg)
558 self.socket.send_string(msg)
607 socks = dict(self.poll.poll(5000))
559 socks = dict(self.poll.poll(5000))
608 if socks.get(self.socket) == zmq.POLLIN:
560 if socks.get(self.socket) == zmq.POLLIN:
609 reply = self.socket.recv_string()
561 reply = self.socket.recv_string()
610 if reply == 'ok':
562 if reply == 'ok':
611 log.log("Response from server ok", self.name)
563 log.log("Response from server ok", self.name)
612 time.sleep(0.2)
564 time.sleep(0.2)
613 continue
565 continue
614 else:
566 else:
615 log.warning(
567 log.warning(
616 "Malformed reply from server: {}".format(reply), self.name)
568 "Malformed reply from server: {}".format(reply), self.name)
617 else:
569 else:
618 log.warning(
570 log.warning(
619 "No response from server, retrying...", self.name)
571 "No response from server, retrying...", self.name)
620 self.sender_queue.put(self.data.tm)
572 self.sender_queue.put(self.data.tm)
621 self.socket.setsockopt(zmq.LINGER, 0)
573 self.socket.setsockopt(zmq.LINGER, 0)
622 self.socket.close()
574 self.socket.close()
623 self.poll.unregister(self.socket)
575 self.poll.unregister(self.socket)
624 time.sleep(0.1)
576 time.sleep(0.1)
625 self.socket = self.context.socket(zmq.REQ)
577 self.socket = self.context.socket(zmq.REQ)
626 self.socket.connect(self.plot_server)
578 self.socket.connect(self.plot_server)
627 self.poll.register(self.socket, zmq.POLLIN)
579 self.poll.register(self.socket, zmq.POLLIN)
628 break
580 break
629
581
630 def setup(self):
582 def setup(self):
631 '''
583 '''
632 This method should be implemented in the child class, the following
584 This method should be implemented in the child class, the following
633 attributes should be set:
585 attributes should be set:
634
586
635 self.nrows: number of rows
587 self.nrows: number of rows
636 self.ncols: number of cols
588 self.ncols: number of cols
637 self.nplots: number of plots (channels or pairs)
589 self.nplots: number of plots (channels or pairs)
638 self.ylabel: label for Y axes
590 self.ylabel: label for Y axes
639 self.titles: list of axes title
591 self.titles: list of axes title
640
592
641 '''
593 '''
642 raise NotImplementedError
594 raise NotImplementedError
643
595
644 def plot(self):
596 def plot(self):
645 '''
597 '''
646 Must be defined in the child class
598 Must be defined in the child class
647 '''
599 '''
648 raise NotImplementedError
600 raise NotImplementedError
649
601
650 def run(self, dataOut, **kwargs):
602 def run(self, dataOut, **kwargs):
651 '''
603 '''
652 Main plotting routine
604 Main plotting routine
653 '''
605 '''
654
606
655 if self.isConfig is False:
607 if self.isConfig is False:
656 self.__setup(**kwargs)
608 self.__setup(**kwargs)
657
609
658 t = getattr(dataOut, self.attr_time)
659
660 if self.localtime:
610 if self.localtime:
661 self.getDateTime = datetime.datetime.fromtimestamp
611 self.getDateTime = datetime.datetime.fromtimestamp
662 else:
612 else:
663 self.getDateTime = datetime.datetime.utcfromtimestamp
613 self.getDateTime = datetime.datetime.utcfromtimestamp
664
614
665 if self.xmin is None:
666 self.tmin = t
667 if 'buffer' in self.plot_type:
668 self.xmin = self.getDateTime(t).hour
669 else:
670 self.tmin = (
671 self.getDateTime(t).replace(
672 hour=int(self.xmin),
673 minute=0,
674 second=0) - self.getDateTime(0)).total_seconds()
675
676 self.data.setup()
615 self.data.setup()
677 self.isConfig = True
616 self.isConfig = True
678 if self.plot_server:
617 if self.plot_server:
679 self.context = zmq.Context()
618 self.context = zmq.Context()
680 self.socket = self.context.socket(zmq.REQ)
619 self.socket = self.context.socket(zmq.REQ)
681 self.socket.connect(self.plot_server)
620 self.socket.connect(self.plot_server)
682 self.poll = zmq.Poller()
621 self.poll = zmq.Poller()
683 self.poll.register(self.socket, zmq.POLLIN)
622 self.poll.register(self.socket, zmq.POLLIN)
684
623
685 tm = getattr(dataOut, self.attr_time)
624 tm = getattr(dataOut, self.attr_time)
686
625
687 if self.data and (tm - self.tmin) >= self.xrange*60*60:
626 if self.data and 'time' in self.xaxis and (tm - self.tmin) >= self.xrange*60*60:
688 self.save_counter = self.save_period
627 self.save_counter = self.save_period
689 self.__plot()
628 self.__plot()
690 if 'time' in self.xaxis:
691 self.xmin += self.xrange
692 if self.xmin >= 24:
693 self.xmin -= 24
694 self.tmin += self.xrange*60*60
629 self.tmin += self.xrange*60*60
695 self.data.setup()
630 self.data.setup()
696 self.clear_figures()
631 self.clear_figures()
697
632
698 self.data.update(dataOut, tm)
633 self.data.update(dataOut, tm)
699
634
700 if self.isPlotConfig is False:
635 if self.isPlotConfig is False:
701 self.__setup_plot()
636 self.__setup_plot()
702 self.isPlotConfig = True
637 self.isPlotConfig = True
638 if self.xaxis == 'time':
639 dt = self.getDateTime(tm)
640 if self.xmin is None:
641 self.tmin = tm
642 self.xmin = dt.hour
643 minutes = (self.xmin-int(self.xmin)) * 60
644 seconds = (minutes - int(minutes)) * 60
645 self.tmin = (dt.replace(hour=int(self.xmin), minute=int(minutes), second=int(seconds)) -
646 datetime.datetime(1970, 1, 1)).total_seconds()
647 if self.localtime:
648 self.tmin += time.timezone
649
650 if self.xmin is not None and self.xmax is not None:
651 self.xrange = self.xmax - self.xmin
703
652
704 if self.throttle == 0:
653 if self.throttle == 0:
705 self.__plot()
654 self.__plot()
706 else:
655 else:
707 self.__throttle_plot(self.__plot)#, coerce=coerce)
656 self.__throttle_plot(self.__plot)#, coerce=coerce)
708
657
709 def close(self):
658 def close(self):
710
659
711 if self.data and not self.data.flagNoData:
660 if self.data and not self.data.flagNoData:
712 self.save_counter = self.save_period
661 self.save_counter = self.save_period
713 self.__plot()
662 self.__plot()
714 if self.data and not self.data.flagNoData and self.pause:
663 if self.data and not self.data.flagNoData and self.pause:
715 figpause(10)
664 figpause(10)
716
665
@@ -1,346 +1,339
1 import os
1 import os
2 import datetime
2 import datetime
3 import numpy
3 import numpy
4
4
5 from schainpy.model.graphics.jroplot_base import Plot, plt
5 from schainpy.model.graphics.jroplot_base import Plot, plt
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot
6 from schainpy.model.graphics.jroplot_spectra import SpectraPlot, RTIPlot, CoherencePlot
7 from schainpy.utils import log
7 from schainpy.utils import log
8
8
9 EARTH_RADIUS = 6.3710e3
9 EARTH_RADIUS = 6.3710e3
10
10
11
11
12 def ll2xy(lat1, lon1, lat2, lon2):
12 def ll2xy(lat1, lon1, lat2, lon2):
13
13
14 p = 0.017453292519943295
14 p = 0.017453292519943295
15 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
15 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
16 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
16 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
17 r = 12742 * numpy.arcsin(numpy.sqrt(a))
17 r = 12742 * numpy.arcsin(numpy.sqrt(a))
18 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
18 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
19 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
19 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
20 theta = -theta + numpy.pi/2
20 theta = -theta + numpy.pi/2
21 return r*numpy.cos(theta), r*numpy.sin(theta)
21 return r*numpy.cos(theta), r*numpy.sin(theta)
22
22
23
23
24 def km2deg(km):
24 def km2deg(km):
25 '''
25 '''
26 Convert distance in km to degrees
26 Convert distance in km to degrees
27 '''
27 '''
28
28
29 return numpy.rad2deg(km/EARTH_RADIUS)
29 return numpy.rad2deg(km/EARTH_RADIUS)
30
30
31
31
32
32
33 class SpectralMomentsPlot(SpectraPlot):
33 class SpectralMomentsPlot(SpectraPlot):
34 '''
34 '''
35 Plot for Spectral Moments
35 Plot for Spectral Moments
36 '''
36 '''
37 CODE = 'spc_moments'
37 CODE = 'spc_moments'
38 colormap = 'jet'
38 colormap = 'jet'
39 plot_name = 'SpectralMoments'
40 plot_type = 'pcolor'
39 plot_type = 'pcolor'
41
40
42
41
43 class SnrPlot(RTIPlot):
42 class SnrPlot(RTIPlot):
44 '''
43 '''
45 Plot for SNR Data
44 Plot for SNR Data
46 '''
45 '''
47
46
48 CODE = 'snr'
47 CODE = 'snr'
49 colormap = 'jet'
48 colormap = 'jet'
50 plot_name = 'SNR'
51
49
52
50
53 class DopplerPlot(RTIPlot):
51 class DopplerPlot(RTIPlot):
54 '''
52 '''
55 Plot for DOPPLER Data (1st moment)
53 Plot for DOPPLER Data (1st moment)
56 '''
54 '''
57
55
58 CODE = 'dop'
56 CODE = 'dop'
59 colormap = 'jet'
57 colormap = 'jet'
60 plot_name = 'DopplerShift'
61
58
62
59
63 class PowerPlot(RTIPlot):
60 class PowerPlot(RTIPlot):
64 '''
61 '''
65 Plot for Power Data (0 moment)
62 Plot for Power Data (0 moment)
66 '''
63 '''
67
64
68 CODE = 'pow'
65 CODE = 'pow'
69 colormap = 'jet'
66 colormap = 'jet'
70 plot_name = 'TotalPower'
71
67
72
68
73 class SpectralWidthPlot(RTIPlot):
69 class SpectralWidthPlot(RTIPlot):
74 '''
70 '''
75 Plot for Spectral Width Data (2nd moment)
71 Plot for Spectral Width Data (2nd moment)
76 '''
72 '''
77
73
78 CODE = 'width'
74 CODE = 'width'
79 colormap = 'jet'
75 colormap = 'jet'
80 plot_name = 'SpectralWidth'
81
76
82
77
83 class SkyMapPlot(Plot):
78 class SkyMapPlot(Plot):
84 '''
79 '''
85 Plot for meteors detection data
80 Plot for meteors detection data
86 '''
81 '''
87
82
88 CODE = 'param'
83 CODE = 'param'
89
84
90 def setup(self):
85 def setup(self):
91
86
92 self.ncols = 1
87 self.ncols = 1
93 self.nrows = 1
88 self.nrows = 1
94 self.width = 7.2
89 self.width = 7.2
95 self.height = 7.2
90 self.height = 7.2
96 self.nplots = 1
91 self.nplots = 1
97 self.xlabel = 'Zonal Zenith Angle (deg)'
92 self.xlabel = 'Zonal Zenith Angle (deg)'
98 self.ylabel = 'Meridional Zenith Angle (deg)'
93 self.ylabel = 'Meridional Zenith Angle (deg)'
99 self.polar = True
94 self.polar = True
100 self.ymin = -180
95 self.ymin = -180
101 self.ymax = 180
96 self.ymax = 180
102 self.colorbar = False
97 self.colorbar = False
103
98
104 def plot(self):
99 def plot(self):
105
100
106 arrayParameters = numpy.concatenate(self.data['param'])
101 arrayParameters = numpy.concatenate(self.data['param'])
107 error = arrayParameters[:, -1]
102 error = arrayParameters[:, -1]
108 indValid = numpy.where(error == 0)[0]
103 indValid = numpy.where(error == 0)[0]
109 finalMeteor = arrayParameters[indValid, :]
104 finalMeteor = arrayParameters[indValid, :]
110 finalAzimuth = finalMeteor[:, 3]
105 finalAzimuth = finalMeteor[:, 3]
111 finalZenith = finalMeteor[:, 4]
106 finalZenith = finalMeteor[:, 4]
112
107
113 x = finalAzimuth * numpy.pi / 180
108 x = finalAzimuth * numpy.pi / 180
114 y = finalZenith
109 y = finalZenith
115
110
116 ax = self.axes[0]
111 ax = self.axes[0]
117
112
118 if ax.firsttime:
113 if ax.firsttime:
119 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
114 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
120 else:
115 else:
121 ax.plot.set_data(x, y)
116 ax.plot.set_data(x, y)
122
117
123 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
118 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
124 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
119 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
125 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
120 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
126 dt2,
121 dt2,
127 len(x))
122 len(x))
128 self.titles[0] = title
123 self.titles[0] = title
129
124
130
125
131 class ParametersPlot(RTIPlot):
126 class ParametersPlot(RTIPlot):
132 '''
127 '''
133 Plot for data_param object
128 Plot for data_param object
134 '''
129 '''
135
130
136 CODE = 'param'
131 CODE = 'param'
137 colormap = 'seismic'
132 colormap = 'seismic'
138 plot_name = 'Parameters'
139
133
140 def setup(self):
134 def setup(self):
141 self.xaxis = 'time'
135 self.xaxis = 'time'
142 self.ncols = 1
136 self.ncols = 1
143 self.nrows = self.data.shape(self.CODE)[0]
137 self.nrows = self.data.shape(self.CODE)[0]
144 self.nplots = self.nrows
138 self.nplots = self.nrows
145 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
139 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95, 'top': 0.95})
146
140
147 if not self.xlabel:
141 if not self.xlabel:
148 self.xlabel = 'Time'
142 self.xlabel = 'Time'
149
143
150 if self.showSNR:
144 if self.showSNR:
151 self.nrows += 1
145 self.nrows += 1
152 self.nplots += 1
146 self.nplots += 1
153
147
154 self.ylabel = 'Height [km]'
148 self.ylabel = 'Height [km]'
155 if not self.titles:
149 if not self.titles:
156 self.titles = self.data.parameters \
150 self.titles = self.data.parameters \
157 if self.data.parameters else ['Param {}'.format(x) for x in range(self.nrows)]
151 if self.data.parameters else ['Param {}'.format(x) for x in range(self.nrows)]
158 if self.showSNR:
152 if self.showSNR:
159 self.titles.append('SNR')
153 self.titles.append('SNR')
160
154
161 def plot(self):
155 def plot(self):
162 self.data.normalize_heights()
156 self.data.normalize_heights()
163 self.x = self.data.times
157 self.x = self.data.times
164 self.y = self.data.heights
158 self.y = self.data.heights
165 if self.showSNR:
159 if self.showSNR:
166 self.z = numpy.concatenate(
160 self.z = numpy.concatenate(
167 (self.data[self.CODE], self.data['snr'])
161 (self.data[self.CODE], self.data['snr'])
168 )
162 )
169 else:
163 else:
170 self.z = self.data[self.CODE]
164 self.z = self.data[self.CODE]
171
165
172 self.z = numpy.ma.masked_invalid(self.z)
166 self.z = numpy.ma.masked_invalid(self.z)
173
167
174 if self.decimation is None:
168 if self.decimation is None:
175 x, y, z = self.fill_gaps(self.x, self.y, self.z)
169 x, y, z = self.fill_gaps(self.x, self.y, self.z)
176 else:
170 else:
177 x, y, z = self.fill_gaps(*self.decimate())
171 x, y, z = self.fill_gaps(*self.decimate())
178
172
179 for n, ax in enumerate(self.axes):
173 for n, ax in enumerate(self.axes):
180
174
181 self.zmax = self.zmax if self.zmax is not None else numpy.max(
175 self.zmax = self.zmax if self.zmax is not None else numpy.max(
182 self.z[n])
176 self.z[n])
183 self.zmin = self.zmin if self.zmin is not None else numpy.min(
177 self.zmin = self.zmin if self.zmin is not None else numpy.min(
184 self.z[n])
178 self.z[n])
185
179
186 if ax.firsttime:
180 if ax.firsttime:
187 if self.zlimits is not None:
181 if self.zlimits is not None:
188 self.zmin, self.zmax = self.zlimits[n]
182 self.zmin, self.zmax = self.zlimits[n]
189
183
190 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
184 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
191 vmin=self.zmin,
185 vmin=self.zmin,
192 vmax=self.zmax,
186 vmax=self.zmax,
193 cmap=self.cmaps[n]
187 cmap=self.cmaps[n]
194 )
188 )
195 else:
189 else:
196 if self.zlimits is not None:
190 if self.zlimits is not None:
197 self.zmin, self.zmax = self.zlimits[n]
191 self.zmin, self.zmax = self.zlimits[n]
198 ax.collections.remove(ax.collections[0])
192 ax.collections.remove(ax.collections[0])
199 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
193 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
200 vmin=self.zmin,
194 vmin=self.zmin,
201 vmax=self.zmax,
195 vmax=self.zmax,
202 cmap=self.cmaps[n]
196 cmap=self.cmaps[n]
203 )
197 )
204
198
205
199
206 class OutputPlot(ParametersPlot):
200 class OutputPlot(ParametersPlot):
207 '''
201 '''
208 Plot data_output object
202 Plot data_output object
209 '''
203 '''
210
204
211 CODE = 'output'
205 CODE = 'output'
212 colormap = 'seismic'
206 colormap = 'seismic'
213 plot_name = 'Output'
214
207
215
208
216 class PolarMapPlot(Plot):
209 class PolarMapPlot(Plot):
217 '''
210 '''
218 Plot for weather radar
211 Plot for weather radar
219 '''
212 '''
220
213
221 CODE = 'param'
214 CODE = 'param'
222 colormap = 'seismic'
215 colormap = 'seismic'
223
216
224 def setup(self):
217 def setup(self):
225 self.ncols = 1
218 self.ncols = 1
226 self.nrows = 1
219 self.nrows = 1
227 self.width = 9
220 self.width = 9
228 self.height = 8
221 self.height = 8
229 self.mode = self.data.meta['mode']
222 self.mode = self.data.meta['mode']
230 if self.channels is not None:
223 if self.channels is not None:
231 self.nplots = len(self.channels)
224 self.nplots = len(self.channels)
232 self.nrows = len(self.channels)
225 self.nrows = len(self.channels)
233 else:
226 else:
234 self.nplots = self.data.shape(self.CODE)[0]
227 self.nplots = self.data.shape(self.CODE)[0]
235 self.nrows = self.nplots
228 self.nrows = self.nplots
236 self.channels = list(range(self.nplots))
229 self.channels = list(range(self.nplots))
237 if self.mode == 'E':
230 if self.mode == 'E':
238 self.xlabel = 'Longitude'
231 self.xlabel = 'Longitude'
239 self.ylabel = 'Latitude'
232 self.ylabel = 'Latitude'
240 else:
233 else:
241 self.xlabel = 'Range (km)'
234 self.xlabel = 'Range (km)'
242 self.ylabel = 'Height (km)'
235 self.ylabel = 'Height (km)'
243 self.bgcolor = 'white'
236 self.bgcolor = 'white'
244 self.cb_labels = self.data.meta['units']
237 self.cb_labels = self.data.meta['units']
245 self.lat = self.data.meta['latitude']
238 self.lat = self.data.meta['latitude']
246 self.lon = self.data.meta['longitude']
239 self.lon = self.data.meta['longitude']
247 self.xmin, self.xmax = float(
240 self.xmin, self.xmax = float(
248 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
241 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
249 self.ymin, self.ymax = float(
242 self.ymin, self.ymax = float(
250 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
243 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
251 # self.polar = True
244 # self.polar = True
252
245
253 def plot(self):
246 def plot(self):
254
247
255 for n, ax in enumerate(self.axes):
248 for n, ax in enumerate(self.axes):
256 data = self.data['param'][self.channels[n]]
249 data = self.data['param'][self.channels[n]]
257
250
258 zeniths = numpy.linspace(
251 zeniths = numpy.linspace(
259 0, self.data.meta['max_range'], data.shape[1])
252 0, self.data.meta['max_range'], data.shape[1])
260 if self.mode == 'E':
253 if self.mode == 'E':
261 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
254 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
262 r, theta = numpy.meshgrid(zeniths, azimuths)
255 r, theta = numpy.meshgrid(zeniths, azimuths)
263 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
256 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
264 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
257 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
265 x = km2deg(x) + self.lon
258 x = km2deg(x) + self.lon
266 y = km2deg(y) + self.lat
259 y = km2deg(y) + self.lat
267 else:
260 else:
268 azimuths = numpy.radians(self.data.heights)
261 azimuths = numpy.radians(self.data.heights)
269 r, theta = numpy.meshgrid(zeniths, azimuths)
262 r, theta = numpy.meshgrid(zeniths, azimuths)
270 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
263 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
271 self.y = zeniths
264 self.y = zeniths
272
265
273 if ax.firsttime:
266 if ax.firsttime:
274 if self.zlimits is not None:
267 if self.zlimits is not None:
275 self.zmin, self.zmax = self.zlimits[n]
268 self.zmin, self.zmax = self.zlimits[n]
276 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
269 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
277 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
270 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
278 vmin=self.zmin,
271 vmin=self.zmin,
279 vmax=self.zmax,
272 vmax=self.zmax,
280 cmap=self.cmaps[n])
273 cmap=self.cmaps[n])
281 else:
274 else:
282 if self.zlimits is not None:
275 if self.zlimits is not None:
283 self.zmin, self.zmax = self.zlimits[n]
276 self.zmin, self.zmax = self.zlimits[n]
284 ax.collections.remove(ax.collections[0])
277 ax.collections.remove(ax.collections[0])
285 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
278 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
286 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
279 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
287 vmin=self.zmin,
280 vmin=self.zmin,
288 vmax=self.zmax,
281 vmax=self.zmax,
289 cmap=self.cmaps[n])
282 cmap=self.cmaps[n])
290
283
291 if self.mode == 'A':
284 if self.mode == 'A':
292 continue
285 continue
293
286
294 # plot district names
287 # plot district names
295 f = open('/data/workspace/schain_scripts/distrito.csv')
288 f = open('/data/workspace/schain_scripts/distrito.csv')
296 for line in f:
289 for line in f:
297 label, lon, lat = [s.strip() for s in line.split(',') if s]
290 label, lon, lat = [s.strip() for s in line.split(',') if s]
298 lat = float(lat)
291 lat = float(lat)
299 lon = float(lon)
292 lon = float(lon)
300 # ax.plot(lon, lat, '.b', ms=2)
293 # ax.plot(lon, lat, '.b', ms=2)
301 ax.text(lon, lat, label.decode('utf8'), ha='center',
294 ax.text(lon, lat, label.decode('utf8'), ha='center',
302 va='bottom', size='8', color='black')
295 va='bottom', size='8', color='black')
303
296
304 # plot limites
297 # plot limites
305 limites = []
298 limites = []
306 tmp = []
299 tmp = []
307 for line in open('/data/workspace/schain_scripts/lima.csv'):
300 for line in open('/data/workspace/schain_scripts/lima.csv'):
308 if '#' in line:
301 if '#' in line:
309 if tmp:
302 if tmp:
310 limites.append(tmp)
303 limites.append(tmp)
311 tmp = []
304 tmp = []
312 continue
305 continue
313 values = line.strip().split(',')
306 values = line.strip().split(',')
314 tmp.append((float(values[0]), float(values[1])))
307 tmp.append((float(values[0]), float(values[1])))
315 for points in limites:
308 for points in limites:
316 ax.add_patch(
309 ax.add_patch(
317 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
310 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
318
311
319 # plot Cuencas
312 # plot Cuencas
320 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
313 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
321 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
314 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
322 values = [line.strip().split(',') for line in f]
315 values = [line.strip().split(',') for line in f]
323 points = [(float(s[0]), float(s[1])) for s in values]
316 points = [(float(s[0]), float(s[1])) for s in values]
324 ax.add_patch(Polygon(points, ec='b', fc='none'))
317 ax.add_patch(Polygon(points, ec='b', fc='none'))
325
318
326 # plot grid
319 # plot grid
327 for r in (15, 30, 45, 60):
320 for r in (15, 30, 45, 60):
328 ax.add_artist(plt.Circle((self.lon, self.lat),
321 ax.add_artist(plt.Circle((self.lon, self.lat),
329 km2deg(r), color='0.6', fill=False, lw=0.2))
322 km2deg(r), color='0.6', fill=False, lw=0.2))
330 ax.text(
323 ax.text(
331 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
324 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
332 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
325 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
333 '{}km'.format(r),
326 '{}km'.format(r),
334 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
327 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
335
328
336 if self.mode == 'E':
329 if self.mode == 'E':
337 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
330 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
338 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
331 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
339 else:
332 else:
340 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
333 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
341 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
334 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
342
335
343 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
336 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
344 self.titles = ['{} {}'.format(
337 self.titles = ['{} {}'.format(
345 self.data.parameters[x], title) for x in self.channels]
338 self.data.parameters[x], title) for x in self.channels]
346
339
@@ -1,651 +1,643
1 '''
1 '''
2 Created on Jul 9, 2014
2 Created on Jul 9, 2014
3 Modified on May 10, 2020
3 Modified on May 10, 2020
4
4
5 @author: Juan C. Espinoza
5 @author: Juan C. Espinoza
6 '''
6 '''
7
7
8 import os
8 import os
9 import datetime
9 import datetime
10 import numpy
10 import numpy
11
11
12 from schainpy.model.graphics.jroplot_base import Plot, plt
12 from schainpy.model.graphics.jroplot_base import Plot, plt
13
13
14
14
15 class SpectraPlot(Plot):
15 class SpectraPlot(Plot):
16 '''
16 '''
17 Plot for Spectra data
17 Plot for Spectra data
18 '''
18 '''
19
19
20 CODE = 'spc'
20 CODE = 'spc'
21 colormap = 'jet'
21 colormap = 'jet'
22 plot_name = 'Spectra'
23 plot_type = 'pcolor'
22 plot_type = 'pcolor'
24
23
25 def setup(self):
24 def setup(self):
26 self.nplots = len(self.data.channels)
25 self.nplots = len(self.data.channels)
27 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
26 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
28 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
27 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
29 self.height = 3 * self.nrows
28 self.height = 2.6 * self.nrows
30 self.cb_label = 'dB'
29 self.cb_label = 'dB'
31 if self.showprofile:
30 if self.showprofile:
32 self.width = 4 * self.ncols
31 self.width = 4 * self.ncols
33 else:
32 else:
34 self.width = 3.5 * self.ncols
33 self.width = 3.5 * self.ncols
35 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
34 self.plots_adjust.update({'wspace': 0.4, 'hspace':0.4, 'left': 0.1, 'right': 0.9, 'bottom': 0.08})
36 self.ylabel = 'Range [km]'
35 self.ylabel = 'Range [km]'
37
36
38 def plot(self):
37 def plot(self):
39 if self.xaxis == "frequency":
38 if self.xaxis == "frequency":
40 x = self.data.xrange[0]
39 x = self.data.xrange[0]
41 self.xlabel = "Frequency (kHz)"
40 self.xlabel = "Frequency (kHz)"
42 elif self.xaxis == "time":
41 elif self.xaxis == "time":
43 x = self.data.xrange[1]
42 x = self.data.xrange[1]
44 self.xlabel = "Time (ms)"
43 self.xlabel = "Time (ms)"
45 else:
44 else:
46 x = self.data.xrange[2]
45 x = self.data.xrange[2]
47 self.xlabel = "Velocity (m/s)"
46 self.xlabel = "Velocity (m/s)"
48
47
49 if self.CODE == 'spc_moments':
48 if self.CODE == 'spc_moments':
50 x = self.data.xrange[2]
49 x = self.data.xrange[2]
51 self.xlabel = "Velocity (m/s)"
50 self.xlabel = "Velocity (m/s)"
52
51
53 self.titles = []
52 self.titles = []
54
53
55 y = self.data.heights
54 y = self.data.heights
56 self.y = y
55 self.y = y
57 z = self.data['spc']
56 z = self.data['spc']
58
57
59 for n, ax in enumerate(self.axes):
58 for n, ax in enumerate(self.axes):
60 noise = self.data['noise'][n][-1]
59 noise = self.data['noise'][n][-1]
61 if self.CODE == 'spc_moments':
60 if self.CODE == 'spc_moments':
62 mean = self.data['moments'][n, :, 1, :][-1]
61 mean = self.data['moments'][n, :, 1, :][-1]
63 if ax.firsttime:
62 if ax.firsttime:
64 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
63 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
65 self.xmin = self.xmin if self.xmin else -self.xmax
64 self.xmin = self.xmin if self.xmin else -self.xmax
66 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
65 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
67 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
66 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
68 ax.plt = ax.pcolormesh(x, y, z[n].T,
67 ax.plt = ax.pcolormesh(x, y, z[n].T,
69 vmin=self.zmin,
68 vmin=self.zmin,
70 vmax=self.zmax,
69 vmax=self.zmax,
71 cmap=plt.get_cmap(self.colormap)
70 cmap=plt.get_cmap(self.colormap)
72 )
71 )
73
72
74 if self.showprofile:
73 if self.showprofile:
75 ax.plt_profile = self.pf_axes[n].plot(
74 ax.plt_profile = self.pf_axes[n].plot(
76 self.data['rti'][n][-1], y)[0]
75 self.data['rti'][n][-1], y)[0]
77 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
76 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
78 color="k", linestyle="dashed", lw=1)[0]
77 color="k", linestyle="dashed", lw=1)[0]
79 if self.CODE == 'spc_moments':
78 if self.CODE == 'spc_moments':
80 ax.plt_mean = ax.plot(mean, y, color='k')[0]
79 ax.plt_mean = ax.plot(mean, y, color='k')[0]
81 else:
80 else:
82 ax.plt.set_array(z[n].T.ravel())
81 ax.plt.set_array(z[n].T.ravel())
83 if self.showprofile:
82 if self.showprofile:
84 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
83 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
85 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
84 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
86 if self.CODE == 'spc_moments':
85 if self.CODE == 'spc_moments':
87 ax.plt_mean.set_data(mean, y)
86 ax.plt_mean.set_data(mean, y)
88 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
87 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
89
88
90
89
91 class CrossSpectraPlot(Plot):
90 class CrossSpectraPlot(Plot):
92
91
93 CODE = 'cspc'
92 CODE = 'cspc'
94 colormap = 'jet'
93 colormap = 'jet'
95 plot_name = 'CrossSpectra'
96 plot_type = 'pcolor'
94 plot_type = 'pcolor'
97 zmin_coh = None
95 zmin_coh = None
98 zmax_coh = None
96 zmax_coh = None
99 zmin_phase = None
97 zmin_phase = None
100 zmax_phase = None
98 zmax_phase = None
101
99
102 def setup(self):
100 def setup(self):
103
101
104 self.ncols = 4
102 self.ncols = 4
105 self.nrows = len(self.data.pairs)
103 self.nrows = len(self.data.pairs)
106 self.nplots = self.nrows * 4
104 self.nplots = self.nrows * 4
107 self.width = 3.4 * self.ncols
105 self.width = 3.1 * self.ncols
108 self.height = 3 * self.nrows
106 self.height = 2.6 * self.nrows
109 self.ylabel = 'Range [km]'
107 self.ylabel = 'Range [km]'
110 self.showprofile = False
108 self.showprofile = False
111 self.plots_adjust.update({'bottom': 0.08})
109 self.plots_adjust.update({'left': 0.08, 'right': 0.92, 'wspace': 0.5, 'hspace':0.4, 'top':0.95, 'bottom': 0.08})
112
110
113 def plot(self):
111 def plot(self):
114
112
115 if self.xaxis == "frequency":
113 if self.xaxis == "frequency":
116 x = self.data.xrange[0]
114 x = self.data.xrange[0]
117 self.xlabel = "Frequency (kHz)"
115 self.xlabel = "Frequency (kHz)"
118 elif self.xaxis == "time":
116 elif self.xaxis == "time":
119 x = self.data.xrange[1]
117 x = self.data.xrange[1]
120 self.xlabel = "Time (ms)"
118 self.xlabel = "Time (ms)"
121 else:
119 else:
122 x = self.data.xrange[2]
120 x = self.data.xrange[2]
123 self.xlabel = "Velocity (m/s)"
121 self.xlabel = "Velocity (m/s)"
124
122
125 self.titles = []
123 self.titles = []
126
124
127 y = self.data.heights
125 y = self.data.heights
128 self.y = y
126 self.y = y
129 nspc = self.data['spc']
127 nspc = self.data['spc']
130 spc = self.data['cspc'][0]
128 spc = self.data['cspc'][0]
131 cspc = self.data['cspc'][1]
129 cspc = self.data['cspc'][1]
132
130
133 for n in range(self.nrows):
131 for n in range(self.nrows):
134 noise = self.data['noise'][:,-1]
132 noise = self.data['noise'][:,-1]
135 pair = self.data.pairs[n]
133 pair = self.data.pairs[n]
136 ax = self.axes[4 * n]
134 ax = self.axes[4 * n]
137 if ax.firsttime:
135 if ax.firsttime:
138 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
136 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
139 self.xmin = self.xmin if self.xmin else -self.xmax
137 self.xmin = self.xmin if self.xmin else -self.xmax
140 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
138 self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc)
141 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
139 self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc)
142 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
140 ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T,
143 vmin=self.zmin,
141 vmin=self.zmin,
144 vmax=self.zmax,
142 vmax=self.zmax,
145 cmap=plt.get_cmap(self.colormap)
143 cmap=plt.get_cmap(self.colormap)
146 )
144 )
147 else:
145 else:
148 ax.plt.set_array(nspc[pair[0]].T.ravel())
146 ax.plt.set_array(nspc[pair[0]].T.ravel())
149 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
147 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]]))
150
148
151 ax = self.axes[4 * n + 1]
149 ax = self.axes[4 * n + 1]
152 if ax.firsttime:
150 if ax.firsttime:
153 ax.plt = ax.pcolormesh(x , y, nspc[pair[1]].T,
151 ax.plt = ax.pcolormesh(x , y, nspc[pair[1]].T,
154 vmin=self.zmin,
152 vmin=self.zmin,
155 vmax=self.zmax,
153 vmax=self.zmax,
156 cmap=plt.get_cmap(self.colormap)
154 cmap=plt.get_cmap(self.colormap)
157 )
155 )
158 else:
156 else:
159 ax.plt.set_array(nspc[pair[1]].T.ravel())
157 ax.plt.set_array(nspc[pair[1]].T.ravel())
160 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
158 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]]))
161
159
162 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
160 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
163 coh = numpy.abs(out)
161 coh = numpy.abs(out)
164 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
162 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
165
163
166 ax = self.axes[4 * n + 2]
164 ax = self.axes[4 * n + 2]
167 if ax.firsttime:
165 if ax.firsttime:
168 ax.plt = ax.pcolormesh(x, y, coh.T,
166 ax.plt = ax.pcolormesh(x, y, coh.T,
169 vmin=0,
167 vmin=0,
170 vmax=1,
168 vmax=1,
171 cmap=plt.get_cmap(self.colormap_coh)
169 cmap=plt.get_cmap(self.colormap_coh)
172 )
170 )
173 else:
171 else:
174 ax.plt.set_array(coh.T.ravel())
172 ax.plt.set_array(coh.T.ravel())
175 self.titles.append(
173 self.titles.append(
176 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
174 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
177
175
178 ax = self.axes[4 * n + 3]
176 ax = self.axes[4 * n + 3]
179 if ax.firsttime:
177 if ax.firsttime:
180 ax.plt = ax.pcolormesh(x, y, phase.T,
178 ax.plt = ax.pcolormesh(x, y, phase.T,
181 vmin=-180,
179 vmin=-180,
182 vmax=180,
180 vmax=180,
183 cmap=plt.get_cmap(self.colormap_phase)
181 cmap=plt.get_cmap(self.colormap_phase)
184 )
182 )
185 else:
183 else:
186 ax.plt.set_array(phase.T.ravel())
184 ax.plt.set_array(phase.T.ravel())
187 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
185 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
188
186
189
187
190 class RTIPlot(Plot):
188 class RTIPlot(Plot):
191 '''
189 '''
192 Plot for RTI data
190 Plot for RTI data
193 '''
191 '''
194
192
195 CODE = 'rti'
193 CODE = 'rti'
196 colormap = 'jet'
194 colormap = 'jet'
197 plot_name = 'RTI'
198 plot_type = 'pcolorbuffer'
195 plot_type = 'pcolorbuffer'
199
196
200 def setup(self):
197 def setup(self):
201 self.xaxis = 'time'
198 self.xaxis = 'time'
202 self.ncols = 1
199 self.ncols = 1
203 self.nrows = len(self.data.channels)
200 self.nrows = len(self.data.channels)
204 self.nplots = len(self.data.channels)
201 self.nplots = len(self.data.channels)
205 self.ylabel = 'Range [km]'
202 self.ylabel = 'Range [km]'
206 self.xlabel = 'Time'
203 self.xlabel = 'Time'
207 self.cb_label = 'dB'
204 self.cb_label = 'dB'
208 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95})
205 self.plots_adjust.update({'hspace':0.8, 'left': 0.1, 'bottom': 0.08, 'right':0.95})
209 self.titles = ['{} Channel {}'.format(
206 self.titles = ['{} Channel {}'.format(
210 self.CODE.upper(), x) for x in range(self.nrows)]
207 self.CODE.upper(), x) for x in range(self.nrows)]
211
208
212 def plot(self):
209 def plot(self):
213 self.x = self.data.times
210 self.x = self.data.times
214 self.y = self.data.heights
211 self.y = self.data.heights
215 self.z = self.data[self.CODE]
212 self.z = self.data[self.CODE]
216 self.z = numpy.ma.masked_invalid(self.z)
213 self.z = numpy.ma.masked_invalid(self.z)
217
214
218 if self.decimation is None:
215 if self.decimation is None:
219 x, y, z = self.fill_gaps(self.x, self.y, self.z)
216 x, y, z = self.fill_gaps(self.x, self.y, self.z)
220 else:
217 else:
221 x, y, z = self.fill_gaps(*self.decimate())
218 x, y, z = self.fill_gaps(*self.decimate())
222
219
223 for n, ax in enumerate(self.axes):
220 for n, ax in enumerate(self.axes):
224 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
221 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
225 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
222 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
226 if ax.firsttime:
223 if ax.firsttime:
227 ax.plt = ax.pcolormesh(x, y, z[n].T,
224 ax.plt = ax.pcolormesh(x, y, z[n].T,
228 vmin=self.zmin,
225 vmin=self.zmin,
229 vmax=self.zmax,
226 vmax=self.zmax,
230 cmap=plt.get_cmap(self.colormap)
227 cmap=plt.get_cmap(self.colormap)
231 )
228 )
232 if self.showprofile:
229 if self.showprofile:
233 ax.plot_profile = self.pf_axes[n].plot(
230 ax.plot_profile = self.pf_axes[n].plot(
234 self.data['rti'][n][-1], self.y)[0]
231 self.data['rti'][n][-1], self.y)[0]
235 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
232 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
236 color="k", linestyle="dashed", lw=1)[0]
233 color="k", linestyle="dashed", lw=1)[0]
237 else:
234 else:
238 ax.collections.remove(ax.collections[0])
235 ax.collections.remove(ax.collections[0])
239 ax.plt = ax.pcolormesh(x, y, z[n].T,
236 ax.plt = ax.pcolormesh(x, y, z[n].T,
240 vmin=self.zmin,
237 vmin=self.zmin,
241 vmax=self.zmax,
238 vmax=self.zmax,
242 cmap=plt.get_cmap(self.colormap)
239 cmap=plt.get_cmap(self.colormap)
243 )
240 )
244 if self.showprofile:
241 if self.showprofile:
245 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
242 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
246 ax.plot_noise.set_data(numpy.repeat(
243 ax.plot_noise.set_data(numpy.repeat(
247 self.data['noise'][n][-1], len(self.y)), self.y)
244 self.data['noise'][n][-1], len(self.y)), self.y)
248
245
249
246
250 class CoherencePlot(RTIPlot):
247 class CoherencePlot(RTIPlot):
251 '''
248 '''
252 Plot for Coherence data
249 Plot for Coherence data
253 '''
250 '''
254
251
255 CODE = 'coh'
252 CODE = 'coh'
256 plot_name = 'Coherence'
257
253
258 def setup(self):
254 def setup(self):
259 self.xaxis = 'time'
255 self.xaxis = 'time'
260 self.ncols = 1
256 self.ncols = 1
261 self.nrows = len(self.data.pairs)
257 self.nrows = len(self.data.pairs)
262 self.nplots = len(self.data.pairs)
258 self.nplots = len(self.data.pairs)
263 self.ylabel = 'Range [km]'
259 self.ylabel = 'Range [km]'
264 self.xlabel = 'Time'
260 self.xlabel = 'Time'
265 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
261 self.plots_adjust.update({'hspace':0.6, 'left': 0.1, 'bottom': 0.1,'right':0.95})
266 if self.CODE == 'coh':
262 if self.CODE == 'coh':
267 self.cb_label = ''
263 self.cb_label = ''
268 self.titles = [
264 self.titles = [
269 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
265 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
270 else:
266 else:
271 self.cb_label = 'Degrees'
267 self.cb_label = 'Degrees'
272 self.titles = [
268 self.titles = [
273 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
269 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
274
270
275
271
276 class PhasePlot(CoherencePlot):
272 class PhasePlot(CoherencePlot):
277 '''
273 '''
278 Plot for Phase map data
274 Plot for Phase map data
279 '''
275 '''
280
276
281 CODE = 'phase'
277 CODE = 'phase'
282 colormap = 'seismic'
278 colormap = 'seismic'
283 plot_name = 'Phase'
284
279
285
280
286 class NoisePlot(Plot):
281 class NoisePlot(Plot):
287 '''
282 '''
288 Plot for noise
283 Plot for noise
289 '''
284 '''
290
285
291 CODE = 'noise'
286 CODE = 'noise'
292 plot_name = 'Noise'
293 plot_type = 'scatterbuffer'
287 plot_type = 'scatterbuffer'
294
288
295
289
296 def setup(self):
290 def setup(self):
297 self.xaxis = 'time'
291 self.xaxis = 'time'
298 self.ncols = 1
292 self.ncols = 1
299 self.nrows = 1
293 self.nrows = 1
300 self.nplots = 1
294 self.nplots = 1
301 self.ylabel = 'Intensity [dB]'
295 self.ylabel = 'Intensity [dB]'
302 self.xlabel = 'Time'
296 self.xlabel = 'Time'
303 self.titles = ['Noise']
297 self.titles = ['Noise']
304 self.colorbar = False
298 self.colorbar = False
305
299
306 def plot(self):
300 def plot(self):
307
301
308 x = self.data.times
302 x = self.data.times
309 xmin = self.data.min_time
303 xmin = self.data.min_time
310 xmax = xmin + self.xrange * 60 * 60
304 xmax = xmin + self.xrange * 60 * 60
311 Y = self.data[self.CODE]
305 Y = self.data[self.CODE]
312
306
313 if self.axes[0].firsttime:
307 if self.axes[0].firsttime:
314 for ch in self.data.channels:
308 for ch in self.data.channels:
315 y = Y[ch]
309 y = Y[ch]
316 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
310 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
317 plt.legend()
311 plt.legend()
318 else:
312 else:
319 for ch in self.data.channels:
313 for ch in self.data.channels:
320 y = Y[ch]
314 y = Y[ch]
321 self.axes[0].lines[ch].set_data(x, y)
315 self.axes[0].lines[ch].set_data(x, y)
322
316
323 self.ymin = numpy.nanmin(Y) - 5
317 self.ymin = numpy.nanmin(Y) - 5
324 self.ymax = numpy.nanmax(Y) + 5
318 self.ymax = numpy.nanmax(Y) + 5
325
319
326
320
327 class PowerProfilePlot(Plot):
321 class PowerProfilePlot(Plot):
328
322
329 CODE = 'spcprofile'
323 CODE = 'spcprofile'
330 plot_name = 'Power Profile'
331 plot_type = 'scatter'
324 plot_type = 'scatter'
332 buffering = False
325 buffering = False
333
326
334 def setup(self):
327 def setup(self):
335
328
336 self.ncols = 1
329 self.ncols = 1
337 self.nrows = 1
330 self.nrows = 1
338 self.nplots = 1
331 self.nplots = 1
339 self.height = 4
332 self.height = 4
340 self.width = 3
333 self.width = 3
341 self.ylabel = 'Range [km]'
334 self.ylabel = 'Range [km]'
342 self.xlabel = 'Intensity [dB]'
335 self.xlabel = 'Intensity [dB]'
343 self.titles = ['Power Profile']
336 self.titles = ['Power Profile']
344 self.colorbar = False
337 self.colorbar = False
345
338
346 def plot(self):
339 def plot(self):
347
340
348 y = self.data.heights
341 y = self.data.heights
349 self.y = y
342 self.y = y
350
343
351 x = self.data['spcprofile']
344 x = self.data['spcprofile']
352
345
353 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
346 if self.xmin is None: self.xmin = numpy.nanmin(x)*0.9
354 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
347 if self.xmax is None: self.xmax = numpy.nanmax(x)*1.1
355
348
356 if self.axes[0].firsttime:
349 if self.axes[0].firsttime:
357 for ch in self.data.channels:
350 for ch in self.data.channels:
358 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
351 self.axes[0].plot(x[ch], y, lw=1, label='Ch{}'.format(ch))
359 plt.legend()
352 plt.legend()
360 else:
353 else:
361 for ch in self.data.channels:
354 for ch in self.data.channels:
362 self.axes[0].lines[ch].set_data(x[ch], y)
355 self.axes[0].lines[ch].set_data(x[ch], y)
363
356
364
357
365 class SpectraCutPlot(Plot):
358 class SpectraCutPlot(Plot):
366
359
367 CODE = 'spc_cut'
360 CODE = 'spc_cut'
368 plot_name = 'Spectra Cut'
369 plot_type = 'scatter'
361 plot_type = 'scatter'
370 buffering = False
362 buffering = False
371
363
372 def setup(self):
364 def setup(self):
373
365
374 self.nplots = len(self.data.channels)
366 self.nplots = len(self.data.channels)
375 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
367 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
376 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
368 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
377 self.width = 3.4 * self.ncols + 1.5
369 self.width = 3.4 * self.ncols + 1.5
378 self.height = 3 * self.nrows
370 self.height = 3 * self.nrows
379 self.ylabel = 'Power [dB]'
371 self.ylabel = 'Power [dB]'
380 self.colorbar = False
372 self.colorbar = False
381 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
373 self.plots_adjust.update({'left':0.1, 'hspace':0.3, 'right': 0.75, 'bottom':0.08})
382
374
383 def plot(self):
375 def plot(self):
384 if self.xaxis == "frequency":
376 if self.xaxis == "frequency":
385 x = self.data.xrange[0][1:]
377 x = self.data.xrange[0][1:]
386 self.xlabel = "Frequency (kHz)"
378 self.xlabel = "Frequency (kHz)"
387 elif self.xaxis == "time":
379 elif self.xaxis == "time":
388 x = self.data.xrange[1]
380 x = self.data.xrange[1]
389 self.xlabel = "Time (ms)"
381 self.xlabel = "Time (ms)"
390 else:
382 else:
391 x = self.data.xrange[2]
383 x = self.data.xrange[2]
392 self.xlabel = "Velocity (m/s)"
384 self.xlabel = "Velocity (m/s)"
393
385
394 self.titles = []
386 self.titles = []
395
387
396 y = self.data.heights
388 y = self.data.heights
397 #self.y = y
389 #self.y = y
398 z = self.data['spc_cut']
390 z = self.data['spc_cut']
399
391
400 if self.height_index:
392 if self.height_index:
401 index = numpy.array(self.height_index)
393 index = numpy.array(self.height_index)
402 else:
394 else:
403 index = numpy.arange(0, len(y), int((len(y))/9))
395 index = numpy.arange(0, len(y), int((len(y))/9))
404
396
405 for n, ax in enumerate(self.axes):
397 for n, ax in enumerate(self.axes):
406 if ax.firsttime:
398 if ax.firsttime:
407 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
399 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
408 self.xmin = self.xmin if self.xmin else -self.xmax
400 self.xmin = self.xmin if self.xmin else -self.xmax
409 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
401 self.ymin = self.ymin if self.ymin else numpy.nanmin(z)
410 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
402 self.ymax = self.ymax if self.ymax else numpy.nanmax(z)
411 ax.plt = ax.plot(x, z[n, :, index].T)
403 ax.plt = ax.plot(x, z[n, :, index].T)
412 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
404 labels = ['Range = {:2.1f}km'.format(y[i]) for i in index]
413 self.figures[0].legend(ax.plt, labels, loc='center right')
405 self.figures[0].legend(ax.plt, labels, loc='center right')
414 else:
406 else:
415 for i, line in enumerate(ax.plt):
407 for i, line in enumerate(ax.plt):
416 line.set_data(x, z[n, :, i])
408 line.set_data(x, z[n, :, i])
417 self.titles.append('CH {}'.format(n))
409 self.titles.append('CH {}'.format(n))
418
410
419
411
420 class BeaconPhase(Plot):
412 class BeaconPhase(Plot):
421
413
422 __isConfig = None
414 __isConfig = None
423 __nsubplots = None
415 __nsubplots = None
424
416
425 PREFIX = 'beacon_phase'
417 PREFIX = 'beacon_phase'
426
418
427 def __init__(self):
419 def __init__(self):
428 Plot.__init__(self)
420 Plot.__init__(self)
429 self.timerange = 24*60*60
421 self.timerange = 24*60*60
430 self.isConfig = False
422 self.isConfig = False
431 self.__nsubplots = 1
423 self.__nsubplots = 1
432 self.counter_imagwr = 0
424 self.counter_imagwr = 0
433 self.WIDTH = 800
425 self.WIDTH = 800
434 self.HEIGHT = 400
426 self.HEIGHT = 400
435 self.WIDTHPROF = 120
427 self.WIDTHPROF = 120
436 self.HEIGHTPROF = 0
428 self.HEIGHTPROF = 0
437 self.xdata = None
429 self.xdata = None
438 self.ydata = None
430 self.ydata = None
439
431
440 self.PLOT_CODE = BEACON_CODE
432 self.PLOT_CODE = BEACON_CODE
441
433
442 self.FTP_WEI = None
434 self.FTP_WEI = None
443 self.EXP_CODE = None
435 self.EXP_CODE = None
444 self.SUB_EXP_CODE = None
436 self.SUB_EXP_CODE = None
445 self.PLOT_POS = None
437 self.PLOT_POS = None
446
438
447 self.filename_phase = None
439 self.filename_phase = None
448
440
449 self.figfile = None
441 self.figfile = None
450
442
451 self.xmin = None
443 self.xmin = None
452 self.xmax = None
444 self.xmax = None
453
445
454 def getSubplots(self):
446 def getSubplots(self):
455
447
456 ncol = 1
448 ncol = 1
457 nrow = 1
449 nrow = 1
458
450
459 return nrow, ncol
451 return nrow, ncol
460
452
461 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
453 def setup(self, id, nplots, wintitle, showprofile=True, show=True):
462
454
463 self.__showprofile = showprofile
455 self.__showprofile = showprofile
464 self.nplots = nplots
456 self.nplots = nplots
465
457
466 ncolspan = 7
458 ncolspan = 7
467 colspan = 6
459 colspan = 6
468 self.__nsubplots = 2
460 self.__nsubplots = 2
469
461
470 self.createFigure(id = id,
462 self.createFigure(id = id,
471 wintitle = wintitle,
463 wintitle = wintitle,
472 widthplot = self.WIDTH+self.WIDTHPROF,
464 widthplot = self.WIDTH+self.WIDTHPROF,
473 heightplot = self.HEIGHT+self.HEIGHTPROF,
465 heightplot = self.HEIGHT+self.HEIGHTPROF,
474 show=show)
466 show=show)
475
467
476 nrow, ncol = self.getSubplots()
468 nrow, ncol = self.getSubplots()
477
469
478 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
470 self.addAxes(nrow, ncol*ncolspan, 0, 0, colspan, 1)
479
471
480 def save_phase(self, filename_phase):
472 def save_phase(self, filename_phase):
481 f = open(filename_phase,'w+')
473 f = open(filename_phase,'w+')
482 f.write('\n\n')
474 f.write('\n\n')
483 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
475 f.write('JICAMARCA RADIO OBSERVATORY - Beacon Phase \n')
484 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
476 f.write('DD MM YYYY HH MM SS pair(2,0) pair(2,1) pair(2,3) pair(2,4)\n\n' )
485 f.close()
477 f.close()
486
478
487 def save_data(self, filename_phase, data, data_datetime):
479 def save_data(self, filename_phase, data, data_datetime):
488 f=open(filename_phase,'a')
480 f=open(filename_phase,'a')
489 timetuple_data = data_datetime.timetuple()
481 timetuple_data = data_datetime.timetuple()
490 day = str(timetuple_data.tm_mday)
482 day = str(timetuple_data.tm_mday)
491 month = str(timetuple_data.tm_mon)
483 month = str(timetuple_data.tm_mon)
492 year = str(timetuple_data.tm_year)
484 year = str(timetuple_data.tm_year)
493 hour = str(timetuple_data.tm_hour)
485 hour = str(timetuple_data.tm_hour)
494 minute = str(timetuple_data.tm_min)
486 minute = str(timetuple_data.tm_min)
495 second = str(timetuple_data.tm_sec)
487 second = str(timetuple_data.tm_sec)
496 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
488 f.write(day+' '+month+' '+year+' '+hour+' '+minute+' '+second+' '+str(data[0])+' '+str(data[1])+' '+str(data[2])+' '+str(data[3])+'\n')
497 f.close()
489 f.close()
498
490
499 def plot(self):
491 def plot(self):
500 log.warning('TODO: Not yet implemented...')
492 log.warning('TODO: Not yet implemented...')
501
493
502 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
494 def run(self, dataOut, id, wintitle="", pairsList=None, showprofile='True',
503 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
495 xmin=None, xmax=None, ymin=None, ymax=None, hmin=None, hmax=None,
504 timerange=None,
496 timerange=None,
505 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
497 save=False, figpath='./', figfile=None, show=True, ftp=False, wr_period=1,
506 server=None, folder=None, username=None, password=None,
498 server=None, folder=None, username=None, password=None,
507 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
499 ftp_wei=0, exp_code=0, sub_exp_code=0, plot_pos=0):
508
500
509 if dataOut.flagNoData:
501 if dataOut.flagNoData:
510 return dataOut
502 return dataOut
511
503
512 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
504 if not isTimeInHourRange(dataOut.datatime, xmin, xmax):
513 return
505 return
514
506
515 if pairsList == None:
507 if pairsList == None:
516 pairsIndexList = dataOut.pairsIndexList[:10]
508 pairsIndexList = dataOut.pairsIndexList[:10]
517 else:
509 else:
518 pairsIndexList = []
510 pairsIndexList = []
519 for pair in pairsList:
511 for pair in pairsList:
520 if pair not in dataOut.pairsList:
512 if pair not in dataOut.pairsList:
521 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
513 raise ValueError("Pair %s is not in dataOut.pairsList" %(pair))
522 pairsIndexList.append(dataOut.pairsList.index(pair))
514 pairsIndexList.append(dataOut.pairsList.index(pair))
523
515
524 if pairsIndexList == []:
516 if pairsIndexList == []:
525 return
517 return
526
518
527 # if len(pairsIndexList) > 4:
519 # if len(pairsIndexList) > 4:
528 # pairsIndexList = pairsIndexList[0:4]
520 # pairsIndexList = pairsIndexList[0:4]
529
521
530 hmin_index = None
522 hmin_index = None
531 hmax_index = None
523 hmax_index = None
532
524
533 if hmin != None and hmax != None:
525 if hmin != None and hmax != None:
534 indexes = numpy.arange(dataOut.nHeights)
526 indexes = numpy.arange(dataOut.nHeights)
535 hmin_list = indexes[dataOut.heightList >= hmin]
527 hmin_list = indexes[dataOut.heightList >= hmin]
536 hmax_list = indexes[dataOut.heightList <= hmax]
528 hmax_list = indexes[dataOut.heightList <= hmax]
537
529
538 if hmin_list.any():
530 if hmin_list.any():
539 hmin_index = hmin_list[0]
531 hmin_index = hmin_list[0]
540
532
541 if hmax_list.any():
533 if hmax_list.any():
542 hmax_index = hmax_list[-1]+1
534 hmax_index = hmax_list[-1]+1
543
535
544 x = dataOut.getTimeRange()
536 x = dataOut.getTimeRange()
545 #y = dataOut.getHeiRange()
537 #y = dataOut.getHeiRange()
546
538
547
539
548 thisDatetime = dataOut.datatime
540 thisDatetime = dataOut.datatime
549
541
550 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
542 title = wintitle + " Signal Phase" # : %s" %(thisDatetime.strftime("%d-%b-%Y"))
551 xlabel = "Local Time"
543 xlabel = "Local Time"
552 ylabel = "Phase (degrees)"
544 ylabel = "Phase (degrees)"
553
545
554 update_figfile = False
546 update_figfile = False
555
547
556 nplots = len(pairsIndexList)
548 nplots = len(pairsIndexList)
557 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
549 #phase = numpy.zeros((len(pairsIndexList),len(dataOut.beacon_heiIndexList)))
558 phase_beacon = numpy.zeros(len(pairsIndexList))
550 phase_beacon = numpy.zeros(len(pairsIndexList))
559 for i in range(nplots):
551 for i in range(nplots):
560 pair = dataOut.pairsList[pairsIndexList[i]]
552 pair = dataOut.pairsList[pairsIndexList[i]]
561 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
553 ccf = numpy.average(dataOut.data_cspc[pairsIndexList[i], :, hmin_index:hmax_index], axis=0)
562 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
554 powa = numpy.average(dataOut.data_spc[pair[0], :, hmin_index:hmax_index], axis=0)
563 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
555 powb = numpy.average(dataOut.data_spc[pair[1], :, hmin_index:hmax_index], axis=0)
564 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
556 avgcoherenceComplex = ccf/numpy.sqrt(powa*powb)
565 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
557 phase = numpy.arctan2(avgcoherenceComplex.imag, avgcoherenceComplex.real)*180/numpy.pi
566
558
567 if dataOut.beacon_heiIndexList:
559 if dataOut.beacon_heiIndexList:
568 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
560 phase_beacon[i] = numpy.average(phase[dataOut.beacon_heiIndexList])
569 else:
561 else:
570 phase_beacon[i] = numpy.average(phase)
562 phase_beacon[i] = numpy.average(phase)
571
563
572 if not self.isConfig:
564 if not self.isConfig:
573
565
574 nplots = len(pairsIndexList)
566 nplots = len(pairsIndexList)
575
567
576 self.setup(id=id,
568 self.setup(id=id,
577 nplots=nplots,
569 nplots=nplots,
578 wintitle=wintitle,
570 wintitle=wintitle,
579 showprofile=showprofile,
571 showprofile=showprofile,
580 show=show)
572 show=show)
581
573
582 if timerange != None:
574 if timerange != None:
583 self.timerange = timerange
575 self.timerange = timerange
584
576
585 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
577 self.xmin, self.xmax = self.getTimeLim(x, xmin, xmax, timerange)
586
578
587 if ymin == None: ymin = 0
579 if ymin == None: ymin = 0
588 if ymax == None: ymax = 360
580 if ymax == None: ymax = 360
589
581
590 self.FTP_WEI = ftp_wei
582 self.FTP_WEI = ftp_wei
591 self.EXP_CODE = exp_code
583 self.EXP_CODE = exp_code
592 self.SUB_EXP_CODE = sub_exp_code
584 self.SUB_EXP_CODE = sub_exp_code
593 self.PLOT_POS = plot_pos
585 self.PLOT_POS = plot_pos
594
586
595 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
587 self.name = thisDatetime.strftime("%Y%m%d_%H%M%S")
596 self.isConfig = True
588 self.isConfig = True
597 self.figfile = figfile
589 self.figfile = figfile
598 self.xdata = numpy.array([])
590 self.xdata = numpy.array([])
599 self.ydata = numpy.array([])
591 self.ydata = numpy.array([])
600
592
601 update_figfile = True
593 update_figfile = True
602
594
603 #open file beacon phase
595 #open file beacon phase
604 path = '%s%03d' %(self.PREFIX, self.id)
596 path = '%s%03d' %(self.PREFIX, self.id)
605 beacon_file = os.path.join(path,'%s.txt'%self.name)
597 beacon_file = os.path.join(path,'%s.txt'%self.name)
606 self.filename_phase = os.path.join(figpath,beacon_file)
598 self.filename_phase = os.path.join(figpath,beacon_file)
607 #self.save_phase(self.filename_phase)
599 #self.save_phase(self.filename_phase)
608
600
609
601
610 #store data beacon phase
602 #store data beacon phase
611 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
603 #self.save_data(self.filename_phase, phase_beacon, thisDatetime)
612
604
613 self.setWinTitle(title)
605 self.setWinTitle(title)
614
606
615
607
616 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
608 title = "Phase Plot %s" %(thisDatetime.strftime("%Y/%m/%d %H:%M:%S"))
617
609
618 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
610 legendlabels = ["Pair (%d,%d)"%(pair[0], pair[1]) for pair in dataOut.pairsList]
619
611
620 axes = self.axesList[0]
612 axes = self.axesList[0]
621
613
622 self.xdata = numpy.hstack((self.xdata, x[0:1]))
614 self.xdata = numpy.hstack((self.xdata, x[0:1]))
623
615
624 if len(self.ydata)==0:
616 if len(self.ydata)==0:
625 self.ydata = phase_beacon.reshape(-1,1)
617 self.ydata = phase_beacon.reshape(-1,1)
626 else:
618 else:
627 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
619 self.ydata = numpy.hstack((self.ydata, phase_beacon.reshape(-1,1)))
628
620
629
621
630 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
622 axes.pmultilineyaxis(x=self.xdata, y=self.ydata,
631 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
623 xmin=self.xmin, xmax=self.xmax, ymin=ymin, ymax=ymax,
632 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
624 xlabel=xlabel, ylabel=ylabel, title=title, legendlabels=legendlabels, marker='x', markersize=8, linestyle="solid",
633 XAxisAsTime=True, grid='both'
625 XAxisAsTime=True, grid='both'
634 )
626 )
635
627
636 self.draw()
628 self.draw()
637
629
638 if dataOut.ltctime >= self.xmax:
630 if dataOut.ltctime >= self.xmax:
639 self.counter_imagwr = wr_period
631 self.counter_imagwr = wr_period
640 self.isConfig = False
632 self.isConfig = False
641 update_figfile = True
633 update_figfile = True
642
634
643 self.save(figpath=figpath,
635 self.save(figpath=figpath,
644 figfile=figfile,
636 figfile=figfile,
645 save=save,
637 save=save,
646 ftp=ftp,
638 ftp=ftp,
647 wr_period=wr_period,
639 wr_period=wr_period,
648 thisDatetime=thisDatetime,
640 thisDatetime=thisDatetime,
649 update_figfile=update_figfile)
641 update_figfile=update_figfile)
650
642
651 return dataOut No newline at end of file
643 return dataOut
@@ -1,302 +1,297
1 '''
1 '''
2 Created on Jul 9, 2014
2 Created on Jul 9, 2014
3
3
4 @author: roj-idl71
4 @author: roj-idl71
5 '''
5 '''
6 import os
6 import os
7 import datetime
7 import datetime
8 import numpy
8 import numpy
9
9
10 from schainpy.model.graphics.jroplot_base import Plot, plt
10 from schainpy.model.graphics.jroplot_base import Plot, plt
11
11
12
12
13 class ScopePlot(Plot):
13 class ScopePlot(Plot):
14
14
15 '''
15 '''
16 Plot for Scope
16 Plot for Scope
17 '''
17 '''
18
18
19 CODE = 'scope'
19 CODE = 'scope'
20 plot_name = 'Scope'
21 plot_type = 'scatter'
20 plot_type = 'scatter'
22
21
23 def setup(self):
22 def setup(self):
24
23
25 self.xaxis = 'Range (Km)'
24 self.xaxis = 'Range (Km)'
26 self.ncols = 1
25 self.ncols = 1
27 self.nrows = 1
26 self.nrows = 1
28 self.nplots = 1
27 self.nplots = 1
29 self.ylabel = 'Intensity [dB]'
28 self.ylabel = 'Intensity [dB]'
30 self.titles = ['Scope']
29 self.titles = ['Scope']
31 self.colorbar = False
30 self.colorbar = False
32 self.width = 6
31 self.width = 6
33 self.height = 4
32 self.height = 4
34
33
35 def plot_iq(self, x, y, channelIndexList, thisDatetime, wintitle):
34 def plot_iq(self, x, y, channelIndexList, thisDatetime, wintitle):
36
35
37 yreal = y[channelIndexList,:].real
36 yreal = y[channelIndexList,:].real
38 yimag = y[channelIndexList,:].imag
37 yimag = y[channelIndexList,:].imag
39 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
38 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
40 self.xlabel = "Range (Km)"
39 self.xlabel = "Range (Km)"
41 self.ylabel = "Intensity - IQ"
40 self.ylabel = "Intensity - IQ"
42
41
43 self.y = yreal
42 self.y = yreal
44 self.x = x
43 self.x = x
45 self.xmin = min(x)
44 self.xmin = min(x)
46 self.xmax = max(x)
45 self.xmax = max(x)
47
46
48
47
49 self.titles[0] = title
48 self.titles[0] = title
50
49
51 for i,ax in enumerate(self.axes):
50 for i,ax in enumerate(self.axes):
52 title = "Channel %d" %(i)
51 title = "Channel %d" %(i)
53 if ax.firsttime:
52 if ax.firsttime:
54 ax.plt_r = ax.plot(x, yreal[i,:], color='b')[0]
53 ax.plt_r = ax.plot(x, yreal[i,:], color='b')[0]
55 ax.plt_i = ax.plot(x, yimag[i,:], color='r')[0]
54 ax.plt_i = ax.plot(x, yimag[i,:], color='r')[0]
56 else:
55 else:
57 ax.plt_r.set_data(x, yreal[i,:])
56 ax.plt_r.set_data(x, yreal[i,:])
58 ax.plt_i.set_data(x, yimag[i,:])
57 ax.plt_i.set_data(x, yimag[i,:])
59
58
60 def plot_power(self, x, y, channelIndexList, thisDatetime, wintitle):
59 def plot_power(self, x, y, channelIndexList, thisDatetime, wintitle):
61 y = y[channelIndexList,:] * numpy.conjugate(y[channelIndexList,:])
60 y = y[channelIndexList,:] * numpy.conjugate(y[channelIndexList,:])
62 yreal = y.real
61 yreal = y.real
63 yreal = 10*numpy.log10(yreal)
62 yreal = 10*numpy.log10(yreal)
64 self.y = yreal
63 self.y = yreal
65 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
64 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
66 self.xlabel = "Range (Km)"
65 self.xlabel = "Range (Km)"
67 self.ylabel = "Intensity"
66 self.ylabel = "Intensity"
68 self.xmin = min(x)
67 self.xmin = min(x)
69 self.xmax = max(x)
68 self.xmax = max(x)
70
69
71
70
72 self.titles[0] = title
71 self.titles[0] = title
73
72
74 for i,ax in enumerate(self.axes):
73 for i,ax in enumerate(self.axes):
75 title = "Channel %d" %(i)
74 title = "Channel %d" %(i)
76
75
77 ychannel = yreal[i,:]
76 ychannel = yreal[i,:]
78
77
79 if ax.firsttime:
78 if ax.firsttime:
80 ax.plt_r = ax.plot(x, ychannel)[0]
79 ax.plt_r = ax.plot(x, ychannel)[0]
81 else:
80 else:
82 #pass
81 #pass
83 ax.plt_r.set_data(x, ychannel)
82 ax.plt_r.set_data(x, ychannel)
84
83
85 def plot_weatherpower(self, x, y, channelIndexList, thisDatetime, wintitle):
84 def plot_weatherpower(self, x, y, channelIndexList, thisDatetime, wintitle):
86
85
87
86
88 y = y[channelIndexList,:]
87 y = y[channelIndexList,:]
89 yreal = y.real
88 yreal = y.real
90 yreal = 10*numpy.log10(yreal)
89 yreal = 10*numpy.log10(yreal)
91 self.y = yreal
90 self.y = yreal
92 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
91 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
93 self.xlabel = "Range (Km)"
92 self.xlabel = "Range (Km)"
94 self.ylabel = "Intensity"
93 self.ylabel = "Intensity"
95 self.xmin = min(x)
94 self.xmin = min(x)
96 self.xmax = max(x)
95 self.xmax = max(x)
97
96
98 self.titles[0] =title
97 self.titles[0] =title
99 for i,ax in enumerate(self.axes):
98 for i,ax in enumerate(self.axes):
100 title = "Channel %d" %(i)
99 title = "Channel %d" %(i)
101
100
102 ychannel = yreal[i,:]
101 ychannel = yreal[i,:]
103
102
104 if ax.firsttime:
103 if ax.firsttime:
105 ax.plt_r = ax.plot(x, ychannel)[0]
104 ax.plt_r = ax.plot(x, ychannel)[0]
106 else:
105 else:
107 #pass
106 #pass
108 ax.plt_r.set_data(x, ychannel)
107 ax.plt_r.set_data(x, ychannel)
109
108
110 def plot_weathervelocity(self, x, y, channelIndexList, thisDatetime, wintitle):
109 def plot_weathervelocity(self, x, y, channelIndexList, thisDatetime, wintitle):
111
110
112 x = x[channelIndexList,:]
111 x = x[channelIndexList,:]
113 yreal = y
112 yreal = y
114 self.y = yreal
113 self.y = yreal
115 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
114 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
116 self.xlabel = "Velocity (m/s)"
115 self.xlabel = "Velocity (m/s)"
117 self.ylabel = "Range (Km)"
116 self.ylabel = "Range (Km)"
118 self.xmin = numpy.min(x)
117 self.xmin = numpy.min(x)
119 self.xmax = numpy.max(x)
118 self.xmax = numpy.max(x)
120 self.titles[0] =title
119 self.titles[0] =title
121 for i,ax in enumerate(self.axes):
120 for i,ax in enumerate(self.axes):
122 title = "Channel %d" %(i)
121 title = "Channel %d" %(i)
123 xchannel = x[i,:]
122 xchannel = x[i,:]
124 if ax.firsttime:
123 if ax.firsttime:
125 ax.plt_r = ax.plot(xchannel, yreal)[0]
124 ax.plt_r = ax.plot(xchannel, yreal)[0]
126 else:
125 else:
127 #pass
126 #pass
128 ax.plt_r.set_data(xchannel, yreal)
127 ax.plt_r.set_data(xchannel, yreal)
129
128
130 def plot_weatherspecwidth(self, x, y, channelIndexList, thisDatetime, wintitle):
129 def plot_weatherspecwidth(self, x, y, channelIndexList, thisDatetime, wintitle):
131
130
132 x = x[channelIndexList,:]
131 x = x[channelIndexList,:]
133 yreal = y
132 yreal = y
134 self.y = yreal
133 self.y = yreal
135 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
134 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y %H:%M:%S"))
136 self.xlabel = "width "
135 self.xlabel = "width "
137 self.ylabel = "Range (Km)"
136 self.ylabel = "Range (Km)"
138 self.xmin = numpy.min(x)
137 self.xmin = numpy.min(x)
139 self.xmax = numpy.max(x)
138 self.xmax = numpy.max(x)
140 self.titles[0] =title
139 self.titles[0] =title
141 for i,ax in enumerate(self.axes):
140 for i,ax in enumerate(self.axes):
142 title = "Channel %d" %(i)
141 title = "Channel %d" %(i)
143 xchannel = x[i,:]
142 xchannel = x[i,:]
144 if ax.firsttime:
143 if ax.firsttime:
145 ax.plt_r = ax.plot(xchannel, yreal)[0]
144 ax.plt_r = ax.plot(xchannel, yreal)[0]
146 else:
145 else:
147 #pass
146 #pass
148 ax.plt_r.set_data(xchannel, yreal)
147 ax.plt_r.set_data(xchannel, yreal)
149
148
150 def plot(self):
149 def plot(self):
151 if self.channels:
150 if self.channels:
152 channels = self.channels
151 channels = self.channels
153 else:
152 else:
154 channels = self.data.channels
153 channels = self.data.channels
155
154
156 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
155 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
157 if self.CODE == "pp_power":
156 if self.CODE == "pp_power":
158 scope = self.data['pp_power']
157 scope = self.data['pp_power']
159 elif self.CODE == "pp_signal":
158 elif self.CODE == "pp_signal":
160 scope = self.data["pp_signal"]
159 scope = self.data["pp_signal"]
161 elif self.CODE == "pp_velocity":
160 elif self.CODE == "pp_velocity":
162 scope = self.data["pp_velocity"]
161 scope = self.data["pp_velocity"]
163 elif self.CODE == "pp_specwidth":
162 elif self.CODE == "pp_specwidth":
164 scope = self.data["pp_specwidth"]
163 scope = self.data["pp_specwidth"]
165 else:
164 else:
166 scope =self.data["scope"]
165 scope =self.data["scope"]
167
166
168 if self.data.flagDataAsBlock:
167 if self.data.flagDataAsBlock:
169
168
170 for i in range(self.data.nProfiles):
169 for i in range(self.data.nProfiles):
171
170
172 wintitle1 = " [Profile = %d] " %i
171 wintitle1 = " [Profile = %d] " %i
173 if self.CODE =="scope":
172 if self.CODE =="scope":
174 if self.type == "power":
173 if self.type == "power":
175 self.plot_power(self.data.heights,
174 self.plot_power(self.data.heights,
176 scope[:,i,:],
175 scope[:,i,:],
177 channels,
176 channels,
178 thisDatetime,
177 thisDatetime,
179 wintitle1
178 wintitle1
180 )
179 )
181
180
182 if self.type == "iq":
181 if self.type == "iq":
183 self.plot_iq(self.data.heights,
182 self.plot_iq(self.data.heights,
184 scope[:,i,:],
183 scope[:,i,:],
185 channels,
184 channels,
186 thisDatetime,
185 thisDatetime,
187 wintitle1
186 wintitle1
188 )
187 )
189 if self.CODE=="pp_power":
188 if self.CODE=="pp_power":
190 self.plot_weatherpower(self.data.heights,
189 self.plot_weatherpower(self.data.heights,
191 scope[:,i,:],
190 scope[:,i,:],
192 channels,
191 channels,
193 thisDatetime,
192 thisDatetime,
194 wintitle
193 wintitle
195 )
194 )
196 if self.CODE=="pp_signal":
195 if self.CODE=="pp_signal":
197 self.plot_weatherpower(self.data.heights,
196 self.plot_weatherpower(self.data.heights,
198 scope[:,i,:],
197 scope[:,i,:],
199 channels,
198 channels,
200 thisDatetime,
199 thisDatetime,
201 wintitle
200 wintitle
202 )
201 )
203 if self.CODE=="pp_velocity":
202 if self.CODE=="pp_velocity":
204 self.plot_weathervelocity(scope[:,i,:],
203 self.plot_weathervelocity(scope[:,i,:],
205 self.data.heights,
204 self.data.heights,
206 channels,
205 channels,
207 thisDatetime,
206 thisDatetime,
208 wintitle
207 wintitle
209 )
208 )
210 if self.CODE=="pp_spcwidth":
209 if self.CODE=="pp_spcwidth":
211 self.plot_weatherspecwidth(scope[:,i,:],
210 self.plot_weatherspecwidth(scope[:,i,:],
212 self.data.heights,
211 self.data.heights,
213 channels,
212 channels,
214 thisDatetime,
213 thisDatetime,
215 wintitle
214 wintitle
216 )
215 )
217 else:
216 else:
218 wintitle = " [Profile = %d] " %self.data.profileIndex
217 wintitle = " [Profile = %d] " %self.data.profileIndex
219 if self.CODE== "scope":
218 if self.CODE== "scope":
220 if self.type == "power":
219 if self.type == "power":
221 self.plot_power(self.data.heights,
220 self.plot_power(self.data.heights,
222 scope,
221 scope,
223 channels,
222 channels,
224 thisDatetime,
223 thisDatetime,
225 wintitle
224 wintitle
226 )
225 )
227
226
228 if self.type == "iq":
227 if self.type == "iq":
229 self.plot_iq(self.data.heights,
228 self.plot_iq(self.data.heights,
230 scope,
229 scope,
231 channels,
230 channels,
232 thisDatetime,
231 thisDatetime,
233 wintitle
232 wintitle
234 )
233 )
235 if self.CODE=="pp_power":
234 if self.CODE=="pp_power":
236 self.plot_weatherpower(self.data.heights,
235 self.plot_weatherpower(self.data.heights,
237 scope,
236 scope,
238 channels,
237 channels,
239 thisDatetime,
238 thisDatetime,
240 wintitle
239 wintitle
241 )
240 )
242 if self.CODE=="pp_signal":
241 if self.CODE=="pp_signal":
243 self.plot_weatherpower(self.data.heights,
242 self.plot_weatherpower(self.data.heights,
244 scope,
243 scope,
245 channels,
244 channels,
246 thisDatetime,
245 thisDatetime,
247 wintitle
246 wintitle
248 )
247 )
249 if self.CODE=="pp_velocity":
248 if self.CODE=="pp_velocity":
250 self.plot_weathervelocity(scope,
249 self.plot_weathervelocity(scope,
251 self.data.heights,
250 self.data.heights,
252 channels,
251 channels,
253 thisDatetime,
252 thisDatetime,
254 wintitle
253 wintitle
255 )
254 )
256 if self.CODE=="pp_specwidth":
255 if self.CODE=="pp_specwidth":
257 self.plot_weatherspecwidth(scope,
256 self.plot_weatherspecwidth(scope,
258 self.data.heights,
257 self.data.heights,
259 channels,
258 channels,
260 thisDatetime,
259 thisDatetime,
261 wintitle
260 wintitle
262 )
261 )
263
262
264
263
265
264
266 class PulsepairPowerPlot(ScopePlot):
265 class PulsepairPowerPlot(ScopePlot):
267 '''
266 '''
268 Plot for P= S+N
267 Plot for P= S+N
269 '''
268 '''
270
269
271 CODE = 'pp_power'
270 CODE = 'pp_power'
272 plot_name = 'PulsepairPower'
273 plot_type = 'scatter'
271 plot_type = 'scatter'
274 buffering = False
272 buffering = False
275
273
276 class PulsepairVelocityPlot(ScopePlot):
274 class PulsepairVelocityPlot(ScopePlot):
277 '''
275 '''
278 Plot for VELOCITY
276 Plot for VELOCITY
279 '''
277 '''
280 CODE = 'pp_velocity'
278 CODE = 'pp_velocity'
281 plot_name = 'PulsepairVelocity'
282 plot_type = 'scatter'
279 plot_type = 'scatter'
283 buffering = False
280 buffering = False
284
281
285 class PulsepairSpecwidthPlot(ScopePlot):
282 class PulsepairSpecwidthPlot(ScopePlot):
286 '''
283 '''
287 Plot for WIDTH
284 Plot for WIDTH
288 '''
285 '''
289 CODE = 'pp_specwidth'
286 CODE = 'pp_specwidth'
290 plot_name = 'PulsepairSpecwidth'
291 plot_type = 'scatter'
287 plot_type = 'scatter'
292 buffering = False
288 buffering = False
293
289
294 class PulsepairSignalPlot(ScopePlot):
290 class PulsepairSignalPlot(ScopePlot):
295 '''
291 '''
296 Plot for S
292 Plot for S
297 '''
293 '''
298
294
299 CODE = 'pp_signal'
295 CODE = 'pp_signal'
300 plot_name = 'PulsepairSignal'
301 plot_type = 'scatter'
296 plot_type = 'scatter'
302 buffering = False
297 buffering = False
@@ -1,326 +1,351
1 '''
1 # Copyright (c) 2012-2020 Jicamarca Radio Observatory
2 @author: Juan C. Espinoza
2 # All rights reserved.
3 '''
3 #
4 # Distributed under the terms of the BSD 3-clause license.
5 """Utilities for publish/send data, files & plots over different protocols
6 """
4
7
5 import os
8 import os
6 import glob
9 import glob
7 import time
10 import time
8 import json
11 import json
9 import numpy
12 import numpy
10 import zmq
13 import zmq
11 import datetime
14 import datetime
12 import ftplib
15 import ftplib
13 from functools import wraps
16 from functools import wraps
14 from threading import Thread
17 from threading import Thread
15 from multiprocessing import Process
18 from multiprocessing import Process
16
19
17 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit, MPDecorator
20 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit, MPDecorator
18 from schainpy.model.data.jrodata import JROData
21 from schainpy.model.data.jrodata import JROData
19 from schainpy.utils import log
22 from schainpy.utils import log
20
23
21 MAXNUMX = 500
22 MAXNUMY = 500
23
24
24 PLOT_CODES = {
25 PLOT_CODES = {
25 'rti': 0, # Range time intensity (RTI).
26 'rti': 0, # Range time intensity (RTI).
26 'spc': 1, # Spectra (and Cross-spectra) information.
27 'spc': 1, # Spectra (and Cross-spectra) information.
27 'cspc': 2, # Cross-Correlation information.
28 'cspc': 2, # Cross-Correlation information.
28 'coh': 3, # Coherence map.
29 'coh': 3, # Coherence map.
29 'base': 4, # Base lines graphic.
30 'base': 4, # Base lines graphic.
30 'row': 5, # Row Spectra.
31 'row': 5, # Row Spectra.
31 'total': 6, # Total Power.
32 'total': 6, # Total Power.
32 'drift': 7, # Drifts graphics.
33 'drift': 7, # Drifts graphics.
33 'height': 8, # Height profile.
34 'height': 8, # Height profile.
34 'phase': 9, # Signal Phase.
35 'phase': 9, # Signal Phase.
35 'power': 16,
36 'power': 16,
36 'noise': 17,
37 'noise': 17,
37 'beacon': 18,
38 'beacon': 18,
38 'wind': 22,
39 'wind': 22,
39 'skymap': 23,
40 'skymap': 23,
40 'Unknown': 24,
41 'Unknown': 24,
41 'V-E': 25, # PIP Velocity.
42 'V-E': 25, # PIP Velocity.
42 'Z-E': 26, # PIP Reflectivity.
43 'Z-E': 26, # PIP Reflectivity.
43 'V-A': 27, # RHI Velocity.
44 'V-A': 27, # RHI Velocity.
44 'Z-A': 28, # RHI Reflectivity.
45 'Z-A': 28, # RHI Reflectivity.
45 }
46 }
46
47
47 def get_plot_code(s):
48 def get_plot_code(s):
48 label = s.split('_')[0]
49 label = s.split('_')[0]
49 codes = [key for key in PLOT_CODES if key in label]
50 codes = [key for key in PLOT_CODES if key in label]
50 if codes:
51 if codes:
51 return PLOT_CODES[codes[0]]
52 return PLOT_CODES[codes[0]]
52 else:
53 else:
53 return 24
54 return 24
54
55
55 def decimate(z, MAXNUMY):
56 dy = int(len(z[0])/MAXNUMY) + 1
57
58 return z[::, ::dy]
59
60
56
61 class PublishData(Operation):
57 class PublishData(Operation):
62 '''
58 '''
63 Operation to send data over zmq.
59 Operation to send data over zmq.
64 '''
60 '''
65
61
66 __attrs__ = ['host', 'port', 'delay', 'verbose']
62 __attrs__ = ['host', 'port', 'delay', 'verbose']
67
63
68 def setup(self, server='zmq.pipe', delay=0, verbose=True, **kwargs):
64 def setup(self, server='zmq.pipe', delay=0, verbose=True, **kwargs):
69 self.counter = 0
65 self.counter = 0
70 self.delay = kwargs.get('delay', 0)
66 self.delay = kwargs.get('delay', 0)
71 self.cnt = 0
67 self.cnt = 0
72 self.verbose = verbose
68 self.verbose = verbose
73 context = zmq.Context()
69 context = zmq.Context()
74 self.zmq_socket = context.socket(zmq.PUSH)
70 self.zmq_socket = context.socket(zmq.PUSH)
75 server = kwargs.get('server', 'zmq.pipe')
71 server = kwargs.get('server', 'zmq.pipe')
76
72
77 if 'tcp://' in server:
73 if 'tcp://' in server:
78 address = server
74 address = server
79 else:
75 else:
80 address = 'ipc:///tmp/%s' % server
76 address = 'ipc:///tmp/%s' % server
81
77
82 self.zmq_socket.connect(address)
78 self.zmq_socket.connect(address)
83 time.sleep(1)
79 time.sleep(1)
84
80
85
81
86 def publish_data(self):
82 def publish_data(self):
87 self.dataOut.finished = False
83 self.dataOut.finished = False
88
84
89 if self.verbose:
85 if self.verbose:
90 log.log(
86 log.log(
91 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
87 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
92 self.name
88 self.name
93 )
89 )
94 self.zmq_socket.send_pyobj(self.dataOut)
90 self.zmq_socket.send_pyobj(self.dataOut)
95
91
96 def run(self, dataOut, **kwargs):
92 def run(self, dataOut, **kwargs):
97 self.dataOut = dataOut
93 self.dataOut = dataOut
98 if not self.isConfig:
94 if not self.isConfig:
99 self.setup(**kwargs)
95 self.setup(**kwargs)
100 self.isConfig = True
96 self.isConfig = True
101
97
102 self.publish_data()
98 self.publish_data()
103 time.sleep(self.delay)
99 time.sleep(self.delay)
104
100
105 def close(self):
101 def close(self):
106
102
107 self.dataOut.finished = True
103 self.dataOut.finished = True
108 self.zmq_socket.send_pyobj(self.dataOut)
104 self.zmq_socket.send_pyobj(self.dataOut)
109 time.sleep(0.1)
105 time.sleep(0.1)
110 self.zmq_socket.close()
106 self.zmq_socket.close()
111
107
112
108
113 class ReceiverData(ProcessingUnit):
109 class ReceiverData(ProcessingUnit):
114
110
115 __attrs__ = ['server']
111 __attrs__ = ['server']
116
112
117 def __init__(self, **kwargs):
113 def __init__(self, **kwargs):
118
114
119 ProcessingUnit.__init__(self, **kwargs)
115 ProcessingUnit.__init__(self, **kwargs)
120
116
121 self.isConfig = False
117 self.isConfig = False
122 server = kwargs.get('server', 'zmq.pipe')
118 server = kwargs.get('server', 'zmq.pipe')
123 if 'tcp://' in server:
119 if 'tcp://' in server:
124 address = server
120 address = server
125 else:
121 else:
126 address = 'ipc:///tmp/%s' % server
122 address = 'ipc:///tmp/%s' % server
127
123
128 self.address = address
124 self.address = address
129 self.dataOut = JROData()
125 self.dataOut = JROData()
130
126
131 def setup(self):
127 def setup(self):
132
128
133 self.context = zmq.Context()
129 self.context = zmq.Context()
134 self.receiver = self.context.socket(zmq.PULL)
130 self.receiver = self.context.socket(zmq.PULL)
135 self.receiver.bind(self.address)
131 self.receiver.bind(self.address)
136 time.sleep(0.5)
132 time.sleep(0.5)
137 log.success('ReceiverData from {}'.format(self.address))
133 log.success('ReceiverData from {}'.format(self.address))
138
134
139
135
140 def run(self):
136 def run(self):
141
137
142 if not self.isConfig:
138 if not self.isConfig:
143 self.setup()
139 self.setup()
144 self.isConfig = True
140 self.isConfig = True
145
141
146 self.dataOut = self.receiver.recv_pyobj()
142 self.dataOut = self.receiver.recv_pyobj()
147 log.log('{} - {}'.format(self.dataOut.type,
143 log.log('{} - {}'.format(self.dataOut.type,
148 self.dataOut.datatime.ctime(),),
144 self.dataOut.datatime.ctime(),),
149 'Receiving')
145 'Receiving')
150
146
151 @MPDecorator
147 @MPDecorator
152 class SendToFTP(Operation):
148 class SendToFTP(Operation):
149 """Operation for send files over FTP
150
151 This operation is used to send files over FTP, you can send different files
152 from different folders by adding as many `pattern` as you wish.
153
154 Parameters:
155 -----------
156 server : str
157 FTP server address.
158 username : str
159 FTP username
160 password : str
161 FTP password
162 timeout : int
163 timeout to restart the connection
164 patternX : list
165 detail of files to be send must have the following order: local, remote
166 ext, period, exp_code, sub_exp_code
167
168 Example:
169 --------
170
171 ftp = proc_unit.addOperation(name='SendToFTP', optype='external')
172 ftp.addParameter(name='server', value='jro-app.igp.gob.pe')
173 ftp.addParameter(name='username', value='wmaster')
174 ftp.addParameter(name='password', value='mst2010vhf')
175 ftp.addParameter(
176 name='pattern1',
177 value='/local/path/rti,/remote/path,png,300,11,0'
178 )
179 ftp.addParameter(
180 name='pattern2',
181 value='/local/path/spc,/remote/path,png,300,11,0'
182 )
183 ftp.addParameter(
184 name='pattern3',
185 value='/local/path/param,/remote/path,hdf5,300,,'
186 )
153
187
154 '''
188 """
155 Operation to send data over FTP.
156 patternX = 'local, remote, ext, period, exp_code, sub_exp_code'
157 '''
158
189
159 __attrs__ = ['server', 'username', 'password', 'timeout', 'patternX']
190 __attrs__ = ['server', 'username', 'password', 'timeout', 'patternX']
160
191
161 def __init__(self):
192 def __init__(self):
162 '''
193 '''
163 '''
194 '''
164 Operation.__init__(self)
195 Operation.__init__(self)
165 self.ftp = None
196 self.ftp = None
166 self.ready = False
197 self.ready = False
167
198
168 def setup(self, server, username, password, timeout, **kwargs):
199 def setup(self, server, username, password, timeout, **kwargs):
169 '''
200 '''
170 '''
201 '''
171
202
172 self.server = server
203 self.server = server
173 self.username = username
204 self.username = username
174 self.password = password
205 self.password = password
175 self.timeout = timeout
206 self.timeout = timeout
176 self.patterns = []
207 self.patterns = []
177 self.times = []
208 self.times = []
178 self.latest = []
209 self.latest = []
179 for arg, value in kwargs.items():
210 for arg, value in kwargs.items():
180 if 'pattern' in arg:
211 if 'pattern' in arg:
181 self.patterns.append(value)
212 self.patterns.append(value)
182 self.times.append(time.time())
213 self.times.append(0)
183 self.latest.append('')
214 self.latest.append('')
184
215
185 def connect(self):
216 def connect(self):
186 '''
217 '''
187 '''
218 '''
188
219
189 log.log('Connecting to ftp://{}'.format(self.server), self.name)
220 log.log('Connecting to ftp://{}'.format(self.server), self.name)
190 try:
221 try:
191 self.ftp = ftplib.FTP(self.server, timeout=self.timeout)
222 self.ftp = ftplib.FTP(self.server, timeout=self.timeout)
192 except ftplib.all_errors:
223 except ftplib.all_errors:
193 log.error('Server connection fail: {}'.format(self.server), self.name)
224 log.error('Server connection fail: {}'.format(self.server), self.name)
194 if self.ftp is not None:
225 if self.ftp is not None:
195 self.ftp.close()
226 self.ftp.close()
196 self.ftp = None
227 self.ftp = None
197 self.ready = False
228 self.ready = False
198 return
229 return
199
230
200 try:
231 try:
201 self.ftp.login(self.username, self.password)
232 self.ftp.login(self.username, self.password)
202 except ftplib.all_errors:
233 except ftplib.all_errors:
203 log.error('The given username y/o password are incorrect', self.name)
234 log.error('The given username y/o password are incorrect', self.name)
204 if self.ftp is not None:
235 if self.ftp is not None:
205 self.ftp.close()
236 self.ftp.close()
206 self.ftp = None
237 self.ftp = None
207 self.ready = False
238 self.ready = False
208 return
239 return
209
240
210 log.success('Connection success', self.name)
241 log.success('Connection success', self.name)
211 self.ready = True
242 self.ready = True
212 return
243 return
213
244
214 def check(self):
245 def check(self):
215
246
216 try:
247 try:
217 self.ftp.voidcmd("NOOP")
248 self.ftp.voidcmd("NOOP")
218 except:
249 except:
219 log.warning('Connection lost... trying to reconnect', self.name)
250 log.warning('Connection lost... trying to reconnect', self.name)
220 if self.ftp is not None:
251 if self.ftp is not None:
221 self.ftp.close()
252 self.ftp.close()
222 self.ftp = None
253 self.ftp = None
223 self.connect()
254 self.connect()
224
255
225 def find_files(self, path, ext):
256 def find_files(self, path, ext):
226
257
227 files = glob.glob1(path, '*{}'.format(ext))
258 files = glob.glob1(path.strip(), '*{}'.format(ext.strip()))
228 files.sort()
259 files.sort()
229 if files:
260 if files:
230 return files[-1]
261 return files[-1]
231 return None
262 return None
232
263
233 def getftpname(self, filename, exp_code, sub_exp_code):
264 def getftpname(self, filename, exp_code, sub_exp_code):
234
265
235 thisDatetime = datetime.datetime.strptime(filename.split('_')[1], '%Y%m%d')
266 thisDatetime = datetime.datetime.strptime(filename.split('_')[1], '%Y%m%d')
236 YEAR_STR = '%4.4d' % thisDatetime.timetuple().tm_year
267 YEAR_STR = '%4.4d' % thisDatetime.timetuple().tm_year
237 DOY_STR = '%3.3d' % thisDatetime.timetuple().tm_yday
268 DOY_STR = '%3.3d' % thisDatetime.timetuple().tm_yday
238 exp_code = '%3.3d' % exp_code
269 exp_code = '%3.3d' % exp_code
239 sub_exp_code = '%2.2d' % sub_exp_code
270 sub_exp_code = '%2.2d' % sub_exp_code
240 plot_code = '%2.2d' % get_plot_code(filename)
271 plot_code = '%2.2d' % get_plot_code(filename)
241 name = YEAR_STR + DOY_STR + '00' + exp_code + sub_exp_code + plot_code + '00.png'
272 name = YEAR_STR + DOY_STR + '00' + exp_code + sub_exp_code + plot_code + '00.png'
242 return name
273 return name
243
274
244 def upload(self, src, dst):
275 def upload(self, src, dst):
245
276
246 log.log('Uploading {} -> {} '.format(
277 log.log('Uploading {} -> {} '.format(
247 src.split('/')[-1], dst.split('/')[-1]),
278 src.split('/')[-1], dst.split('/')[-1]),
248 self.name,
279 self.name,
249 nl=False
280 nl=False
250 )
281 )
251
282
252 fp = open(src, 'rb')
283 fp = open(src, 'rb')
253 command = 'STOR {}'.format(dst)
284 command = 'STOR {}'.format(dst)
254
285
255 try:
286 try:
256 self.ftp.storbinary(command, fp, blocksize=1024)
287 self.ftp.storbinary(command, fp, blocksize=1024)
257 except Exception as e:
288 except Exception as e:
258 log.error('{}'.format(e), self.name)
289 log.error('{}'.format(e), self.name)
259 if self.ftp is not None:
260 self.ftp.close()
261 self.ftp = None
262 return 0
290 return 0
263
291
264 try:
292 try:
265 self.ftp.sendcmd('SITE CHMOD 755 {}'.format(dst))
293 self.ftp.sendcmd('SITE CHMOD 755 {}'.format(dst))
266 except Exception as e:
294 except Exception as e:
267 log.error('{}'.format(e), self.name)
295 log.error('{}'.format(e), self.name)
268 if self.ftp is not None:
269 self.ftp.close()
270 self.ftp = None
271 return 0
296 return 0
272
297
273 fp.close()
298 fp.close()
274 log.success('OK', tag='')
299 log.success('OK', tag='')
275 return 1
300 return 1
276
301
277 def send_files(self):
302 def send_files(self):
278
303
279 for x, pattern in enumerate(self.patterns):
304 for x, pattern in enumerate(self.patterns):
280 local, remote, ext, period, exp_code, sub_exp_code = pattern
305 local, remote, ext, period, exp_code, sub_exp_code = pattern
281 if time.time()-self.times[x] >= int(period):
306
307 if (self.dataOut.utctime - self.times[x]) < int(period):
308 continue
309
282 srcname = self.find_files(local, ext)
310 srcname = self.find_files(local, ext)
283 src = os.path.join(local, srcname)
311
284 if os.path.getmtime(src) < time.time() - 30*60:
312 if srcname is None:
285 log.warning('Skipping old file {}'.format(srcname))
286 continue
313 continue
287
314
288 if srcname is None or srcname == self.latest[x]:
315 if srcname == self.latest[x]:
289 log.warning('File alreday uploaded {}'.format(srcname))
316 log.warning('File alreday uploaded {}'.format(srcname))
290 continue
317 continue
291
318
292 if 'png' in ext:
319 if exp_code.strip():
293 dstname = self.getftpname(srcname, int(exp_code), int(sub_exp_code))
320 dstname = self.getftpname(srcname, int(exp_code), int(sub_exp_code))
294 else:
321 else:
295 dstname = srcname
322 dstname = srcname
296
323
297 dst = os.path.join(remote, dstname)
324 src = os.path.join(local, srcname)
325 dst = os.path.join(remote.strip(), dstname)
298
326
299 if self.upload(src, dst):
327 if self.upload(src, dst):
300 self.times[x] = time.time()
328 self.times[x] = self.dataOut.utctime
301 self.latest[x] = srcname
329 self.latest[x] = srcname
302 else:
303 self.ready = False
304 break
305
330
306 def run(self, dataOut, server, username, password, timeout=10, **kwargs):
331 def run(self, dataOut, server, username, password, timeout=10, **kwargs):
307
332
308 if not self.isConfig:
333 if not self.isConfig:
309 self.setup(
334 self.setup(
310 server=server,
335 server=server,
311 username=username,
336 username=username,
312 password=password,
337 password=password,
313 timeout=timeout,
338 timeout=timeout,
314 **kwargs
339 **kwargs
315 )
340 )
316 self.isConfig = True
341 self.isConfig = True
317 if not self.ready:
318 self.connect()
342 self.connect()
319 if self.ftp is not None:
343
344 self.dataOut = dataOut
320 self.check()
345 self.check()
321 self.send_files()
346 self.send_files()
322
347
323 def close(self):
348 def close(self):
324
349
325 if self.ftp is not None:
350 if self.ftp is not None:
326 self.ftp.close()
351 self.ftp.close()
General Comments 0
You need to be logged in to leave comments. Login now