Beispiel #1
0
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)
Beispiel #2
0
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
    })
Beispiel #3
0
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!')
Beispiel #4
0
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)