##// END OF EJS Templates
Fix SendToFTP operation for v3
Juan C. Espinoza -
r1209:53188d049ed7
parent child
Show More
@@ -1,747 +1,748
1 '''
1 '''
2 New Plots Operations
2 New Plots Operations
3
3
4 @author: juan.espinoza@jro.igp.gob.pe
4 @author: juan.espinoza@jro.igp.gob.pe
5 '''
5 '''
6
6
7
7
8 import time
8 import time
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 from schainpy.utils import log
13 from schainpy.utils import log
14
14
15 EARTH_RADIUS = 6.3710e3
15 EARTH_RADIUS = 6.3710e3
16
16
17
17
18 def ll2xy(lat1, lon1, lat2, lon2):
18 def ll2xy(lat1, lon1, lat2, lon2):
19
19
20 p = 0.017453292519943295
20 p = 0.017453292519943295
21 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
21 a = 0.5 - numpy.cos((lat2 - lat1) * p)/2 + numpy.cos(lat1 * p) * \
22 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
22 numpy.cos(lat2 * p) * (1 - numpy.cos((lon2 - lon1) * p)) / 2
23 r = 12742 * numpy.arcsin(numpy.sqrt(a))
23 r = 12742 * numpy.arcsin(numpy.sqrt(a))
24 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
24 theta = numpy.arctan2(numpy.sin((lon2-lon1)*p)*numpy.cos(lat2*p), numpy.cos(lat1*p)
25 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
25 * numpy.sin(lat2*p)-numpy.sin(lat1*p)*numpy.cos(lat2*p)*numpy.cos((lon2-lon1)*p))
26 theta = -theta + numpy.pi/2
26 theta = -theta + numpy.pi/2
27 return r*numpy.cos(theta), r*numpy.sin(theta)
27 return r*numpy.cos(theta), r*numpy.sin(theta)
28
28
29
29
30 def km2deg(km):
30 def km2deg(km):
31 '''
31 '''
32 Convert distance in km to degrees
32 Convert distance in km to degrees
33 '''
33 '''
34
34
35 return numpy.rad2deg(km/EARTH_RADIUS)
35 return numpy.rad2deg(km/EARTH_RADIUS)
36
36
37
37
38 class SpectraPlot(Plot):
38 class SpectraPlot(Plot):
39 '''
39 '''
40 Plot for Spectra data
40 Plot for Spectra data
41 '''
41 '''
42
42
43 CODE = 'spc'
43 CODE = 'spc'
44 colormap = 'jro'
44 colormap = 'jro'
45
45
46 def setup(self):
46 def setup(self):
47 self.nplots = len(self.data.channels)
47 self.nplots = len(self.data.channels)
48 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
48 self.ncols = int(numpy.sqrt(self.nplots) + 0.9)
49 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
49 self.nrows = int((1.0 * self.nplots / self.ncols) + 0.9)
50 self.width = 3.4 * self.ncols
50 self.width = 3.4 * self.ncols
51 self.height = 3 * self.nrows
51 self.height = 3 * self.nrows
52 self.cb_label = 'dB'
52 self.cb_label = 'dB'
53 if self.showprofile:
53 if self.showprofile:
54 self.width += 0.8 * self.ncols
54 self.width += 0.8 * self.ncols
55
55
56 self.ylabel = 'Range [km]'
56 self.ylabel = 'Range [km]'
57
57
58 def plot(self):
58 def plot(self):
59 if self.xaxis == "frequency":
59 if self.xaxis == "frequency":
60 x = self.data.xrange[0]
60 x = self.data.xrange[0]
61 self.xlabel = "Frequency (kHz)"
61 self.xlabel = "Frequency (kHz)"
62 elif self.xaxis == "time":
62 elif self.xaxis == "time":
63 x = self.data.xrange[1]
63 x = self.data.xrange[1]
64 self.xlabel = "Time (ms)"
64 self.xlabel = "Time (ms)"
65 else:
65 else:
66 x = self.data.xrange[2]
66 x = self.data.xrange[2]
67 self.xlabel = "Velocity (m/s)"
67 self.xlabel = "Velocity (m/s)"
68
68
69 if self.CODE == 'spc_moments':
69 if self.CODE == 'spc_moments':
70 x = self.data.xrange[2]
70 x = self.data.xrange[2]
71 self.xlabel = "Velocity (m/s)"
71 self.xlabel = "Velocity (m/s)"
72
72
73 self.titles = []
73 self.titles = []
74
74
75 y = self.data.heights
75 y = self.data.heights
76 self.y = y
76 self.y = y
77 z = self.data['spc']
77 z = self.data['spc']
78
78
79 for n, ax in enumerate(self.axes):
79 for n, ax in enumerate(self.axes):
80 noise = self.data['noise'][n][-1]
80 noise = self.data['noise'][n][-1]
81 if self.CODE == 'spc_moments':
81 if self.CODE == 'spc_moments':
82 mean = self.data['moments'][n, :, 1, :][-1]
82 mean = self.data['moments'][n, :, 1, :][-1]
83 if ax.firsttime:
83 if ax.firsttime:
84 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
84 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
85 self.xmin = self.xmin if self.xmin else -self.xmax
85 self.xmin = self.xmin if self.xmin else -self.xmax
86 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
86 self.zmin = self.zmin if self.zmin else numpy.nanmin(z)
87 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
87 self.zmax = self.zmax if self.zmax else numpy.nanmax(z)
88 ax.plt = ax.pcolormesh(x, y, z[n].T,
88 ax.plt = ax.pcolormesh(x, y, z[n].T,
89 vmin=self.zmin,
89 vmin=self.zmin,
90 vmax=self.zmax,
90 vmax=self.zmax,
91 cmap=plt.get_cmap(self.colormap)
91 cmap=plt.get_cmap(self.colormap)
92 )
92 )
93
93
94 if self.showprofile:
94 if self.showprofile:
95 ax.plt_profile = self.pf_axes[n].plot(
95 ax.plt_profile = self.pf_axes[n].plot(
96 self.data['rti'][n][-1], y)[0]
96 self.data['rti'][n][-1], y)[0]
97 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
97 ax.plt_noise = self.pf_axes[n].plot(numpy.repeat(noise, len(y)), y,
98 color="k", linestyle="dashed", lw=1)[0]
98 color="k", linestyle="dashed", lw=1)[0]
99 if self.CODE == 'spc_moments':
99 if self.CODE == 'spc_moments':
100 ax.plt_mean = ax.plot(mean, y, color='k')[0]
100 ax.plt_mean = ax.plot(mean, y, color='k')[0]
101 else:
101 else:
102 ax.plt.set_array(z[n].T.ravel())
102 ax.plt.set_array(z[n].T.ravel())
103 if self.showprofile:
103 if self.showprofile:
104 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
104 ax.plt_profile.set_data(self.data['rti'][n][-1], y)
105 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
105 ax.plt_noise.set_data(numpy.repeat(noise, len(y)), y)
106 if self.CODE == 'spc_moments':
106 if self.CODE == 'spc_moments':
107 ax.plt_mean.set_data(mean, y)
107 ax.plt_mean.set_data(mean, y)
108 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
108 self.titles.append('CH {}: {:3.2f}dB'.format(n, noise))
109
109
110
110
111 class CrossSpectraPlot(Plot):
111 class CrossSpectraPlot(Plot):
112
112
113 CODE = 'cspc'
113 CODE = 'cspc'
114 colormap = 'jet'
114 colormap = 'jet'
115 zmin_coh = None
115 zmin_coh = None
116 zmax_coh = None
116 zmax_coh = None
117 zmin_phase = None
117 zmin_phase = None
118 zmax_phase = None
118 zmax_phase = None
119
119
120 def setup(self):
120 def setup(self):
121
121
122 self.ncols = 4
122 self.ncols = 4
123 self.nrows = len(self.data.pairs)
123 self.nrows = len(self.data.pairs)
124 self.nplots = self.nrows * 4
124 self.nplots = self.nrows * 4
125 self.width = 3.4 * self.ncols
125 self.width = 3.4 * self.ncols
126 self.height = 3 * self.nrows
126 self.height = 3 * self.nrows
127 self.ylabel = 'Range [km]'
127 self.ylabel = 'Range [km]'
128 self.showprofile = False
128 self.showprofile = False
129
129
130 def plot(self):
130 def plot(self):
131
131
132 if self.xaxis == "frequency":
132 if self.xaxis == "frequency":
133 x = self.data.xrange[0]
133 x = self.data.xrange[0]
134 self.xlabel = "Frequency (kHz)"
134 self.xlabel = "Frequency (kHz)"
135 elif self.xaxis == "time":
135 elif self.xaxis == "time":
136 x = self.data.xrange[1]
136 x = self.data.xrange[1]
137 self.xlabel = "Time (ms)"
137 self.xlabel = "Time (ms)"
138 else:
138 else:
139 x = self.data.xrange[2]
139 x = self.data.xrange[2]
140 self.xlabel = "Velocity (m/s)"
140 self.xlabel = "Velocity (m/s)"
141
141
142 self.titles = []
142 self.titles = []
143
143
144 y = self.data.heights
144 y = self.data.heights
145 self.y = y
145 self.y = y
146 spc = self.data['spc']
146 spc = self.data['spc']
147 cspc = self.data['cspc']
147 cspc = self.data['cspc']
148
148
149 for n in range(self.nrows):
149 for n in range(self.nrows):
150 noise = self.data['noise'][n][-1]
150 noise = self.data['noise'][n][-1]
151 pair = self.data.pairs[n]
151 pair = self.data.pairs[n]
152 ax = self.axes[4 * n]
152 ax = self.axes[4 * n]
153 spc0 = 10.*numpy.log10(spc[pair[0]]/self.data.factor)
153 spc0 = 10.*numpy.log10(spc[pair[0]]/self.data.factor)
154 if ax.firsttime:
154 if ax.firsttime:
155 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
155 self.xmax = self.xmax if self.xmax else numpy.nanmax(x)
156 self.xmin = self.xmin if self.xmin else -self.xmax
156 self.xmin = self.xmin if self.xmin else -self.xmax
157 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
157 self.zmin = self.zmin if self.zmin else numpy.nanmin(spc)
158 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
158 self.zmax = self.zmax if self.zmax else numpy.nanmax(spc)
159 ax.plt = ax.pcolormesh(x , y , spc0.T,
159 ax.plt = ax.pcolormesh(x , y , spc0.T,
160 vmin=self.zmin,
160 vmin=self.zmin,
161 vmax=self.zmax,
161 vmax=self.zmax,
162 cmap=plt.get_cmap(self.colormap)
162 cmap=plt.get_cmap(self.colormap)
163 )
163 )
164 else:
164 else:
165 ax.plt.set_array(spc0.T.ravel())
165 ax.plt.set_array(spc0.T.ravel())
166 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise))
166 self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise))
167
167
168 ax = self.axes[4 * n + 1]
168 ax = self.axes[4 * n + 1]
169 spc1 = 10.*numpy.log10(spc[pair[1]]/self.data.factor)
169 spc1 = 10.*numpy.log10(spc[pair[1]]/self.data.factor)
170 if ax.firsttime:
170 if ax.firsttime:
171 ax.plt = ax.pcolormesh(x , y, spc1.T,
171 ax.plt = ax.pcolormesh(x , y, spc1.T,
172 vmin=self.zmin,
172 vmin=self.zmin,
173 vmax=self.zmax,
173 vmax=self.zmax,
174 cmap=plt.get_cmap(self.colormap)
174 cmap=plt.get_cmap(self.colormap)
175 )
175 )
176 else:
176 else:
177 ax.plt.set_array(spc1.T.ravel())
177 ax.plt.set_array(spc1.T.ravel())
178 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise))
178 self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise))
179
179
180 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
180 out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]])
181 coh = numpy.abs(out)
181 coh = numpy.abs(out)
182 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
182 phase = numpy.arctan2(out.imag, out.real) * 180 / numpy.pi
183
183
184 ax = self.axes[4 * n + 2]
184 ax = self.axes[4 * n + 2]
185 if ax.firsttime:
185 if ax.firsttime:
186 ax.plt = ax.pcolormesh(x, y, coh.T,
186 ax.plt = ax.pcolormesh(x, y, coh.T,
187 vmin=0,
187 vmin=0,
188 vmax=1,
188 vmax=1,
189 cmap=plt.get_cmap(self.colormap_coh)
189 cmap=plt.get_cmap(self.colormap_coh)
190 )
190 )
191 else:
191 else:
192 ax.plt.set_array(coh.T.ravel())
192 ax.plt.set_array(coh.T.ravel())
193 self.titles.append(
193 self.titles.append(
194 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
194 'Coherence Ch{} * Ch{}'.format(pair[0], pair[1]))
195
195
196 ax = self.axes[4 * n + 3]
196 ax = self.axes[4 * n + 3]
197 if ax.firsttime:
197 if ax.firsttime:
198 ax.plt = ax.pcolormesh(x, y, phase.T,
198 ax.plt = ax.pcolormesh(x, y, phase.T,
199 vmin=-180,
199 vmin=-180,
200 vmax=180,
200 vmax=180,
201 cmap=plt.get_cmap(self.colormap_phase)
201 cmap=plt.get_cmap(self.colormap_phase)
202 )
202 )
203 else:
203 else:
204 ax.plt.set_array(phase.T.ravel())
204 ax.plt.set_array(phase.T.ravel())
205 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
205 self.titles.append('Phase CH{} * CH{}'.format(pair[0], pair[1]))
206
206
207
207
208 class SpectralMomentsPlot(SpectraPlot):
208 class SpectralMomentsPlot(SpectraPlot):
209 '''
209 '''
210 Plot for Spectral Moments
210 Plot for Spectral Moments
211 '''
211 '''
212 CODE = 'spc_moments'
212 CODE = 'spc_moments'
213 colormap = 'jro'
213 colormap = 'jro'
214
214
215
215
216 class RTIPlot(Plot):
216 class RTIPlot(Plot):
217 '''
217 '''
218 Plot for RTI data
218 Plot for RTI data
219 '''
219 '''
220
220
221 CODE = 'rti'
221 CODE = 'rti'
222 colormap = 'jro'
222 colormap = 'jro'
223
223
224 def setup(self):
224 def setup(self):
225 self.xaxis = 'time'
225 self.xaxis = 'time'
226 self.ncols = 1
226 self.ncols = 1
227 self.nrows = len(self.data.channels)
227 self.nrows = len(self.data.channels)
228 self.nplots = len(self.data.channels)
228 self.nplots = len(self.data.channels)
229 self.ylabel = 'Range [km]'
229 self.ylabel = 'Range [km]'
230 self.cb_label = 'dB'
230 self.cb_label = 'dB'
231 self.titles = ['{} Channel {}'.format(
231 self.titles = ['{} Channel {}'.format(
232 self.CODE.upper(), x) for x in range(self.nrows)]
232 self.CODE.upper(), x) for x in range(self.nrows)]
233
233
234 def plot(self):
234 def plot(self):
235 self.x = self.data.times
235 self.x = self.data.times
236 self.y = self.data.heights
236 self.y = self.data.heights
237 self.z = self.data[self.CODE]
237 self.z = self.data[self.CODE]
238 self.z = numpy.ma.masked_invalid(self.z)
238 self.z = numpy.ma.masked_invalid(self.z)
239
239
240 if self.decimation is None:
240 if self.decimation is None:
241 x, y, z = self.fill_gaps(self.x, self.y, self.z)
241 x, y, z = self.fill_gaps(self.x, self.y, self.z)
242 else:
242 else:
243 x, y, z = self.fill_gaps(*self.decimate())
243 x, y, z = self.fill_gaps(*self.decimate())
244
244
245 for n, ax in enumerate(self.axes):
245 for n, ax in enumerate(self.axes):
246 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
246 self.zmin = self.zmin if self.zmin else numpy.min(self.z)
247 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
247 self.zmax = self.zmax if self.zmax else numpy.max(self.z)
248 if ax.firsttime:
248 if ax.firsttime:
249 ax.plt = ax.pcolormesh(x, y, z[n].T,
249 ax.plt = ax.pcolormesh(x, y, z[n].T,
250 vmin=self.zmin,
250 vmin=self.zmin,
251 vmax=self.zmax,
251 vmax=self.zmax,
252 cmap=plt.get_cmap(self.colormap)
252 cmap=plt.get_cmap(self.colormap)
253 )
253 )
254 if self.showprofile:
254 if self.showprofile:
255 ax.plot_profile = self.pf_axes[n].plot(
255 ax.plot_profile = self.pf_axes[n].plot(
256 self.data['rti'][n][-1], self.y)[0]
256 self.data['rti'][n][-1], self.y)[0]
257 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
257 ax.plot_noise = self.pf_axes[n].plot(numpy.repeat(self.data['noise'][n][-1], len(self.y)), self.y,
258 color="k", linestyle="dashed", lw=1)[0]
258 color="k", linestyle="dashed", lw=1)[0]
259 else:
259 else:
260 ax.collections.remove(ax.collections[0])
260 ax.collections.remove(ax.collections[0])
261 ax.plt = ax.pcolormesh(x, y, z[n].T,
261 ax.plt = ax.pcolormesh(x, y, z[n].T,
262 vmin=self.zmin,
262 vmin=self.zmin,
263 vmax=self.zmax,
263 vmax=self.zmax,
264 cmap=plt.get_cmap(self.colormap)
264 cmap=plt.get_cmap(self.colormap)
265 )
265 )
266 if self.showprofile:
266 if self.showprofile:
267 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
267 ax.plot_profile.set_data(self.data['rti'][n][-1], self.y)
268 ax.plot_noise.set_data(numpy.repeat(
268 ax.plot_noise.set_data(numpy.repeat(
269 self.data['noise'][n][-1], len(self.y)), self.y)
269 self.data['noise'][n][-1], len(self.y)), self.y)
270
270
271
271
272 class CoherencePlot(RTIPlot):
272 class CoherencePlot(RTIPlot):
273 '''
273 '''
274 Plot for Coherence data
274 Plot for Coherence data
275 '''
275 '''
276
276
277 CODE = 'coh'
277 CODE = 'coh'
278
278
279 def setup(self):
279 def setup(self):
280 self.xaxis = 'time'
280 self.xaxis = 'time'
281 self.ncols = 1
281 self.ncols = 1
282 self.nrows = len(self.data.pairs)
282 self.nrows = len(self.data.pairs)
283 self.nplots = len(self.data.pairs)
283 self.nplots = len(self.data.pairs)
284 self.ylabel = 'Range [km]'
284 self.ylabel = 'Range [km]'
285 if self.CODE == 'coh':
285 if self.CODE == 'coh':
286 self.cb_label = ''
286 self.cb_label = ''
287 self.titles = [
287 self.titles = [
288 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
288 'Coherence Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
289 else:
289 else:
290 self.cb_label = 'Degrees'
290 self.cb_label = 'Degrees'
291 self.titles = [
291 self.titles = [
292 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
292 'Phase Map Ch{} * Ch{}'.format(x[0], x[1]) for x in self.data.pairs]
293
293
294
294
295 class PhasePlot(CoherencePlot):
295 class PhasePlot(CoherencePlot):
296 '''
296 '''
297 Plot for Phase map data
297 Plot for Phase map data
298 '''
298 '''
299
299
300 CODE = 'phase'
300 CODE = 'phase'
301 colormap = 'seismic'
301 colormap = 'seismic'
302
302
303
303
304 class NoisePlot(Plot):
304 class NoisePlot(Plot):
305 '''
305 '''
306 Plot for noise
306 Plot for noise
307 '''
307 '''
308
308
309 CODE = 'noise'
309 CODE = 'noise'
310
310
311 def setup(self):
311 def setup(self):
312 self.xaxis = 'time'
312 self.xaxis = 'time'
313 self.ncols = 1
313 self.ncols = 1
314 self.nrows = 1
314 self.nrows = 1
315 self.nplots = 1
315 self.nplots = 1
316 self.ylabel = 'Intensity [dB]'
316 self.ylabel = 'Intensity [dB]'
317 self.titles = ['Noise']
317 self.titles = ['Noise']
318 self.colorbar = False
318 self.colorbar = False
319
319
320 def plot(self):
320 def plot(self):
321
321
322 x = self.data.times
322 x = self.data.times
323 xmin = self.data.min_time
323 xmin = self.data.min_time
324 xmax = xmin + self.xrange * 60 * 60
324 xmax = xmin + self.xrange * 60 * 60
325 Y = self.data[self.CODE]
325 Y = self.data[self.CODE]
326
326
327 if self.axes[0].firsttime:
327 if self.axes[0].firsttime:
328 for ch in self.data.channels:
328 for ch in self.data.channels:
329 y = Y[ch]
329 y = Y[ch]
330 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
330 self.axes[0].plot(x, y, lw=1, label='Ch{}'.format(ch))
331 plt.legend()
331 plt.legend()
332 else:
332 else:
333 for ch in self.data.channels:
333 for ch in self.data.channels:
334 y = Y[ch]
334 y = Y[ch]
335 self.axes[0].lines[ch].set_data(x, y)
335 self.axes[0].lines[ch].set_data(x, y)
336
336
337 self.ymin = numpy.nanmin(Y) - 5
337 self.ymin = numpy.nanmin(Y) - 5
338 self.ymax = numpy.nanmax(Y) + 5
338 self.ymax = numpy.nanmax(Y) + 5
339
339
340
340
341 class SnrPlot(RTIPlot):
341 class SnrPlot(RTIPlot):
342 '''
342 '''
343 Plot for SNR Data
343 Plot for SNR Data
344 '''
344 '''
345
345
346 CODE = 'snr'
346 CODE = 'snr'
347 colormap = 'jet'
347 colormap = 'jet'
348
348
349
349
350 class DopplerPlot(RTIPlot):
350 class DopplerPlot(RTIPlot):
351 '''
351 '''
352 Plot for DOPPLER Data
352 Plot for DOPPLER Data
353 '''
353 '''
354
354
355 CODE = 'dop'
355 CODE = 'dop'
356 colormap = 'jet'
356 colormap = 'jet'
357
357
358
358
359 class SkyMapPlot(Plot):
359 class SkyMapPlot(Plot):
360 '''
360 '''
361 Plot for meteors detection data
361 Plot for meteors detection data
362 '''
362 '''
363
363
364 CODE = 'param'
364 CODE = 'param'
365
365
366 def setup(self):
366 def setup(self):
367
367
368 self.ncols = 1
368 self.ncols = 1
369 self.nrows = 1
369 self.nrows = 1
370 self.width = 7.2
370 self.width = 7.2
371 self.height = 7.2
371 self.height = 7.2
372 self.nplots = 1
372 self.nplots = 1
373 self.xlabel = 'Zonal Zenith Angle (deg)'
373 self.xlabel = 'Zonal Zenith Angle (deg)'
374 self.ylabel = 'Meridional Zenith Angle (deg)'
374 self.ylabel = 'Meridional Zenith Angle (deg)'
375 self.polar = True
375 self.polar = True
376 self.ymin = -180
376 self.ymin = -180
377 self.ymax = 180
377 self.ymax = 180
378 self.colorbar = False
378 self.colorbar = False
379
379
380 def plot(self):
380 def plot(self):
381
381
382 arrayParameters = numpy.concatenate(self.data['param'])
382 arrayParameters = numpy.concatenate(self.data['param'])
383 error = arrayParameters[:, -1]
383 error = arrayParameters[:, -1]
384 indValid = numpy.where(error == 0)[0]
384 indValid = numpy.where(error == 0)[0]
385 finalMeteor = arrayParameters[indValid, :]
385 finalMeteor = arrayParameters[indValid, :]
386 finalAzimuth = finalMeteor[:, 3]
386 finalAzimuth = finalMeteor[:, 3]
387 finalZenith = finalMeteor[:, 4]
387 finalZenith = finalMeteor[:, 4]
388
388
389 x = finalAzimuth * numpy.pi / 180
389 x = finalAzimuth * numpy.pi / 180
390 y = finalZenith
390 y = finalZenith
391
391
392 ax = self.axes[0]
392 ax = self.axes[0]
393
393
394 if ax.firsttime:
394 if ax.firsttime:
395 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
395 ax.plot = ax.plot(x, y, 'bo', markersize=5)[0]
396 else:
396 else:
397 ax.plot.set_data(x, y)
397 ax.plot.set_data(x, y)
398
398
399 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
399 dt1 = self.getDateTime(self.data.min_time).strftime('%y/%m/%d %H:%M:%S')
400 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
400 dt2 = self.getDateTime(self.data.max_time).strftime('%y/%m/%d %H:%M:%S')
401 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
401 title = 'Meteor Detection Sky Map\n %s - %s \n Number of events: %5.0f\n' % (dt1,
402 dt2,
402 dt2,
403 len(x))
403 len(x))
404 self.titles[0] = title
404 self.titles[0] = title
405
405
406
406
407 class ParametersPlot(RTIPlot):
407 class ParametersPlot(RTIPlot):
408 '''
408 '''
409 Plot for data_param object
409 Plot for data_param object
410 '''
410 '''
411
411
412 CODE = 'param'
412 CODE = 'param'
413 colormap = 'seismic'
413 colormap = 'seismic'
414
414
415 def setup(self):
415 def setup(self):
416 self.xaxis = 'time'
416 self.xaxis = 'time'
417 self.ncols = 1
417 self.ncols = 1
418 self.nrows = self.data.shape(self.CODE)[0]
418 self.nrows = self.data.shape(self.CODE)[0]
419 self.nplots = self.nrows
419 self.nplots = self.nrows
420 if self.showSNR:
420 if self.showSNR:
421 self.nrows += 1
421 self.nrows += 1
422 self.nplots += 1
422 self.nplots += 1
423
423
424 self.ylabel = 'Height [km]'
424 self.ylabel = 'Height [km]'
425 if not self.titles:
425 if not self.titles:
426 self.titles = self.data.parameters \
426 self.titles = self.data.parameters \
427 if self.data.parameters else ['Param {}'.format(x) for x in range(self.nrows)]
427 if self.data.parameters else ['Param {}'.format(x) for x in range(self.nrows)]
428 if self.showSNR:
428 if self.showSNR:
429 self.titles.append('SNR')
429 self.titles.append('SNR')
430
430
431 def plot(self):
431 def plot(self):
432 self.data.normalize_heights()
432 self.data.normalize_heights()
433 self.x = self.data.times
433 self.x = self.data.times
434 self.y = self.data.heights
434 self.y = self.data.heights
435 if self.showSNR:
435 if self.showSNR:
436 self.z = numpy.concatenate(
436 self.z = numpy.concatenate(
437 (self.data[self.CODE], self.data['snr'])
437 (self.data[self.CODE], self.data['snr'])
438 )
438 )
439 else:
439 else:
440 self.z = self.data[self.CODE]
440 self.z = self.data[self.CODE]
441
441
442 self.z = numpy.ma.masked_invalid(self.z)
442 self.z = numpy.ma.masked_invalid(self.z)
443
443
444 if self.decimation is None:
444 if self.decimation is None:
445 x, y, z = self.fill_gaps(self.x, self.y, self.z)
445 x, y, z = self.fill_gaps(self.x, self.y, self.z)
446 else:
446 else:
447 x, y, z = self.fill_gaps(*self.decimate())
447 x, y, z = self.fill_gaps(*self.decimate())
448
448
449 for n, ax in enumerate(self.axes):
449 for n, ax in enumerate(self.axes):
450
450
451 self.zmax = self.zmax if self.zmax is not None else numpy.max(
451 self.zmax = self.zmax if self.zmax is not None else numpy.max(
452 self.z[n])
452 self.z[n])
453 self.zmin = self.zmin if self.zmin is not None else numpy.min(
453 self.zmin = self.zmin if self.zmin is not None else numpy.min(
454 self.z[n])
454 self.z[n])
455
455
456 if ax.firsttime:
456 if ax.firsttime:
457 if self.zlimits is not None:
457 if self.zlimits is not None:
458 self.zmin, self.zmax = self.zlimits[n]
458 self.zmin, self.zmax = self.zlimits[n]
459
459
460 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
460 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
461 vmin=self.zmin,
461 vmin=self.zmin,
462 vmax=self.zmax,
462 vmax=self.zmax,
463 cmap=self.cmaps[n]
463 cmap=self.cmaps[n]
464 )
464 )
465 else:
465 else:
466 if self.zlimits is not None:
466 if self.zlimits is not None:
467 self.zmin, self.zmax = self.zlimits[n]
467 self.zmin, self.zmax = self.zlimits[n]
468 ax.collections.remove(ax.collections[0])
468 ax.collections.remove(ax.collections[0])
469 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
469 ax.plt = ax.pcolormesh(x, y, z[n].T * self.factors[n],
470 vmin=self.zmin,
470 vmin=self.zmin,
471 vmax=self.zmax,
471 vmax=self.zmax,
472 cmap=self.cmaps[n]
472 cmap=self.cmaps[n]
473 )
473 )
474
474
475
475
476 class OutputPlot(ParametersPlot):
476 class OutputPlot(ParametersPlot):
477 '''
477 '''
478 Plot data_output object
478 Plot data_output object
479 '''
479 '''
480
480
481 CODE = 'output'
481 CODE = 'output'
482 colormap = 'seismic'
482 colormap = 'seismic'
483
483
484
484
485 class PolarMapPlot(Plot):
485 class PolarMapPlot(Plot):
486 '''
486 '''
487 Plot for weather radar
487 Plot for weather radar
488 '''
488 '''
489
489
490 CODE = 'param'
490 CODE = 'param'
491 colormap = 'seismic'
491 colormap = 'seismic'
492
492
493 def setup(self):
493 def setup(self):
494 self.ncols = 1
494 self.ncols = 1
495 self.nrows = 1
495 self.nrows = 1
496 self.width = 9
496 self.width = 9
497 self.height = 8
497 self.height = 8
498 self.mode = self.data.meta['mode']
498 self.mode = self.data.meta['mode']
499 if self.channels is not None:
499 if self.channels is not None:
500 self.nplots = len(self.channels)
500 self.nplots = len(self.channels)
501 self.nrows = len(self.channels)
501 self.nrows = len(self.channels)
502 else:
502 else:
503 self.nplots = self.data.shape(self.CODE)[0]
503 self.nplots = self.data.shape(self.CODE)[0]
504 self.nrows = self.nplots
504 self.nrows = self.nplots
505 self.channels = list(range(self.nplots))
505 self.channels = list(range(self.nplots))
506 if self.mode == 'E':
506 if self.mode == 'E':
507 self.xlabel = 'Longitude'
507 self.xlabel = 'Longitude'
508 self.ylabel = 'Latitude'
508 self.ylabel = 'Latitude'
509 else:
509 else:
510 self.xlabel = 'Range (km)'
510 self.xlabel = 'Range (km)'
511 self.ylabel = 'Height (km)'
511 self.ylabel = 'Height (km)'
512 self.bgcolor = 'white'
512 self.bgcolor = 'white'
513 self.cb_labels = self.data.meta['units']
513 self.cb_labels = self.data.meta['units']
514 self.lat = self.data.meta['latitude']
514 self.lat = self.data.meta['latitude']
515 self.lon = self.data.meta['longitude']
515 self.lon = self.data.meta['longitude']
516 self.xmin, self.xmax = float(
516 self.xmin, self.xmax = float(
517 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
517 km2deg(self.xmin) + self.lon), float(km2deg(self.xmax) + self.lon)
518 self.ymin, self.ymax = float(
518 self.ymin, self.ymax = float(
519 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
519 km2deg(self.ymin) + self.lat), float(km2deg(self.ymax) + self.lat)
520 # self.polar = True
520 # self.polar = True
521
521
522 def plot(self):
522 def plot(self):
523
523
524 for n, ax in enumerate(self.axes):
524 for n, ax in enumerate(self.axes):
525 data = self.data['param'][self.channels[n]]
525 data = self.data['param'][self.channels[n]]
526
526
527 zeniths = numpy.linspace(
527 zeniths = numpy.linspace(
528 0, self.data.meta['max_range'], data.shape[1])
528 0, self.data.meta['max_range'], data.shape[1])
529 if self.mode == 'E':
529 if self.mode == 'E':
530 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
530 azimuths = -numpy.radians(self.data.heights)+numpy.pi/2
531 r, theta = numpy.meshgrid(zeniths, azimuths)
531 r, theta = numpy.meshgrid(zeniths, azimuths)
532 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
532 x, y = r*numpy.cos(theta)*numpy.cos(numpy.radians(self.data.meta['elevation'])), r*numpy.sin(
533 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
533 theta)*numpy.cos(numpy.radians(self.data.meta['elevation']))
534 x = km2deg(x) + self.lon
534 x = km2deg(x) + self.lon
535 y = km2deg(y) + self.lat
535 y = km2deg(y) + self.lat
536 else:
536 else:
537 azimuths = numpy.radians(self.data.heights)
537 azimuths = numpy.radians(self.data.heights)
538 r, theta = numpy.meshgrid(zeniths, azimuths)
538 r, theta = numpy.meshgrid(zeniths, azimuths)
539 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
539 x, y = r*numpy.cos(theta), r*numpy.sin(theta)
540 self.y = zeniths
540 self.y = zeniths
541
541
542 if ax.firsttime:
542 if ax.firsttime:
543 if self.zlimits is not None:
543 if self.zlimits is not None:
544 self.zmin, self.zmax = self.zlimits[n]
544 self.zmin, self.zmax = self.zlimits[n]
545 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
545 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
546 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
546 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
547 vmin=self.zmin,
547 vmin=self.zmin,
548 vmax=self.zmax,
548 vmax=self.zmax,
549 cmap=self.cmaps[n])
549 cmap=self.cmaps[n])
550 else:
550 else:
551 if self.zlimits is not None:
551 if self.zlimits is not None:
552 self.zmin, self.zmax = self.zlimits[n]
552 self.zmin, self.zmax = self.zlimits[n]
553 ax.collections.remove(ax.collections[0])
553 ax.collections.remove(ax.collections[0])
554 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
554 ax.plt = ax.pcolormesh( # r, theta, numpy.ma.array(data, mask=numpy.isnan(data)),
555 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
555 x, y, numpy.ma.array(data, mask=numpy.isnan(data)),
556 vmin=self.zmin,
556 vmin=self.zmin,
557 vmax=self.zmax,
557 vmax=self.zmax,
558 cmap=self.cmaps[n])
558 cmap=self.cmaps[n])
559
559
560 if self.mode == 'A':
560 if self.mode == 'A':
561 continue
561 continue
562
562
563 # plot district names
563 # plot district names
564 f = open('/data/workspace/schain_scripts/distrito.csv')
564 f = open('/data/workspace/schain_scripts/distrito.csv')
565 for line in f:
565 for line in f:
566 label, lon, lat = [s.strip() for s in line.split(',') if s]
566 label, lon, lat = [s.strip() for s in line.split(',') if s]
567 lat = float(lat)
567 lat = float(lat)
568 lon = float(lon)
568 lon = float(lon)
569 # ax.plot(lon, lat, '.b', ms=2)
569 # ax.plot(lon, lat, '.b', ms=2)
570 ax.text(lon, lat, label.decode('utf8'), ha='center',
570 ax.text(lon, lat, label.decode('utf8'), ha='center',
571 va='bottom', size='8', color='black')
571 va='bottom', size='8', color='black')
572
572
573 # plot limites
573 # plot limites
574 limites = []
574 limites = []
575 tmp = []
575 tmp = []
576 for line in open('/data/workspace/schain_scripts/lima.csv'):
576 for line in open('/data/workspace/schain_scripts/lima.csv'):
577 if '#' in line:
577 if '#' in line:
578 if tmp:
578 if tmp:
579 limites.append(tmp)
579 limites.append(tmp)
580 tmp = []
580 tmp = []
581 continue
581 continue
582 values = line.strip().split(',')
582 values = line.strip().split(',')
583 tmp.append((float(values[0]), float(values[1])))
583 tmp.append((float(values[0]), float(values[1])))
584 for points in limites:
584 for points in limites:
585 ax.add_patch(
585 ax.add_patch(
586 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
586 Polygon(points, ec='k', fc='none', ls='--', lw=0.5))
587
587
588 # plot Cuencas
588 # plot Cuencas
589 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
589 for cuenca in ('rimac', 'lurin', 'mala', 'chillon', 'chilca', 'chancay-huaral'):
590 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
590 f = open('/data/workspace/schain_scripts/{}.csv'.format(cuenca))
591 values = [line.strip().split(',') for line in f]
591 values = [line.strip().split(',') for line in f]
592 points = [(float(s[0]), float(s[1])) for s in values]
592 points = [(float(s[0]), float(s[1])) for s in values]
593 ax.add_patch(Polygon(points, ec='b', fc='none'))
593 ax.add_patch(Polygon(points, ec='b', fc='none'))
594
594
595 # plot grid
595 # plot grid
596 for r in (15, 30, 45, 60):
596 for r in (15, 30, 45, 60):
597 ax.add_artist(plt.Circle((self.lon, self.lat),
597 ax.add_artist(plt.Circle((self.lon, self.lat),
598 km2deg(r), color='0.6', fill=False, lw=0.2))
598 km2deg(r), color='0.6', fill=False, lw=0.2))
599 ax.text(
599 ax.text(
600 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
600 self.lon + (km2deg(r))*numpy.cos(60*numpy.pi/180),
601 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
601 self.lat + (km2deg(r))*numpy.sin(60*numpy.pi/180),
602 '{}km'.format(r),
602 '{}km'.format(r),
603 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
603 ha='center', va='bottom', size='8', color='0.6', weight='heavy')
604
604
605 if self.mode == 'E':
605 if self.mode == 'E':
606 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
606 title = 'El={}$^\circ$'.format(self.data.meta['elevation'])
607 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
607 label = 'E{:02d}'.format(int(self.data.meta['elevation']))
608 else:
608 else:
609 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
609 title = 'Az={}$^\circ$'.format(self.data.meta['azimuth'])
610 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
610 label = 'A{:02d}'.format(int(self.data.meta['azimuth']))
611
611
612 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
612 self.save_labels = ['{}-{}'.format(lbl, label) for lbl in self.labels]
613 self.titles = ['{} {}'.format(
613 self.titles = ['{} {}'.format(
614 self.data.parameters[x], title) for x in self.channels]
614 self.data.parameters[x], title) for x in self.channels]
615
615
616
616 class ScopePlot(Plot):
617 class ScopePlot(Plot):
617
618
618 '''
619 '''
619 Plot for Scope
620 Plot for Scope
620 '''
621 '''
621
622
622 CODE = 'scope'
623 CODE = 'scope'
623
624
624 def setup(self):
625 def setup(self):
625
626
626 self.xaxis = 'Range (Km)'
627 self.xaxis = 'Range (Km)'
627 self.ncols = 1
628 self.ncols = 1
628 self.nrows = 1
629 self.nrows = 1
629 self.nplots = 1
630 self.nplots = 1
630 self.ylabel = 'Intensity [dB]'
631 self.ylabel = 'Intensity [dB]'
631 self.titles = ['Scope']
632 self.titles = ['Scope']
632 self.colorbar = False
633 self.colorbar = False
633 colspan = 3
634 colspan = 3
634 rowspan = 1
635 rowspan = 1
635
636
636 def plot_iq(self, x, y, channelIndexList, thisDatetime, wintitle):
637 def plot_iq(self, x, y, channelIndexList, thisDatetime, wintitle):
637
638
638 yreal = y[channelIndexList,:].real
639 yreal = y[channelIndexList,:].real
639 yimag = y[channelIndexList,:].imag
640 yimag = y[channelIndexList,:].imag
640 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
641 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
641 self.xlabel = "Range (Km)"
642 self.xlabel = "Range (Km)"
642 self.ylabel = "Intensity - IQ"
643 self.ylabel = "Intensity - IQ"
643
644
644 self.y = yreal
645 self.y = yreal
645 self.x = x
646 self.x = x
646 self.xmin = min(x)
647 self.xmin = min(x)
647 self.xmax = max(x)
648 self.xmax = max(x)
648
649
649
650
650 self.titles[0] = title
651 self.titles[0] = title
651
652
652 for i,ax in enumerate(self.axes):
653 for i,ax in enumerate(self.axes):
653 title = "Channel %d" %(i)
654 title = "Channel %d" %(i)
654 if ax.firsttime:
655 if ax.firsttime:
655 ax.plt_r = ax.plot(x, yreal[i,:], color='b')[0]
656 ax.plt_r = ax.plot(x, yreal[i,:], color='b')[0]
656 ax.plt_i = ax.plot(x, yimag[i,:], color='r')[0]
657 ax.plt_i = ax.plot(x, yimag[i,:], color='r')[0]
657 else:
658 else:
658 #pass
659 #pass
659 ax.plt_r.set_data(x, yreal[i,:])
660 ax.plt_r.set_data(x, yreal[i,:])
660 ax.plt_i.set_data(x, yimag[i,:])
661 ax.plt_i.set_data(x, yimag[i,:])
661
662
662 def plot_power(self, x, y, channelIndexList, thisDatetime, wintitle):
663 def plot_power(self, x, y, channelIndexList, thisDatetime, wintitle):
663 y = y[channelIndexList,:] * numpy.conjugate(y[channelIndexList,:])
664 y = y[channelIndexList,:] * numpy.conjugate(y[channelIndexList,:])
664 yreal = y.real
665 yreal = y.real
665 self.y = yreal
666 self.y = yreal
666 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
667 title = wintitle + " Scope: %s" %(thisDatetime.strftime("%d-%b-%Y"))
667 self.xlabel = "Range (Km)"
668 self.xlabel = "Range (Km)"
668 self.ylabel = "Intensity"
669 self.ylabel = "Intensity"
669 self.xmin = min(x)
670 self.xmin = min(x)
670 self.xmax = max(x)
671 self.xmax = max(x)
671
672
672
673
673 self.titles[0] = title
674 self.titles[0] = title
674
675
675 for i,ax in enumerate(self.axes):
676 for i,ax in enumerate(self.axes):
676 title = "Channel %d" %(i)
677 title = "Channel %d" %(i)
677
678
678 ychannel = yreal[i,:]
679 ychannel = yreal[i,:]
679
680
680 if ax.firsttime:
681 if ax.firsttime:
681 ax.plt_r = ax.plot(x, ychannel)[0]
682 ax.plt_r = ax.plot(x, ychannel)[0]
682 else:
683 else:
683 #pass
684 #pass
684 ax.plt_r.set_data(x, ychannel)
685 ax.plt_r.set_data(x, ychannel)
685
686
686
687
687 def plot(self):
688 def plot(self):
688
689
689 if self.channels:
690 if self.channels:
690 channels = self.channels
691 channels = self.channels
691 else:
692 else:
692 channels = self.data.channels
693 channels = self.data.channels
693
694
694
695
695
696
696 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
697 thisDatetime = datetime.datetime.utcfromtimestamp(self.data.times[-1])
697
698
698 scope = self.data['scope']
699 scope = self.data['scope']
699
700
700
701
701 if self.data.flagDataAsBlock:
702 if self.data.flagDataAsBlock:
702
703
703 for i in range(self.data.nProfiles):
704 for i in range(self.data.nProfiles):
704
705
705 wintitle1 = " [Profile = %d] " %i
706 wintitle1 = " [Profile = %d] " %i
706
707
707 if self.type == "power":
708 if self.type == "power":
708 self.plot_power(self.data.heights,
709 self.plot_power(self.data.heights,
709 scope[:,i,:],
710 scope[:,i,:],
710 channels,
711 channels,
711 thisDatetime,
712 thisDatetime,
712 wintitle1
713 wintitle1
713 )
714 )
714
715
715 if self.type == "iq":
716 if self.type == "iq":
716 self.plot_iq(self.data.heights,
717 self.plot_iq(self.data.heights,
717 scope[:,i,:],
718 scope[:,i,:],
718 channels,
719 channels,
719 thisDatetime,
720 thisDatetime,
720 wintitle1
721 wintitle1
721 )
722 )
722
723
723
724
724
725
725
726
726
727
727 else:
728 else:
728 wintitle = " [Profile = %d] " %self.data.profileIndex
729 wintitle = " [Profile = %d] " %self.data.profileIndex
729
730
730 if self.type == "power":
731 if self.type == "power":
731 self.plot_power(self.data.heights,
732 self.plot_power(self.data.heights,
732 scope,
733 scope,
733 channels,
734 channels,
734 thisDatetime,
735 thisDatetime,
735 wintitle
736 wintitle
736 )
737 )
737
738
738 if self.type == "iq":
739 if self.type == "iq":
739 self.plot_iq(self.data.heights,
740 self.plot_iq(self.data.heights,
740 scope,
741 scope,
741 channels,
742 channels,
742 thisDatetime,
743 thisDatetime,
743 wintitle
744 wintitle
744 )
745 )
745
746
746
747
747 No newline at end of file
748
@@ -1,309 +1,326
1 '''
1 '''
2 @author: Juan C. Espinoza
2 @author: Juan C. Espinoza
3 '''
3 '''
4
4
5 import os
5 import os
6 import glob
6 import glob
7 import time
7 import time
8 import json
8 import json
9 import numpy
9 import numpy
10 import zmq
10 import zmq
11 import datetime
11 import datetime
12 import ftplib
12 import ftplib
13 from functools import wraps
13 from functools import wraps
14 from threading import Thread
14 from threading import Thread
15 from multiprocessing import Process
15 from multiprocessing import Process
16
16
17 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit
17 from schainpy.model.proc.jroproc_base import Operation, ProcessingUnit, MPDecorator
18 from schainpy.model.data.jrodata import JROData
18 from schainpy.model.data.jrodata import JROData
19 from schainpy.utils import log
19 from schainpy.utils import log
20
20
21 MAXNUMX = 500
21 MAXNUMX = 500
22 MAXNUMY = 500
22 MAXNUMY = 500
23
23
24 PLOT_CODES = {
24 PLOT_CODES = {
25 'rti': 0, # Range time intensity (RTI).
25 'rti': 0, # Range time intensity (RTI).
26 'spc': 1, # Spectra (and Cross-spectra) information.
26 'spc': 1, # Spectra (and Cross-spectra) information.
27 'cspc': 2, # Cross-Correlation information.
27 'cspc': 2, # Cross-Correlation information.
28 'coh': 3, # Coherence map.
28 'coh': 3, # Coherence map.
29 'base': 4, # Base lines graphic.
29 'base': 4, # Base lines graphic.
30 'row': 5, # Row Spectra.
30 'row': 5, # Row Spectra.
31 'total': 6, # Total Power.
31 'total': 6, # Total Power.
32 'drift': 7, # Drifts graphics.
32 'drift': 7, # Drifts graphics.
33 'height': 8, # Height profile.
33 'height': 8, # Height profile.
34 'phase': 9, # Signal Phase.
34 'phase': 9, # Signal Phase.
35 'power': 16,
35 'power': 16,
36 'noise': 17,
36 'noise': 17,
37 'beacon': 18,
37 'beacon': 18,
38 'wind': 22,
38 'wind': 22,
39 'skymap': 23,
39 'skymap': 23,
40 'Unknown': 24,
40 'Unknown': 24,
41 'V-E': 25, # PIP Velocity.
41 'V-E': 25, # PIP Velocity.
42 'Z-E': 26, # PIP Reflectivity.
42 'Z-E': 26, # PIP Reflectivity.
43 'V-A': 27, # RHI Velocity.
43 'V-A': 27, # RHI Velocity.
44 'Z-A': 28, # RHI Reflectivity.
44 'Z-A': 28, # RHI Reflectivity.
45 }
45 }
46
46
47 def get_plot_code(s):
47 def get_plot_code(s):
48 label = s.split('_')[0]
48 label = s.split('_')[0]
49 codes = [key for key in PLOT_CODES if key in label]
49 codes = [key for key in PLOT_CODES if key in label]
50 if codes:
50 if codes:
51 return PLOT_CODES[codes[0]]
51 return PLOT_CODES[codes[0]]
52 else:
52 else:
53 return 24
53 return 24
54
54
55 def decimate(z, MAXNUMY):
55 def decimate(z, MAXNUMY):
56 dy = int(len(z[0])/MAXNUMY) + 1
56 dy = int(len(z[0])/MAXNUMY) + 1
57
57
58 return z[::, ::dy]
58 return z[::, ::dy]
59
59
60
60
61 class PublishData(Operation):
61 class PublishData(Operation):
62 '''
62 '''
63 Operation to send data over zmq.
63 Operation to send data over zmq.
64 '''
64 '''
65
65
66 __attrs__ = ['host', 'port', 'delay', 'verbose']
66 __attrs__ = ['host', 'port', 'delay', 'verbose']
67
67
68 def __init__(self, **kwargs):
69 """Inicio."""
70 Operation.__init__(self, **kwargs)
71 self.isConfig = False
72
73 def setup(self, server='zmq.pipe', delay=0, verbose=True, **kwargs):
68 def setup(self, server='zmq.pipe', delay=0, verbose=True, **kwargs):
74 self.counter = 0
69 self.counter = 0
75 self.delay = kwargs.get('delay', 0)
70 self.delay = kwargs.get('delay', 0)
76 self.cnt = 0
71 self.cnt = 0
77 self.verbose = verbose
72 self.verbose = verbose
78 setup = []
79 context = zmq.Context()
73 context = zmq.Context()
80 self.zmq_socket = context.socket(zmq.PUSH)
74 self.zmq_socket = context.socket(zmq.PUSH)
81 server = kwargs.get('server', 'zmq.pipe')
75 server = kwargs.get('server', 'zmq.pipe')
82
76
83 if 'tcp://' in server:
77 if 'tcp://' in server:
84 address = server
78 address = server
85 else:
79 else:
86 address = 'ipc:///tmp/%s' % server
80 address = 'ipc:///tmp/%s' % server
87
81
88 self.zmq_socket.connect(address)
82 self.zmq_socket.connect(address)
89 time.sleep(1)
83 time.sleep(1)
90
84
91
85
92 def publish_data(self):
86 def publish_data(self):
93 self.dataOut.finished = False
87 self.dataOut.finished = False
94
88
95 if self.verbose:
89 if self.verbose:
96 log.log(
90 log.log(
97 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
91 'Sending {} - {}'.format(self.dataOut.type, self.dataOut.datatime),
98 self.name
92 self.name
99 )
93 )
100 self.zmq_socket.send_pyobj(self.dataOut)
94 self.zmq_socket.send_pyobj(self.dataOut)
101
95
102 def run(self, dataOut, **kwargs):
96 def run(self, dataOut, **kwargs):
103 self.dataOut = dataOut
97 self.dataOut = dataOut
104 if not self.isConfig:
98 if not self.isConfig:
105 self.setup(**kwargs)
99 self.setup(**kwargs)
106 self.isConfig = True
100 self.isConfig = True
107
101
108 self.publish_data()
102 self.publish_data()
109 time.sleep(self.delay)
103 time.sleep(self.delay)
110
104
111 def close(self):
105 def close(self):
112
106
113 self.dataOut.finished = True
107 self.dataOut.finished = True
114 self.zmq_socket.send_pyobj(self.dataOut)
108 self.zmq_socket.send_pyobj(self.dataOut)
115 time.sleep(0.1)
109 time.sleep(0.1)
116 self.zmq_socket.close()
110 self.zmq_socket.close()
117
111
118
112
119 class ReceiverData(ProcessingUnit):
113 class ReceiverData(ProcessingUnit):
120
114
121 __attrs__ = ['server']
115 __attrs__ = ['server']
122
116
123 def __init__(self, **kwargs):
117 def __init__(self, **kwargs):
124
118
125 ProcessingUnit.__init__(self, **kwargs)
119 ProcessingUnit.__init__(self, **kwargs)
126
120
127 self.isConfig = False
121 self.isConfig = False
128 server = kwargs.get('server', 'zmq.pipe')
122 server = kwargs.get('server', 'zmq.pipe')
129 if 'tcp://' in server:
123 if 'tcp://' in server:
130 address = server
124 address = server
131 else:
125 else:
132 address = 'ipc:///tmp/%s' % server
126 address = 'ipc:///tmp/%s' % server
133
127
134 self.address = address
128 self.address = address
135 self.dataOut = JROData()
129 self.dataOut = JROData()
136
130
137 def setup(self):
131 def setup(self):
138
132
139 self.context = zmq.Context()
133 self.context = zmq.Context()
140 self.receiver = self.context.socket(zmq.PULL)
134 self.receiver = self.context.socket(zmq.PULL)
141 self.receiver.bind(self.address)
135 self.receiver.bind(self.address)
142 time.sleep(0.5)
136 time.sleep(0.5)
143 log.success('ReceiverData from {}'.format(self.address))
137 log.success('ReceiverData from {}'.format(self.address))
144
138
145
139
146 def run(self):
140 def run(self):
147
141
148 if not self.isConfig:
142 if not self.isConfig:
149 self.setup()
143 self.setup()
150 self.isConfig = True
144 self.isConfig = True
151
145
152 self.dataOut = self.receiver.recv_pyobj()
146 self.dataOut = self.receiver.recv_pyobj()
153 log.log('{} - {}'.format(self.dataOut.type,
147 log.log('{} - {}'.format(self.dataOut.type,
154 self.dataOut.datatime.ctime(),),
148 self.dataOut.datatime.ctime(),),
155 'Receiving')
149 'Receiving')
156
150
157
151 @MPDecorator
158 class SendToFTP(Operation, Process):
152 class SendToFTP(Operation):
159
153
160 '''
154 '''
161 Operation to send data over FTP.
155 Operation to send data over FTP.
156 patternX = 'local, remote, ext, period, exp_code, sub_exp_code'
162 '''
157 '''
163
158
164 __attrs__ = ['server', 'username', 'password', 'patterns', 'timeout']
159 __attrs__ = ['server', 'username', 'password', 'timeout', 'patternX']
165
160
166 def __init__(self, **kwargs):
161 def __init__(self):
167 '''
162 '''
168 patterns = [(local1, remote1, ext, delay, exp_code, sub_exp_code), ...]
169 '''
163 '''
170 Operation.__init__(self, **kwargs)
164 Operation.__init__(self)
171 Process.__init__(self)
172 self.server = kwargs.get('server')
173 self.username = kwargs.get('username')
174 self.password = kwargs.get('password')
175 self.patterns = kwargs.get('patterns')
176 self.timeout = kwargs.get('timeout', 30)
177 self.times = [time.time() for p in self.patterns]
178 self.latest = ['' for p in self.patterns]
179 self.mp = False
180 self.ftp = None
165 self.ftp = None
166 self.ready = False
181
167
182 def setup(self):
168 def setup(self, server, username, password, timeout, **kwargs):
169 '''
170 '''
171
172 self.server = server
173 self.username = username
174 self.password = password
175 self.timeout = timeout
176 self.patterns = []
177 self.times = []
178 self.latest = []
179 for arg, value in kwargs.items():
180 if 'pattern' in arg:
181 self.patterns.append(value)
182 self.times.append(time.time())
183 self.latest.append('')
184
185 def connect(self):
186 '''
187 '''
183
188
184 log.log('Connecting to ftp://{}'.format(self.server), self.name)
189 log.log('Connecting to ftp://{}'.format(self.server), self.name)
185 try:
190 try:
186 self.ftp = ftplib.FTP(self.server, timeout=self.timeout)
191 self.ftp = ftplib.FTP(self.server, timeout=self.timeout)
187 except ftplib.all_errors:
192 except ftplib.all_errors:
188 log.error('Server connection fail: {}'.format(self.server), self.name)
193 log.error('Server connection fail: {}'.format(self.server), self.name)
189 if self.ftp is not None:
194 if self.ftp is not None:
190 self.ftp.close()
195 self.ftp.close()
191 self.ftp = None
196 self.ftp = None
192 self.isConfig = False
197 self.ready = False
193 return
198 return
194
199
195 try:
200 try:
196 self.ftp.login(self.username, self.password)
201 self.ftp.login(self.username, self.password)
197 except ftplib.all_errors:
202 except ftplib.all_errors:
198 log.error('The given username y/o password are incorrect', self.name)
203 log.error('The given username y/o password are incorrect', self.name)
199 if self.ftp is not None:
204 if self.ftp is not None:
200 self.ftp.close()
205 self.ftp.close()
201 self.ftp = None
206 self.ftp = None
202 self.isConfig = False
207 self.ready = False
203 return
208 return
204
209
205 log.success('Connection success', self.name)
210 log.success('Connection success', self.name)
206 self.isConfig = True
211 self.ready = True
207 return
212 return
208
213
209 def check(self):
214 def check(self):
210
215
211 try:
216 try:
212 self.ftp.voidcmd("NOOP")
217 self.ftp.voidcmd("NOOP")
213 except:
218 except:
214 log.warning('Connection lost... trying to reconnect', self.name)
219 log.warning('Connection lost... trying to reconnect', self.name)
215 if self.ftp is not None:
220 if self.ftp is not None:
216 self.ftp.close()
221 self.ftp.close()
217 self.ftp = None
222 self.ftp = None
218 self.setup()
223 self.connect()
219
224
220 def find_files(self, path, ext):
225 def find_files(self, path, ext):
221
226
222 files = glob.glob1(path, '*{}'.format(ext))
227 files = glob.glob1(path, '*{}'.format(ext))
223 files.sort()
228 files.sort()
224 if files:
229 if files:
225 return files[-1]
230 return files[-1]
226 return None
231 return None
227
232
228 def getftpname(self, filename, exp_code, sub_exp_code):
233 def getftpname(self, filename, exp_code, sub_exp_code):
229
234
230 thisDatetime = datetime.datetime.strptime(filename.split('_')[1], '%Y%m%d')
235 thisDatetime = datetime.datetime.strptime(filename.split('_')[1], '%Y%m%d')
231 YEAR_STR = '%4.4d'%thisDatetime.timetuple().tm_year
236 YEAR_STR = '%4.4d' % thisDatetime.timetuple().tm_year
232 DOY_STR = '%3.3d'%thisDatetime.timetuple().tm_yday
237 DOY_STR = '%3.3d' % thisDatetime.timetuple().tm_yday
233 exp_code = '%3.3d'%exp_code
238 exp_code = '%3.3d' % exp_code
234 sub_exp_code = '%2.2d'%sub_exp_code
239 sub_exp_code = '%2.2d' % sub_exp_code
235 plot_code = '%2.2d'% get_plot_code(filename)
240 plot_code = '%2.2d' % get_plot_code(filename)
236 name = YEAR_STR + DOY_STR + '00' + exp_code + sub_exp_code + plot_code + '00.png'
241 name = YEAR_STR + DOY_STR + '00' + exp_code + sub_exp_code + plot_code + '00.png'
237 return name
242 return name
238
243
239 def upload(self, src, dst):
244 def upload(self, src, dst):
240
245
241 log.log('Uploading {} '.format(src), self.name, nl=False)
246 log.log('Uploading {} -> {} '.format(
247 src.split('/')[-1], dst.split('/')[-1]),
248 self.name,
249 nl=False
250 )
242
251
243 fp = open(src, 'rb')
252 fp = open(src, 'rb')
244 command = 'STOR {}'.format(dst)
253 command = 'STOR {}'.format(dst)
245
254
246 try:
255 try:
247 self.ftp.storbinary(command, fp, blocksize=1024)
256 self.ftp.storbinary(command, fp, blocksize=1024)
248 except Exception as e:
257 except Exception as e:
249 log.error('{}'.format(e), self.name)
258 log.error('{}'.format(e), self.name)
250 if self.ftp is not None:
259 if self.ftp is not None:
251 self.ftp.close()
260 self.ftp.close()
252 self.ftp = None
261 self.ftp = None
253 return 0
262 return 0
254
263
255 try:
264 try:
256 self.ftp.sendcmd('SITE CHMOD 755 {}'.format(dst))
265 self.ftp.sendcmd('SITE CHMOD 755 {}'.format(dst))
257 except Exception as e:
266 except Exception as e:
258 log.error('{}'.format(e), self.name)
267 log.error('{}'.format(e), self.name)
259 if self.ftp is not None:
268 if self.ftp is not None:
260 self.ftp.close()
269 self.ftp.close()
261 self.ftp = None
270 self.ftp = None
262 return 0
271 return 0
263
272
264 fp.close()
273 fp.close()
265 log.success('OK', tag='')
274 log.success('OK', tag='')
266 return 1
275 return 1
267
276
268 def send_files(self):
277 def send_files(self):
269
278
270 for x, pattern in enumerate(self.patterns):
279 for x, pattern in enumerate(self.patterns):
271 local, remote, ext, delay, exp_code, sub_exp_code = pattern
280 local, remote, ext, period, exp_code, sub_exp_code = pattern
272 if time.time()-self.times[x] >= delay:
281 if time.time()-self.times[x] >= int(period):
273 srcname = self.find_files(local, ext)
282 srcname = self.find_files(local, ext)
274 src = os.path.join(local, srcname)
283 src = os.path.join(local, srcname)
275 if os.path.getmtime(src) < time.time() - 30*60:
284 if os.path.getmtime(src) < time.time() - 30*60:
285 log.warning('Skipping old file {}'.format(srcname))
276 continue
286 continue
277
287
278 if srcname is None or srcname == self.latest[x]:
288 if srcname is None or srcname == self.latest[x]:
289 log.warning('File alreday uploaded {}'.format(srcname))
279 continue
290 continue
280
291
281 if 'png' in ext:
292 if 'png' in ext:
282 dstname = self.getftpname(srcname, exp_code, sub_exp_code)
293 dstname = self.getftpname(srcname, int(exp_code), int(sub_exp_code))
283 else:
294 else:
284 dstname = srcname
295 dstname = srcname
285
296
286 dst = os.path.join(remote, dstname)
297 dst = os.path.join(remote, dstname)
287
298
288 if self.upload(src, dst):
299 if self.upload(src, dst):
289 self.times[x] = time.time()
300 self.times[x] = time.time()
290 self.latest[x] = srcname
301 self.latest[x] = srcname
291 else:
302 else:
292 self.isConfig = False
303 self.ready = False
293 break
304 break
294
305
295 def run(self):
306 def run(self, dataOut, server, username, password, timeout=10, **kwargs):
296
307
297 while True:
308 if not self.isConfig:
298 if not self.isConfig:
309 self.setup(
299 self.setup()
310 server=server,
300 if self.ftp is not None:
311 username=username,
301 self.check()
312 password=password,
302 self.send_files()
313 timeout=timeout,
303 time.sleep(10)
314 **kwargs
315 )
316 self.isConfig = True
317 if not self.ready:
318 self.connect()
319 if self.ftp is not None:
320 self.check()
321 self.send_files()
304
322
305 def close():
323 def close(self):
306
324
307 if self.ftp is not None:
325 if self.ftp is not None:
308 self.ftp.close()
326 self.ftp.close()
309 self.terminate() No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now