diff --git a/schainpy/controller.py b/schainpy/controller.py index cb7e10c..3bbf5f4 100644 --- a/schainpy/controller.py +++ b/schainpy/controller.py @@ -152,7 +152,7 @@ class OperationConf(ConfBase): className = eval(self.name) - if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name: + if 'Plot' in self.name or 'Writer' in self.name or 'Send' in self.name or 'print' in self.name: kwargs = self.getKwargs() opObj = className(self.id, self.id, self.project_id, self.err_queue, **kwargs) opObj.start() diff --git a/schainpy/model/data/jrodata.py b/schainpy/model/data/jrodata.py index e1cedf6..cad8930 100644 --- a/schainpy/model/data/jrodata.py +++ b/schainpy/model/data/jrodata.py @@ -1122,13 +1122,14 @@ class PlotterData(object): self.localtime = False self.data = {} self.meta = {} - self.__times = [] self.__heights = [] if 'snr' in code: self.plottypes = ['snr'] elif code == 'spc': self.plottypes = ['spc', 'noise', 'rti'] + elif code == 'cspc': + self.plottypes = ['cspc', 'spc', 'noise', 'rti'] elif code == 'rti': self.plottypes = ['noise', 'rti'] else: @@ -1143,17 +1144,17 @@ class PlotterData(object): def __str__(self): dum = ['{}{}'.format(key, self.shape(key)) for key in self.data] - return 'Data[{}][{}]'.format(';'.join(dum), len(self.__times)) + return 'Data[{}][{}]'.format(';'.join(dum), len(self.times)) def __len__(self): - return len(self.__times) + return len(self.data[self.key]) def __getitem__(self, key): if key not in self.data: raise KeyError(log.error('Missing key: {}'.format(key))) if 'spc' in key or not self.buffering: - ret = self.data[key] + ret = self.data[key][self.tm] elif 'scope' in key: ret = numpy.array(self.data[key][float(self.tm)]) else: @@ -1171,8 +1172,8 @@ class PlotterData(object): ''' self.type = '' self.ready = False + del self.data self.data = {} - self.__times = [] self.__heights = [] self.__all_heights = set() for plot in self.plottypes: @@ -1198,15 +1199,14 @@ class PlotterData(object): if len(self.data[key]): if 'spc' in key or not self.buffering: return self.data[key].shape - return self.data[key][self.__times[0]].shape + return self.data[key][self.times[0]].shape return (0,) def update(self, dataOut, tm): ''' Update data object with new dataOut ''' - if tm in self.__times: - return + self.profileIndex = dataOut.profileIndex self.tm = tm self.type = dataOut.type @@ -1223,16 +1223,14 @@ class PlotterData(object): if True in ['spc' in ptype for ptype in self.plottypes]: self.xrange = (dataOut.getFreqRange(1)/1000., dataOut.getAcfRange(1), dataOut.getVelRange(1)) - self.factor = dataOut.normFactor self.__heights.append(dataOut.heightList) self.__all_heights.update(dataOut.heightList) - self.__times.append(tm) + for plot in self.plottypes: if plot in ('spc', 'spc_moments', 'spc_cut'): z = dataOut.data_spc/dataOut.normFactor buffer = 10*numpy.log10(z) if plot == 'cspc': - z = dataOut.data_spc/dataOut.normFactor buffer = (dataOut.data_spc, dataOut.data_cspc) if plot == 'noise': buffer = 10*numpy.log10(dataOut.getNoise()/dataOut.normFactor) @@ -1270,18 +1268,17 @@ class PlotterData(object): self.nProfiles = dataOut.nProfiles if plot == 'spc': - self.data['spc'] = buffer + self.data['spc'][tm] = buffer elif plot == 'cspc': - self.data['spc'] = buffer[0] - self.data['cspc'] = buffer[1] + self.data['cspc'][tm] = buffer elif plot == 'spc_moments': - self.data['spc'] = buffer + self.data['spc'][tm] = buffer self.data['moments'][tm] = dataOut.moments else: if self.buffering: self.data[plot][tm] = buffer else: - self.data[plot] = buffer + self.data[plot][tm] = buffer if dataOut.channelList is None: self.channels = range(buffer.shape[0]) @@ -1302,7 +1299,7 @@ class PlotterData(object): for key in self.data: shape = self.shape(key)[:-1] + H.shape for tm, obj in list(self.data[key].items()): - h = self.__heights[self.__times.index(tm)] + h = self.__heights[self.times.index(tm)] if H.size == h.size: continue index = numpy.where(numpy.in1d(H, h))[0] @@ -1313,19 +1310,18 @@ class PlotterData(object): dummy[index] = obj self.data[key][tm] = dummy - self.__heights = [H for tm in self.__times] + self.__heights = [H for tm in self.times] - def jsonify(self, plot_name, plot_type, decimate=False): + def jsonify(self, tm, plot_name, plot_type, decimate=False): ''' Convert data to json ''' - tm = self.times[-1] dy = int(self.heights.size/self.MAXNUMY) + 1 - if self.key in ('spc', 'cspc') or not self.buffering: - dx = int(self.data[self.key].shape[1]/self.MAXNUMX) + 1 + if self.key in ('spc', 'cspc'): + dx = int(self.data[self.key][tm].shape[1]/self.MAXNUMX) + 1 data = self.roundFloats( - self.data[self.key][::, ::dx, ::dy].tolist()) + self.data[self.key][tm][::, ::dx, ::dy].tolist()) else: if self.key is 'noise': data = [[x] for x in self.roundFloats(self.data[self.key][tm].tolist())] @@ -1358,8 +1354,9 @@ class PlotterData(object): Return the list of times of the current data ''' - ret = numpy.array(self.__times) - ret.sort() + ret = numpy.array([*self.data[self.key]]) + if self: + ret.sort() return ret @property diff --git a/schainpy/model/graphics/jroplot_base.py b/schainpy/model/graphics/jroplot_base.py index 7943177..ccfbbc3 100644 --- a/schainpy/model/graphics/jroplot_base.py +++ b/schainpy/model/graphics/jroplot_base.py @@ -202,7 +202,7 @@ class Plot(Operation): self.zlimits = kwargs.get('zlimits', None) self.xmin = kwargs.get('xmin', None) self.xmax = kwargs.get('xmax', None) - self.xrange = kwargs.get('xrange', 24) + self.xrange = kwargs.get('xrange', 12) self.xscale = kwargs.get('xscale', None) self.ymin = kwargs.get('ymin', None) self.ymax = kwargs.get('ymax', None) @@ -228,6 +228,7 @@ class Plot(Operation): self.exp_code = kwargs.get('exp_code', None) self.plot_server = kwargs.get('plot_server', False) self.sender_period = kwargs.get('sender_period', 60) + self.tag = kwargs.get('tag', '') self.height_index = kwargs.get('height_index', None) self.__throttle_plot = apply_throttle(self.throttle) self.data = PlotterData( @@ -572,19 +573,29 @@ class Plot(Operation): self.sender_time = self.data.tm - attrs = ['titles', 'zmin', 'zmax', 'colormap'] + attrs = ['titles', 'zmin', 'zmax', 'tag', 'ymin', 'ymax'] for attr in attrs: value = getattr(self, attr) - if value is not None: - self.data.meta[attr] = getattr(self, attr) + if value: + if isinstance(value, (numpy.float32, numpy.float64)): + value = round(float(value), 2) + self.data.meta[attr] = value + if self.colormap == 'jet': + self.data.meta['colormap'] = 'Jet' + elif 'RdBu' in self.colormap: + self.data.meta['colormap'] = 'RdBu' + else: + self.data.meta['colormap'] = 'Viridis' self.data.meta['interval'] = int(interval) - msg = self.data.jsonify(self.plot_name, self.plot_type) - self.sender_queue.put(msg) + # msg = self.data.jsonify(self.data.tm, self.plot_name, self.plot_type) + self.sender_queue.put(self.data.tm) while True: if self.sender_queue.empty(): break - self.socket.send_string(self.sender_queue.get()) + tm = self.sender_queue.get() + msg = self.data.jsonify(tm, self.plot_name, self.plot_type) + self.socket.send_string(msg) socks = dict(self.poll.poll(5000)) if socks.get(self.socket) == zmq.POLLIN: reply = self.socket.recv_string() @@ -598,7 +609,7 @@ class Plot(Operation): else: log.warning( "No response from server, retrying...", self.name) - self.sender_queue.put(msg) + self.sender_queue.put(self.data.tm) self.socket.setsockopt(zmq.LINGER, 0) self.socket.close() self.poll.unregister(self.socket) @@ -647,16 +658,16 @@ class Plot(Operation): if self.localtime: t -= time.timezone - if 'buffer' in self.plot_type: - if self.xmin is None: - self.tmin = t + if self.xmin is None: + self.tmin = t + if 'buffer' in self.plot_type: self.xmin = self.getDateTime(t).hour - else: - self.tmin = ( - self.getDateTime(t).replace( - hour=int(self.xmin), - minute=0, - second=0) - self.getDateTime(0)).total_seconds() + else: + self.tmin = ( + self.getDateTime(t).replace( + hour=int(self.xmin), + minute=0, + second=0) - self.getDateTime(0)).total_seconds() self.data.setup() self.isConfig = True @@ -674,12 +685,13 @@ class Plot(Operation): if dataOut.useLocalTime and not self.localtime: tm += time.timezone - if self.xaxis is 'time' and self.data and (tm - self.tmin) >= self.xrange*60*60: + if self.data and (tm - self.tmin) >= self.xrange*60*60: self.save_counter = self.save_period self.__plot() - self.xmin += self.xrange - if self.xmin >= 24: - self.xmin -= 24 + if 'time' in self.xaxis: + self.xmin += self.xrange + if self.xmin >= 24: + self.xmin -= 24 self.tmin += self.xrange*60*60 self.data.setup() self.clear_figures() diff --git a/schainpy/model/graphics/jroplot_spectra.py b/schainpy/model/graphics/jroplot_spectra.py index 7918b7b..3ef5c6e 100644 --- a/schainpy/model/graphics/jroplot_spectra.py +++ b/schainpy/model/graphics/jroplot_spectra.py @@ -126,39 +126,38 @@ class CrossSpectraPlot(Plot): y = self.data.heights self.y = y - spc = self.data['spc'] - cspc = self.data['cspc'] + nspc = self.data['spc'] + spc = self.data['cspc'][0] + cspc = self.data['cspc'][1] for n in range(self.nrows): - noise = self.data['noise'][n][-1] + noise = self.data['noise'][:,-1] pair = self.data.pairs[n] ax = self.axes[4 * n] - spc0 = 10.*numpy.log10(spc[pair[0]]/self.data.factor) if ax.firsttime: self.xmax = self.xmax if self.xmax else numpy.nanmax(x) self.xmin = self.xmin if self.xmin else -self.xmax - self.zmin = self.zmin if self.zmin else numpy.nanmin(spc) - self.zmax = self.zmax if self.zmax else numpy.nanmax(spc) - ax.plt = ax.pcolormesh(x , y , spc0.T, + self.zmin = self.zmin if self.zmin else numpy.nanmin(nspc) + self.zmax = self.zmax if self.zmax else numpy.nanmax(nspc) + ax.plt = ax.pcolormesh(x , y , nspc[pair[0]].T, vmin=self.zmin, vmax=self.zmax, cmap=plt.get_cmap(self.colormap) ) else: - ax.plt.set_array(spc0.T.ravel()) - self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise)) + ax.plt.set_array(nspc[pair[0]].T.ravel()) + self.titles.append('CH {}: {:3.2f}dB'.format(pair[0], noise[pair[0]])) ax = self.axes[4 * n + 1] - spc1 = 10.*numpy.log10(spc[pair[1]]/self.data.factor) if ax.firsttime: - ax.plt = ax.pcolormesh(x , y, spc1.T, + ax.plt = ax.pcolormesh(x , y, nspc[pair[1]].T, vmin=self.zmin, vmax=self.zmax, cmap=plt.get_cmap(self.colormap) ) else: - ax.plt.set_array(spc1.T.ravel()) - self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise)) + ax.plt.set_array(nspc[pair[1]].T.ravel()) + self.titles.append('CH {}: {:3.2f}dB'.format(pair[1], noise[pair[1]])) out = cspc[n] / numpy.sqrt(spc[pair[0]] * spc[pair[1]]) coh = numpy.abs(out) @@ -300,6 +299,7 @@ class NoisePlot(Plot): self.nrows = 1 self.nplots = 1 self.ylabel = 'Intensity [dB]' + self.xlabel = 'Time' self.titles = ['Noise'] self.colorbar = False diff --git a/schainpy/model/io/__init__.py b/schainpy/model/io/__init__.py index 4bb334f..f6c6768 100644 --- a/schainpy/model/io/__init__.py +++ b/schainpy/model/io/__init__.py @@ -20,4 +20,5 @@ from .bltrIO_spectra import * from .jroIO_mira35c import * from .julIO_param import * -from .pxIO_param import * \ No newline at end of file +from .pxIO_param import * +from .jroIO_simulator import * \ No newline at end of file diff --git a/schainpy/model/io/jroIO_base.py b/schainpy/model/io/jroIO_base.py index 8452897..d9ad1f4 100644 --- a/schainpy/model/io/jroIO_base.py +++ b/schainpy/model/io/jroIO_base.py @@ -14,7 +14,7 @@ import time import datetime import zmq -from schainpy.model.proc.jroproc_base import Operation +from schainpy.model.proc.jroproc_base import Operation, MPDecorator from schainpy.model.data.jroheaderIO import PROCFLAG, BasicHeader, SystemHeader, RadarControllerHeader, ProcessingHeader from schainpy.model.data.jroheaderIO import get_dtype_index, get_numpy_dtype, get_procflag_dtype, get_dtype_width from schainpy.utils import log @@ -1555,6 +1555,7 @@ class JRODataWriter(Reader): self.putData() return self.dataOut +@MPDecorator class printInfo(Operation): def __init__(self): @@ -1564,7 +1565,7 @@ class printInfo(Operation): def run(self, dataOut, headers = ['systemHeaderObj', 'radarControllerHeaderObj', 'processingHeaderObj']): if self.__printInfo == False: - return dataOut + return for header in headers: if hasattr(dataOut, header): @@ -1577,4 +1578,3 @@ class printInfo(Operation): log.warning('Header {} Not found in object'.format(header)) self.__printInfo = False - return dataOut \ No newline at end of file diff --git a/schainpy/model/proc/jroproc_voltage.py b/schainpy/model/proc/jroproc_voltage.py index 8e99b76..8b02d9e 100644 --- a/schainpy/model/proc/jroproc_voltage.py +++ b/schainpy/model/proc/jroproc_voltage.py @@ -377,6 +377,23 @@ class setAttribute(Operation): return dataOut +@MPDecorator +class printAttribute(Operation): + ''' + Print an arbitrary attribute of dataOut + ''' + + def __init__(self): + + Operation.__init__(self) + + def run(self, dataOut, attributes): + + for attr in attributes: + if hasattr(dataOut, attr): + log.log(getattr(dataOut, attr), attr) + + class interpolateHeights(Operation): def run(self, dataOut, topLim, botLim):