def plot_country(doc): country_source = ColumnDataSource({ 'Lat': [], 'Lon': [], 'Country': [], 'Native': [], 'Lang': [], 'x': [], 'y': [] }) country_df = pd.read_csv('countries.csv') country_df.columns = ['Lat', 'Lon', 'Country', 'Native', 'Lang'] wgs84_to_web_mercator(country_df) n_roll = len(country_df.index) country_source.stream(country_df.to_dict(orient='list'), n_roll) x_range, y_range = ([687604.14, 537676.59], [4808266.66, 8448058.87]) p = figure(x_range=x_range, y_range=y_range, x_axis_type='mercator', y_axis_type='mercator', sizing_mode='scale_width', plot_height=300) my_hover = HoverTool() color_mapper = LinearColorMapper(palette=palette) my_hover.tooltips = [('Country', '@Country'), ('Native', '@Native'), ('Language', '@Lang')] p.add_tile(CARTODBPOSITRON_RETINA) p.circle('x', 'y', source=country_source, fill_color={ 'field': 'Native', 'transform': color_mapper }, hover_color='yellow', size=10, fill_alpha=0.8, line_width=0.5) p.add_tools(my_hover) doc.title = 'Countries' doc.add_root(p)
def make_doc(request): #Defines format for data dataFormat = { "Time": [], "EyeR": [], } #Establishes the dict that new data will be added to source = ColumnDataSource(dataFormat) newData = { "Time": [0], "EyeR": [0], } ##THIS IS THE FUNCTION THAT SHOULD TAKE IN THE Avg EyeR of last 20sec and Time ##Function describes how new data will be added if request.method == "POST": form = ChangeForm(request.POST) print(request.POST.get('time')) #only listens to on / off switch if form.is_valid(): #change the state of the driver print(form.cleaned_data['time']) time = form.cleaned_data['time'] eyeR = form.cleaned_data['overallAverage'] newData = update(time, eyeR) #calls the update every 100 ms #doc.add_periodic_callback(update, 100) print(newData['Time']) source.stream(newData) #Creates the actual graphs linePlot = figure(title="Eye Tracking", plot_width=800, plot_height=500) #Creates circles linePlot.circle(x='Time', y='EyeR', source=source) #Creates line connections between points linePlot.line(x='Time', y='EyeR', source=source) #making it the root means the page updates any times the figure changes #doc.add_root(linePlot) script, div = components(linePlot, CDN) return render(request, "simple_chart.html", { "the_script": script, "the_div": div })
def record_and_display(config): sample_index = 0 start_time = datetime.datetime.now() done = False pd_source = pd.DataFrame(columns=['datetime', 'sensor', 'mv_c0', 'mv_c1', 'mv_c2', 'mv_c3']) logging.debug('Starting program') #################################### if interactive_mode: bokeh_figure = figure(title='MCP3204 Voltage Plot', sizing_mode='stretch_width', x_axis_type='datetime', plot_height = 400, tools = 'pan, wheel_zoom, box_zoom, reset, crosshair, hover, save') bokeh_csource = {} channels = ['c0', 'c1', 'c2', 'c3']; #bokeh_csource[next(iter(config['mqtt_topics']))] = ColumnDataSource(data = dict(x = [], mv_c0 = [], mv_c1 = [], mv_c2 = [], mv_c3 = [])) bokeh_csource = ColumnDataSource(data = dict(x = [], mv_c0 = [], mv_c1 = [], mv_c2 = [], mv_c3 = [])) #bokeh_figure.vbar(x='x', top='counts', width=0.9, source=bokeh_csource, line_color='white') for channel, color in zip(channels, palette): bokeh_figure.line(x = 'x', y = 'mv_' + channel, source = bokeh_csource, color = color) bokeh_figure.circle(x = 'x', y = 'mv_' + channel, source = bokeh_csource, legend_label = channel, color = color, fill_color = 'white') bokeh_figure.yaxis.axis_label = 'Voltage (mV)' bokeh_figure.xaxis.axis_label = 'Time' bokeh_handle = show(bokeh_figure, notebook_handle = True) mqtt_client = mqtt.Client(client_id = config['mqtt_id'], userdata=config) mqtt_client.on_connect = on_connect mqtt_client.on_message = on_message mqtt_client.connect(config['mqtt_broker'], 1883, 60) mqtt_client.loop_start() logging.debug('Starting loop') while not done: if config['record_sample_limit'] > 0 and sample_index > config['record_sample_limit']: logging.info('Reached sample limit, stopping') done = True if config['record_duration_limit'] > 0 and (datetime.datetime.now() - start_time) > datetime.timedelta(seconds=config['record_duration_limit']): logging.info('Reached runtime limit, stopping') done = True try: # Receive message from queue msg = mqtt_queue.get(block = True, timeout = 0.1) # We expect JSON payload sensor_data = json.loads(msg.payload) # Check if we have all required fields if not 'mv_c0' in sensor_data: logging.error('missing key in sensor_data:') logging.error(sensor_data) continue if sensor_data['mv_c0'] is None: logging.error('Sensor value error:') logging.error(sensor_data) continue if msg.topic in sensor_meta and True: # Rollover if sensor_data['uptime'] < sensor_meta[msg.topic]['fist_uptime']: sensor_meta[msg.topic]['first_datetime'] = datetime.datetime.now() sensor_meta[msg.topic]['fist_uptime'] = sensor_data['uptime'] sensor_value_datetime = sensor_meta[msg.topic]['first_datetime'] - datetime.timedelta(milliseconds=sensor_meta[msg.topic]['fist_uptime']) + datetime.timedelta(milliseconds=sensor_data['uptime']) else: sensor_meta[msg.topic] = {} sensor_meta[msg.topic]['first_datetime'] = datetime.datetime.now() sensor_meta[msg.topic]['fist_uptime'] = sensor_data['uptime'] sensor_value_datetime = datetime.datetime.now() # Build object for pandas dataframe and append if config['export_json'] or config['export_csv'] or config['export_excel']: pd_data = {} pd_data['datetime'] = sensor_value_datetime pd_data['sensor'] = msg.topic pd_data['mv_c0'] = float(sensor_data['mv_c0']) pd_data['mv_c1'] = float(sensor_data['mv_c1']) pd_data['mv_c2'] = float(sensor_data['mv_c2']) pd_data['mv_c3'] = float(sensor_data['mv_c3']) pd_source.loc[len(pd_source)] = pd_data sample_index = sample_index + 1 except queue.Empty: #print('NOTE - timeout!') continue except json.JSONDecodeError: logging.error('JSONDecodeError') done = True continue; except ValueError: logging.error('ValueError') done = True continue; except KeyboardInterrupt: logging.warning('Keyboard interrup!'); done = True; continue; except Exception as e: logging.error('Unexpected error!') print(e) done = True continue; if interactive_mode: bokeh_data = {} bokeh_data['x'] = [sensor_value_datetime] bokeh_data['mv_c0'] = [float(sensor_data['mv_c0'])] bokeh_data['mv_c1'] = [float(sensor_data['mv_c1'])] bokeh_data['mv_c2'] = [float(sensor_data['mv_c2'])] bokeh_data['mv_c3'] = [float(sensor_data['mv_c3'])] #print(bokeh_data) #bokeh_csource[msg.topic].stream(bokeh_data, config['bokeh_stream_rollover']) bokeh_csource.stream(bokeh_data, config['bokeh_stream_rollover']) push_notebook(handle = bokeh_handle) else: print('{sensor} - {temp:.2f} C'.format(sensor=msg.topic, temp=float(sensor_data['mv_c0']))) # We are done, disconnect MQTT client mqtt_client.disconnect() # Export collected data if config['export_csv']: pd_source.to_csv(datetime.datetime.now().strftime('%Y%m%d%H%M%S') + '.csv') logging.info('Data written to ' + datetime.datetime.now().strftime('%Y%m%d%H%M%S') + '.csv') if config['export_json']: pd_source.to_json(datetime.datetime.now().strftime('%Y%m%d%H%M%S') + '.json') logging.info('Data written to ' + datetime.datetime.now().strftime('%Y%m%d%H%M%S') + '.json') if config['export_excel']: pd_source.to_excel(datetime.datetime.now().strftime('%Y%m%d%H%M%S') + '.xlsx') logging.info('Data written to ' + datetime.datetime.now().strftime('%Y%m%d%H%M%S') + '.xlsx') mqtt_client.disconnect(); logging.info('Finished!')
class Plotter(object): """@brief Responsible for plotting the DMM values.""" def __init__(self, yRangeLimits, bokehPort=5001, plotTitle="RS310P"): """@brief Constructor. @param yRangeLimits Limits of the Y axis. By default auto range. @param bokehPort The TCP IP port for the bokeh server. @param plotTitle The title text for the plot area.""" self._yRangeLimits = yRangeLimits self._bokehPort = bokehPort self._plotTitle = plotTitle self._voltsSource = ColumnDataSource({'x': [], 'y': []}) self._ampsSource = ColumnDataSource({'x': [], 'y': []}) self._wattsSource = ColumnDataSource({'x': [], 'y': []}) self._evtLoop = None self._queue = queue.Queue() def runBokehServer(self): """@brief Run the bokeh server. This is a blocking method.""" apps = {'/': Application(FunctionHandler(self._createPlot))} #As this gets run in a thread we need to start an event loop evtLoop = asyncio.new_event_loop() asyncio.set_event_loop(evtLoop) server = Server(apps, port=self._bokehPort) server.start() #Show the server in a web browser window server.io_loop.add_callback(server.show, "/") server.io_loop.start() def _createPlot( self, doc, ): """@brief create a plot figure. @param doc The document to add the plot to.""" if self._yRangeLimits and len(self._yRangeLimits) == 2: yrange = Range1d(self._yRangeLimits[0], self._yRangeLimits[1]) else: yrange = None fig = figure(title=self._plotTitle, toolbar_location='above', x_axis_type="datetime", x_axis_location="below", y_range=yrange) fig.line(source=self._voltsSource, line_color="blue", legend_label="Volts") fig.line(source=self._ampsSource, line_color="green", legend_label="Amps") fig.line(source=self._wattsSource, line_color="red", legend_label="Watts") grid = gridplot(children=[[fig]], sizing_mode='stretch_both') doc.title = self._plotTitle doc.add_root(grid) doc.add_periodic_callback(self._update, 100) def _update(self): """@brief called periodically to update the plot trace.""" while not self._queue.empty(): reading = self._queue.get() newVolts = {'x': [reading.time], 'y': [reading.volts]} self._voltsSource.stream(newVolts) newAmps = {'x': [reading.time], 'y': [reading.amps]} self._ampsSource.stream(newAmps) newWatts = {'x': [reading.time], 'y': [reading.watts]} self._wattsSource.stream(newWatts) def addReading(self, reading): """@brief Add a value to be plotted @param reading The reading containing the values to be plotted.""" self._queue.put(reading)
class RtiBokehPlotData: """ The data will be averaged and saved to a CSV file. This will also plot the averaged data live to a web browser. """ def __init__(self, rti_config): self.rti_config = rti_config self.cds = ColumnDataSource(data=dict(date=[], wave_height=[], earth_east_1=[], earth_east_2=[], earth_east_3=[], earth_north_1=[], earth_north_2=[], earth_north_3=[], mag_1=[], mag_2=[], mag_3=[], dir_1=[], dir_2=[], dir_3=[], bin_num=[], bin_depth=[], amp_0=[], amp_1=[], amp_2=[], amp_3=[])) self.buffer_datetime = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_wave_height = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_range_track = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_earth_east_1 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_earth_east_2 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_earth_east_3 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_earth_north_1 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_earth_north_2 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_earth_north_3 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_mag_1 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_mag_2 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_mag_3 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_dir_1 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_dir_2 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_dir_3 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_dash_df = deque( maxlen=int(self.rti_config.config['Waves']['ENS_IN_BURST']) * 2) self.buffer_dash_ens = deque( maxlen=int(self.rti_config.config['Waves']['ENS_IN_BURST']) * 2) self.buffer_bin_num = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_bin_depth = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_amp_0 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_amp_1 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_amp_2 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.buffer_amp_3 = deque( maxlen=int(self.rti_config.config['PLOT']['BUFF_SIZE'])) self.thread_lock = Lock() self.max_points = 4096 if int(self.rti_config.config['PLOT']['MAX_POINTS']) > 0: self.max_points = int(self.rti_config.config['PLOT']['MAX_POINTS']) def create_bokeh_plots(self): """ Create the bokeh plot. Create the ColumnDataSource to hold all the plot's data. Create all the plots and use the ColumnDataSource for the data. :return: """ self.cds = ColumnDataSource(data=dict(date=[], wave_height=[], range_track=[], earth_east_1=[], earth_east_2=[], earth_east_3=[], earth_north_1=[], earth_north_2=[], earth_north_3=[], mag_1=[], mag_2=[], mag_3=[], dir_1=[], dir_2=[], dir_3=[], bin_num=[], bin_depth=[], amp_0=[], amp_1=[], amp_2=[], amp_3=[])) # Specify the selection tools to be made available select_tools = [ 'box_select', 'lasso_select', 'poly_select', 'tap', 'reset', 'previewsave', 'pan', 'wheel_zoom', 'box_zoom', 'hover' ] # Format the tooltip tooltips_wave_height = HoverTool(tooltips=[ ('Date-Time', '@date{%F %H:%M:%S}'), ('Pressure Height (m)', '@wave_height'), ('Range Tracking Height (m)', '@range_track'), ], formatters={'date': 'datetime'}) # Format the tooltip tooltips_vel_east = HoverTool(tooltips=[ ('Time', '@date{%F %T}'), ('Velocity (m/s) Bin 1', '@earth_east_1'), ('Velocity (m/s) Bin 2', '@earth_east_2'), ('Velocity (m/s) Bin 3', '@earth_east_3'), ], formatters={'date': 'datetime'}) # Format the tooltip tooltips_vel_north = HoverTool(tooltips=[ ('Time', '@date{%F %T}'), ('Velocity (m/s) Bin 1', '@earth_north_1'), ('Velocity (m/s) Bin 2', '@earth_north_2'), ('Velocity (m/s) Bin 3', '@earth_north_3'), ], formatters={'date': 'datetime'}) # Format the tooltip tooltips_mag = HoverTool(tooltips=[ ('Time', '@date{%F %T}'), ('Velocity (m/s) Bin 1', '@mag_1'), ('Velocity (m/s) Bin 2', '@mag_2'), ('Velocity (m/s) Bin 3', '@mag_3'), ], formatters={'date': 'datetime'}) # Format the tooltip tooltips_dir = HoverTool(tooltips=[ ('Time', '@date{%F %T}'), ('Velocity (deg) Bin 1', '@dir_1'), ('Velocity (deg) Bin 2', '@dir_2'), ('Velocity (deg) Bin 3', '@dir_3'), ], formatters={'date': 'datetime'}) # Format the tooltip Amplitude tooltips_amp = HoverTool( tooltips=[('Bin', '@bin_num'), ( 'Bin Depth (m)', '@bin_depth'), ( 'Beam 0 (dB)', '@amp_0'), ('Beam 1 (dB)', '@amp_1'), ('Beam 2 (dB)', '@amp_2'), ('Beam 3 (dB)', '@amp_3')]) max_display = 200 self.plot_range = figure(x_axis_type='datetime', title="Wave Height") self.plot_range.x_range.follow_interval = max_display self.plot_range.xaxis.axis_label = "Time" self.plot_range.yaxis.axis_label = "Wave Height (m)" self.plot_range.add_tools(tooltips_wave_height) self.line_wave_height = self.plot_range.line(x='date', y='wave_height', line_width=2, legend="Pressure", source=self.cds, color='navy', name="wave_height") self.line_range_track = self.plot_range.line(x='date', y='range_track', line_width=2, legend="Range Track", source=self.cds, color='orange', name="range track") legend_bin_1 = "Bin" + self.rti_config.config['Waves']['selected_bin_1'] legend_bin_2 = "Bin" + self.rti_config.config['Waves']['selected_bin_2'] legend_bin_3 = "Bin" + self.rti_config.config['Waves']['selected_bin_3'] self.plot_earth_east = figure(x_axis_type='datetime', title="Earth Velocity East") self.plot_earth_east.x_range.follow_interval = max_display self.plot_earth_east.xaxis.axis_label = "Time" self.plot_earth_east.yaxis.axis_label = "Velocity (m/s)" self.plot_earth_east.add_tools(tooltips_vel_east) self.line_east_1 = self.plot_earth_east.line(x='date', y='earth_east_1', line_width=2, source=self.cds, legend=legend_bin_1, color='navy', name="east_1") self.line_east_2 = self.plot_earth_east.line(x='date', y='earth_east_2', line_width=2, source=self.cds, legend=legend_bin_2, color='skyblue', name="east_2") self.line_east_3 = self.plot_earth_east.line(x='date', y='earth_east_3', line_width=2, source=self.cds, legend=legend_bin_3, color='orange', name="east_3") self.plot_earth_north = figure(x_axis_type='datetime', title="Earth Velocity North") self.plot_earth_north.x_range.follow_interval = max_display self.plot_earth_north.xaxis.axis_label = "Time" self.plot_earth_north.yaxis.axis_label = "Velocity (m/s)" self.plot_earth_north.add_tools(tooltips_vel_north) self.line_north_1 = self.plot_earth_north.line(x='date', y='earth_north_1', line_width=2, source=self.cds, legend=legend_bin_1, color='navy', name="north_1") self.line_north_2 = self.plot_earth_north.line(x='date', y='earth_north_2', line_width=2, source=self.cds, legend=legend_bin_2, color='skyblue', name="north_2") self.line_north_3 = self.plot_earth_north.line(x='date', y='earth_north_3', line_width=2, source=self.cds, legend=legend_bin_3, color='orange', name="north_3") self.plot_mag = figure(x_axis_type='datetime', title="Water Velocity") self.plot_mag.x_range.follow_interval = max_display self.plot_mag.xaxis.axis_label = "Time" self.plot_mag.yaxis.axis_label = "Velocity (m/s)" self.plot_mag.add_tools(tooltips_mag) self.line_mag_1 = self.plot_mag.line(x='date', y='mag_1', line_width=2, source=self.cds, legend=legend_bin_1, color='navy', name="mag_1") self.line_mag_2 = self.plot_mag.line(x='date', y='mag_2', line_width=2, source=self.cds, legend=legend_bin_2, color='skyblue', name="mag_2") self.line_mag_3 = self.plot_mag.line(x='date', y='mag_3', line_width=2, source=self.cds, legend=legend_bin_3, color='orange', name="mag_3") self.plot_dir = figure(x_axis_type='datetime', title="Water Direction") self.plot_dir.x_range.follow_interval = max_display self.plot_dir.xaxis.axis_label = "Time" self.plot_dir.yaxis.axis_label = "Direction (degrees)" self.plot_dir.add_tools(tooltips_dir) self.line_dir_1 = self.plot_dir.line(x='date', y='dir_1', line_width=2, source=self.cds, legend=legend_bin_1, color='navy', name="dir_1") self.line_dir_2 = self.plot_dir.line(x='date', y='dir_2', line_width=2, source=self.cds, legend=legend_bin_2, color='skyblue', name="dir_2") self.line_dir_3 = self.plot_dir.line(x='date', y='dir_3', line_width=2, source=self.cds, legend=legend_bin_3, color='orange', name="dir_3") self.plot_amp = figure(title="Amplitude") self.plot_amp.xaxis.axis_label = "dB" self.plot_amp.yaxis.axis_label = "Bin" self.plot_amp.add_tools(tooltips_amp) self.line_amp_0 = self.plot_amp.line(x='bin_num', y='amp_0', line_width=2, source=self.cds, legend="Beam 0", color='yellow', name="amp_0") self.line_amp_1 = self.plot_amp.line(x='bin_num', y='amp_1', line_width=2, source=self.cds, legend="Beam 1", color='navy', name="amp_1") self.line_amp_2 = self.plot_amp.line(x='bin_num', y='amp_2', line_width=2, source=self.cds, legend="Beam 2", color='skyblue', name="amp_2") self.line_amp_3 = self.plot_amp.line(x='bin_num', y='amp_3', line_width=2, source=self.cds, legend="Beam 3", color='orange', name="amp_3") def setup_bokeh_server(self, doc): """ Setup the bokeh server in the mainwindow.py. The server must be started on the main thread. Use the doc given to create a layout. Also create a callback to update the plot to view the live data. :param doc: Doc used to display the data to the webpage :return: """ self.create_bokeh_plots() plot_layout_dash = layout( [[self.plot_range], [self.plot_earth_east, self.plot_earth_north], [self.plot_mag, self.plot_dir]], sizing_mode='stretch_both') plot_layout_profile = layout([[self.plot_amp]], sizing_mode='stretch_both') # Create tabs tab1 = Panel(child=plot_layout_dash, title="Dashboard") tab2 = Panel(child=plot_layout_profile, title="Profile") tabs = Tabs(tabs=[tab1, tab2]) # Document to display doc.add_root(tabs) # Callback toupdate the plot callback_rate = 2500 doc.add_periodic_callback(self.update_live_plot, callback_rate) doc.title = "ADCP Dashboard" def update_live_plot(self): """ Update the plot with live data. This will be called by the bokeh callback. Take all the data from the buffers and populate the ColumnDataSource. All the lists in the ColumnDataSource must have the same size. Call Stream to update the plot. This will append the latest data to the plot. :return: """ # Lock the thread so not updating the data while # trying to update the display #t = time.process_time() with self.thread_lock: # Verify that a least one complete dataset has been received if len(self.buffer_datetime) > 0 and len( self.buffer_wave_height ) > 0 and len(self.buffer_range_track) > 0 and len( self.buffer_earth_east_1 ) > 0 and len(self.buffer_earth_east_2) > 0 and len( self.buffer_earth_east_3 ) > 0 and len(self.buffer_earth_north_1) > 0 and len( self.buffer_earth_north_2) > 0 and len( self.buffer_earth_north_3) > 0 and len( self.buffer_mag_1) > 0 and len( self.buffer_mag_2) > 0 and len( self.buffer_mag_3) > 0 and len( self.buffer_dir_1) > 0 and len( self.buffer_dir_2) > 0 and len( self.buffer_dir_3) > 0: date_list = [] wave_height_list = [] range_track_list = [] earth_east_1 = [] earth_east_2 = [] earth_east_3 = [] earth_north_1 = [] earth_north_2 = [] earth_north_3 = [] mag_1 = [] mag_2 = [] mag_3 = [] dir_1 = [] dir_2 = [] dir_3 = [] bin_num = [] bin_depth = [] amp_0 = [] amp_1 = [] amp_2 = [] amp_3 = [] while self.buffer_datetime: date_list.append(self.buffer_datetime.popleft()) while self.buffer_wave_height: wave_height_list.append(self.buffer_wave_height.popleft()) while self.buffer_range_track: range_track_list.append(self.buffer_range_track.popleft()) while self.buffer_earth_east_1: earth_east_1.append(self.buffer_earth_east_1.popleft()) while self.buffer_earth_east_2: earth_east_2.append(self.buffer_earth_east_2.popleft()) while self.buffer_earth_east_3: earth_east_3.append(self.buffer_earth_east_3.popleft()) while self.buffer_earth_north_1: earth_north_1.append(self.buffer_earth_north_1.popleft()) while self.buffer_earth_north_2: earth_north_2.append(self.buffer_earth_north_2.popleft()) while self.buffer_earth_north_3: earth_north_3.append(self.buffer_earth_north_3.popleft()) while self.buffer_mag_1: mag_1.append(self.buffer_mag_1.popleft()) while self.buffer_mag_2: mag_2.append(self.buffer_mag_2.popleft()) while self.buffer_mag_3: mag_3.append(self.buffer_mag_3.popleft()) while self.buffer_dir_1: dir_1.append(self.buffer_dir_1.popleft()) while self.buffer_dir_2: dir_2.append(self.buffer_dir_2.popleft()) while self.buffer_dir_3: dir_3.append(self.buffer_dir_3.popleft()) while self.buffer_bin_num: bin_num.append(self.buffer_bin_num.popleft()) while self.buffer_bin_depth: bin_depth.append(self.buffer_bin_depth.popleft()) while self.buffer_amp_0: amp_0.append(self.buffer_amp_0.popleft()) while self.buffer_amp_1: amp_1.append(self.buffer_amp_1.popleft()) while self.buffer_amp_2: amp_2.append(self.buffer_amp_2.popleft()) while self.buffer_amp_3: amp_3.append(self.buffer_amp_3.popleft()) # Set the new data new_data = { 'date': date_list, 'wave_height': wave_height_list, 'range_track': range_track_list, 'earth_east_1': earth_east_1, 'earth_east_2': earth_east_2, 'earth_east_3': earth_east_3, 'earth_north_1': earth_north_1, 'earth_north_2': earth_north_2, 'earth_north_3': earth_north_3, 'mag_1': mag_1, 'mag_2': mag_2, 'mag_3': mag_3, 'dir_1': dir_1, 'dir_2': dir_2, 'dir_3': dir_3, 'bin_num': bin_num, 'bin_depth': bin_depth, 'amp_0': amp_0, 'amp_1': amp_1, 'amp_2': amp_2, 'amp_3': amp_3 } self.cds.stream(new_data, rollover=self.max_points) #print("Update Plot: " + str(time.process_time() - t)) def process_ens_group(self, fourbeam_ens, vert_ens): """ Add the Ensemble group to the plot buffers. This will take a 4 beam ensemble and a vertical beam ensemble and extract the data. It will then add the data to buffers so they can be plotted. If vert_ens is None, it means no vertical beam data is available, so use only the 4 beam data. :param fourbeam_ens: 4 or 3 Beam ensemble. :param vert_ens: Vertical ensemble. :return: """ #t = time.process_time() with self.thread_lock: # Selected bins bin_1 = int(self.rti_config.config['Waves']['selected_bin_1']) bin_2 = int(self.rti_config.config['Waves']['selected_bin_2']) bin_3 = int(self.rti_config.config['Waves']['selected_bin_3']) # Vertical beam data if vert_ens: if vert_ens.IsAncillaryData: self.buffer_wave_height.append( vert_ens.AncillaryData.TransducerDepth) # Xdcr Depth if vert_ens.IsEnsembleData: self.buffer_datetime.append( vert_ens.EnsembleData.datetime()) # Datetime if vert_ens.IsRangeTracking: self.buffer_range_track.append( vert_ens.RangeTracking.avg_range()) # Range Tracking # 4 Beam data if fourbeam_ens: # Check if no vertical beam exists if not vert_ens: if fourbeam_ens.IsAncillaryData: self.buffer_wave_height.append( fourbeam_ens.AncillaryData.TransducerDepth ) # Xdcr Depth if fourbeam_ens.IsEnsembleData: self.buffer_datetime.append( fourbeam_ens.EnsembleData.datetime()) # Datetime if fourbeam_ens.IsRangeTracking: self.buffer_range_track.append( fourbeam_ens.RangeTracking.avg_range( )) # Range Tracking # No Ancillary Pressure data but there is range tracking data, use Range Tracking if not fourbeam_ens.IsAncillaryData and fourbeam_ens.IsRangeTracking: self.buffer_range_track.append( fourbeam_ens.RangeTracking.avg_range( )) # Range Tracking # If no Range Tracking, but Ancillary Data Pressure exist, use Pressure data if not fourbeam_ens.IsRangeTracking and fourbeam_ens.IsAncillaryData: self.buffer_wave_height.append( fourbeam_ens.AncillaryData.TransducerDepth ) # Xdcr Depth if fourbeam_ens.IsAncillaryData and fourbeam_ens.IsEnsembleData and fourbeam_ens.IsAmplitude: # Set the Bin Num and Bin Depth num_bins = fourbeam_ens.EnsembleData.NumBins bin_size = fourbeam_ens.AncillaryData.BinSize blank = fourbeam_ens.AncillaryData.FirstBinRange bin_nums = [] bin_depths = [] amp_0 = [] amp_1 = [] amp_2 = [] amp_3 = [] for bin_num in range(num_bins): bin_nums.append(bin_num) bin_depths.append(blank + (bin_num * bin_size)) if fourbeam_ens.Amplitude.num_elements > 0: amp_0.append( fourbeam_ens.Amplitude.Amplitude[bin_num][0]) if fourbeam_ens.Amplitude.num_elements > 1: amp_1.append( fourbeam_ens.Amplitude.Amplitude[bin_num][1]) if fourbeam_ens.Amplitude.num_elements > 2: amp_2.append( fourbeam_ens.Amplitude.Amplitude[bin_num][2]) if fourbeam_ens.Amplitude.num_elements > 3: amp_3.append( fourbeam_ens.Amplitude.Amplitude[bin_num][3]) # Set the buffer self.buffer_bin_num.append(bin_nums) self.buffer_bin_depth.append(bin_depths) self.buffer_amp_0.append(amp_0) self.buffer_amp_1.append(amp_1) self.buffer_amp_2.append(amp_2) self.buffer_amp_3.append(amp_3) if fourbeam_ens.IsEarthVelocity: # East Bin 1 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Velocities[bin_1][0]): self.buffer_earth_east_1.append( fourbeam_ens.EarthVelocity.Velocities[bin_1][0]) else: self.buffer_earth_east_1.append(0.0) # East Bin 2 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Velocities[bin_2][0]): self.buffer_earth_east_2.append( fourbeam_ens.EarthVelocity.Velocities[bin_2][0]) else: self.buffer_earth_east_2.append(0.0) # East Bin 3 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Velocities[bin_3][0]): self.buffer_earth_east_3.append( fourbeam_ens.EarthVelocity.Velocities[bin_3][0]) else: self.buffer_earth_east_3.append(0.0) # North Bin 1 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Velocities[bin_1][1]): self.buffer_earth_north_1.append( fourbeam_ens.EarthVelocity.Velocities[bin_1][1]) else: self.buffer_earth_north_1.append(0.0) # North Bin 2 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Velocities[bin_2][1]): self.buffer_earth_north_2.append( fourbeam_ens.EarthVelocity.Velocities[bin_2][1]) else: self.buffer_earth_north_2.append(0.0) # North Bin 3 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Velocities[bin_3][1]): self.buffer_earth_north_3.append( fourbeam_ens.EarthVelocity.Velocities[bin_3][1]) else: self.buffer_earth_north_3.append(0.0) # Mag 1 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Magnitude[bin_1]): self.buffer_mag_1.append( fourbeam_ens.EarthVelocity.Magnitude[bin_1]) else: self.buffer_mag_1.append(0.0) # Mag 2 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Magnitude[bin_2]): self.buffer_mag_2.append( fourbeam_ens.EarthVelocity.Magnitude[bin_2]) else: self.buffer_mag_2.append(0.0) # Mag 3 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Magnitude[bin_3]): self.buffer_mag_3.append( fourbeam_ens.EarthVelocity.Magnitude[bin_3]) else: self.buffer_mag_3.append(0.0) # Dir 1 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Direction[bin_1]): self.buffer_dir_1.append( fourbeam_ens.EarthVelocity.Direction[bin_1]) else: self.buffer_dir_1.append(0.0) # Dir 2 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Direction[bin_2]): self.buffer_dir_2.append( fourbeam_ens.EarthVelocity.Direction[bin_2]) else: self.buffer_dir_2.append(0.0) # Dir 3 if not Ensemble.Ensemble.is_bad_velocity( fourbeam_ens.EarthVelocity.Direction[bin_3]): self.buffer_dir_3.append( fourbeam_ens.EarthVelocity.Direction[bin_3]) else: self.buffer_dir_3.append(0.0) #print("Process ENS: " + str(time.process_time() - t)) def process_awc_group(self, fourbeam_awc, vert_awc): """ Add the AverageWaterColumn data to the plot buffers. This will take the AverageWaterColumn object and extract the data. It will then add the data to buffers so they can be plotted. AWC [ss_code, ss_config, num_beams, num_bins, Beam, Instrument, Earth, Mag, Dir, Pressure, xdcr_depth, first_time, last_time, range_track] If vert_awc is None, it means no vertical beam data is available, so use only the 4 beam data. :param fourbeam_awc: Average Water Column data for 4 beam data. :param vert_awc: Average Water Column data for vert beam data. :return: """ #t = time.process_time() with self.thread_lock: # Selected bins bin_1 = int(self.rti_config.config['Waves']['selected_bin_1']) bin_2 = int(self.rti_config.config['Waves']['selected_bin_2']) bin_3 = int(self.rti_config.config['Waves']['selected_bin_3']) if vert_awc: # Datetime if vert_awc[AverageWaterColumn.INDEX_LAST_TIME]: self.buffer_datetime.append( vert_awc[AverageWaterColumn. INDEX_LAST_TIME]) # Should only be 1 value # Xdcr Depth if vert_awc[AverageWaterColumn.INDEX_XDCR_DEPTH] and len( vert_awc[AverageWaterColumn.INDEX_XDCR_DEPTH]) > 0: self.buffer_wave_height.append( vert_awc[AverageWaterColumn.INDEX_XDCR_DEPTH] [-1]) # Should only be 1 value # Range Tracking if vert_awc[AverageWaterColumn.INDEX_RANGE_TRACK] and len( vert_awc[AverageWaterColumn.INDEX_RANGE_TRACK]) > 0: self.buffer_range_track.append( vert_awc[AverageWaterColumn.INDEX_RANGE_TRACK] [-1]) # Should only be 1 beam # 4 Beam data if fourbeam_awc: # Check if no vertical beam exist if not vert_awc: # Datetime if fourbeam_awc[AverageWaterColumn.INDEX_LAST_TIME]: self.buffer_datetime.append( fourbeam_awc[AverageWaterColumn.INDEX_LAST_TIME] ) # Should only be 1 value # Xdcr Depth if fourbeam_awc[ AverageWaterColumn.INDEX_XDCR_DEPTH] and len( fourbeam_awc[ AverageWaterColumn.INDEX_XDCR_DEPTH]) > 0: self.buffer_wave_height.append( fourbeam_awc[AverageWaterColumn.INDEX_XDCR_DEPTH] [-1]) # Should only be 1 value # Range Tracking if fourbeam_awc[ AverageWaterColumn.INDEX_RANGE_TRACK] and len( fourbeam_awc[ AverageWaterColumn.INDEX_RANGE_TRACK]) > 0: self.buffer_range_track.append( fourbeam_awc[AverageWaterColumn.INDEX_RANGE_TRACK] [-1]) # Should only be 1 beam # East Bin 1 if len(fourbeam_awc[AverageWaterColumn.INDEX_EARTH] ) > bin_1 and len(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_1]) > 0: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_EARTH][bin_1] [0]): # Check for bad velocity self.buffer_earth_east_1.append(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_1][0]) else: self.buffer_earth_east_1.append(0.0) else: self.buffer_earth_east_1.append(0.0) # East Bin 2 if len(fourbeam_awc[AverageWaterColumn.INDEX_EARTH] ) > bin_2 and len(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_2]) > 0: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_EARTH][bin_2] [0]): # Check for bad velocity self.buffer_earth_east_2.append(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_2][0]) else: self.buffer_earth_east_2.append(0.0) else: self.buffer_earth_east_2.append(0.0) # East Bin 3 if len(fourbeam_awc[AverageWaterColumn.INDEX_EARTH] ) > bin_3 and len(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_3]) > 0: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_EARTH][bin_3] [0]): # Check for bad velocity self.buffer_earth_east_3.append(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_3][0]) else: self.buffer_earth_east_3.append(0.0) else: self.buffer_earth_east_3.append(0.0) # North Bin 1 if len(fourbeam_awc[AverageWaterColumn.INDEX_EARTH] ) > bin_1 and len(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_1]) > 1: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_EARTH][bin_1] [1]): # Check for bad velocity self.buffer_earth_north_1.append(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_1][1]) else: self.buffer_earth_north_1.append(0.0) else: self.buffer_earth_north_1.append(0.0) # North Bin 2 if len(fourbeam_awc[AverageWaterColumn.INDEX_EARTH] ) > bin_2 and len(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_2]) > 1: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_EARTH][bin_2] [1]): # Check for bad velocity self.buffer_earth_north_2.append(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_2][1]) else: self.buffer_earth_north_2.append(0.0) else: self.buffer_earth_north_2.append(0.0) # North Bin 3 if len(fourbeam_awc[AverageWaterColumn.INDEX_EARTH] ) > bin_3 and len(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_3]) > 1: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_EARTH][bin_3] [1]): # Check for bad velocity self.buffer_earth_north_3.append(fourbeam_awc[ AverageWaterColumn.INDEX_EARTH][bin_3][1]) else: self.buffer_earth_north_3.append(0.0) else: self.buffer_earth_north_3.append(0.0) # Mag 1 if len(fourbeam_awc[AverageWaterColumn.INDEX_MAG]) > bin_1: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_MAG] [bin_1]): # Check for bad velocity self.buffer_mag_1.append( fourbeam_awc[AverageWaterColumn.INDEX_MAG][bin_1]) else: self.buffer_mag_1.append(0.0) else: self.buffer_mag_1.append(0.0) # Mag 2 if len(fourbeam_awc[AverageWaterColumn.INDEX_MAG]) > bin_2: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_MAG][bin_2]): self.buffer_mag_2.append( fourbeam_awc[AverageWaterColumn.INDEX_MAG][bin_2]) else: self.buffer_mag_2.append(0.0) else: self.buffer_mag_2.append(0.0) # Mag 3 if len(fourbeam_awc[AverageWaterColumn.INDEX_MAG]) > bin_3: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_MAG][bin_3]): self.buffer_mag_3.append( fourbeam_awc[AverageWaterColumn.INDEX_MAG][bin_3]) else: self.buffer_mag_3.append(0.0) else: self.buffer_mag_3.append(0.0) # Dir 1 if len(fourbeam_awc[AverageWaterColumn.INDEX_DIR]) > bin_1: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_DIR][bin_1]): self.buffer_dir_1.append( fourbeam_awc[AverageWaterColumn.INDEX_DIR][bin_1]) else: self.buffer_dir_1.append(0.0) else: self.buffer_dir_1.append(0.0) # Dir 2 if len(fourbeam_awc[AverageWaterColumn.INDEX_DIR]) > bin_2: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_DIR][bin_2]): self.buffer_dir_2.append( fourbeam_awc[AverageWaterColumn.INDEX_DIR][bin_2]) else: self.buffer_dir_2.append(0.0) else: self.buffer_dir_2.append(0.0) # Dir 3 if len(fourbeam_awc[AverageWaterColumn.INDEX_DIR]) > bin_3: if not Ensemble.Ensemble.is_bad_velocity( fourbeam_awc[AverageWaterColumn.INDEX_DIR][bin_3]): self.buffer_dir_3.append( fourbeam_awc[AverageWaterColumn.INDEX_DIR][bin_3]) else: self.buffer_dir_3.append(0.0) else: self.buffer_dir_3.append(0.0)