import os import time import numpy import datetime import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.axes_grid1 import make_axes_locatable from matplotlib.ticker import FuncFormatter, LinearLocator from schainpy.model.proc.jroproc_base import Operation func = lambda x, pos: ('%s') %(datetime.datetime.utcfromtimestamp(x).strftime('%H:%M')) d1970 = datetime.datetime(1970,1,1) class PlotData(Operation): __code = 'Figure' __MAXNUMX = 80 __MAXNUMY = 80 __missing = 1E30 def __init__(self): Operation.__init__(self) self.xmin = None self.xmax = None self.newdataOut = None self.dataOut = None self.isConfig = False self.figure = None self.width = 6 self.height = 4 def setup(self, dataOut, **kwargs): self.first = True self.localtime = kwargs.pop('localtime', True) self.show = kwargs.pop('show', True) self.save = kwargs.pop('save', False) self.pause = kwargs.pop('pause', False) self.time = [] self.nblock = 0 self.z = [] self.data = [{} for __ in dataOut.channelList] self.axes = [] self.colormap = kwargs.get('colormap', 'jet') self.title = kwargs.get('wintitle', '') self.xaxis = kwargs.get('xaxis', None) self.zmin = kwargs.get('zmin', None) self.zmax = kwargs.get('zmax', None) xmin = kwargs.get('xmin', 0) xmax = kwargs.get('xmax', xmin+4) dt = dataOut.datatime.date() dtmin = datetime.datetime.combine(dt, datetime.time(xmin, 0, 0)) dtmax = datetime.datetime.combine(dt, datetime.time(xmax, 59, 59)) self.xmin = (dtmin-d1970).total_seconds() self.xmax = (dtmax-d1970).total_seconds() self.ymin = kwargs.get('ymin', None) self.ymax = kwargs.get('ymax', None) if self.figure is None: self.figure = plt.figure() else: self.figure.clf() self.setup_fig() for n in range(dataOut.nChannels): ax = self.figure.add_subplot(self.nrows, self.ncols, n+1) ax.firsttime = True self.axes.append(ax) self.setup_fig() self.figure.set_size_inches (self.width, self.height) def fill_gaps(self, x_buffer, y_buffer, z_buffer): if x_buffer.shape[0] < 2: return x_buffer, y_buffer, z_buffer deltas = x_buffer[1:] - x_buffer[0:-1] x_median = np.median(deltas) index = np.where(deltas > 5*x_median) if len(index[0]) != 0: z_buffer[::,index[0],::] = self.__missing z_buffer = np.ma.masked_inside(z_buffer, 0.99*self.__missing, 1.01*self.__missing) return x_buffer, y_buffer, z_buffer def decimate(self): dx = int(len(self.x)/self.__MAXNUMX) + 1 dy = int(len(self.y)/self.__MAXNUMY) + 1 x = self.x[::dx] y = self.y[::dy] z = self.z[::, ::dx, ::dy] return x, y, z def _plot(self): self.plot() self.figure.suptitle(self.title+self.__code) if self.save: figname = os.path.join(self.save, '{}_{}.png'.format(self.__code, self.plot_dt.strftime('%y%m%d_%H%M%S'))) print 'Saving figure: {}'.format(figname) self.figure.savefig(figname) self.figure.canvas.draw() if self.show: self.figure.show() if self.pause: raw_input('Press to continue') def update(self): pass def run(self, dataOut, **kwargs): self.dataOut = dataOut if not self.isConfig: self.setup(dataOut, **kwargs) self.isConfig = True self.nblock += 1 self.update() if dataOut.ltctime>=self.xmax: self._plot() self.isConfig = False def close(self): if self.dataOut: self._plot() class PlotSpectraData(PlotData): __code = 'Spectra' def setup_fig(self): pass def update(self): for ch in self.dataOut.channelList: self.data[ch] = self.dataOut.data_spc[ch] def plot(self): pass class PlotRTIData(PlotData): __code = 'RTI' def setup_fig(self): self.ncols = 1 self.nrows = self.dataOut.nChannels self.width = 8 self.height = 2.2*self.nrows self.ylabel = 'Range [Km]' def update(self): self.time.append(self.dataOut.ltctime) for ch in self.dataOut.channelList: self.data[ch][self.dataOut.ltctime] = self.dataOut.getPower()[ch] def plot(self): self.plot_dt = datetime.datetime.utcfromtimestamp(self.time[-2]) self.time.sort() self.x = self.time self.y = self.dataOut.getHeiRange() self.z = [] for ch in self.dataOut.channelList: self.z.append([self.data[ch][t] for t in self.time]) self.x = np.array(self.x) self.z = np.array(self.z) for n, ax in enumerate(self.axes): if self.xaxis=='time': ax.xaxis.set_major_formatter(FuncFormatter(func)) ax.xaxis.set_major_locator(LinearLocator(6)) ax.yaxis.set_major_locator(LinearLocator(4)) ax.set_ylabel(self.ylabel) ax.set_xlim(self.xmin, self.xmax) ax.set_title('Channel {} {}'.format(self.dataOut.channelList[n], self.plot_dt.strftime('%y/%m/%d %H:%M:%S')), size=8) self.decimate() for n, ax in enumerate(self.axes): x, y, z = self.fill_gaps(*self.decimate()) if ax.firsttime: ymin = self.ymin if self.ymin else np.nanmin(self.y) ymax = self.ymax if self.ymax else np.nanmax(self.y) zmin = self.zmin if self.zmin else np.nanmin(self.z) zmax = self.zmax if self.zmax else np.nanmax(self.z) plot = ax.pcolormesh(x, y, z[n].T, vmin=zmin, vmax=zmax, cmap=plt.get_cmap(self.colormap) ) divider = make_axes_locatable(ax) cax = divider.new_horizontal(size='3%', pad=0.05) self.figure.add_axes(cax) plt.colorbar(plot, cax) ax.set_ylim(self.ymin, self.ymax) ax.firsttime = False else: plot = ax.pcolormesh(x, y, z[n].T) self.figure.subplots_adjust(wspace=None, hspace=0.5) class PlotSNRData(PlotRTIData): __code = 'SNR' def update(self): self.time.append(self.dataOut.ltctime) for ch in self.dataOut.channelList: self.data[ch][self.dataOut.ltctime] = 10*np.log10(self.dataOut.data_SNR[ch])