Beispiel #1
0
class IMUView(HasTraits):
    python_console_cmds = Dict()
    plot = Instance(Plot)
    plot_data = Instance(ArrayPlotData)
    imu_temp = Float(0)
    imu_conf = Int(0)
    rms_acc_x = Float(0)
    rms_acc_y = Float(0)
    rms_acc_z = Float(0)

    traits_view = View(
        VGroup(
            Item(
                'plot',
                editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8)),
                show_label=False,
            ),
            HGroup(
                Item('imu_temp', format_str='%.2f C'),
                Item('imu_conf', format_str='0x%02X'),
                Item('rms_acc_x', format_str='%.2f g'),
                Item('rms_acc_y', format_str='%.2f g'),
                Item('rms_acc_z', format_str='%.2f g'),
            ),
        ))

    def imu_set_data(self):
        self.plot_data.set_data('acc_x', self.acc[:, 0])
        self.plot_data.set_data('acc_y', self.acc[:, 1])
        self.plot_data.set_data('acc_z', self.acc[:, 2])
        self.plot_data.set_data('gyr_x', self.gyro[:, 0])
        self.plot_data.set_data('gyr_y', self.gyro[:, 1])
        self.plot_data.set_data('gyr_z', self.gyro[:, 2])

    def imu_aux_callback(self, sbp_msg, **metadata):
        if sbp_msg.imu_type == 0:
            self.imu_temp = 23 + sbp_msg.temp / 2.**9
            self.imu_conf = sbp_msg.imu_conf
        else:
            print("IMU type %d not known" % sbp_msg.imu_type)

    def imu_raw_callback(self, sbp_msg, **metadata):
        self.acc[:-1, :] = self.acc[1:, :]
        self.gyro[:-1, :] = self.gyro[1:, :]
        self.acc[-1] = (sbp_msg.acc_x, sbp_msg.acc_y, sbp_msg.acc_z)
        self.gyro[-1] = (sbp_msg.gyr_x, sbp_msg.gyr_y, sbp_msg.gyr_z)

        if self.imu_conf is not None:
            acc_range = self.imu_conf & 0xF
            sf = 2.**(acc_range + 1) / 2.**15
            self.rms_acc_x = sf * np.sqrt(np.mean(np.square(self.acc[:, 0])))
            self.rms_acc_y = sf * np.sqrt(np.mean(np.square(self.acc[:, 1])))
            self.rms_acc_z = sf * np.sqrt(np.mean(np.square(self.acc[:, 2])))

    def __init__(self, link):
        super(IMUView, self).__init__()

        self.acc = np.zeros((NUM_POINTS, 3))
        self.gyro = np.zeros((NUM_POINTS, 3))

        self.plot_data = ArrayPlotData(t=np.arange(NUM_POINTS),
                                       acc_x=[0.0],
                                       acc_y=[0.0],
                                       acc_z=[0.0],
                                       gyr_x=[0.0],
                                       gyr_y=[0.0],
                                       gyr_z=[0.0])

        self.plot = Plot(self.plot_data,
                         auto_colors=colours_list,
                         emphasized=True)
        self.plot.title = 'Raw IMU Data'
        self.plot.title_color = [0, 0, 0.43]
        self.ylim = self.plot.value_mapper.range
        self.ylim.low = -32768
        self.ylim.high = 32767
        # self.plot.value_range.bounds_func = lambda l, h, m, tb: (0, h * (1 + m))
        self.plot.value_axis.orientation = 'right'
        self.plot.value_axis.axis_line_visible = False
        self.plot.value_axis.title = 'LSB count'
        call_repeatedly(0.2, self.imu_set_data)

        self.legend_visible = True
        self.plot.legend.visible = True
        self.plot.legend.align = 'll'
        self.plot.legend.line_spacing = 1
        self.plot.legend.font = 'modern 8'
        self.plot.legend.draw_layer = 'overlay'
        self.plot.legend.tools.append(
            LegendTool(self.plot.legend, drag_button="right"))

        acc_x = self.plot.plot(('t', 'acc_x'),
                               type='line',
                               color='auto',
                               name='Accn. X')
        acc_x = self.plot.plot(('t', 'acc_y'),
                               type='line',
                               color='auto',
                               name='Accn. Y')
        acc_x = self.plot.plot(('t', 'acc_z'),
                               type='line',
                               color='auto',
                               name='Accn. Z')
        acc_x = self.plot.plot(('t', 'gyr_x'),
                               type='line',
                               color='auto',
                               name='Gyro X')
        acc_x = self.plot.plot(('t', 'gyr_y'),
                               type='line',
                               color='auto',
                               name='Gyro Y')
        acc_x = self.plot.plot(('t', 'gyr_z'),
                               type='line',
                               color='auto',
                               name='Gyro Z')

        self.link = link
        self.link.add_callback(self.imu_raw_callback, SBP_MSG_IMU_RAW)
        self.link.add_callback(self.imu_aux_callback, SBP_MSG_IMU_AUX)
        self.python_console_cmds = {'track': self}
Beispiel #2
0
class Confocal( ManagedJob, GetSetItemsMixin ):
    
    (Item('submit_gsd_button', show_label=False),
                                                   Item('remove_gsd_button', show_label=False),
                                                   Item('priority_gsd'),
                                                   Item('state_gsd', style='readonly'),
                                                   Item('history_back_gsd', show_label=False),
                                                   Item('history_forward_gsd', show_label=False),
    
    # scanner position
    x = Range(low=scanner.getXRange()[0], high=scanner.getXRange()[1], value=0.5*(scanner.getXRange()[0]+scanner.getXRange()[1]), desc='x [micron]', label='x [micron]', mode='slider')
    y = Range(low=scanner.getYRange()[0], high=scanner.getYRange()[1], value=0.5*(scanner.getYRange()[0]+scanner.getYRange()[1]), desc='y [micron]', label='y [micron]', mode='slider')
    z = Range(low=scanner.getZRange()[0], high=scanner.getZRange()[1], value=0.5*(scanner.getZRange()[0]+scanner.getZRange()[1]), desc='z [micron]', label='z [micron]', mode='slider')

    # imagging parameters
    x1 = Range(low=scanner.getXRange()[0], high=scanner.getXRange()[1], value=scanner.getXRange()[0], desc='x1 [micron]', label='x1', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float, format_str='%.2f'))
    y1 = Range(low=scanner.getYRange()[0], high=scanner.getYRange()[1], value=scanner.getYRange()[0], desc='y1 [micron]', label='y1', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float, format_str='%.2f'))
    z1 = Range(low=scanner.getZRange()[0], high=scanner.getZRange()[1], value=scanner.getZRange()[0], desc='z1 [micron]', label='z1', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float, format_str='%.2f'))
    x2 = Range(low=scanner.getXRange()[0], high=scanner.getXRange()[1], value=scanner.getXRange()[1], desc='x2 [micron]', label='x2', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float, format_str='%.2f'))
    y2 = Range(low=scanner.getYRange()[0], high=scanner.getYRange()[1], value=scanner.getYRange()[1], desc='y2 [micron]', label='y2', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float, format_str='%.2f'))
    z2 = Range(low=scanner.getZRange()[0], high=scanner.getZRange()[1], value=scanner.getZRange()[1], desc='z2 [micron]', label='z2', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float, format_str='%.2f'))
    resolution = Range(low=1, high=1000, value=100, desc='Number of point in long direction', label='resolution', auto_set=False, enter_set=True)
    seconds_per_point = Range(low=1e-3, high=10, value=0.005, desc='Seconds per point [s]', label='Seconds per point [s]', mode='text', auto_set=False, enter_set=True)
    bidirectional = Bool( True )
    return_speed = Range(low=1.0, high=100., value=10., desc='Multiplier for return speed of Scanner if mode is monodirectional', label='return speed', mode='text', auto_set=False, enter_set=True)
    constant_axis = Enum('z', 'x', 'y',
                         label='constant axis',
                         desc='axis that is not scanned when acquiring an image',
                         editor=EnumEditor(values={'x':'1:x','y':'2:y','z':'3:z',},cols=3),)

    # buttons
    history_back    = Button(label='Back')
    history_forward = Button(label='Forward')
    reset_range     = Button(label='reset range')
    reset_cursor    = Button(label='reset position')

    # plot parameters
    thresh_high = Trait( 'auto', Str('auto'), Float(10000.), desc='High Limit of image plot', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float))
    thresh_low = Trait( 'auto', Str('auto'), Float(0.), desc='Low Limit of image plot', editor=TextEditor(auto_set=False, enter_set=True, evaluate=float))
    colormap = Enum('Spectral','gray')
    show_labels = Bool(False)

    # scan data
    X = Array()
    Y = Array()
    image = Array()

    # plots
    plot_data           = Instance( ArrayPlotData )
    scan_plot           = Instance( CMapImagePlot )
    cursor              = Instance( CursorTool2D )
    zoom                = Instance( AspectZoomTool )
    figure              = Instance( Plot )
    figure_container    = Instance( HPlotContainer, editor=ComponentEditor() )
    z_label_text    = Str('z:0.0')
    cursor_position = Property(depends_on=['x','y','z','constant_axis'])
    
    get_set_items=['constant_axis', 'X', 'Y', 'thresh_high', 'thresh_low', 'seconds_per_point',
                   'return_speed', 'bidirectional', 'history', 'image', 'z_label_text',
                   'resolution', 'x', 'x1', 'x2', 'y', 'y1', 'y2', 'z', 'z1', 'z2']

    def __init__(self):
        super(Confocal, self).__init__()
        self.X = numpy.linspace(scanner.getXRange()[0], scanner.getXRange()[-1], self.resolution+1)
        self.Y = numpy.linspace(scanner.getYRange()[0], scanner.getYRange()[-1], self.resolution+1)
        self.image = numpy.zeros((len(self.X), len(self.Y)))
        self._create_plot()
        self.figure.index_range.on_trait_change(self.update_axis_li, '_low_value', dispatch='ui')
        self.figure.index_range.on_trait_change(self.update_axis_hi, '_high_value', dispatch='ui')
        self.figure.value_range.on_trait_change(self.update_axis_lv, '_low_value', dispatch='ui')
        self.figure.value_range.on_trait_change(self.update_axis_hv, '_high_value', dispatch='ui')
        self.zoom.on_trait_change(self.check_zoom, 'box', dispatch='ui')
        self.on_trait_change(self.set_mesh_and_aspect_ratio, 'X,Y', dispatch='ui')
        self.on_trait_change(self.update_image_plot, 'image', dispatch='ui')
        self.sync_trait('cursor_position', self.cursor, 'current_position')
        self.sync_trait('thresh_high', self.scan_plot.value_range, 'high_setting')
        self.sync_trait('thresh_low', self.scan_plot.value_range, 'low_setting')
        self.on_trait_change(self.scan_plot.request_redraw, 'thresh_high', dispatch='ui')
        self.on_trait_change(self.scan_plot.request_redraw, 'thresh_low', dispatch='ui')
        self.history = History(length = 10)
        self.history.put( self.copy_items(['constant_axis', 'X', 'Y', 'image', 'z_label_text', 'resolution'] ) )
        self.labels = {}
        self.label_list = []

    # scanner position

    @on_trait_change('x,y,z')
    def _set_scanner_position(self):
        if self.state != 'run':
            scanner.setPosition(self.x, self.y, self.z)
    
    @cached_property
    def _get_cursor_position(self):
        if self.constant_axis == 'x':
            return self.z, self.y
        elif self.constant_axis == 'y':
            return self.x, self.z
        elif self.constant_axis == 'z':
            return self.x, self.y
    
    def _set_cursor_position(self, position):
        if self.constant_axis == 'x':
            self.z, self.y = position
        elif self.constant_axis == 'y':
            self.x, self.z = position
        elif self.constant_axis == 'z':
            self.x, self.y = position
    
    # image acquisition
    
    def _run(self):
        """Acquire a scan"""

        try:
            self.state='run'

            self.update_mesh()
            X = self.X
            Y = self.Y
            
            XP = X[::-1]
    
            self.image=numpy.zeros((len(Y),len(X)))
            
            """
            if not self.bidirectional:
                scanner.initImageScan(len(X), len(Y), self.seconds_per_point, return_speed=self.return_speed)
            else:
                scanner.initImageScan(len(X), len(Y), self.seconds_per_point, return_speed=None)
            """
            for i,y in enumerate(Y):
                if threading.current_thread().stop_request.isSet():
                    break
                if i%2 != 0 and self.bidirectional:
                    XL = XP
                else:
                    XL = X
                YL = y * numpy.ones(X.shape)
                
                if self.constant_axis == 'x':
                      const = self.x * numpy.ones(X.shape)
                      Line = numpy.vstack( (const, YL, XL) )
                elif self.constant_axis == 'y':
                      const = self.y * numpy.ones(X.shape)
                      Line = numpy.vstack( (XL, const, YL) )
                elif self.constant_axis == 'z':
                      const = self.z * numpy.ones(X.shape)
                      Line = numpy.vstack( (XL, YL, const) )
                
                if self.bidirectional:
                    c = scanner.scanLine(Line, self.seconds_per_point)
                else:
                    c = scanner.scanLine(Line, self.seconds_per_point, return_speed=self.return_speed)
                if i%2 != 0 and self.bidirectional:
                    self.image[i,:] = c[-1::-1]
                else:
                    self.image[i,:] = c[:]
                
                """
                scanner.doImageLine(Line)
                self.image = scanner.getImage()
                """
                self.trait_property_changed('image', self.image)
          
                if self.constant_axis == 'x':
                    self.z_label_text='x:%.2f'%self.x
                elif self.constant_axis == 'y':
                    self.z_label_text='y:%.2f'%self.y
                elif self.constant_axis == 'z':
                    self.z_label_text='z:%.2f'%self.z

            """
            # block at the end until the image is ready 
            if not threading.current_thread().stop_request.isSet(): 
                self.image = scanner.getImage(1)
                self._image_changed()
            """
                
            scanner.setPosition(self.x, self.y, self.z)

            #save scan data to history
            self.history.put( self.copy_items(['constant_axis', 'X', 'Y', 'image', 'z_label_text', 'resolution'] ) )

        finally:
            self.state = 'idle'

    # plotting
    
    def _create_plot(self):
        plot_data = ArrayPlotData(image=self.image)
        plot = Plot(plot_data, width=500, height=500, resizable='hv', aspect_ratio=1.0, padding=8, padding_left=32, padding_bottom=32)
        plot.img_plot('image',  colormap=Spectral, xbounds=(self.X[0],self.X[-1]), ybounds=(self.Y[0],self.Y[-1]), name='image')
        image = plot.plots['image'][0]
        image.x_mapper.domain_limits = (scanner.getXRange()[0],scanner.getXRange()[1])
        image.y_mapper.domain_limits = (scanner.getYRange()[0],scanner.getYRange()[1])
        zoom = AspectZoomTool(image, enable_wheel=False)
        cursor = CursorTool2D(image, drag_button='left', color='blue', marker_size=1.0, line_width=1.0 )
        image.overlays.append(cursor)
        image.overlays.append(zoom)
        colormap = image.color_mapper
        colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range),
                            color_mapper=colormap,
                            plot=plot,
                            orientation='v',
                            resizable='v',
                            width=16,
                            height=320,
                            padding=8,
                            padding_left=32)
        container = HPlotContainer()
        container.add(plot)
        container.add(colorbar)
        z_label = PlotLabel(text='z=0.0', color='red', hjustify='left', vjustify='bottom', position=[10,10])
        container.overlays.append(z_label)

        self.plot_data = plot_data
        self.scan_plot = image
        self.cursor = cursor
        self.zoom = zoom
        self.figure = plot
        self.figure_container = container
        self.sync_trait('z_label_text', z_label, 'text')

    def set_mesh_and_aspect_ratio(self):
        self.scan_plot.index.set_data(self.X,self.Y)
        x1=self.X[0]
        x2=self.X[-1]
        y1=self.Y[0]
        y2=self.Y[-1]
        
        self.figure.aspect_ratio = (x2-x1) / float((y2-y1))
        self.figure.index_range.low = x1
        self.figure.index_range.high = x2
        self.figure.value_range.low = y1
        self.figure.value_range.high = y2

    def check_zoom(self, box):
        li,lv,hi,hv=box
        if self.constant_axis == 'x':
            if not li<self.z<hi:
                self.z = 0.5*(li+hi)
            if not lv<self.y<hv:
                self.y = 0.5*(lv+hv)
        elif self.constant_axis == 'y':
            if not li<self.x<hi:
                self.x = 0.5*(li+hi)
            if not lv<self.z<hv:
                self.z = 0.5*(lv+hv)
        elif self.constant_axis == 'z':
            if not li<self.x<hi:
                self.x = 0.5*(li+hi)
            if not lv<self.y<hv:
                self.y = 0.5*(lv+hv)
        
    def center_cursor(self):
        i = 0.5 * (self.figure.index_range.low + self.figure.index_range.high) 
        v = 0.5 * (self.figure.value_range.low + self.figure.value_range.high) 
        if self.constant_axis == 'x':
            self.z = i
            self.y = v
        elif self.constant_axis == 'y':
            self.x = i
            self.z = v
        elif self.constant_axis == 'z':
            self.x = i
            self.y = v
    
    def _constant_axis_changed(self):
        self.update_mesh()
        self.image = numpy.zeros((len(self.X), len(self.Y)))  
        self.update_axis()
        self.set_mesh_and_aspect_ratio()

    def update_image_plot(self):
        self.plot_data.set_data('image', self.image)
    
    def _colormap_changed(self, new):
        data = self.figure.datasources['image']
        func = getattr(chaco.api,new)
        self.figure.color_mapper=func(DataRange1D(data))
        self.figure.request_redraw()

    def _show_labels_changed(self, name, old, new):
        for item in self.scan_plot.overlays:
            if isinstance(item, DataLabel) and item.label_format in self.labels:
                item.visible = new
        self.scan_plot.request_redraw()
        
    def get_label_index(self, key):
        for index, item in enumerate(self.scan_plot.overlays):
            if isinstance(item, DataLabel) and item.label_format == key:
                 return index
        return None

    def set_label(self, key, coordinates, **kwargs):

        plot = self.scan_plot

        if self.constant_axis == 'x':
            point = (coordinates[2],coordinates[1])
        elif self.constant_axis == 'y':
            point = (coordinates[0],coordinates[2])
        elif self.constant_axis == 'z':
            point = (coordinates[0],coordinates[1])

        defaults = {'component':plot,
                    'data_point':point,
                    'label_format':key,
                    'label_position':'top right',
                    'bgcolor':'transparent',
                    'text_color':'black',
                    'border_visible':False,
                    'padding_bottom':8,
                    'marker':'cross',
                    'marker_color':'black',
                    'marker_line_color':'black',
                    'marker_line_width':1.5,
                    'marker_size':6,
                    'arrow_visible':False,
                    'clip_to_plot':False,
                    'visible':self.show_labels}

        defaults.update(kwargs)

        label = DataLabel(**defaults)

        index = self.get_label_index(key)
        if index is None:
            plot.overlays.append(label)
        else:
            plot.overlays[index] = label
        self.labels[key] = coordinates
        plot.request_redraw()

    def remove_label(self, key):
        plot = self.scan_plot
        index = self.get_label_index(key)
        plot.overlays.pop(index)
        plot.request_redraw()
        self.labels.pop(key)
        
    def remove_all_labels(self):
        plot = self.scan_plot
        new_overlays = []
        for item in plot.overlays:
            if not ( isinstance(item, DataLabel) and item.label_format in self.labels ) :
                 new_overlays.append(item)
        plot.overlays = new_overlays
        plot.request_redraw()
        self.labels.clear()
        
    @on_trait_change('constant_axis')
    def relocate_labels(self):
        for item in self.scan_plot.overlays:
            if isinstance(item, DataLabel) and item.label_format in self.labels:
                coordinates = self.labels[item.label_format]
                if self.constant_axis == 'x':
                    point = (coordinates[2],coordinates[1])
                elif self.constant_axis == 'y':
                    point = (coordinates[0],coordinates[2])
                elif self.constant_axis == 'z':
                    point = (coordinates[0],coordinates[1])
                item.data_point = point

    def update_axis_li(self):
        if self.constant_axis == 'x':
            self.z1 = self.figure.index_range.low
        elif self.constant_axis == 'y':
            self.x1 = self.figure.index_range.low
        elif self.constant_axis == 'z':
            self.x1 = self.figure.index_range.low 
    def update_axis_hi(self):
        if self.constant_axis == 'x':
            self.z2 = self.figure.index_range.high
        elif self.constant_axis == 'y':
            self.x2 = self.figure.index_range.high
        elif self.constant_axis == 'z':
            self.x2 = self.figure.index_range.high 
    def update_axis_lv(self):
        if self.constant_axis == 'x':
            self.y1 = self.figure.value_range.low
        elif self.constant_axis == 'y':
            self.z1 = self.figure.value_range.low
        elif self.constant_axis == 'z':
            self.y1 = self.figure.value_range.low 
    def update_axis_hv(self):
        if self.constant_axis == 'x':
            self.y2 = self.figure.value_range.high
        elif self.constant_axis == 'y':
            self.z2 = self.figure.value_range.high
        elif self.constant_axis == 'z':
            self.y2 = self.figure.value_range.high
    
    def update_axis(self):
        self.update_axis_li()
        self.update_axis_hi()
        self.update_axis_lv()
        self.update_axis_hv()

    def update_mesh(self):
        if self.constant_axis == 'x':
            x1=self.z1
            x2=self.z2
            y1=self.y1
            y2=self.y2
        elif self.constant_axis == 'y':
            x1=self.x1
            x2=self.x2
            y1=self.z1
            y2=self.z2
        elif self.constant_axis == 'z':
            x1=self.x1
            x2=self.x2
            y1=self.y1
            y2=self.y2

        if (x2-x1) >= (y2-y1):
            self.X = numpy.linspace(x1,x2,self.resolution)
            self.Y = numpy.linspace(y1,y2,int(self.resolution*(y2-y1)/(x2-x1)))
        else:
            self.Y = numpy.linspace(y1,y2,self.resolution)
            self.X = numpy.linspace(x1,x2,int(self.resolution*(x2-x1)/(y2-y1)))
        
    # GUI buttons

    def _history_back_fired(self):
        self.stop()
        self.set_items( self.history.back() )

    def _history_forward_fired(self):
        self.stop()
        self.set_items( self.history.forward() )

    def _reset_range_fired(self):
        self.x1 = scanner.getXRange()[0]
        self.x2 = scanner.getXRange()[1]
        self.y1 = scanner.getYRange()[0]
        self.y2 = scanner.getYRange()[1]
        self.z1 = scanner.getZRange()[0]
        self.z2 = scanner.getZRange()[1]

    def _reset_cursor_fired(self):
        self.center_cursor()

    # saving images

    def save_image(self, filename=None):
        self.save_figure(self.figure_container, filename)
        
    traits_view = View(VGroup(Hsplit(HGroup(HGroup(Item('submit_button', show_label=False),
                                                   Item('remove_button', show_label=False),
                                                   Item('priority'),
                                                   Item('state', style='readonly'),
                                                   Item('history_back', show_label=False),
                                                   Item('history_forward', show_label=False),
                                                   ),
                                            Item('figure_container', show_label=False, resizable=True,enabled_when='state != "run"'),
                                            HGroup(Item('thresh_low', width=-80),
                                                   Item('thresh_high', width=-80),
                                                   Item('colormap', width=-100),
                                                   Item('show_labels'),
                                                   ),
                                            ),
                                      HGroup(HGroup(Item('submit_gsd_button', show_label=False),
                                                   Item('remove_button', show_label=False),
                                                   Item('history_back_gsd', show_label=False),
                                                   Item('history_forward_gsd', show_label=False),
                                                   ),
                                            Item('figure_container_gsd', show_label=False, resizable=True,enabled_when='state != "run"'),
                                            HGroup(Item('thresh_low_gsd', width=-80),
                                                   Item('thresh_high_gsd', width=-80),
                                                   Item('colormap_gsd', width=-100),
                                                   Item('show_labels'),
                                                   ),
                                            ),
                                     ),
                              HGroup(Item('resolution', enabled_when='state != "run"', width=-60),
                                     Item('x1', width=-60),
                                     Item('x2', width=-60),
                                     Item('y1', width=-60),
                                     Item('y2', width=-60),
                                     Item('z1', width=-60),
                                     Item('z2', width=-60),
                                     Item('reset_range', show_label=False),
                                     ),
                              HGroup(Item('constant_axis', style='custom', show_label=False, enabled_when='state != "run"'),
                                     Item('bidirectional', enabled_when='state != "run"'),
                                     Item('seconds_per_point', width=-80),
                                     Item('return_speed', width=-80),
                                     Item('reset_cursor', show_label=False),
                                     ),
                              Item('x', enabled_when='state != "run" or (state == "run" and constant_axis == "x")'),
                              Item('y', enabled_when='state != "run" or (state == "run" and constant_axis == "y")'),
                              Item('z', enabled_when='state != "run" or (state == "run" and constant_axis == "z")'),
                       ),
                       menubar = MenuBar(Menu(Action(action='save_image', name='Save Image (.png)'),
                                              Action(action='save', name='Save (.pyd or .pys)'),
                                              Action(action='load', name='Load'),
                                              Action(action='_on_close', name='Quit'),
                                              name='File'),),
                       title='Confocal', width=880, height=800, buttons=[], resizable=True, x=0, y=0,
                       handler=GetSetSaveImageHandler)
    
    
class MandelbrotView(ModelView):
    """ Traits UI and Chaco view of a Mandelbrot set. """

    # The model part of this UI.
    model = Instance(MandelbrotParameters)

    # The Chaco plot.
    mandelbrot_plot = Instance(Plot)
    def _mandelbrot_plot_default(self):
        return self._create_mandelbrot_plot()

    # The Chaco data source for the Mandelbrot set.
    mandelbrot_plot_data = Instance(ArrayPlotData)
    def _mandelbrot_plot_data_default(self):
        plot_data = ArrayPlotData()
        self._set_plot_data(plot_data)
        return plot_data

    # The Chaco plot renderer.
    mandelbrot_renderer = Instance(AbstractPlotRenderer)

    # A button that resets the view to the default one.
    reset_view = Button
    def _reset_view_fired(self):
        self.model.set(xmin=-2, xmax=1, ymin=-1.5, ymax=1.5)

    # The colormap of the plot.
    colormap = Enum(dc.color_map_name_dict.keys())

    @on_trait_change('colormap')
    def set_colormap(self):
        data_range = DataRange1D(low=-1.0, high=200)
        colormap = dc.color_map_name_dict[self.colormap](data_range)

        self.mandelbrot_renderer.color_mapper = colormap
        self.mandelbrot_renderer.invalidate_and_redraw()

    @on_trait_change('model:xmin,model:xmax,model:ymin,model:ymax')
    def _update_plot_data_and_bounds(self):
        """ Update the image data and the plot bounds when the bounds change.
        """
        self._set_plot_data(self.mandelbrot_plot_data)
        self.mandelbrot_plot = self._create_mandelbrot_plot()

    def _create_mandelbrot_plot(self):
        plot = Plot(self.mandelbrot_plot_data)

        self.mandelbrot_renderer = plot.img_plot(
            'mandelbrot',
            xbounds=self.model.x_coords,
            ybounds=self.model.y_coords,
            name='mandelbrot_plot')[0]

        plot.aspect_ratio = 1.0
        plot.tools.append(MandelzoomTool(component=plot, params=self.model))
        self.set_colormap()

        return plot

    def _set_plot_data(self, plot_data):
        mandelbrot = mandelbrot_grid(
            self.model.x_bounds,
            self.model.y_bounds,
            self.model.grid_size
        )

        plot_data.set_data('mandelbrot', mandelbrot)

    # Traits UI definition of the UI.
    traits_view = View(
        VGroup(
            Item('mandelbrot_plot', editor=ComponentEditor(), show_label=False),
            HGroup(
                Item('colormap'),
                Item('reset_view', show_label=False)
            ),
        ),
        resizable=True,
    )
Beispiel #4
0
class GSODDataPlotterView(HasTraits):
    """ Application of the zoom tool to the GSOD plotting tool.
Load a HDF file containing one or more timeseries and plot the entire data inside.
The zoom tool allows to explore a subset of it. The legend allows to (de)select some
timeseries.
"""
    data_file = File()
    ts_data = Dict()
    ts_plot = Instance(ToolbarPlot)
    index_is_dates = Bool()

    traits_view = View(
        VGroup(
            Item('data_file', style='simple', label="HDF file to load"),
            Item('ts_plot',
                 editor=ComponentEditor(size=(800, 600)),
                 show_label=False),
        ),
        title='Chaco Plot with file loader and legend highlighter',
        width=900,
        height=800,
        resizable=True)

    def __init__(self, pandas_list=[], array_dict={}, *args, **kw):
        """ If a (list of) pandas or a dict of arrays is passed, load them up.
        """
        ts_data = {}
        super(GSODDataPlotterView, self).__init__(*args, **kw)
        if not isinstance(pandas_list, list):
            pandas_list = [pandas_list]
        if pandas_list:
            array_dict, self.index_is_dates = pandas2array_dict(pandas_list)
            ts_data.update(array_dict)
        if array_dict:
            ts_data.update(ts_dict)
        self.ts_data = ts_data  # Now trigger the plot redraw

    def _data_file_changed(self):
        """ Update the data from the HDF5 file.
       """
        ts_data, self.index_is_dates = pandas_hdf_to_data_dict2(self.data_file)
        assert ("index" in ts_data)
        self.ts_data = ts_data

    def _ts_data_changed(self):
        """ Dataset has changed: update the plot.
        ENH: add the possibility to pass a dict to ArrayPlotData.
        """
        print "data changed: updating the plot..."
        arr_data = ArrayPlotData()
        for k, v in self.ts_data.items():
            arr_data.set_data(k, v)
        self.ts_plot = ToolbarPlot(arr_data)
        for i, k in enumerate([k for k in self.ts_data.keys()
                               if k != "index"]):
            self.ts_plot.plot(("index", k),
                              name=k,
                              color=colors[i % len(colors)])
        if self.index_is_dates:
            # Index was an array of datetime: overwrite the x axis
            self.ts_plot.x_axis = None
            x_axis = PlotAxis(self.ts_plot,
                              orientation="bottom",
                              tick_generator=ScalesTickGenerator(
                                  scale=CalendarScaleSystem()))
            self.ts_plot.overlays.append(x_axis)
            self.ts_plot.x_grid.tick_generator = x_axis.tick_generator

        if self.data_file:
            self.ts_plot.title = "Time series visualization from %s" % self.data_file
        else:
            self.ts_plot.title = "Time series visualization"
        attach_tools(self.ts_plot)
Beispiel #5
0
class App(HasTraits):

    audio_stream = Instance(AudioStream, ())
    timer = Instance(Timer)

    decoder = Instance(SpeechDecoder)
    data_queue = Instance(Collapsible, ())
    results_queue = Instance(queue.Queue, ())
    decoder_thread = Instance(threading.Thread)

    spectrum_data = Instance(ArrayPlotData)
    time_data = Instance(ArrayPlotData)
    spectrogram_plotdata = Instance(ArrayPlotData)

    text = Str

    plot = Instance(Component)

    traits_view = View(
        VGroup(
            Group(Item('plot',
                       editor=ComponentEditor(size=(900, 500)),
                       show_label=False),
                  orientation="vertical"),
            UItem('text', style='custom'),
        ),
        resizable=True,
        title="Audio Spectrum",
        width=900,
        height=500,
    )

    def start(self):
        self.audio_stream.start()
        self.decoder_thread.start()

        self.timer = Timer(20, self.update)

    def stop(self):
        self.timer.Stop()

        self.data_queue.put(DONE)
        self.decoder_thread.join()

        self.audio_stream.stop()

    def update(self):
        audio_data = self.audio_stream.get_audio_data()

        normalized_time = audio_data / 32768.0
        spectrum = np.abs(scipy.fft(normalized_time))[:NUM_SAMPLES // 2]

        # Update plot data
        self.spectrum_data.set_data('amplitude', spectrum)
        self.time_data.set_data('amplitude', normalized_time)
        spectrogram_data = self.spectrogram_plotdata.get_data('imagedata')
        spectrogram_data = np.hstack(
            (spectrogram_data[:, 1:], np.transpose([spectrum])))
        self.spectrogram_plotdata.set_data('imagedata', spectrogram_data)

        # Update decoder
        self.data_queue.put(audio_data)
        try:
            self.text += self.results_queue.get_nowait()
        except queue.Empty:
            pass

    def _decoder_default(self):
        return SpeechDecoder.from_paths(
            model="deepspeech-0.5.1-models/output_graph.pbmm",
            alphabet="deepspeech-0.5.1-models/alphabet.txt",
            lm="deepspeech-0.5.1-models/lm.binary",
            trie="deepspeech-0.5.1-models/trie")

    def _decoder_thread_default(self):
        return threading.Thread(target=self._transcribe)

    def _transcribe(self):
        self.decoder.start()
        done = False
        while not done:
            for _ in range(8):
                data = self.data_queue.get()
                if data is DONE:
                    done = True
                    break
                self.decoder.update_content(data)
            result = self.decoder.decode()
            self.results_queue.put(result)
        self.decoder.stop()

    def _spectrum_data_default(self):
        frequencies = np.linspace(0.0, SAMPLING_RATE / 2, num=NUM_SAMPLES // 2)
        spectrum_data = ArrayPlotData(frequency=frequencies)
        empty_amplitude = np.zeros(NUM_SAMPLES // 2)
        spectrum_data.set_data('amplitude', empty_amplitude)
        return spectrum_data

    def _time_data_default(self):
        ts = np.linspace(0.0, NUM_SAMPLES / SAMPLING_RATE, num=NUM_SAMPLES)
        time_data = ArrayPlotData(time=ts)
        empty_amplitude = np.zeros(NUM_SAMPLES)
        time_data.set_data('amplitude', empty_amplitude)
        return time_data

    def _spectrogram_plotdata_default(self):
        spectrogram_data = np.zeros((NUM_SAMPLES // 2, SPECTROGRAM_LENGTH))
        spectrogram_plotdata = ArrayPlotData()
        spectrogram_plotdata.set_data('imagedata', spectrogram_data)
        return spectrogram_plotdata

    def _plot_default(self):
        # Set up the spectrum plot
        spectrum_plot = Plot(self.spectrum_data)
        spectrum_plot.plot(("frequency", "amplitude"),
                           name="Spectrum",
                           color="red")
        spectrum_plot.padding = 50
        spectrum_plot.title = "Spectrum"
        spec_range = list(
            spectrum_plot.plots.values())[0][0].value_mapper.range  # noqa
        spec_range.low = 0.0
        spec_range.high = 5.0
        spectrum_plot.index_axis.title = 'Frequency (Hz)'
        spectrum_plot.value_axis.title = 'Amplitude'

        # Time series plot
        time_plot = Plot(self.time_data)
        time_plot.plot(("time", "amplitude"), name="Time", color="blue")
        time_plot.padding = 50
        time_plot.title = "Time"
        time_plot.index_axis.title = 'Time (seconds)'
        time_plot.value_axis.title = 'Amplitude'
        time_range = list(time_plot.plots.values())[0][0].value_mapper.range
        time_range.low = -0.2
        time_range.high = 0.2

        # Spectrogram plot
        spectrogram_plot = Plot(self.spectrogram_plotdata)
        max_time = SPECTROGRAM_LENGTH * NUM_SAMPLES / SAMPLING_RATE
        max_freq = SAMPLING_RATE / 2
        spectrogram_plot.img_plot(
            'imagedata',
            name='Spectrogram',
            xbounds=(0, max_time),
            ybounds=(0, max_freq),
            colormap=hot,
        )
        range_obj = spectrogram_plot.plots['Spectrogram'][0].value_mapper.range
        range_obj.high = 5
        range_obj.low = 0.0
        spectrogram_plot.title = 'Spectrogram'

        container = HPlotContainer()
        container.add(spectrum_plot)
        container.add(time_plot)
        container.add(spectrogram_plot)

        return container
Beispiel #6
0
class TimeTrace( GetSetItemsMixin ):

    number_of_points = Int(200, desc='Length of Count Trace', label='Number of points', mode='text', auto_set=False, enter_set=True)
    seconds_per_point = Float(0.05, desc='Seconds per point [s]', label='Seconds per point [s]', mode='text', auto_set=False, enter_set=True)

    # trace data
    count_rate = Array()
    time = Array()

    enable_0 = Bool(True, label='channel 0', desc='enable channel 0')
    enable_1 = Bool(False, label='channel 1', desc='enable channel 1')
    enable_2 = Bool(False, label='channel 2', desc='enable channel 2')
    enable_3 = Bool(False, label='channel 3', desc='enable channel 3')
    enable_4 = Bool(False, label='channel 4', desc='enable channel 4')
    enable_5 = Bool(False, label='channel 5', desc='enable channel 5')
    enable_6 = Bool(False, label='channel 6', desc='enable channel 6')
    enable_7 = Bool(False, label='channel 7', desc='enable channel 7')

    channels = Instance( list, factory=list )

    plot = Instance( Plot )
    plot_data = Instance( ArrayPlotData )

    start_button = Button(label='start', show_label=False)
    stop_button = Button(label='stop', show_label=False)
    clear_button = Button(label='clear', show_label=False)

    get_set_items= ['count_rate', 'time', 'channels', 'number_of_points', 'seconds_per_point']

    def __init__(self, tagger, **kwargs):
        super(TimeTrace, self).__init__(**kwargs)
        self.tagger = tagger
        self._reset()

    def _channels_default(self):
        return list(np.arange(8)[np.array([self.enable_0, self.enable_1, self.enable_2, self.enable_3, self.enable_4, self.enable_5, self.enable_6, self.enable_7])])

    @on_trait_change('enable_0,enable_1,enable_2,enable_3,enable_4,enable_5,enable_6,enable_7')
    def _update_channels(self):
        self.channels = self._channels_default()

    @on_trait_change('channels,number_of_points,seconds_per_point')
    def _reset(self):
        if hasattr(self,'_timer'):
            self._timer.Stop()
        self._create_plot()
        self._counter = Counter(self.tagger, self.channels, int(self.seconds_per_point*1e12), self.number_of_points)
        self.time = self._counter.getIndex() * 1e-12
        self.count_rate = self._counter.getData() / self.seconds_per_point
        self._timer = Timer(100, self._refresh_data)
        self._timer.Start()

    def _refresh_data(self):
        self.count_rate = self._counter.getData() / self.seconds_per_point

    def _count_rate_changed(self, new):
        for i, line_i in enumerate(new):
            self.plot_data.set_data('channel_'+str(self.channels[i]), line_i)

    def _time_changed(self, new):
        self.plot_data.set_data('time', new)

    def _create_plot(self):
        kwargs = {}
        for i, channel_i in enumerate(self.channels):
            kwargs['channel_'+str(channel_i)] = np.array(())
        data = ArrayPlotData(time=np.array(()), **kwargs)
        plot = Plot(data, width=100, height=100, resizable='hv', padding_left=96, padding_bottom=32)
        plot.index_axis.title = 'time [s]'
        plot.value_axis.title = 'count rate [counts/s]'

        color_map = {0:'blue', 1:'red', 2:'green', 3:'black', 4:'brown', 5:'yellow', 6:'magenta', 7:'cyan'}

        for channel in self.channels:
            plot.plot(('time','channel_'+str(channel)), type='line', color=color_map[channel], name='channel '+str(channel))

        plot.legend.align = 'll'
        if len(self.channels) > 1:
            plot.legend.visible = True
        else:
            plot.legend.visible = False

        self.plot_data = data
        self.plot = plot

    def _clear_button_fired(self):
        self._counter.clear()
        self.count_rate = self._counter.getData()

    def _start_button_fired(self):
        self._counter.start()
        self._timer.Start()

    def _stop_button_fired(self):
        self._counter.stop()
        self._timer.Stop()

    def __del__(self):
        self._timer.Stop()

    traits_view = View(VGroup(
                       HGroup(Item('clear_button', show_label=False),
                              Item('start_button', show_label=False),
                              Item('stop_button', show_label=False),
                              Item('save_button', show_label=False),
                              ),
                       HGroup(Item('plot', editor=ComponentEditor(size=(100,100)), show_label=False),
                              VGroup(Item('enable_0'),
                                     Item('enable_1'),
                                     Item('enable_2'),
                                     Item('enable_3'),
                                     Item('enable_4'),
                                     Item('enable_5'),
                                     Item('enable_6'),
                                     Item('enable_7'),
                                     ),
                              ),
                       HGroup(Item('number_of_points'),
                              Item ('seconds_per_point'),
                              ),
                       ),
                       title='Counter',
                       width=780,
                       height=520,
                       buttons=[],
                       resizable=True,
                       )
Beispiel #7
0
class SolutionView(HasTraits):
    python_console_cmds = Dict()
    # we need to doubleup on Lists to store the psuedo absolutes separately
    # without rewriting everything
    lats = List()
    lngs = List()
    alts = List()
    """
  logging_v : toggle logging for velocity files
  directory_name_v : location and name of velocity files
  logging_p : toggle logging for position files
  directory_name_p : location and name of velocity files
  """

    logging_v = Bool(False)
    directory_name_v = File

    logging_p = Bool(False)
    directory_name_p = File

    lats_psuedo_abs = List()
    lngs_psuedo_abs = List()
    alts_psuedo_abs = List()

    table_spp = List()
    table_psuedo_abs = List()
    dops_table = List()
    pos_table_spp = List()
    vel_table = List()

    rtk_pos_note = Str(
        "It is necessary to enter the \"Surveyed Position\" settings for the base station in order to view the psuedo-absolute RTK Positions in this tab."
    )

    plot = Instance(Plot)
    plot_data = Instance(ArrayPlotData)
    # Store plots we care about for legend

    running = Bool(True)
    zoomall = Bool(False)
    position_centered = Bool(False)

    clear_button = SVGButton(label='',
                             tooltip='Clear',
                             filename=os.path.join(determine_path(), 'images',
                                                   'iconic', 'x.svg'),
                             width=16,
                             height=16)
    zoomall_button = SVGButton(label='',
                               tooltip='Zoom All',
                               toggle=True,
                               filename=os.path.join(determine_path(),
                                                     'images', 'iconic',
                                                     'fullscreen.svg'),
                               width=16,
                               height=16)
    center_button = SVGButton(label='',
                              tooltip='Center on Solution',
                              toggle=True,
                              filename=os.path.join(determine_path(), 'images',
                                                    'iconic', 'target.svg'),
                              width=16,
                              height=16)
    paused_button = SVGButton(label='',
                              tooltip='Pause',
                              toggle_tooltip='Run',
                              toggle=True,
                              filename=os.path.join(determine_path(), 'images',
                                                    'iconic', 'pause.svg'),
                              toggle_filename=os.path.join(
                                  determine_path(), 'images', 'iconic',
                                  'play.svg'),
                              width=16,
                              height=16)

    traits_view = View(
        HSplit(
            Tabbed(
                VGroup(Item('',
                            label='Single Point Position (SPP)',
                            emphasized=True),
                       Item('table_spp',
                            style='readonly',
                            editor=TabularEditor(adapter=SimpleAdapter()),
                            show_label=False,
                            width=0.3),
                       label='Single Point Position'),
                VGroup(Item('', label='RTK Position', emphasized=True),
                       Item('table_psuedo_abs',
                            style='readonly',
                            editor=TabularEditor(adapter=SimpleAdapter()),
                            show_label=False,
                            width=0.3,
                            height=0.9),
                       Item('rtk_pos_note',
                            show_label=False,
                            resizable=True,
                            editor=MultilineTextEditor(
                                TextEditor(multi_line=True)),
                            style='readonly',
                            width=0.3,
                            height=-40),
                       label='RTK Position')),
            VGroup(
                HGroup(
                    Item('paused_button', show_label=False),
                    Item('clear_button', show_label=False),
                    Item('zoomall_button', show_label=False),
                    Item('center_button', show_label=False),
                ),
                Item('plot',
                     show_label=False,
                     editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8))),
            )))

    def _zoomall_button_fired(self):
        self.zoomall = not self.zoomall

    def _center_button_fired(self):
        self.position_centered = not self.position_centered

    def _paused_button_fired(self):
        self.running = not self.running

    def _clear_button_fired(self):
        self.lats = []
        self.lngs = []
        self.alts = []
        self.lats_psuedo_abs = []
        self.lngs_psuedo_abs = []
        self.alts_psuedo_abs = []
        self.plot_data.set_data('lat', [])
        self.plot_data.set_data('lng', [])
        self.plot_data.set_data('alt', [])
        self.plot_data.set_data('t', [])
        self.plot_data.set_data('lat_ps', [])
        self.plot_data.set_data('lng_ps', [])
        self.plot_data.set_data('alt_ps', [])
        self.plot_data.set_data('t_ps', [])

    def _pos_llh_callback(self, sbp_msg, **metadata):
        # Updating an ArrayPlotData isn't thread safe (see chaco issue #9), so
        # actually perform the update in the UI thread.
        if self.running:
            GUI.invoke_later(self.pos_llh_callback, sbp_msg)

    def mode_string(self, msg):
        if msg:
            if (msg.flags & 0xff) == 0:
                return 'SPP (single point position)'
            elif (msg.flags & 0xff) == 1:
                return 'Fixed RTK'
            elif (msg.flags & 0xff) == 2:
                return 'Float RTK'
        return 'None'

    def update_table(self):
        self._table_list = self.table_spp.items()

    def auto_survey(self):
        if self.counter < 1000:
            self.counter = self.counter + 1
        self.latitude_list.append(self.last_soln.lat)
        self.longitude_list.append(self.last_soln.lon)
        self.altitude_list.append(self.last_soln.height)
        self.latitude_list = self.latitude_list[-1000:]
        self.longitude_list = self.longitude_list[-1000:]
        self.altitude_list = self.altitude_list[-1000:]
        self.latitude = (sum(self.latitude_list)) / self.counter
        self.altitude = (sum(self.altitude_list)) / self.counter
        self.longitude = (sum(self.longitude_list)) / self.counter

    def pos_llh_callback(self, sbp_msg, **metadata):
        self.last_stime_update = time.time()
        soln = MsgPosLLH(sbp_msg)
        self.last_soln = soln
        masked_flag = soln.flags & 0x7
        if masked_flag == 0:
            psuedo_absolutes = False
        else:
            psuedo_absolutes = True
        pos_table = []

        tow = soln.tow * 1e-3
        if self.nsec is not None:
            tow += self.nsec * 1e-9

        if self.week is not None:
            t = datetime.datetime(1980, 1, 6) + \
                datetime.timedelta(weeks=self.week) + \
                datetime.timedelta(seconds=tow)
            pos_table.append(('GPS Time', t))
            pos_table.append(('GPS Week', str(self.week)))

            if (self.directory_name_p == ''):
                filepath_p = time.strftime("position_log_%Y%m%d-%H%M%S.csv")
            else:
                filepath_p = os.path.join(
                    self.directory_name_p,
                    time.strftime("position_log_%Y%m%d-%H%M%S.csv"))

            if self.logging_p == False:
                self.log_file = None

            if self.logging_p:
                if self.log_file is None:
                    self.log_file = open(filepath_p, 'w')
                    self.log_file.write(
                        "time,latitude(degrees),longitude(degrees),altitude(meters),n_signals,flags\n"
                    )

                self.log_file.write('%s,%.10f,%.10f,%.4f,%d,%d\n' %
                                    (str(t), soln.lat, soln.lon, soln.height,
                                     soln.n_sats, soln.flags))
                self.log_file.flush()

        pos_table.append(('GPS ToW', tow))

        pos_table.append(('Num. Signals', soln.n_sats))

        pos_table.append(('Lat', soln.lat))
        pos_table.append(('Lng', soln.lon))
        pos_table.append(('Alt', soln.height))
        pos_table.append(('Flags', '0x%02x' % soln.flags))

        pos_table.append(('Mode', self.mode_string(soln)))

        self.auto_survey()

        if psuedo_absolutes:
            # setup_plot variables
            self.lats_psuedo_abs.append(soln.lat)
            self.lngs_psuedo_abs.append(soln.lon)
            self.alts_psuedo_abs.append(soln.height)

            self.lats_psuedo_abs = self.lats_psuedo_abs[-1000:]
            self.lngs_psuedo_abs = self.lngs_psuedo_abs[-1000:]
            self.alts_psuedo_abs = self.alts_psuedo_abs[-1000:]

            self.plot_data.set_data('lat_ps', self.lats_psuedo_abs)
            self.plot_data.set_data('lng_ps', self.lngs_psuedo_abs)
            self.plot_data.set_data('alt_ps', self.alts_psuedo_abs)
            self.plot_data.set_data('cur_lat_ps', [soln.lat])
            self.plot_data.set_data('cur_lng_ps', [soln.lon])
            t_psuedo_abs = range(len(self.lats))
            if t is not None:
                self.plot_data.set_data('t', t)
            self.plot_data.set_data('t_ps', t_psuedo_abs)
            # set-up table variables
            self.table_psuedo_abs = pos_table

        else:
            # setup_plot variables
            self.lats.append(soln.lat)
            self.lngs.append(soln.lon)
            self.alts.append(soln.height)

            self.lats = self.lats[-1000:]
            self.lngs = self.lngs[-1000:]
            self.alts = self.alts[-1000:]

            self.plot_data.set_data('lat', self.lats)
            self.plot_data.set_data('lng', self.lngs)
            self.plot_data.set_data('alt', self.alts)
            self.plot_data.set_data('cur_lat', [soln.lat])
            self.plot_data.set_data('cur_lng', [soln.lon])
            t = range(len(self.lats))
            self.plot_data.set_data('t', t)

            # set-up table variables
            self.pos_table_spp = pos_table
            self.table_spp = self.pos_table_spp + self.vel_table + self.dops_table
            # TODO: figure out how to center the graph now that we have two separate messages
            # when we selectivtely send only SPP, the centering function won't work anymore
            if self.position_centered:
                d = (self.plot.index_range.high -
                     self.plot.index_range.low) / 2.
                self.plot.index_range.set_bounds(soln.lon - d, soln.lon + d)
                d = (self.plot.value_range.high -
                     self.plot.value_range.low) / 2.
                self.plot.value_range.set_bounds(soln.lat - d, soln.lat + d)
        if self.zoomall:
            plot_square_axes(self.plot, 'lng', 'lat')

    def dops_callback(self, sbp_msg, **metadata):
        dops = MsgDops(sbp_msg)
        self.dops_table = [('PDOP', '%.1f' % (dops.pdop * 0.01)),
                           ('GDOP', '%.1f' % (dops.gdop * 0.01)),
                           ('TDOP', '%.1f' % (dops.tdop * 0.01)),
                           ('HDOP', '%.1f' % (dops.hdop * 0.01)),
                           ('VDOP', '%.1f' % (dops.vdop * 0.01))]
        self.table_spp = self.pos_table_spp + self.vel_table + self.dops_table

    def vel_ned_callback(self, sbp_msg, **metadata):
        vel_ned = MsgVelNED(sbp_msg)

        tow = vel_ned.tow * 1e-3
        if self.nsec is not None:
            tow += self.nsec * 1e-9

        if self.week is not None:
            t = datetime.datetime(1980, 1, 6) + \
                datetime.timedelta(weeks=self.week) + \
                datetime.timedelta(seconds=tow)

            if self.directory_name_v == '':
                filepath_v = time.strftime("velocity_log_%Y%m%d-%H%M%S.csv")
            else:
                filepath_v = os.path.join(
                    self.directory_name_v,
                    time.strftime("velocity_log_%Y%m%d-%H%M%S.csv"))

            if self.logging_v == False:
                self.vel_log_file = None

            if self.logging_v:

                if self.vel_log_file is None:
                    self.vel_log_file = open(filepath_v, 'w')
                    self.vel_log_file.write(
                        'time,north(m/s),east(m/s),down(m/s),speed(m/s),num_signals\n'
                    )

                self.vel_log_file.write(
                    '%s,%.6f,%.6f,%.6f,%.6f,%d\n' %
                    (str(t), vel_ned.n * 1e-3, vel_ned.e * 1e-3,
                     vel_ned.d * 1e-3,
                     math.sqrt(vel_ned.n * vel_ned.n + vel_ned.e * vel_ned.e) *
                     1e-3, vel_ned.n_sats))
                self.vel_log_file.flush()

        self.vel_table = [
            ('Vel. N', '% 8.4f' % (vel_ned.n * 1e-3)),
            ('Vel. E', '% 8.4f' % (vel_ned.e * 1e-3)),
            ('Vel. D', '% 8.4f' % (vel_ned.d * 1e-3)),
        ]
        self.table_spp = self.pos_table_spp + self.vel_table + self.dops_table

    def gps_time_callback(self, sbp_msg, **metadata):
        self.week = MsgGPSTime(sbp_msg).wn
        self.nsec = MsgGPSTime(sbp_msg).ns

    def __init__(self, link, dirname=''):
        super(SolutionView, self).__init__()

        self.log_file = None
        self.directory_name_v = dirname
        self.directory_name_p = dirname
        self.vel_log_file = None
        self.last_stime_update = 0
        self.last_soln = None

        self.counter = 0
        self.latitude_list = []
        self.longitude_list = []
        self.altitude_list = []
        self.altitude = 0
        self.longitude = 0
        self.latitude = 0

        self.plot_data = ArrayPlotData(lat=[],
                                       lng=[],
                                       alt=[],
                                       t=[],
                                       cur_lat=[],
                                       cur_lng=[],
                                       cur_lat_ps=[],
                                       cur_lng_ps=[],
                                       lat_ps=[],
                                       lng_ps=[],
                                       alt_ps=[],
                                       t_ps=[])
        self.plot = Plot(self.plot_data)

        # 1000 point buffer
        self.plot.plot(('lng', 'lat'),
                       type='line',
                       name='',
                       color=(0, 0, 0.9, 0.1))
        self.plot.plot(('lng', 'lat'),
                       type='scatter',
                       name='',
                       color='blue',
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        self.plot.plot(('lng_ps', 'lat_ps'),
                       type='line',
                       name='',
                       color=(1, 0.4, 0, 0.1))
        self.plot.plot(('lng_ps', 'lat_ps'),
                       type='scatter',
                       name='',
                       color='orange',
                       marker='diamond',
                       line_width=0.0,
                       marker_size=1.0)
        # current values
        spp = self.plot.plot(('cur_lng', 'cur_lat'),
                             type='scatter',
                             name='SPP',
                             color='blue',
                             marker='plus',
                             line_width=1.5,
                             marker_size=5.0)
        rtk = self.plot.plot(('cur_lng_ps', 'cur_lat_ps'),
                             type='scatter',
                             name='RTK',
                             color='orange',
                             marker='plus',
                             line_width=1.5,
                             marker_size=5.0)
        plot_labels = ['SPP', 'RTK']
        plots_legend = dict(zip(plot_labels, [spp, rtk]))
        self.plot.legend.plots = plots_legend
        self.plot.legend.visible = True

        self.plot.index_axis.tick_label_position = 'inside'
        self.plot.index_axis.tick_label_color = 'gray'
        self.plot.index_axis.tick_color = 'gray'
        self.plot.index_axis.title = 'Longitude (degrees)'
        self.plot.index_axis.title_spacing = 5
        self.plot.value_axis.tick_label_position = 'inside'
        self.plot.value_axis.tick_label_color = 'gray'
        self.plot.value_axis.tick_color = 'gray'
        self.plot.value_axis.title = 'Latitude (degrees)'
        self.plot.value_axis.title_spacing = 5
        self.plot.padding = (25, 25, 25, 25)

        self.plot.tools.append(PanTool(self.plot))
        zt = ZoomTool(self.plot,
                      zoom_factor=1.1,
                      tool_mode="box",
                      always_on=False)
        self.plot.overlays.append(zt)

        self.link = link
        self.link.add_callback(self._pos_llh_callback, SBP_MSG_POS_LLH)
        self.link.add_callback(self.vel_ned_callback, SBP_MSG_VEL_NED)
        self.link.add_callback(self.dops_callback, SBP_MSG_DOPS)
        self.link.add_callback(self.gps_time_callback, SBP_MSG_GPS_TIME)

        self.week = None
        self.nsec = 0

        self.python_console_cmds = {
            'solution': self,
        }
class PandasPlot(HasTraits):
    '''Plot to interface a pandas df'''

    ### For testing
    rnd_cols = Bool(False)
    samecols = Bool(False)
    transpose = Bool(False)

    ### Traits of the actual plot and plotdatasource handler ###
    _dffull = Instance(DataFrame)  #Any?
    plot = Instance(Plot)
    plotdata = Instance(
        PandasPlotData)  #Data stored at any given time in the plot
    df = Instance(DataFrame)

    ### Axis traits
    idxname = Str('Index')
    colname = Str('Column')
    idxorient = DefaultEnum('top', 'bottom', 'left', 'right', default='bottom')
    colorient = DefaultEnum('top', 'bottom', 'left', 'right', default='top')
    selection_axis = DefaultEnum(
        'index', 'value',
        default='index')  #Which axis does selection tool sample

    ### Aesthetic traits
    title = Str('Title')  #Defaults from df name
    linecolor = Str('yellow')
    pointcolor = Str('red')
    linestyle = Enum('line', 'scatter', 'both')
    markersize = Range(low=1, high=5)

    sampling = Range(low=0.0, high=100., value=100.0)
    _spacing = Property(depends_on='sampling')

    ### _Event Handlers

    def _rnd_cols_changed(self):

        x = np.linspace(0, 100, 100)  #Index generator
        y = np.linspace(0, 100, 100)  #Column generator

        scale = randint(1, 1000)

        self.df = DataFrame((np.random.rand(len(x), len(y))),
                            columns=(scale / 2.0) * y,
                            index=scale * x)

    def _samecols_changed(self):
        self.df = DataFrame((np.random.rand(100, 100)))

    def _transpose_changed(self):
        self.df = self.df.transpose()

    ### Axis Aesthetics
    @on_trait_change('idxname', 'idxcolumn', 'idxorient', 'colorient')
    def _axis_changed(self, trait, new):
        '''Change plot axis name or orientation'''
        setattr(self, trait, new)
        self._update_axis()
        self.plot.request_redraw(
        )  #Necessary but how do I only call axis redraw?

    def _title_changed(self, old, new):
        if old != new:
            self.plot.title = new
            self.plot.request_redraw(
            )  #HOW TO PREVENT COLLISION WITH TOP OVERLAY

    def _selection_axis_changed(self, old, new):
        if old != new:
            self._update_lines()

    def _df_changed(self, old, new):
        ''' Handles how updates occur when df changes.  Evaluates if columns or columnlabels
        have been changed.  Provides entry condition as well.

        Note: New automatically sets self.df, so when I refer to new, I am actually
        referring to self.df.  Using "new" instead of self.df is just for readability'''

        ### Initialize plot first time df is passed into the class.  Boolean listeners
        ### for df behave oddly, so uses self.plotdata for entry condition.

        if not self.plotdata:
            self.plotdata = PandasPlotData(df=new)

            self._dffull = new

            ### Try to infer plot title from df name ###
            try:
                self.title = new.name  #Turn into a "transfer" method where I pass list of attributes i want look for
            except AttributeError:
                pass

            ### Draw barebones of plot
            self._plot_default()
            self._update_lines()

        ### Decide to update columns or completely redraw df.
        else:
            changed = self.plotdata.set_df(new)

            ### If 'event changed', don't bother updaing lines
            if not changed:
                self._update_lines()

    ### Plot spacing

    def _get__spacing(self):
        '''Integer spacing given % sampling'''
        samp = self.sampling / 100.0
        colsize = df.shape[0]
        return colsize - int(round(colsize * samp, 0))

    def _sampling_changed(self, old, new):
        if old != new:
            self._update_samples()

    def _update_samples(self):
        '''Updates the list of line plots shown or hidden based on plot sampling.'''
        if self._spacing == 0:
            return

        ### Hide all plots
        to_hide = self.plot.plots.keys()
        self.plot.hideplot(*to_hide)

        ### Show only plots in samples
        to_show = self.plot.plots.keys()[::self._spacing]
        self.plot.showplot(*to_show)
        self.plot.request_redraw()

    def _update_rangeselect(self):
        ''' Overwrites range selection tool in current plot.'''

        #### Remove current overlay
        self.plot.overlays = [
            obj for obj in self.plot.overlays
            if not isinstance(obj, RangeSelectionOverlay)
        ]

        mycomp = self.plot.plots.itervalues().next()[
            0]  #Quick wayt to get first value in dictionary

        inds = range(len(self.df.index))
        idx = ArrayDataSource(inds)
        vals = ArrayDataSource(df.index.values)

        index_range = DataRange1D(idx)
        val_range = DataRange1D(vals)
        imap = LinearMapper(
            range=index_range)  #,stretch_data=self.index_mapper.stretch_data)
        vmap = LinearMapper(range=val_range)
        #   mycomp.index_range.refresh()

        mycomp.index_mapper = imap
        mycomp.value_mapper = vmap

        self.rangeselect = RangeSelection(mycomp, axis=self.selection_axis)
        self.plot.active_tool = self.rangeselect
        self.plot.overlays.append(RangeSelectionOverlay(component=mycomp))
        self.rangeselect.on_trait_change(self.on_selection_changed,
                                         "selection")

    def _update_lines(self):
        ''' Redraws lines, plots and reapplies line selection.'''

        oldplots = self.plot.plots.keys()
        newplots = [name for name in self.plotdata.list_data(as_strings=True)]

        to_remove = [p for p in oldplots if p not in newplots]
        to_add = [p for p in newplots if p not in oldplots]

        if to_remove:
            for p in to_remove:
                self.plot.delplot(p)

        if to_add:
            for name in to_add:
                self.plot.plot(('index', name),
                               name=name,
                               color=self.linecolor)

        self._update_axis()
        self._update_samples()
        self._update_rangeselect()

    def on_selection_changed(self, selection):
        if selection != None:
            self.rangeXMin, self.rangeXMax = selection
            print selection

    def _update_axis(self):
        ''' Forces a label axis onto the plot. '''

        print 'updaing axis', self.idxname

        indexlabels = [str(round(i, 1)) for i in self.df.index]
        columnlabels = [str(round(i, 1)) for i in self.df.columns]

        index_axis = LabelAxis(
            self.plot,
            orientation=self.idxorient,
            positions=range(int(float(indexlabels[0])),
                            int(float(indexlabels[-1]))),
            labels=indexlabels,  #, resizable='hv',
            title=self.idxname)

        col_axis = LabelAxis(
            self.plot,
            orientation=self.colorient,
            positions=range(int(float(columnlabels[0])),
                            int(float(columnlabels[-1]))),
            labels=columnlabels,  #, resizable='hv',
            title=self.colname)

        ### Remove underlays
        self.plot.underlays = [
            obj for obj in self.plot.underlays
            if not isinstance(obj, PlotAxis)
        ]
        self.plot.underlays = [
            obj for obj in self.plot.underlays
            if not isinstance(obj, LabelAxis)
        ]

        self.plot.underlays.append(index_axis)
        self.plot.underlays.append(col_axis)

    def _plot_default(self, toolbar=True, **pltkwds):
        ''' Draw bare plot, including main plotting area, toolbar, etc...
         either at initialization or global redo'''

        if toolbar:
            self.plot = ToolbarPlot(self.plotdata, **pltkwds)
        else:
            self.plot = Plot(self.plotdata, **pltkwds)

        self.plot.title = self.title
        self.plot.padding = 50
        self.plot.legend.visible = False

        self.plot.tools.append(PanTool(self.plot))
        zoom = BetterSelectingZoom(component=self.plot,
                                   tool_mode="box",
                                   always_on=False)
        self.plot.overlays.append(zoom)

    def _overwrite_plotdata(self):
        '''When a new instance of PandasPlotData is created, this overwrites the
        data source and updates the axis values.'''
        self.plotdata = PandasPlotData(df=self.df)
        self._plot_default()  #CAN THIS JUST DRAW LINES

    ### Traits View

    main_group = Group(
        HGroup(
            Item('rnd_cols'),
            Item('samecols'),
            Item('transpose'),
        ),
        Item('plot', editor=ComponentEditor(), show_label=False),
        Item('idxname'),
        Item('idxorient'),
        Item('selection_axis'),
        Item('title'),
        Item('sampling'),

        #   Item('df_new'), Item('df_change'),
        #Include('sample_group'),
        #Include('axis_traits_group')
    )

    traits_view = View(Include('main_group'), height=600, width=800)
Beispiel #9
0
class Viewer(HasTraits):

    iterations = Range(0, 'max_iters')

    triangle = Instance(Component)

    comp = Instance(Component)

    base_width = Int(500)

    max_iters = Property(observe="base_width, viewport.zoom")

    viewport = Instance(Viewport)

    def _get_bounds(self):
        return [self.base_width, self.base_width * (SQRT3 / 2)]

    def _get_max_iters(self):
        factor = 1
        if self.viewport:
            factor = self.viewport.zoom
        return int(np.log(4 / (factor * self.base_width)) / np.log(.5) + 1)

    def _comp_default(self):
        canvas = Canvas(draw_axes=True, bgcolor="gray")
        self.triangle = SierpinskiTriangle(
            position=[0.0, 0.0],
            bounds=[self.base_width, self.base_width * (SQRT3 / 2)],
            iterations=self.iterations,
            max_iters=self.max_iters,
            base_width=self.base_width,
            bgcolor="gray")
        canvas.add(self.triangle)

        self.viewport = Viewport(component=canvas,
                                 enable_zoom=True,
                                 stay_inside=True)
        self.viewport.zoom_tool.min_zoom = 1.0
        self.viewport.tools.append(
            ViewportPanTool(self.viewport, drag_button="right"))

        scrolled = Scrolled(
            canvas,
            inside_padding_width=0,
            mousewheel_scroll=False,
            viewport_component=self.viewport,
            always_show_sb=True,
            continuous_drag_update=True,
        )
        return scrolled

    @observe("base_width")
    def _update_base_width(self, event):
        self.triangle.bounds = [event.new, event.new * (SQRT3 / 2)]
        self.triangle.base_width = event.new
        self.triangle.invalidate_and_redraw()

    @observe("iterations")
    def _redraw(self, event):
        self.triangle.iterations = event.new
        self.triangle.invalidate_and_redraw()

    traits_view = View(
        Item(name='iterations'),
        Item(name='base_width'),
        UItem("comp", editor=ComponentEditor(size=(500, 500)), resizable=True),
        resizable=True,
        buttons=["OK"],
        title="Sierpinski's triangle",
    )
Beispiel #10
0
class MagView(HasTraits):
    python_console_cmds = Dict()
    plot = Instance(Plot)
    plot_data = Instance(ArrayPlotData)

    traits_view = View(
        VGroup(
            Item('plot',
                 editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8)),
                 show_label=False), ))

    def mag_set_data(self):
        self.last_plot_update_time = monotonic()
        min_data = np.min(self.mag)
        max_data = np.max(self.mag)
        padding = (max_data - min_data) / 4.0
        if (self.plot.value_range.low_setting == 'auto'
                or (min_data - padding) < self.plot.value_range.low_setting):
            self.plot.value_range.low_setting = min_data - padding
        if (self.plot.value_range.high_setting == 'auto'
                or (max_data + padding) > self.plot.value_range.high_setting):
            self.plot.value_range.high_setting = max_data + padding
        self.plot_data.set_data('mag_x', self.mag[:, 0])
        self.plot_data.set_data('mag_y', self.mag[:, 1])
        self.plot_data.set_data('mag_z', self.mag[:, 2])

    def mag_raw_callback(self, sbp_msg, **metadata):
        self.mag[:-1, :] = self.mag[1:, :]
        self.mag[-1] = (sbp_msg.mag_x, sbp_msg.mag_y, sbp_msg.mag_z)
        if monotonic() - self.last_plot_update_time > GUI_UPDATE_PERIOD:
            self.mag_set_data()

    def __init__(self, link):
        super(MagView, self).__init__()

        self.mag = np.zeros((NUM_POINTS, 3))
        self.last_plot_update_time = 0

        self.plot_data = ArrayPlotData(t=np.arange(NUM_POINTS),
                                       mag_x=[0.0],
                                       mag_y=[0.0],
                                       mag_z=[0.0])

        self.plot = Plot(self.plot_data,
                         auto_colors=colours_list,
                         emphasized=True)
        self.plot.title = 'Raw Magnetometer Data'
        self.plot.title_color = [0, 0, 0.43]
        self.plot.value_axis.orientation = 'right'
        self.plot.value_axis.axis_line_visible = False
        self.legend_visible = True
        self.plot.legend.visible = True
        self.plot.legend.align = 'll'
        self.plot.legend.line_spacing = 1
        self.plot.legend.font = 'modern 8'
        self.plot.legend.draw_layer = 'overlay'
        self.plot.legend.tools.append(
            LegendTool(self.plot.legend, drag_button="right"))

        mag_x = self.plot.plot(('t', 'mag_x'),
                               type='line',
                               color='auto',
                               name='Mag. X (uT)')
        mag_y = self.plot.plot(('t', 'mag_y'),
                               type='line',
                               color='auto',
                               name='Mag. Y (uT)')
        mag_z = self.plot.plot(('t', 'mag_z'),
                               type='line',
                               color='auto',
                               name='Mag. Z (uT)')

        self.link = link
        self.link.add_callback(self.mag_raw_callback, SBP_MSG_MAG_RAW)
        self.python_console_cmds = {'track': self}
Beispiel #11
0
class PulsedTool(GetSetItemsMixin):
    """
    Widget to plot a pulsed measurement.
    
    We plot
      * the raw data as an image
      * the average fluorescence response as a line plot
        (the average fluorescence response
        is used to determine a trigger point).
      * the spin state as a line plot
    """

    # the measurement to analyze
    measurement = Any(editor=InstanceEditor)

    # plotting
    matrix_data = Instance(ArrayPlotData)
    line_data = Instance(ArrayPlotData)
    pulse_data = Instance(ArrayPlotData)
    matrix_plot = Instance(Plot, editor=ComponentEditor())
    pulse_plot = Instance(Plot, editor=ComponentEditor())
    line_plot = Instance(Plot, editor=ComponentEditor())

    get_set_items = ['__doc__', 'measurement']

    traits_view = View(VGroup(
        Item(name='measurement', style='custom', show_label=False),
        VSplit(
            Item('matrix_plot',
                 show_label=False,
                 width=500,
                 height=-300,
                 resizable=True),
            Item('line_plot',
                 show_label=False,
                 width=500,
                 height=-300,
                 resizable=True),
            Item('pulse_plot',
                 show_label=False,
                 width=500,
                 height=-300,
                 resizable=True),
        ),
    ),
                       title='Pulsed Tool',
                       buttons=[],
                       resizable=True,
                       height=-640)

    def __init__(self, **kwargs):
        super(PulsedTool, self).__init__(**kwargs)
        self._create_matrix_plot()
        self._create_pulse_plot()
        self._create_line_plot()
        self.on_trait_change(self._update_matrix_index,
                             'measurement.time_bins,measurement.n_laser',
                             dispatch='ui')
        self.on_trait_change(self._update_matrix_value,
                             'measurement.count_data',
                             dispatch='ui')
        self.on_trait_change(self._update_pulse_index,
                             'measurement.time_bins',
                             dispatch='ui')
        self.on_trait_change(self._update_pulse_value,
                             'measurement.pulse',
                             dispatch='ui')
        self.on_trait_change(self._update_line_plot_value,
                             'measurement.spin_state',
                             dispatch='ui')
        self.on_trait_change(self._on_edge_change,
                             'measurement.edge',
                             dispatch='ui')

    # plotting
    def _create_matrix_plot(self):
        matrix_data = ArrayPlotData(image=np.zeros((2, 2)))
        plot = Plot(matrix_data,
                    width=500,
                    height=500,
                    resizable='hv',
                    padding=8,
                    padding_left=48,
                    padding_bottom=36)
        plot.index_axis.title = 'time [ns]'
        plot.value_axis.title = 'laser pulse #'
        plot.img_plot('image',
                      xbounds=(0, 1),
                      ybounds=(0, 1),
                      colormap=Spectral)[0]
        plot.tools.append(SaveTool(plot))
        self.matrix_data = matrix_data
        self.matrix_plot = plot

    def _create_pulse_plot(self):
        pulse_data = ArrayPlotData(x=np.array((0., 0.1, 0.2)),
                                   y=np.array((0, 1, 2)))
        plot = Plot(pulse_data, padding=8, padding_left=64, padding_bottom=36)
        line = plot.plot(('x', 'y'), style='line', color='blue',
                         name='data')[0]
        plot.index_axis.title = 'time [ns]'
        plot.value_axis.title = 'intensity'
        edge_marker = LinePlot(
            index=ArrayDataSource(np.array((0, 0))),
            value=ArrayDataSource(np.array((0, 1e9))),
            color='red',
            index_mapper=LinearMapper(range=plot.index_range),
            value_mapper=LinearMapper(range=plot.value_range),
            name='marker')
        plot.add(edge_marker)
        plot.tools.append(SaveTool(plot))
        self.pulse_data = pulse_data
        self.pulse_plot = plot

    def _create_line_plot(self):
        line_data = ArrayPlotData(
            index=np.array((0, 1)),
            spin_state=np.array((0, 0)),
        )
        plot = Plot(line_data, padding=8, padding_left=64, padding_bottom=36)
        plot.plot(('index', 'spin_state'), color='blue', name='spin_state')
        plot.index_axis.title = 'pulse #'
        plot.value_axis.title = 'spin state'
        plot.tools.append(SaveTool(plot))
        self.line_data = line_data
        self.line_plot = plot

    def _update_matrix_index(self):
        if self.measurement is not None:
            self.matrix_plot.components[0].index.set_data(
                (self.measurement.time_bins[0],
                 self.measurement.time_bins[-1]),
                (0.0, float(self.measurement.n_laser)))

    def _update_matrix_value(self):
        if self.measurement is not None:
            s = self.measurement.count_data.shape
            if not s[0] * s[1] > 1000000:
                self.matrix_data.set_data('image', self.measurement.count_data)

    def _update_pulse_index(self):
        if self.measurement is not None:
            self.pulse_data.set_data('x', self.measurement.time_bins)

    def _update_pulse_value(self):
        if self.measurement is not None:
            self.pulse_data.set_data('y', self.measurement.pulse)

    def _on_edge_change(self):
        if self.measurement is not None:
            y = self.measurement.edge
            self.pulse_plot.components[1].index.set_data(np.array((y, y)))

    def _update_line_plot_value(self):
        if self.measurement is not None:
            y = self.measurement.spin_state
            n = len(y)
            old_index = self.line_data.get_data('index')
            if old_index is not None and len(old_index) != n:
                self.line_data.set_data('index', np.arange(n))
            self.line_data.set_data('spin_state', y)

    def save_matrix_plot(self, filename):
        save_figure(self.matrix_plot, filename)

    def save_line_plot(self, filename):
        save_figure(self.line_plot, filename)
Beispiel #12
0
class PlotExample(HasTraits):
    plot = Instance(Component)
    numpoints = Int(500)

    low_mode = Enum("value", "track")
    high_mode = Enum("value", "track")

    traits_view = View(Group(
        Item('plot', editor=ComponentEditor(), show_label=False),
        HGroup(
            HGroup(Item(
                'object.plot.x_mapper.range.low_setting',
                label='Low',
                editor=TextEditor(),
                visible_when='object.low_mode == "value" ',
            ),
                   Item('low_mode', label='Low Mode'),
                   Item('object.plot.x_mapper.range.high_setting',
                        label='High',
                        editor=TextEditor(),
                        visible_when='object.high_mode == "value" '),
                   Item('high_mode', label='High Mode'),
                   Item('object.plot.x_mapper.range.tracking_amount',
                        label='Tracking Amount',
                        editor=TextEditor(read_only=True),
                        visible_when='object.high_mode == "track" or '
                        'object.low_mode == "track"'),
                   label='X',
                   show_border=True),
            HGroup(Item('object.plot.y_mapper.range.low_setting',
                        label='Low',
                        editor=TextEditor()),
                   Item('object.plot.y_mapper.range.high_setting',
                        label='High',
                        editor=TextEditor()),
                   label='Y',
                   show_border=True),
        ),
        orientation="vertical"),
                       resizable=True,
                       title="Function Plot",
                       width=900,
                       height=600)

    def xfunc(self, low, high):
        dx = (high - low) / self.numpoints
        real_low = ceil(low / dx) * dx
        real_high = ceil(high / dx) * dx
        return linspace(real_low, real_high, self.numpoints)

    def yfunc(self, low, high):
        x = self.xfunc(low, high)
        return sin(1.0 / x)

    def _low_mode_changed(self, newvalue):
        if newvalue != "value":
            self.plot.x_mapper.range.low_setting = newvalue

    def _high_mode_changed(self, newvalue):
        if newvalue != "value":
            self.plot.x_mapper.range.high_setting = newvalue

    def _plot_default(self):
        container = DataView()

        xds = FunctionDataSource(func=self.xfunc)
        yds = FunctionDataSource(func=self.yfunc)

        xmapper = container.x_mapper
        ymapper = container.y_mapper

        xds.data_range = xmapper.range
        yds.data_range = xmapper.range

        xmapper.range.set_bounds(-5, 10)
        ymapper.range.set_bounds(-1, 1.2)

        plot = ScatterPlot(index=xds,
                           value=yds,
                           index_mapper=xmapper,
                           value_mapper=ymapper,
                           color="green",
                           marker="circle",
                           marker_size=3,
                           line_width=0)

        plot2 = LinePlot(index=xds,
                         value=yds,
                         index_mapper=xmapper,
                         value_mapper=ymapper,
                         color="lightgray")

        container.add(plot2, plot)
        plot.tools.append(
            PanTool(plot, constrain_direction="x", constrain=True))
        plot.tools.append(ZoomTool(plot, axis="index", tool_mode="range"))

        return container
class DataBlockTablePlot(HasTraits):

    # the ParametersTable holding the actual array
    dataset = Instance(DataBlockTable)

    # a local reference to the data array in the dataset, for convenience
    selected = Property(Any, depends_on='dataset.selected')

    # ArrayPlotData for plot
    plot_data = Instance(ArrayPlotData, ())

    # Chaco Plot instance
    plot = Instance(Plot)

    traits_view = View(
        VGroup(
            Item('dataset',
                 show_label=False,
                 style='custom',
                 editor=InstanceEditor()),
            Item('plot',
                 show_label=False,
                 editor=ComponentEditor(),
                 width=0.25,
                 height=0.35),
        ),
        width=0.60,
        height=0.60,
        resizable=True,
        title='Parameters Plot',
    )

    def cview(self):
        return View(
            VGroup(
                Item('dataset',
                     show_label=False,
                     style='custom',
                     editor=InstanceEditor()),
                Item('plot',
                     show_label=False,
                     editor=ComponentEditor(),
                     width=0.25,
                     height=0.35),
            ),
            width=0.60,
            height=0.60,
            resizable=True,
            title='Raw Data Plot',
        )

    @cached_property
    def _get_selected(self):
        return self.dataset.selected

    @on_trait_change('selected')
    def _data_source_change(self):
        """Handler for changes of ther selected table row
        """
        if self.selected is None:
            return

        x = np.linspace(0, \
                        len(self.selected['raw_data']), \
                        len(self.selected['raw_data']))

        self.plot_data.set_data('x', x)
        self.plot_data.set_data('y', self.selected['raw_data'])

    def _plot_data_default(self):
        """ This creates a list of ArrayPlotData instances,
        one for each species.
        """
        plot_data = ArrayPlotData()

        plot_data.set_data('x', [])
        plot_data.set_data('y', [])

        return plot_data

    def _plot_default(self):
        """ This creates the default value for the plot.
        """
        # create the main plot object
        plot = Plot(self.plot_data)

        plot.plot(('x', 'y'), type='line', name='raw data', color='lightgreen')

        # add the additional information
        plot.title = 'Row Data'
        plot.x_axis.title = 'Samples'
        plot.y_axis.title = 'Amplitude'

        # tools for basic interactivity
        plot.tools.append(PanTool(plot))
        plot.tools.append(ZoomTool(plot))
        plot.tools.append(DragZoom(plot, drag_button="right"))

        return plot
Beispiel #14
0
class BaselineView(HasTraits):
    python_console_cmds = Dict()

    ns = List()
    es = List()
    ds = List()

    table = List()

    plot = Instance(Plot)
    plot_data = Instance(ArrayPlotData)

    running = Bool(True)
    position_centered = Bool(False)

    clear_button = SVGButton(label='',
                             tooltip='Clear',
                             filename=os.path.join(os.path.dirname(__file__),
                                                   'images', 'iconic',
                                                   'x.svg'),
                             width=16,
                             height=16)
    zoomall_button = SVGButton(label='',
                               tooltip='Zoom All',
                               filename=os.path.join(os.path.dirname(__file__),
                                                     'images', 'iconic',
                                                     'fullscreen.svg'),
                               width=16,
                               height=16)
    center_button = SVGButton(label='',
                              tooltip='Center on Baseline',
                              toggle=True,
                              filename=os.path.join(os.path.dirname(__file__),
                                                    'images', 'iconic',
                                                    'target.svg'),
                              width=16,
                              height=16)
    paused_button = SVGButton(
        label='',
        tooltip='Pause',
        toggle_tooltip='Run',
        toggle=True,
        filename=os.path.join(os.path.dirname(__file__), 'images', 'iconic',
                              'pause.svg'),
        toggle_filename=os.path.join(os.path.dirname(__file__), 'images',
                                     'iconic', 'play.svg'),
        width=16,
        height=16)

    reset_button = Button(label='Reset Filters')
    reset_iar_button = Button(label='Reset IAR')
    init_base_button = Button(label='Init. with known baseline')

    traits_view = View(
        HSplit(
            Item('table',
                 style='readonly',
                 editor=TabularEditor(adapter=SimpleAdapter()),
                 show_label=False,
                 width=0.3),
            VGroup(
                HGroup(
                    Item('paused_button', show_label=False),
                    Item('clear_button', show_label=False),
                    Item('zoomall_button', show_label=False),
                    Item('center_button', show_label=False),
                    Item('reset_button', show_label=False),
                    Item('reset_iar_button', show_label=False),
                    Item('init_base_button', show_label=False),
                ),
                Item(
                    'plot',
                    show_label=False,
                    editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8)),
                ))))

    def _zoomall_button_fired(self):
        self.plot.index_range.low_setting = 'auto'
        self.plot.index_range.high_setting = 'auto'
        self.plot.value_range.low_setting = 'auto'
        self.plot.value_range.high_setting = 'auto'

    def _center_button_fired(self):
        self.position_centered = not self.position_centered

    def _paused_button_fired(self):
        self.running = not self.running

    def _reset_button_fired(self):
        self.link.send(SBP_MSG_RESET_FILTERS, '\x00')

    def _reset_iar_button_fired(self):
        self.link.send(SBP_MSG_RESET_FILTERS, '\x01')

    def _init_base_button_fired(self):
        self.link.send(SBP_MSG_INIT_BASE, '')

    def _clear_button_fired(self):
        self.ns = []
        self.es = []
        self.ds = []
        self.plot_data.set_data('n', [])
        self.plot_data.set_data('e', [])
        self.plot_data.set_data('d', [])
        self.plot_data.set_data('t', [])
        self.plot_data.set_data('curr_n', [])
        self.plot_data.set_data('curr_e', [])
        self.plot_data.set_data('curr_d', [])

    def _baseline_callback_ecef(self, data):
        #Don't do anything for ECEF currently
        return

    def iar_state_callback(self, sbp_msg):
        self.num_hyps = struct.unpack('<I', sbp_msg.payload)[0]

    def _baseline_callback_ned(self, sbp_msg):
        # Updating an ArrayPlotData isn't thread safe (see chaco issue #9), so
        # actually perform the update in the UI thread.
        if self.running:
            GUI.invoke_later(self.baseline_callback, sbp_msg)

    def update_table(self):
        self._table_list = self.table.items()

    def gps_time_callback(self, sbp_msg):
        self.week = MsgGPSTime(sbp_msg).wn
        self.nsec = MsgGPSTime(sbp_msg).ns

    def baseline_callback(self, sbp_msg):
        soln = MsgBaselineNED(sbp_msg)
        table = []

        soln.n = soln.n * 1e-3
        soln.e = soln.e * 1e-3
        soln.d = soln.d * 1e-3

        dist = np.sqrt(soln.n**2 + soln.e**2 + soln.d**2)

        tow = soln.tow * 1e-3
        if self.nsec is not None:
            tow += self.nsec * 1e-9

        if self.week is not None:
            t = datetime.datetime(1980, 1, 6) + \
                datetime.timedelta(weeks=self.week) + \
                datetime.timedelta(seconds=tow)

            table.append(('GPS Time', t))
            table.append(('GPS Week', str(self.week)))

            if self.log_file is None:
                self.log_file = open(
                    time.strftime("baseline_log_%Y%m%d-%H%M%S.csv"), 'w')

            self.log_file.write('%s,%.4f,%.4f,%.4f,%.4f,%d,0x%02x,%d\n' %
                                (str(t), soln.n, soln.e, soln.d, dist,
                                 soln.n_sats, soln.flags, self.num_hyps))
            self.log_file.flush()

        table.append(('GPS ToW', tow))

        table.append(('N', soln.n))
        table.append(('E', soln.e))
        table.append(('D', soln.d))
        table.append(('Dist.', dist))
        table.append(('Num. Sats.', soln.n_sats))
        table.append(('Flags', '0x%02x' % soln.flags))
        if soln.flags & 1:
            table.append(('Mode', 'Fixed RTK'))
        else:
            table.append(('Mode', 'Float'))
        table.append(('IAR Num. Hyps.', self.num_hyps))

        self.ns.append(soln.n)
        self.es.append(soln.e)
        self.ds.append(soln.d)

        self.ns = self.ns[-1000:]
        self.es = self.es[-1000:]
        self.ds = self.ds[-1000:]

        self.plot_data.set_data('n', self.ns)
        self.plot_data.set_data('e', self.es)
        self.plot_data.set_data('d', self.ds)
        self.plot_data.set_data('curr_n', [soln.n])
        self.plot_data.set_data('curr_e', [soln.e])
        self.plot_data.set_data('curr_d', [soln.d])
        self.plot_data.set_data('ref_n', [0.0])
        self.plot_data.set_data('ref_e', [0.0])
        self.plot_data.set_data('ref_d', [0.0])

        t = range(len(self.ns))
        self.plot_data.set_data('t', t)

        if self.position_centered:
            d = (self.plot.index_range.high - self.plot.index_range.low) / 2.
            self.plot.index_range.set_bounds(soln.e - d, soln.e + d)
            d = (self.plot.value_range.high - self.plot.value_range.low) / 2.
            self.plot.value_range.set_bounds(soln.n - d, soln.n + d)

        self.table = table

    def __init__(self, link):
        super(BaselineView, self).__init__()

        self.log_file = None

        self.num_hyps = 0

        self.plot_data = ArrayPlotData(n=[0.0],
                                       e=[0.0],
                                       d=[0.0],
                                       t=[0.0],
                                       ref_n=[0.0],
                                       ref_e=[0.0],
                                       ref_d=[0.0],
                                       curr_e=[0.0],
                                       curr_n=[0.0],
                                       curr_d=[0.0])
        self.plot = Plot(self.plot_data)
        lin = self.plot.plot(('e', 'n'), type='line', color=(0, 0, 1, 0.1))
        pts = self.plot.plot(('e', 'n'),
                             type='scatter',
                             color='blue',
                             marker='dot',
                             line_width=0.0,
                             marker_size=1.0)
        ref = self.plot.plot(('ref_e', 'ref_n'),
                             type='scatter',
                             color='red',
                             marker='plus',
                             marker_size=5,
                             line_width=1.5)
        cur = self.plot.plot(('curr_e', 'curr_n'),
                             type='scatter',
                             color='orange',
                             marker='plus',
                             marker_size=5,
                             line_width=1.5)
        plot_labels = [
            'Base Position', 'Rover Relative Position', 'Rover Path'
        ]
        plots_legend = dict(zip(plot_labels, [ref, cur, pts]))
        self.plot.legend.plots = plots_legend
        self.plot.legend.visible = True

        self.plot.index_axis.tick_label_position = 'inside'
        self.plot.index_axis.tick_label_color = 'gray'
        self.plot.index_axis.tick_color = 'gray'
        self.plot.index_axis.title = 'E (meters)'
        self.plot.index_axis.title_spacing = 5
        self.plot.value_axis.tick_label_position = 'inside'
        self.plot.value_axis.tick_label_color = 'gray'
        self.plot.value_axis.tick_color = 'gray'
        self.plot.value_axis.title = 'N (meters)'
        self.plot.value_axis.title_spacing = 5
        self.plot.padding = (25, 25, 25, 25)

        self.plot.tools.append(PanTool(self.plot))
        zt = ZoomTool(self.plot,
                      zoom_factor=1.1,
                      tool_mode="box",
                      always_on=False)
        self.plot.overlays.append(zt)

        self.week = None
        self.nsec = 0

        self.link = link
        self.link.add_callback(self._baseline_callback_ned,
                               SBP_MSG_BASELINE_NED)
        self.link.add_callback(self._baseline_callback_ecef,
                               SBP_MSG_BASELINE_ECEF)
        self.link.add_callback(self.iar_state_callback, SBP_MSG_IAR_STATE)
        self.link.add_callback(self.gps_time_callback, SBP_MSG_GPS_TIME)

        self.python_console_cmds = {'baseline': self}
Beispiel #15
0
class SolutionView(HasTraits):
    python_console_cmds = Dict()
    # we need to doubleup on Lists to store the psuedo absolutes separately
    # without rewriting everything
    """
  logging_v : toggle logging for velocity files
  directory_name_v : location and name of velocity files
  logging_p : toggle logging for position files
  directory_name_p : location and name of velocity files
  """
    plot_history_max = Int(1000)
    last_plot_update_time = Float()
    last_stale_update_time = Float()
    logging_v = Bool(False)
    display_units = Enum(["degrees", "meters"])
    directory_name_v = File

    logging_p = Bool(False)
    directory_name_p = File

    lats_psuedo_abs = List()
    lngs_psuedo_abs = List()
    alts_psuedo_abs = List()

    table = List()
    dops_table = List()
    pos_table = List()
    vel_table = List()

    rtk_pos_note = Str(
        "It is necessary to enter the \"Surveyed Position\" settings for the base station in order to view the RTK Positions in this tab."
    )

    plot = Instance(Plot)
    plot_data = Instance(ArrayPlotData)
    # Store plots we care about for legend

    running = Bool(True)
    zoomall = Bool(False)
    position_centered = Bool(False)

    clear_button = SVGButton(
        label='',
        tooltip='Clear',
        filename=resource_filename('console/images/iconic/x.svg'),
        width=16,
        height=16)
    zoomall_button = SVGButton(
        label='',
        tooltip='Zoom All',
        toggle=True,
        filename=resource_filename('console/images/iconic/fullscreen.svg'),
        width=16,
        height=16)
    center_button = SVGButton(
        label='',
        tooltip='Center on Solution',
        toggle=True,
        filename=resource_filename('console/images/iconic/target.svg'),
        width=16,
        height=16)
    paused_button = SVGButton(
        label='',
        tooltip='Pause',
        toggle_tooltip='Run',
        toggle=True,
        filename=resource_filename('console/images/iconic/pause.svg'),
        toggle_filename=resource_filename('console/images/iconic/play.svg'),
        width=16,
        height=16)

    traits_view = View(
        HSplit(
            VGroup(
                Item('table',
                     style='readonly',
                     editor=TabularEditor(adapter=SimpleAdapter()),
                     show_label=False,
                     width=0.3),
                Item('rtk_pos_note',
                     show_label=False,
                     resizable=True,
                     editor=MultilineTextEditor(TextEditor(multi_line=True)),
                     style='readonly',
                     width=0.3,
                     height=-40),
            ),
            VGroup(
                HGroup(
                    Item('paused_button', show_label=False),
                    Item('clear_button', show_label=False),
                    Item('zoomall_button', show_label=False),
                    Item('center_button', show_label=False),
                    Item('display_units', label="Display Units"),
                ),
                Item('plot',
                     show_label=False,
                     editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8))),
            )))

    def _zoomall_button_fired(self):
        self.zoomall = not self.zoomall

    def _center_button_fired(self):
        self.position_centered = not self.position_centered

    def _paused_button_fired(self):
        self.running = not self.running

    def _reset_remove_current(self):
        self.plot_data.update_data(self._get_update_current())

    def _get_update_current(self, current_dict={}):
        out_dict = {
            'cur_lat_spp': [],
            'cur_lng_spp': [],
            'cur_lat_dgnss': [],
            'cur_lng_dgnss': [],
            'cur_lat_float': [],
            'cur_lng_float': [],
            'cur_lat_fixed': [],
            'cur_lng_fixed': [],
            'cur_lat_sbas': [],
            'cur_lng_sbas': [],
            'cur_lat_dr': [],
            'cur_lng_dr': []
        }
        out_dict.update(current_dict)
        return out_dict

    def _synchronize_plot_data_by_mode(self,
                                       mode_string,
                                       update_current=False):
        # do all required plot_data updates for a single
        # new solution with mode defined by mode_string
        pending_update = {
            'lat_' + mode_string:
            [x for x in self.slns['lat_' + mode_string] if not np.isnan(x)],
            'lng_' + mode_string:
            [y for y in self.slns['lng_' + mode_string] if not np.isnan(y)]
        }
        if update_current:
            current = {}
            if len(pending_update['lat_' + mode_string]) != 0:
                current = {
                    'cur_lat_' + mode_string:
                    [pending_update['lat_' + mode_string][-1]],
                    'cur_lng_' + mode_string:
                    [pending_update['lng_' + mode_string][-1]]
                }
            else:
                current = {
                    'cur_lat_' + mode_string: [],
                    'cur_lng_' + mode_string: []
                }
            pending_update.update(self._get_update_current(current))
        self.plot_data.update_data(pending_update)

    def _append_empty_sln_data(self, exclude_mode=None):
        for each_mode in mode_string_dict.values():
            if exclude_mode is None or each_mode != exclude_mode:
                self.slns['lat_' + each_mode].append(np.nan)
                self.slns['lng_' + each_mode].append(np.nan)

    def _update_sln_data_by_mode(self, soln, mode_string):
        # do backend deque updates for a new solution of type
        # mode string
        self.scaling_lock.acquire()
        lat = (soln.lat - self.offset[0]) * self.sf[0]
        lng = (soln.lon - self.offset[1]) * self.sf[1]
        self.scaling_lock.release()
        self.slns['lat_' + mode_string].append(lat)
        self.slns['lng_' + mode_string].append(lng)
        # Rotate old data out by appending to deque
        self._append_empty_sln_data(exclude_mode=mode_string)

    def _clr_sln_data(self):
        for each in self.slns:
            self.slns[each].clear()

    def _clear_history(self):
        for each in self.slns:
            self.slns[each].clear()
        pending_update = {
            'lat_spp': [],
            'lng_spp': [],
            'alt_spp': [],
            'lat_dgnss': [],
            'lng_dgnss': [],
            'alt_dgnss': [],
            'lat_float': [],
            'lng_float': [],
            'alt_float': [],
            'lat_fixed': [],
            'lng_fixed': [],
            'alt_fixed': [],
            'lat_sbas': [],
            'lng_sbas': [],
            'alt_sbas': [],
            'lat_dr': [],
            'lng_dr': [],
            'alt_dr': []
        }
        pending_update.update(self._get_update_current())
        self.plot_data.update(pending_update)

    def _clear_button_fired(self):
        self._clear_history()

    def age_corrections_callback(self, sbp_msg, **metadata):
        age_msg = MsgAgeCorrections(sbp_msg)
        if age_msg.age != 0xFFFF:
            self.age_corrections = age_msg.age / 10.0
        else:
            self.age_corrections = None

    def update_table(self):
        self.table = self.pos_table + self.vel_table + self.dops_table

    def auto_survey(self):
        if len(self.lats) != 0:
            self.latitude = sum(self.lats) / len(self.lats)
            self.altitude = sum(self.alts) / len(self.alts)
            self.longitude = sum(self.lngs) / len(self.lngs)

    def pos_llh_callback(self, sbp_msg, **metadata):
        if sbp_msg.msg_type == SBP_MSG_POS_LLH_DEP_A:
            soln = MsgPosLLHDepA(sbp_msg)
        else:
            soln = MsgPosLLH(sbp_msg)

        self.last_pos_mode = get_mode(soln)
        if self.last_pos_mode != 0:
            self.last_soln = soln
            mode_string = mode_string_dict[self.last_pos_mode]
            if mode_string not in self.pending_draw_modes:
                # this list allows us to tell GUI thread which solutions to update
                # (if we decide not to update at full data rate)
                # we use short strings to identify each solution mode
                self.pending_draw_modes.append(mode_string)
            self.list_lock.acquire()
            self._update_sln_data_by_mode(soln, mode_string)
            self.list_lock.release()
        else:
            self.list_lock.acquire()
            self._append_empty_sln_data()
            self.list_lock.release()
        self.ins_used = ((soln.flags & 0x8) >> 3) == 1
        pos_table = []
        soln.h_accuracy *= 1e-3
        soln.v_accuracy *= 1e-3

        tow = soln.tow * 1e-3
        if self.nsec is not None:
            tow += self.nsec * 1e-9

        # Return the best estimate of my local and receiver time in convenient
        # format that allows changing precision of the seconds
        ((tloc, secloc), (tgps, secgps)) = log_time_strings(self.week, tow)
        if self.utc_time:
            ((tutc, secutc)) = datetime_2_str(self.utc_time)

        if (self.directory_name_p == ''):
            filepath_p = time.strftime("position_log_%Y%m%d-%H%M%S.csv")
        else:
            filepath_p = os.path.join(
                self.directory_name_p,
                time.strftime("position_log_%Y%m%d-%H%M%S.csv"))

        if not self.logging_p:
            self.log_file = None

        if self.logging_p:
            if self.log_file is None:
                self.log_file = sopen(filepath_p, 'w')
                self.log_file.write(
                    "pc_time,gps_time,tow(sec),latitude(degrees),longitude(degrees),altitude(meters),"
                    "h_accuracy(meters),v_accuracy(meters),n_sats,flags\n")
            log_str_gps = ""
            if tgps != "" and secgps != 0:
                log_str_gps = "{0}:{1:06.6f}".format(tgps, float(secgps))
            self.log_file.write(
                '%s,%s,%.3f,%.10f,%.10f,%.4f,%.4f,%.4f,%d,%d\n' %
                ("{0}:{1:06.6f}".format(tloc, float(secloc)), log_str_gps, tow,
                 soln.lat, soln.lon, soln.height, soln.h_accuracy,
                 soln.v_accuracy, soln.n_sats, soln.flags))
            self.log_file.flush()

        if self.last_pos_mode == 0:
            pos_table.append(('GPS Week', EMPTY_STR))
            pos_table.append(('GPS TOW', EMPTY_STR))
            pos_table.append(('GPS Time', EMPTY_STR))
            pos_table.append(('Num. Signals', EMPTY_STR))
            pos_table.append(('Lat', EMPTY_STR))
            pos_table.append(('Lng', EMPTY_STR))
            pos_table.append(('Height', EMPTY_STR))
            pos_table.append(('Horiz Acc', EMPTY_STR))
            pos_table.append(('Vert Acc', EMPTY_STR))
        else:
            self.last_stime_update = time.time()

            if self.week is not None:
                pos_table.append(('GPS Week', str(self.week)))
            pos_table.append(('GPS TOW', "{:.3f}".format(tow)))

            if self.week is not None:
                pos_table.append(
                    ('GPS Time', "{0}:{1:06.3f}".format(tgps, float(secgps))))
            if self.utc_time is not None:
                pos_table.append(
                    ('UTC Time', "{0}:{1:06.3f}".format(tutc, float(secutc))))
                pos_table.append(('UTC Src', self.utc_source))
            if self.utc_time is None:
                pos_table.append(('UTC Time', EMPTY_STR))
                pos_table.append(('UTC Src', EMPTY_STR))

            pos_table.append(('Sats Used', soln.n_sats))
            pos_table.append(('Lat', soln.lat))
            pos_table.append(('Lng', soln.lon))
            pos_table.append(('Height', "{0:.3f}".format(soln.height)))
            pos_table.append(('Horiz Acc', soln.h_accuracy))
            pos_table.append(('Vert Acc', soln.v_accuracy))

        pos_table.append(('Pos Flags', '0x%03x' % soln.flags))
        pos_table.append(('INS Used', '{}'.format(self.ins_used)))
        pos_table.append(('Pos Fix Mode', mode_dict[self.last_pos_mode]))
        if self.age_corrections is not None:
            pos_table.append(('Corr. Age [s]', self.age_corrections))

        # only store valid solutions for auto survey and degrees to meter transformation
        if self.last_pos_mode != 0:
            self.lats.append(soln.lat)
            self.lngs.append(soln.lon)
            self.alts.append(soln.height)
            self.tows.append(soln.tow)
            self.modes.append(self.last_pos_mode)
        self.auto_survey()

        # set-up table variables
        self.pos_table = pos_table
        self.update_table()
        # setup_plot variables
        # Updating array plot data is not thread safe, so we have to fire an event
        # and have the GUI thread do it
        if time.time() - self.last_plot_update_time > GUI_UPDATE_PERIOD:
            GUI.invoke_later(self._solution_draw)

    def _display_units_changed(self):
        # we store current extents of plot and current scalefactlrs
        self.scaling_lock.acquire()
        self.recenter = True  # recenter flag tells _solution_draw to update view extents
        self.prev_extents = (self.plot.index_range.low_setting,
                             self.plot.index_range.high_setting,
                             self.plot.value_range.low_setting,
                             self.plot.value_range.high_setting)
        self.prev_offsets = (self.offset[0], self.offset[1])
        self.prev_sfs = (self.sf[0], self.sf[1])
        if self.display_units == "meters":
            self.offset = (
                np.mean(
                    np.array(self.lats)[~(np.equal(np.array(self.modes), 0))]),
                np.mean(
                    np.array(self.lngs)[~(np.equal(np.array(self.modes), 0))]),
                np.mean(
                    np.array(self.alts)[~(np.equal(np.array(self.modes), 0))]))
            (self.meters_per_lat, self.meters_per_lon) = meters_per_deg(
                np.mean(
                    np.array(self.lats)[~(np.equal(np.array(self.modes), 0))]))
            self.sf = (self.meters_per_lat, self.meters_per_lon)
            self.plot.value_axis.title = 'Latitude (meters)'
            self.plot.index_axis.title = 'Longitude (meters)'
        else:
            self.offset = (0, 0, 0)
            self.sf = (1, 1)
            self.plot.value_axis.title = 'Latitude (degrees)'
            self.plot.index_axis.title = 'Longitude (degrees)'
        self.scaling_lock.release()
        self.list_lock.acquire()
        # now we update the existing sln deques to go from meters back to degrees or vice versa
        for each_array in self.slns:
            index = 0 if 'lat' in str(each_array) else 1
            # going from degrees to meters; do scaling with new offset and sf
            if self.display_units == "meters":
                self.slns[each_array] = deque(
                    (np.array(self.slns[each_array]) - self.offset[index]) *
                    self.sf[index],
                    maxlen=PLOT_HISTORY_MAX)
            # going from degrees to meters; do inverse scaling with former offset and sf
            if self.display_units == "degrees":
                self.slns[each_array] = deque(
                    np.array(self.slns[each_array]) / self.prev_sfs[index] +
                    self.prev_offsets[index],
                    maxlen=PLOT_HISTORY_MAX)
        self.pending_draw_modes = mode_string_dict.values()
        self.list_lock.release()

    def rescale_for_units_change(self):
        # Chaco scales view automatically when 'auto' is stored
        if self.prev_extents[0] != 'auto':
            # Otherwise use has used mousewheel zoom and we need to transform
            if self.display_units == 'meters':
                new_scaling = (
                    (self.prev_extents[0] - self.offset[1]) * self.sf[1],
                    (self.prev_extents[1] - self.offset[1]) * self.sf[1],
                    (self.prev_extents[2] - self.offset[0]) * self.sf[0],
                    (self.prev_extents[3] - self.offset[0]) * self.sf[0])
            else:
                new_scaling = (self.prev_extents[0] / self.prev_sfs[1] +
                               self.prev_offsets[1],
                               self.prev_extents[1] / self.prev_sfs[1] +
                               self.prev_offsets[1],
                               self.prev_extents[2] / self.prev_sfs[0] +
                               self.prev_offsets[0],
                               self.prev_extents[3] / self.prev_sfs[0] +
                               self.prev_offsets[0])

            # set plot scaling accordingly
            self.plot.index_range.low_setting = new_scaling[0]
            self.plot.index_range.high_setting = new_scaling[1]
            self.plot.value_range.low_setting = new_scaling[2]
            self.plot.value_range.high_setting = new_scaling[3]

    def _solution_draw(self):
        self.list_lock.acquire()
        current_time = time.time()
        self.last_plot_update_time = current_time
        pending_draw_modes = self.pending_draw_modes
        current_mode = pending_draw_modes[-1] if len(
            pending_draw_modes) > 0 else None
        # Periodically, we make sure to redraw older data to expire old plot data
        if current_time - self.last_stale_update_time > STALE_DATA_PERIOD:
            # we don't update old solution modes every timestep to try and save CPU
            pending_draw_modes = mode_string_dict.values()
            self.last_stale_update_time = current_time
        for mode_string in pending_draw_modes:
            if self.running:
                update_current = mode_string == current_mode if current_mode else True
                self._synchronize_plot_data_by_mode(
                    mode_string, update_current=update_current)
                if mode_string in self.pending_draw_modes:
                    self.pending_draw_modes.remove(mode_string)

        self.list_lock.release()
        if not self.zoomall and self.position_centered and self.running:
            d = (self.plot.index_range.high - self.plot.index_range.low) / 2.
            self.plot.index_range.set_bounds(
                (self.last_soln.lon - self.offset[1]) * self.sf[1] - d,
                (self.last_soln.lon - self.offset[1]) * self.sf[1] + d)
            d = (self.plot.value_range.high - self.plot.value_range.low) / 2.
            self.plot.value_range.set_bounds(
                (self.last_soln.lat - self.offset[0]) * self.sf[0] - d,
                (self.last_soln.lat - self.offset[0]) * self.sf[0] + d)
        if self.zoomall:
            self.recenter = False
            plot_square_axes(self.plot, ('lng_spp', 'lng_dgnss', 'lng_float',
                                         'lng_fixed', 'lng_sbas', 'lng_dr'),
                             ('lat_spp', 'lat_dgnss', 'lat_float', 'lat_fixed',
                              'lat_sbas', 'lat_dr'))
        if self.recenter:
            try:
                self.rescale_for_units_change()
                self.recenter = False
            except AttributeError:
                pass

    def dops_callback(self, sbp_msg, **metadata):
        flags = 0
        if sbp_msg.msg_type == SBP_MSG_DOPS_DEP_A:
            dops = MsgDopsDepA(sbp_msg)
            flags = 1
        else:
            dops = MsgDops(sbp_msg)
            flags = dops.flags
        if flags != 0:
            self.dops_table = [('PDOP', '%.1f' % (dops.pdop * 0.01)),
                               ('GDOP', '%.1f' % (dops.gdop * 0.01)),
                               ('TDOP', '%.1f' % (dops.tdop * 0.01)),
                               ('HDOP', '%.1f' % (dops.hdop * 0.01)),
                               ('VDOP', '%.1f' % (dops.vdop * 0.01))]
        else:
            self.dops_table = [('PDOP', EMPTY_STR), ('GDOP', EMPTY_STR),
                               ('TDOP', EMPTY_STR), ('HDOP', EMPTY_STR),
                               ('VDOP', EMPTY_STR)]

        self.dops_table.append(('DOPS Flags', '0x%03x' % flags))

    def vel_ned_callback(self, sbp_msg, **metadata):
        flags = 0
        if sbp_msg.msg_type == SBP_MSG_VEL_NED_DEP_A:
            vel_ned = MsgVelNEDDepA(sbp_msg)
            flags = 1
        else:
            vel_ned = MsgVelNED(sbp_msg)
            flags = vel_ned.flags
        tow = vel_ned.tow * 1e-3
        if self.nsec is not None:
            tow += self.nsec * 1e-9

        ((tloc, secloc), (tgps, secgps)) = log_time_strings(self.week, tow)

        if self.directory_name_v == '':
            filepath_v = time.strftime("velocity_log_%Y%m%d-%H%M%S.csv")
        else:
            filepath_v = os.path.join(
                self.directory_name_v,
                time.strftime("velocity_log_%Y%m%d-%H%M%S.csv"))

        if not self.logging_v:
            self.vel_log_file = None

        if self.logging_v:
            if self.vel_log_file is None:
                self.vel_log_file = sopen(filepath_v, 'w')
                self.vel_log_file.write(
                    'pc_time,gps_time,tow(sec),north(m/s),east(m/s),down(m/s),speed(m/s),flags,num_signals\n'
                )
            log_str_gps = ''
            if tgps != "" and secgps != 0:
                log_str_gps = "{0}:{1:06.6f}".format(tgps, float(secgps))
            self.vel_log_file.write(
                '%s,%s,%.3f,%.6f,%.6f,%.6f,%.6f,%d,%d\n' %
                ("{0}:{1:06.6f}".format(tloc, float(secloc)), log_str_gps, tow,
                 vel_ned.n * 1e-3, vel_ned.e * 1e-3, vel_ned.d * 1e-3,
                 math.sqrt(vel_ned.n * vel_ned.n + vel_ned.e * vel_ned.e) *
                 1e-3, flags, vel_ned.n_sats))
            self.vel_log_file.flush()
        if (flags & 0x7) != 0:
            self.vel_table = [
                ('Vel. N', '% 8.4f' % (vel_ned.n * 1e-3)),
                ('Vel. E', '% 8.4f' % (vel_ned.e * 1e-3)),
                ('Vel. D', '% 8.4f' % (vel_ned.d * 1e-3)),
            ]
        else:
            self.vel_table = [
                ('Vel. N', EMPTY_STR),
                ('Vel. E', EMPTY_STR),
                ('Vel. D', EMPTY_STR),
            ]
        self.vel_table.append(('Vel Flags', '0x%03x' % flags))
        self.update_table()

    def gps_time_callback(self, sbp_msg, **metadata):
        if sbp_msg.msg_type == SBP_MSG_GPS_TIME_DEP_A:
            time_msg = MsgGPSTimeDepA(sbp_msg)
            flags = 1
        elif sbp_msg.msg_type == SBP_MSG_GPS_TIME:
            time_msg = MsgGPSTime(sbp_msg)
            flags = time_msg.flags
            if flags != 0:
                self.week = time_msg.wn
                self.nsec = time_msg.ns_residual

    def utc_time_callback(self, sbp_msg, **metadata):
        tmsg = MsgUtcTime(sbp_msg)
        microseconds = int(tmsg.ns / 1000.00)
        if tmsg.flags & 0x7 != 0:
            dt = datetime.datetime(tmsg.year, tmsg.month, tmsg.day, tmsg.hours,
                                   tmsg.minutes, tmsg.seconds, microseconds)
            self.utc_time = dt
            self.utc_time_flags = tmsg.flags
            if (tmsg.flags >> 3) & 0x3 == 0:
                self.utc_source = "Factory Default"
            elif (tmsg.flags >> 3) & 0x3 == 1:
                self.utc_source = "Non Volatile Memory"
            elif (tmsg.flags >> 3) & 0x3 == 2:
                self.utc_source = "Decoded this Session"
            else:
                self.utc_source = "Unknown"
        else:
            self.utc_time = None
            self.utc_source = None

    def __init__(self, link, dirname=''):
        super(SolutionView, self).__init__()
        self.pending_draw_modes = []
        self.recenter = False
        self.offset = (0, 0, 0)
        self.sf = (1, 1)
        self.list_lock = threading.Lock()
        self.scaling_lock = threading.Lock()
        self.slns = {
            'lat_spp': deque(maxlen=PLOT_HISTORY_MAX),
            'lng_spp': deque(maxlen=PLOT_HISTORY_MAX),
            'alt_spp': deque(maxlen=PLOT_HISTORY_MAX),
            'lat_dgnss': deque(maxlen=PLOT_HISTORY_MAX),
            'lng_dgnss': deque(maxlen=PLOT_HISTORY_MAX),
            'alt_dgnss': deque(maxlen=PLOT_HISTORY_MAX),
            'lat_float': deque(maxlen=PLOT_HISTORY_MAX),
            'lng_float': deque(maxlen=PLOT_HISTORY_MAX),
            'alt_float': deque(maxlen=PLOT_HISTORY_MAX),
            'lat_fixed': deque(maxlen=PLOT_HISTORY_MAX),
            'lng_fixed': deque(maxlen=PLOT_HISTORY_MAX),
            'alt_fixed': deque(maxlen=PLOT_HISTORY_MAX),
            'lat_sbas': deque(maxlen=PLOT_HISTORY_MAX),
            'lng_sbas': deque(maxlen=PLOT_HISTORY_MAX),
            'alt_sbas': deque(maxlen=PLOT_HISTORY_MAX),
            'lat_dr': deque(maxlen=PLOT_HISTORY_MAX),
            'lng_dr': deque(maxlen=PLOT_HISTORY_MAX),
            'alt_dr': deque(maxlen=PLOT_HISTORY_MAX)
        }
        self.lats = deque(maxlen=PLOT_HISTORY_MAX)
        self.lngs = deque(maxlen=PLOT_HISTORY_MAX)
        self.alts = deque(maxlen=PLOT_HISTORY_MAX)
        self.tows = deque(maxlen=PLOT_HISTORY_MAX)
        self.modes = deque(maxlen=PLOT_HISTORY_MAX)
        self.log_file = None
        self.directory_name_v = dirname
        self.directory_name_p = dirname
        self.vel_log_file = None
        self.last_stime_update = 0
        self.last_soln = None

        self.altitude = 0
        self.longitude = 0
        self.latitude = 0
        self.last_pos_mode = 0
        self.ins_used = False
        self.last_plot_update_time = 0
        self.last_stale_update_time = 0

        self.plot_data = ArrayPlotData(lat_spp=[],
                                       lng_spp=[],
                                       alt_spp=[],
                                       cur_lat_spp=[],
                                       cur_lng_spp=[],
                                       lat_dgnss=[],
                                       lng_dgnss=[],
                                       alt_dgnss=[],
                                       cur_lat_dgnss=[],
                                       cur_lng_dgnss=[],
                                       lat_float=[],
                                       lng_float=[],
                                       alt_float=[],
                                       cur_lat_float=[],
                                       cur_lng_float=[],
                                       lat_fixed=[],
                                       lng_fixed=[],
                                       alt_fixed=[],
                                       cur_lat_fixed=[],
                                       cur_lng_fixed=[],
                                       lat_sbas=[],
                                       lng_sbas=[],
                                       cur_lat_sbas=[],
                                       cur_lng_sbas=[],
                                       lng_dr=[],
                                       lat_dr=[],
                                       cur_lat_dr=[],
                                       cur_lng_dr=[])
        self.plot = Plot(self.plot_data)

        # 1000 point buffer
        self.plot.plot(('lng_spp', 'lat_spp'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[SPP_MODE])
        self.plot.plot(('lng_spp', 'lat_spp'),
                       type='scatter',
                       name='',
                       color=color_dict[SPP_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        self.plot.plot(('lng_dgnss', 'lat_dgnss'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[DGNSS_MODE])
        self.plot.plot(('lng_dgnss', 'lat_dgnss'),
                       type='scatter',
                       name='',
                       color=color_dict[DGNSS_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        self.plot.plot(('lng_float', 'lat_float'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[FLOAT_MODE])
        self.plot.plot(('lng_float', 'lat_float'),
                       type='scatter',
                       name='',
                       color=color_dict[FLOAT_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        self.plot.plot(('lng_fixed', 'lat_fixed'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[FIXED_MODE])
        self.plot.plot(('lng_fixed', 'lat_fixed'),
                       type='scatter',
                       name='',
                       color=color_dict[FIXED_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        self.plot.plot(('lng_sbas', 'lat_sbas'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[SBAS_MODE])
        self.plot.plot(('lng_sbas', 'lat_sbas'),
                       type='scatter',
                       name='',
                       color=color_dict[SBAS_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        self.plot.plot(('lng_dr', 'lat_dr'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[DR_MODE])
        self.plot.plot(('lng_dr', 'lat_dr'),
                       type='scatter',
                       color=color_dict[DR_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        # current values
        spp = self.plot.plot(('cur_lng_spp', 'cur_lat_spp'),
                             type='scatter',
                             name=mode_dict[SPP_MODE],
                             color=color_dict[SPP_MODE],
                             marker='plus',
                             line_width=1.5,
                             marker_size=5.0)
        dgnss = self.plot.plot(('cur_lng_dgnss', 'cur_lat_dgnss'),
                               type='scatter',
                               name=mode_dict[DGNSS_MODE],
                               color=color_dict[DGNSS_MODE],
                               marker='plus',
                               line_width=1.5,
                               marker_size=5.0)
        rtkfloat = self.plot.plot(('cur_lng_float', 'cur_lat_float'),
                                  type='scatter',
                                  name=mode_dict[FLOAT_MODE],
                                  color=color_dict[FLOAT_MODE],
                                  marker='plus',
                                  line_width=1.5,
                                  marker_size=5.0)
        rtkfix = self.plot.plot(('cur_lng_fixed', 'cur_lat_fixed'),
                                type='scatter',
                                name=mode_dict[FIXED_MODE],
                                color=color_dict[FIXED_MODE],
                                marker='plus',
                                line_width=1.5,
                                marker_size=5.0)
        sbas = self.plot.plot(('cur_lng_sbas', 'cur_lat_sbas'),
                              type='scatter',
                              name=mode_dict[SBAS_MODE],
                              color=color_dict[SBAS_MODE],
                              marker='plus',
                              line_width=1.5,
                              marker_size=5.0)
        dr = self.plot.plot(('cur_lng_dr', 'cur_lat_dr'),
                            type='scatter',
                            name=mode_dict[DR_MODE],
                            color=color_dict[DR_MODE],
                            marker='plus',
                            line_width=1.5,
                            marker_size=5.0)
        plot_labels = ['SPP', 'SBAS', 'DGPS', 'RTK float', 'RTK fixed', 'DR']
        plots_legend = dict(
            zip(plot_labels, [spp, sbas, dgnss, rtkfloat, rtkfix, dr]))
        self.plot.legend.plots = plots_legend
        self.plot.legend.labels = plot_labels  # sets order
        self.plot.legend.visible = True

        self.plot.index_axis.tick_label_position = 'inside'
        self.plot.index_axis.tick_label_color = 'gray'
        self.plot.index_axis.tick_color = 'gray'
        self.plot.index_axis.title = 'Longitude (degrees)'
        self.plot.index_axis.title_spacing = 5
        self.plot.value_axis.tick_label_position = 'inside'
        self.plot.value_axis.tick_label_color = 'gray'
        self.plot.value_axis.tick_color = 'gray'
        self.plot.value_axis.title = 'Latitude (degrees)'
        self.plot.value_axis.title_spacing = 5
        self.plot.padding = (25, 25, 25, 25)

        self.plot.tools.append(PanTool(self.plot))
        zt = ZoomTool(self.plot,
                      zoom_factor=1.1,
                      tool_mode="box",
                      always_on=False)
        self.plot.overlays.append(zt)

        self.link = link
        self.link.add_callback(self.pos_llh_callback,
                               [SBP_MSG_POS_LLH_DEP_A, SBP_MSG_POS_LLH])
        self.link.add_callback(self.vel_ned_callback,
                               [SBP_MSG_VEL_NED_DEP_A, SBP_MSG_VEL_NED])
        self.link.add_callback(self.dops_callback,
                               [SBP_MSG_DOPS_DEP_A, SBP_MSG_DOPS])
        self.link.add_callback(self.gps_time_callback,
                               [SBP_MSG_GPS_TIME_DEP_A, SBP_MSG_GPS_TIME])
        self.link.add_callback(self.utc_time_callback, [SBP_MSG_UTC_TIME])
        self.link.add_callback(self.age_corrections_callback,
                               SBP_MSG_AGE_CORRECTIONS)
        self.week = None
        self.utc_time = None
        self.age_corrections = None
        self.nsec = 0
        self.meters_per_lat = None
        self.meters_per_lon = None

        self.python_console_cmds = {
            'solution': self,
        }
class MatrixViewer(HasTraits):
    
    tplot = Instance(Plot)
    plot = Instance(Component)
    custtool = Instance(CustomTool)
    colorbar = Instance(ColorBar)
    
    edge_para = Any
    data_name = Enum("a", "b")
    
    fro = Int
    to = Int
    data = None
    val = Float

    traits_view = View(
                    Group(
                        Item('plot', editor=ComponentEditor(size=(800,600)),
                             show_label=False),
                        HGroup(
                        Item('fro', label="From", style = 'readonly', springy=True),
                        Item('to', label="To", style = 'readonly', springy=True),
                        Item('val', label="Value", style = 'readonly', springy=True),
                        ),
                        orientation = "vertical"),
                    Item('data_name', label="Image data"),
                    handler=CustomHandler(),
                    resizable=True, title="Matrix Viewer"
                    )

    
    def __init__(self, data, **traits):
        """ Data is a nxn numpy array """
        super(HasTraits, self).__init__(**traits)
        
        self.data_name = data.keys()[0]
        self.data = data
        self.plot = self._create_plot_component()
        
        # set trait notification on customtool
        self.custtool.on_trait_change(self._update_fields, "xval")
        self.custtool.on_trait_change(self._update_fields, "yval")

    def _data_name_changed(self, old, new):
        self.pd.set_data("imagedata", self.data[self.data_name])
        self.my_plot.set_value_selection((0, 2))
        
    def _update_fields(self):
        from numpy import trunc
        
        # map mouse location to array index
        frotmp = int(trunc(self.custtool.yval))
        totmp = int(trunc(self.custtool.xval))
        
        # check if within range
        sh = self.data[self.data_name].shape
        # assume matrix whose shape is (# of rows, # of columns)
        if frotmp >= 0 and frotmp < sh[0] and totmp >= 0 and totmp < sh[1]:
            self.fro = frotmp
            self.to = totmp
            self.val = self.data[self.data_name][self.fro, self.to]
        
    def _create_plot_component(self):
        
        # Create a plot data object and give it this data
        self.pd = ArrayPlotData()
        self.pd.set_data("imagedata", self.data[self.data_name])
    
        # Create the plot
        self.tplot = Plot(self.pd, default_origin="top left")
        self.tplot.x_axis.orientation = "top"
        self.tplot.img_plot("imagedata", 
                      name="my_plot",
                      #xbounds=(0,10),
                      #ybounds=(0,10),
                      colormap=jet)
    
        # Tweak some of the plot properties
        self.tplot.title = "Matrix"
        self.tplot.padding = 50
    
        # Right now, some of the tools are a little invasive, and we need the 
        # actual CMapImage object to give to them
        self.my_plot = self.tplot.plots["my_plot"][0]
    
        # Attach some tools to the plot
        self.tplot.tools.append(PanTool(self.tplot))
        zoom = ZoomTool(component=self.tplot, tool_mode="box", always_on=False)
        self.tplot.overlays.append(zoom)
        
        # my custom tool to get the connection information
        self.custtool = CustomTool(self.tplot)
        self.tplot.tools.append(self.custtool)
    
        # Create the colorbar, handing in the appropriate range and colormap
        colormap = self.my_plot.color_mapper
        self.colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range),
                            color_mapper=colormap,
                            plot=self.my_plot,
                            orientation='v',
                            resizable='v',
                            width=30,
                            padding=20)
            
        self.colorbar.padding_top = self.tplot.padding_top
        self.colorbar.padding_bottom = self.tplot.padding_bottom
        
        # create a range selection for the colorbar
        self.range_selection = RangeSelection(component=self.colorbar)
        self.colorbar.tools.append(self.range_selection)
        self.colorbar.overlays.append(RangeSelectionOverlay(component=self.colorbar,
                                                       border_color="white",
                                                       alpha=0.8,
                                                       fill_color="lightgray"))
    
        # we also want to the range selection to inform the cmap plot of
        # the selection, so set that up as well
        self.range_selection.listeners.append(self.my_plot)
    
        # Create a container to position the plot and the colorbar side-by-side
        container = HPlotContainer(use_backbuffer = True)
        container.add(self.tplot)
        container.add(self.colorbar)
        container.bgcolor = "white"
    
        return container
 def traits_view(self):
     additional_param_controls = self._build_additional_param_editors()
     param_list_with_cost = [ALL_COST_COL_NAME] + self.param_list
     two_d_plot_shown = "show_cost_data_nd == '2D' and y_axis_param != " \
                        "'{}'".format(ALL_COST_COL_NAME)
     weight_range_editor = RangeEditor(low=0., high=MAX_WEIGHT)
     weight_doc = Label("The following control the relative importance or "
                        "the various components that go into computing the"
                        " cost of a model,\nthat is the difference between "
                        "a simulation with that model and the corresponding"
                        " experiment."),
     view = KromView(VGroup(
         VGroup(weight_doc,
                HGroup(
                    Item("peak_time_weight", label="Peak time"),
                    Item("peak_height_weight", label="Peak height"),
                    Item("peak_slope_weight", label="Peak slope"),
                ),
                show_border=True,
                label="Weights",
                enabled_when="False",
                visible_when="not weight_edit_mode"),
         VGroup(weight_doc,
                Item("peak_time_weight",
                     label="Peak time",
                     editor=weight_range_editor),
                Item("peak_height_weight",
                     label="Peak height",
                     editor=weight_range_editor),
                Item("peak_slope_weight",
                     label="Peak slope",
                     editor=weight_range_editor),
                show_border=True,
                label="Weights",
                visible_when="weight_edit_mode"),
         HGroup(
             Spring(),
             Item("edit_weights_button",
                  show_label=False,
                  enabled_when="can_change_weights")),
         VGroup(HGroup(
             Item("show_cost_data_nd",
                  label="Plot type",
                  style="custom",
                  enabled_when="len(param_list) > 1"),
             Item("x_axis_param",
                  editor=EnumEditor(values=self.param_list)),
             Item("y_axis_param",
                  editor=EnumEditor(values=param_list_with_cost),
                  enabled_when="show_cost_data_nd != '1D'"),
         ),
                Item("plot1_2d_container",
                     editor=ComponentEditor(),
                     show_label=False),
                HGroup(
                    Spring(),
                    Item('color_bar_max_percentile',
                         editor=RangeEditor(low=1, high=100,
                                            mode='spinner'),
                         label='Colorbar high percentile (%)',
                         visible_when=two_d_plot_shown)),
                VGroup(*additional_param_controls),
                label="Cost function plot",
                show_border=True,
                visible_when="not no_cost_data"),
     ),
                     buttons=[OKButton],
                     title="View/Edit optimizer cost function")
     return view
class TrackingView(HasTraits):
  python_console_cmds = Dict()
  states = List(Instance(TrackingState))
  cn0_history = List()

  plot = Instance(Plot)
  plots = List()
  plot_data = Instance(ArrayPlotData)

  traits_view = View(
    HSplit(
      Item(
        'plot',
        editor = ComponentEditor(bgcolor = (0.8, 0.8, 0.8)),
        show_label = False,
      )
    )
  )

  def tracking_state_callback(self, data):
    n_channels = len(data) / TRACKING_STATE_BYTES_PER_CHANNEL

    if n_channels != self.n_channels:
      # Update number of channels
      self.n_channels = n_channels
      self.states = [TrackingState(0, 0, 0) for _ in range(n_channels)]
      for pl in self.plot.plots.iterkeys():
        self.plot.delplot(pl.name)
      self.plots = []
      for n in range(n_channels):
        self.plot_data.set_data('ch'+str(n), [0.0])
        pl = self.plot.plot(('t', 'ch'+str(n)), type='line', color='auto', name='ch'+str(n))
        self.plots.append(pl)
      print 'Number of tracking channels changed to', n_channels

    fmt = '<' + n_channels * 'BBf'
    state_data = struct.unpack(fmt, data)
    for n, s in enumerate(self.states):
      s.update(*state_data[3*n:3*(n+1)])
    GUI.invoke_later(self.update_plot)

  def update_plot(self):
    self.cn0_history.append([s.cn0 for s in self.states])
    self.cn0_history = self.cn0_history[-1000:]

    chans = np.transpose(self.cn0_history[-NUM_POINTS:])
    plot_labels = []
    for n in range(self.n_channels):
      self.plot_data.set_data('ch'+str(n), chans[n])
      if self.states[n].state == 0:
        plot_labels.append('Ch %02d (Disabled)' % n)
      else:
        plot_labels.append('Ch %02d (PRN%02d)' % (n, self.states[n].prn+1))
    plots = dict(zip(plot_labels, self.plots))
    self.plot.legend.plots = plots

  def __init__(self, link):
    super(TrackingView, self).__init__()

    self.n_channels = None

    self.plot_data = ArrayPlotData(t=[0.0])
    self.plot = Plot(self.plot_data, auto_colors=colours_list)
    self.plot.title = "Tracking C/N0"
    self.plot.value_range.margin = 0.1
    self.plot.value_range.bounds_func = lambda l, h, m, tb: (0, h*(1+m))
    self.plot.value_axis.orientation = 'right'
    self.plot.value_axis.axis_line_visible = False
    t = range(NUM_POINTS)
    self.plot_data.set_data('t', t)

    self.plot.legend.visible = True
    self.plot.legend.align = 'ul'
    self.plot.legend.tools.append(LegendTool(self.plot.legend, drag_button="right"))

    self.link = link
    self.link.add_callback(ids.TRACKING_STATE, self.tracking_state_callback)

    self.python_console_cmds = {
      'track': self
    }
class ConnectionMatrixViewer(HasTraits):

    tplot = Instance(Plot)
    plot = Instance(Component)
    custtool = Instance(CustomTool)
    colorbar = Instance(ColorBar)

    fro = Any
    to = Any
    data = None
    val = Float
    nodelabels = Any

    traits_view = View(
        Group(Item('plot',
                   editor=ComponentEditor(size=(800, 600)),
                   show_label=False),
              HGroup(
                  Item('fro', label="From", style='readonly', springy=True),
                  Item('to', label="To", style='readonly', springy=True),
                  Item('val', label="Value", style='readonly', springy=True),
              ),
              orientation="vertical"),
        Item('data_name', label="Edge key"),
        # handler=CustomHandler(),
        resizable=True,
        title="Connection Matrix Viewer")

    def __init__(self, nodelabels, matdict, **traits):
        """ Starts a matrix inspector
        
        Parameters
        ----------
        nodelables : list
            List of strings of labels for the rows of the matrix
        matdict : dictionary
            Keys are the edge type and values are NxN Numpy arrays """
        super(HasTraits, self).__init__(**traits)

        self.add_trait('data_name', Enum(matdict.keys()))

        self.data_name = matdict.keys()[0]
        self.data = matdict
        self.nodelables = nodelabels
        self.plot = self._create_plot_component()

        # set trait notification on customtool
        self.custtool.on_trait_change(self._update_fields, "xval")
        self.custtool.on_trait_change(self._update_fields, "yval")

    def _data_name_changed(self, old, new):
        self.pd.set_data("imagedata", self.data[self.data_name])
        #self.my_plot.set_value_selection((0, 2))
        self.tplot.title = "Connection Matrix for %s" % self.data_name

    def _update_fields(self):

        # map mouse location to array index
        frotmp = int(round(self.custtool.yval) - 1)
        totmp = int(round(self.custtool.xval) - 1)

        # check if within range
        sh = self.data[self.data_name].shape
        # assume matrix whose shape is (# of rows, # of columns)
        if frotmp >= 0 and frotmp < sh[0] and totmp >= 0 and totmp < sh[1]:
            row = " (index: %i" % (frotmp + 1) + ")"
            col = " (index: %i" % (totmp + 1) + ")"
            self.fro = " " + str(self.nodelables[frotmp]) + row
            self.to = " " + str(self.nodelables[totmp]) + col
            self.val = self.data[self.data_name][frotmp, totmp]

    def _create_plot_component(self):

        # Create a plot data object and give it this data
        self.pd = ArrayPlotData()
        self.pd.set_data("imagedata", self.data[self.data_name])

        # find dimensions
        xdim = self.data[self.data_name].shape[1]
        ydim = self.data[self.data_name].shape[0]

        # Create the plot
        self.tplot = Plot(self.pd, default_origin="top left")
        self.tplot.x_axis.orientation = "top"
        self.tplot.img_plot("imagedata",
                            name="my_plot",
                            xbounds=(0.5, xdim + 0.5),
                            ybounds=(0.5, ydim + 0.5),
                            colormap=jet)

        # Tweak some of the plot properties
        self.tplot.title = "Connection Matrix for %s" % self.data_name
        self.tplot.padding = 80

        # Right now, some of the tools are a little invasive, and we need the
        # actual CMapImage object to give to them
        self.my_plot = self.tplot.plots["my_plot"][0]

        # Attach some tools to the plot
        self.tplot.tools.append(PanTool(self.tplot))
        zoom = ZoomTool(component=self.tplot, tool_mode="box", always_on=False)
        self.tplot.overlays.append(zoom)

        # my custom tool to get the connection information
        self.custtool = CustomTool(self.tplot)
        self.tplot.tools.append(self.custtool)

        # Create the colorbar, handing in the appropriate range and colormap
        colormap = self.my_plot.color_mapper
        self.colorbar = ColorBar(
            index_mapper=LinearMapper(range=colormap.range),
            color_mapper=colormap,
            plot=self.my_plot,
            orientation='v',
            resizable='v',
            width=30,
            padding=20)

        self.colorbar.padding_top = self.tplot.padding_top
        self.colorbar.padding_bottom = self.tplot.padding_bottom

        # create a range selection for the colorbar
        self.range_selection = RangeSelection(component=self.colorbar)
        self.colorbar.tools.append(self.range_selection)
        self.colorbar.overlays.append(
            RangeSelectionOverlay(component=self.colorbar,
                                  border_color="white",
                                  alpha=0.8,
                                  fill_color="lightgray"))

        # we also want to the range selection to inform the cmap plot of
        # the selection, so set that up as well
        self.range_selection.listeners.append(self.my_plot)

        # Create a container to position the plot and the colorbar side-by-side
        container = HPlotContainer(use_backbuffer=True)
        container.add(self.tplot)
        container.add(self.colorbar)
        container.bgcolor = "white"

        return container
class CMatrixViewer(MatrixViewer):

    tplot = Instance(Plot)
    plot = Instance(Component)
    custtool = Instance(CustomTool)
    colorbar = Instance(ColorBar)

    edge_parameter = Instance(EdgeParameters)
    network_reference = Any
    matrix_data_ref = Any
    labels = Any
    fro = Any
    to = Any
    val = Float

    traits_view = View(Group(Item('plot',
                                  editor=ComponentEditor(size=(800, 600)),
                                  show_label=False),
                             HGroup(
                                 Item('fro',
                                      label="From",
                                      style='readonly',
                                      springy=True),
                                 Item('to',
                                      label="To",
                                      style='readonly',
                                      springy=True),
                                 Item('val',
                                      label="Value",
                                      style='readonly',
                                      springy=True),
                             ),
                             orientation="vertical"),
                       Item('edge_parameter_name', label="Choose edge"),
                       handler=CustomHandler(),
                       resizable=True,
                       title="Matrix Viewer")

    def __init__(self, net_ref, **traits):
        """ net_ref is a reference to a cnetwork """
        super(MatrixViewer, self).__init__(**traits)

        self.network_reference = net_ref
        self.edge_parameter = self.network_reference._edge_para
        self.matrix_data_ref = self.network_reference.datasourcemanager._srcobj.edgeattributes_matrix_dict
        self.labels = self.network_reference.datasourcemanager._srcobj.labels

        # get the currently selected edge
        self.curr_edge = self.edge_parameter.parameterset.name
        # create plot
        self.plot = self._create_plot_component()

        # set trait notification on customtool
        self.custtool.on_trait_change(self._update_fields, "xval")
        self.custtool.on_trait_change(self._update_fields, "yval")

        # add edge parameter enum
        self.add_trait('edge_parameter_name',
                       Enum(self.matrix_data_ref.keys()))
        self.edge_parameter_name = self.curr_edge

    def _edge_parameter_name_changed(self, new):
        # update edge parameter dialog
        self.edge_parameter.set_to_edge_parameter(self.edge_parameter_name)

        # update the data
        self.pd.set_data("imagedata",
                         self.matrix_data_ref[self.edge_parameter_name])

        # set range
        #self.my_plot.set_value_selection((0.0, 1.0))

    def _update_fields(self):
        from numpy import trunc

        # map mouse location to array index
        frotmp = int(trunc(self.custtool.yval))
        totmp = int(trunc(self.custtool.xval))

        # check if within range
        sh = self.matrix_data_ref[self.edge_parameter_name].shape
        # assume matrix whose shape is (# of rows, # of columns)
        if frotmp >= 0 and frotmp < sh[0] and totmp >= 0 and totmp < sh[1]:
            self.fro = self.labels[frotmp]
            self.to = self.labels[totmp]
            self.val = self.matrix_data_ref[self.edge_parameter_name][frotmp,
                                                                      totmp]

    def _create_plot_component(self):

        # we need the matrices!
        # start with the currently selected one
        #nr_nodes = self.matrix_data_ref[curr_edge].shape[0]

        # Create a plot data obect and give it this data
        self.pd = ArrayPlotData()
        self.pd.set_data("imagedata", self.matrix_data_ref[self.curr_edge])

        # Create the plot
        self.tplot = Plot(self.pd, default_origin="top left")
        self.tplot.x_axis.orientation = "top"
        self.tplot.img_plot(
            "imagedata",
            name="my_plot",
            #xbounds=(0,nr_nodes),
            #ybounds=(0,nr_nodes),
            colormap=jet)

        # Tweak some of the plot properties
        self.tplot.title = self.curr_edge
        self.tplot.padding = 50

        # Right now, some of the tools are a little invasive, and we need the
        # actual CMapImage object to give to them
        self.my_plot = self.tplot.plots["my_plot"][0]

        # Attach some tools to the plot
        self.tplot.tools.append(PanTool(self.tplot))
        zoom = ZoomTool(component=self.tplot, tool_mode="box", always_on=False)
        self.tplot.overlays.append(zoom)

        # my custom tool to get the connection information
        self.custtool = CustomTool(self.tplot)
        self.tplot.tools.append(self.custtool)

        # Create the colorbar, handing in the appropriate range and colormap
        colormap = self.my_plot.color_mapper
        self.colorbar = ColorBar(
            index_mapper=LinearMapper(range=colormap.range),
            color_mapper=colormap,
            plot=self.my_plot,
            orientation='v',
            resizable='v',
            width=30,
            padding=20)

        self.colorbar.padding_top = self.tplot.padding_top
        self.colorbar.padding_bottom = self.tplot.padding_bottom

        # TODO: the range selection gives a Segmentation Fault,
        # but why, the matrix_viewer.py example works just fine!
        # create a range selection for the colorbar
        self.range_selection = RangeSelection(component=self.colorbar)
        self.colorbar.tools.append(self.range_selection)
        self.colorbar.overlays.append(
            RangeSelectionOverlay(component=self.colorbar,
                                  border_color="white",
                                  alpha=0.8,
                                  fill_color="lightgray"))

        # we also want to the range selection to inform the cmap plot of
        # the selection, so set that up as well
        #self.range_selection.listeners.append(self.my_plot)

        # Create a container to position the plot and the colorbar side-by-side
        container = HPlotContainer(use_backbuffer=True)
        container.add(self.tplot)
        container.add(self.colorbar)
        container.bgcolor = "white"

        # my_plot.set_value_selection((-1.3, 6.9))

        return container
Beispiel #21
0
class BaselineView(HasTraits):
    python_console_cmds = Dict()

    table = List()

    logging_b = Bool(False)
    directory_name_b = File

    plot = Instance(Plot)
    plot_data = Instance(ArrayPlotData)

    running = Bool(True)
    zoomall = Bool(False)
    position_centered = Bool(False)

    clear_button = SVGButton(label='',
                             tooltip='Clear',
                             filename=os.path.join(determine_path(), 'images',
                                                   'iconic', 'x.svg'),
                             width=16,
                             height=16)
    zoomall_button = SVGButton(label='',
                               tooltip='Zoom All',
                               toggle=True,
                               filename=os.path.join(determine_path(),
                                                     'images', 'iconic',
                                                     'fullscreen.svg'),
                               width=16,
                               height=16)
    center_button = SVGButton(label='',
                              tooltip='Center on Baseline',
                              toggle=True,
                              filename=os.path.join(determine_path(), 'images',
                                                    'iconic', 'target.svg'),
                              width=16,
                              height=16)
    paused_button = SVGButton(label='',
                              tooltip='Pause',
                              toggle_tooltip='Run',
                              toggle=True,
                              filename=os.path.join(determine_path(), 'images',
                                                    'iconic', 'pause.svg'),
                              toggle_filename=os.path.join(
                                  determine_path(), 'images', 'iconic',
                                  'play.svg'),
                              width=16,
                              height=16)

    reset_button = Button(label='Reset Filters')
    reset_iar_button = Button(label='Reset IAR')
    init_base_button = Button(label='Init. with known baseline')

    traits_view = View(
        HSplit(
            Item('table',
                 style='readonly',
                 editor=TabularEditor(adapter=SimpleAdapter()),
                 show_label=False,
                 width=0.3),
            VGroup(
                HGroup(
                    Item('paused_button', show_label=False),
                    Item('clear_button', show_label=False),
                    Item('zoomall_button', show_label=False),
                    Item('center_button', show_label=False),
                    Item('reset_button', show_label=False),
                    Item('reset_iar_button', show_label=False),
                    Item('init_base_button', show_label=False),
                ),
                Item(
                    'plot',
                    show_label=False,
                    editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8)),
                ))))

    def _zoomall_button_fired(self):
        self.zoomall = not self.zoomall

    def _center_button_fired(self):
        self.position_centered = not self.position_centered

    def _paused_button_fired(self):
        self.running = not self.running

    def _reset_button_fired(self):
        self.link(MsgResetFilters(filter=0))

    def _reset_iar_button_fired(self):
        self.link(MsgResetFilters(filter=1))

    def _init_base_button_fired(self):
        self.link(MsgInitBase())

    def _clear_button_fired(self):
        self.neds[:] = np.NAN
        self.fixeds[:] = False
        self.plot_data.set_data('n_fixed', [])
        self.plot_data.set_data('e_fixed', [])
        self.plot_data.set_data('d_fixed', [])
        self.plot_data.set_data('n_float', [])
        self.plot_data.set_data('e_float', [])
        self.plot_data.set_data('d_float', [])
        self.plot_data.set_data('t', [])
        self.plot_data.set_data('cur_fixed_n', [])
        self.plot_data.set_data('cur_fixed_e', [])
        self.plot_data.set_data('cur_fixed_d', [])
        self.plot_data.set_data('cur_float_n', [])
        self.plot_data.set_data('cur_float_e', [])
        self.plot_data.set_data('cur_float_d', [])

    def iar_state_callback(self, sbp_msg, **metadata):
        self.num_hyps = sbp_msg.num_hyps
        self.last_hyp_update = time.time()

    def _baseline_callback_ned(self, sbp_msg, **metadata):
        # Updating an ArrayPlotData isn't thread safe (see chaco issue #9), so
        # actually perform the update in the UI thread.
        if self.running:
            GUI.invoke_later(self.baseline_callback, sbp_msg)

    def update_table(self):
        self._table_list = self.table.items()

    def gps_time_callback(self, sbp_msg, **metadata):
        self.week = MsgGPSTime(sbp_msg).wn
        self.nsec = MsgGPSTime(sbp_msg).ns

    def mode_string(self, msg):
        if msg:
            self.fixed = (msg.flags & 1) == 1
            if self.fixed:
                return 'Fixed RTK'
            else:
                return 'Float'
        return 'None'

    def baseline_callback(self, sbp_msg):
        self.last_btime_update = time.time()
        soln = MsgBaselineNED(sbp_msg)
        self.last_soln = soln
        table = []

        soln.n = soln.n * 1e-3
        soln.e = soln.e * 1e-3
        soln.d = soln.d * 1e-3

        dist = np.sqrt(soln.n**2 + soln.e**2 + soln.d**2)

        tow = soln.tow * 1e-3
        if self.nsec is not None:
            tow += self.nsec * 1e-9

        if self.week is not None:
            t = datetime.datetime(1980, 1, 6) + \
                datetime.timedelta(weeks=self.week) + \
                datetime.timedelta(seconds=tow)

            table.append(('GPS Time', t))
            table.append(('GPS Week', str(self.week)))

            if self.directory_name_b == '':
                filepath = time.strftime("baseline_log_%Y%m%d-%H%M%S.csv")
            else:
                filepath = os.path.join(
                    self.directory_name_b,
                    time.strftime("baseline_log_%Y%m%d-%H%M%S.csv"))

            if self.logging_b == False:
                self.log_file = None

            if self.logging_b:
                if self.log_file is None:
                    self.log_file = open(filepath, 'w')

                    self.log_file.write(
                        'time,north(meters),east(meters),down(meters),distance(meters),num_sats,flags,num_hypothesis\n'
                    )

                self.log_file.write('%s,%.4f,%.4f,%.4f,%.4f,%d,0x%02x,%d\n' %
                                    (str(t), soln.n, soln.e, soln.d, dist,
                                     soln.n_sats, soln.flags, self.num_hyps))
                self.log_file.flush()

        table.append(('GPS ToW', tow))

        table.append(('N', soln.n))
        table.append(('E', soln.e))
        table.append(('D', soln.d))
        table.append(('Dist.', dist))
        table.append(('Num. Sats.', soln.n_sats))
        table.append(('Flags', '0x%02x' % soln.flags))
        table.append(('Mode', self.mode_string(soln)))
        if time.time() - self.last_hyp_update < 10 and self.num_hyps != 1:
            table.append(('IAR Num. Hyps.', self.num_hyps))
        else:
            table.append(('IAR Num. Hyps.', "None"))

        # Rotate array, deleting oldest entries to maintain
        # no more than N in plot
        self.neds[1:] = self.neds[:-1]
        self.fixeds[1:] = self.fixeds[:-1]

        # Insert latest position
        self.neds[0][:] = [soln.n, soln.e, soln.d]
        self.fixeds[0] = self.fixed

        neds_fixed = self.neds[self.fixeds]
        neds_float = self.neds[np.logical_not(self.fixeds)]

        if not all(map(any, np.isnan(neds_fixed))):
            self.plot_data.set_data('n_fixed', neds_fixed.T[0])
            self.plot_data.set_data('e_fixed', neds_fixed.T[1])
            self.plot_data.set_data('d_fixed', neds_fixed.T[2])
        if not all(map(any, np.isnan(neds_float))):
            self.plot_data.set_data('n_float', neds_float.T[0])
            self.plot_data.set_data('e_float', neds_float.T[1])
            self.plot_data.set_data('d_float', neds_float.T[2])

        if self.fixed:
            self.plot_data.set_data('cur_fixed_n', [soln.n])
            self.plot_data.set_data('cur_fixed_e', [soln.e])
            self.plot_data.set_data('cur_fixed_d', [soln.d])
            self.plot_data.set_data('cur_float_n', [])
            self.plot_data.set_data('cur_float_e', [])
            self.plot_data.set_data('cur_float_d', [])
        else:
            self.plot_data.set_data('cur_float_n', [soln.n])
            self.plot_data.set_data('cur_float_e', [soln.e])
            self.plot_data.set_data('cur_float_d', [soln.d])
            self.plot_data.set_data('cur_fixed_n', [])
            self.plot_data.set_data('cur_fixed_e', [])
            self.plot_data.set_data('cur_fixed_d', [])

        self.plot_data.set_data('ref_n', [0.0])
        self.plot_data.set_data('ref_e', [0.0])
        self.plot_data.set_data('ref_d', [0.0])

        if self.position_centered:
            d = (self.plot.index_range.high - self.plot.index_range.low) / 2.
            self.plot.index_range.set_bounds(soln.e - d, soln.e + d)
            d = (self.plot.value_range.high - self.plot.value_range.low) / 2.
            self.plot.value_range.set_bounds(soln.n - d, soln.n + d)

        if self.zoomall:
            plot_square_axes(self.plot, ('e_fixed', 'e_float'),
                             ('n_fixed', 'n_float'))
        self.table = table

    def __init__(self, link, plot_history_max=1000, dirname=''):
        super(BaselineView, self).__init__()
        self.log_file = None
        self.directory_name_b = dirname
        self.num_hyps = 0
        self.last_hyp_update = 0
        self.last_btime_update = 0
        self.last_soln = None
        self.plot_data = ArrayPlotData(n_fixed=[0.0],
                                       e_fixed=[0.0],
                                       d_fixed=[0.0],
                                       n_float=[0.0],
                                       e_float=[0.0],
                                       d_float=[0.0],
                                       t=[0.0],
                                       ref_n=[0.0],
                                       ref_e=[0.0],
                                       ref_d=[0.0],
                                       cur_fixed_e=[],
                                       cur_fixed_n=[],
                                       cur_fixed_d=[],
                                       cur_float_e=[],
                                       cur_float_n=[],
                                       cur_float_d=[])
        self.plot_history_max = plot_history_max

        self.neds = np.empty((plot_history_max, 3))
        self.neds[:] = np.NAN
        self.fixeds = np.zeros(plot_history_max, dtype=bool)

        self.plot = Plot(self.plot_data)
        color_float = (0.5, 0.5, 1.0)
        color_fixed = 'orange'
        pts_float = self.plot.plot(('e_float', 'n_float'),
                                   type='scatter',
                                   color=color_float,
                                   marker='dot',
                                   line_width=0.0,
                                   marker_size=1.0)
        pts_fixed = self.plot.plot(('e_fixed', 'n_fixed'),
                                   type='scatter',
                                   color=color_fixed,
                                   marker='dot',
                                   line_width=0.0,
                                   marker_size=1.0)
        lin = self.plot.plot(('e_fixed', 'n_fixed'),
                             type='line',
                             color=(1, 0.65, 0, 0.1))
        ref = self.plot.plot(('ref_e', 'ref_n'),
                             type='scatter',
                             color='red',
                             marker='plus',
                             marker_size=5,
                             line_width=1.5)
        cur_fixed = self.plot.plot(('cur_fixed_e', 'cur_fixed_n'),
                                   type='scatter',
                                   color=color_fixed,
                                   marker='plus',
                                   marker_size=5,
                                   line_width=1.5)
        cur_float = self.plot.plot(('cur_float_e', 'cur_float_n'),
                                   type='scatter',
                                   color=color_float,
                                   marker='plus',
                                   marker_size=5,
                                   line_width=1.5)
        plot_labels = ['Base Position', 'RTK Fixed', 'RTK Float']
        plots_legend = dict(zip(plot_labels, [ref, cur_fixed, cur_float]))
        self.plot.legend.plots = plots_legend
        self.plot.legend.visible = True

        self.plot.index_axis.tick_label_position = 'inside'
        self.plot.index_axis.tick_label_color = 'gray'
        self.plot.index_axis.tick_color = 'gray'
        self.plot.index_axis.title = 'E (meters)'
        self.plot.index_axis.title_spacing = 5
        self.plot.value_axis.tick_label_position = 'inside'
        self.plot.value_axis.tick_label_color = 'gray'
        self.plot.value_axis.tick_color = 'gray'
        self.plot.value_axis.title = 'N (meters)'
        self.plot.value_axis.title_spacing = 5
        self.plot.padding = (25, 25, 25, 25)

        self.plot.tools.append(PanTool(self.plot))
        zt = ZoomTool(self.plot,
                      zoom_factor=1.1,
                      tool_mode="box",
                      always_on=False)
        self.plot.overlays.append(zt)

        self.week = None
        self.nsec = 0

        self.link = link
        self.link.add_callback(self._baseline_callback_ned,
                               SBP_MSG_BASELINE_NED)
        self.link.add_callback(self.iar_state_callback, SBP_MSG_IAR_STATE)
        self.link.add_callback(self.gps_time_callback, SBP_MSG_GPS_TIME)

        self.python_console_cmds = {'baseline': self}
class ODMR_2MW(ManagedJob, GetSetItemsMixin):
    """Provides ODMR measurements."""

    # starting and stopping
    keep_data = Bool(
        False)  # helper variable to decide whether to keep existing data
    resubmit_button = Button(
        label='resubmit',
        desc=
        'Submits the measurement to the job manager. Tries to keep previously acquired data. Behaves like a normal submit if sequence or time bins have changed since previous run.'
    )

    # measurement parameters
    power = Range(low=-100.,
                  high=25.,
                  value=-8,
                  desc='Power [dBm]',
                  label='Power [dBm]',
                  mode='text',
                  auto_set=False,
                  enter_set=True)
    frequency_begin = Range(low=1,
                            high=20e9,
                            value=2.85e9,
                            desc='Start Frequency [Hz]',
                            label='Begin [Hz]',
                            editor=TextEditor(auto_set=False,
                                              enter_set=True,
                                              evaluate=float,
                                              format_str='%e'))
    frequency_end = Range(low=1,
                          high=20e9,
                          value=2.90e9,
                          desc='Stop Frequency [Hz]',
                          label='End [Hz]',
                          editor=TextEditor(auto_set=False,
                                            enter_set=True,
                                            evaluate=float,
                                            format_str='%e'))
    frequency_delta = Range(low=1e-3,
                            high=20e9,
                            value=1e6,
                            desc='frequency step [Hz]',
                            label='Delta [Hz]',
                            editor=TextEditor(auto_set=False,
                                              enter_set=True,
                                              evaluate=float,
                                              format_str='%e'))
    t_pi = Range(low=1.,
                 high=100000.,
                 value=1000.,
                 desc='length of pi pulse [ns]',
                 label='pi [ns]',
                 mode='text',
                 auto_set=False,
                 enter_set=True)
    laser = Range(low=1.,
                  high=10000.,
                  value=300.,
                  desc='laser [ns]',
                  label='laser [ns]',
                  mode='text',
                  auto_set=False,
                  enter_set=True)
    wait = Range(low=1.,
                 high=10000.,
                 value=1000.,
                 desc='wait [ns]',
                 label='wait [ns]',
                 mode='text',
                 auto_set=False,
                 enter_set=True)
    pulsed = Bool(False, label='pulsed')
    power_p = Range(low=-100.,
                    high=25.,
                    value=-20,
                    desc='Power Pmode [dBm]',
                    label='Power[dBm]',
                    mode='text',
                    auto_set=False,
                    enter_set=True)
    frequency_begin_p = Range(low=1,
                              high=20e9,
                              value=2.87e9,
                              desc='Start Frequency Pmode[Hz]',
                              label='Begin[Hz]',
                              editor=TextEditor(auto_set=False,
                                                enter_set=True,
                                                evaluate=float,
                                                format_str='%e'))
    frequency_end_p = Range(low=1,
                            high=20e9,
                            value=2.88e9,
                            desc='Stop Frequency Pmode[Hz]',
                            label='End[Hz]',
                            editor=TextEditor(auto_set=False,
                                              enter_set=True,
                                              evaluate=float,
                                              format_str='%e'))
    frequency_delta_p = Range(low=1e-3,
                              high=20e9,
                              value=1e5,
                              desc='frequency step Pmode[Hz]',
                              label='Delta[Hz]',
                              editor=TextEditor(auto_set=False,
                                                enter_set=True,
                                                evaluate=float,
                                                format_str='%e'))
    mw_source = Enum('mw',
                     'mw2',
                     desc='Select microwave source to use',
                     label='axis',
                     editor=EnumEditor(cols=3, values={
                         'x': '1:X',
                         'y': '2:Y'
                     }))
    seconds_per_point = Range(low=20e-3,
                              high=1,
                              value=20e-3,
                              desc='Seconds per point',
                              label='Seconds per point',
                              mode='text',
                              auto_set=False,
                              enter_set=True)
    stop_time = Range(
        low=1.,
        value=np.inf,
        desc='Time after which the experiment stops by itself [s]',
        label='Stop time [s]',
        mode='text',
        auto_set=False,
        enter_set=True)
    n_lines = Range(low=1,
                    high=10000,
                    value=50,
                    desc='Number of lines in Matrix',
                    label='Matrix lines',
                    mode='text',
                    auto_set=False,
                    enter_set=True)

    # control data fitting
    perform_fit = Bool(False, label='perform fit')
    number_of_resonances = Trait(
        'auto', String('auto', auto_set=False, enter_set=True),
        Int(10000.,
            desc='Number of Lorentzians used in fit',
            label='N',
            auto_set=False,
            enter_set=True))
    threshold = Range(
        low=-99,
        high=99.,
        value=-50.,
        desc=
        'Threshold for detection of resonances [%]. The sign of the threshold specifies whether the resonances are negative or positive.',
        label='threshold [%]',
        mode='text',
        auto_set=False,
        enter_set=True)

    # fit result
    fit_parameters = Array(value=np.array((np.nan, np.nan, np.nan, np.nan)))
    fit_frequencies = Array(value=np.array((np.nan, )), label='frequency [Hz]')
    fit_line_width = Array(value=np.array((np.nan, )), label='line_width [Hz]')
    fit_contrast = Array(value=np.array((np.nan, )), label='contrast [%]')

    # measurement data
    frequency = Array()
    counts = Array()
    counts_matrix = Array()
    run_time = Float(value=0.0, desc='Run time [s]', label='Run time [s]')

    # plotting
    line_label = Instance(PlotLabel)
    line_data = Instance(ArrayPlotData)
    matrix_data = Instance(ArrayPlotData)
    line_plot = Instance(Plot, editor=ComponentEditor())
    matrix_plot = Instance(Plot, editor=ComponentEditor())

    def __init__(self):
        super(ODMR_2MW, self).__init__()
        self._create_line_plot()
        self._create_matrix_plot()
        self.on_trait_change(self._update_line_data_index,
                             'frequency',
                             dispatch='ui')
        self.on_trait_change(self._update_line_data_value,
                             'counts',
                             dispatch='ui')
        self.on_trait_change(self._update_line_data_fit,
                             'fit_parameters',
                             dispatch='ui')
        self.on_trait_change(self._update_matrix_data_value,
                             'counts_matrix',
                             dispatch='ui')
        self.on_trait_change(self._update_matrix_data_index,
                             'n_lines,frequency',
                             dispatch='ui')
        self.on_trait_change(
            self._update_fit,
            'counts,perform_fit,number_of_resonances,threshold',
            dispatch='ui')

    def _counts_matrix_default(self):
        return np.zeros((self.n_lines, len(self.frequency)))

    def _frequency_default(self):
        if self.pulsed:
            return np.arange(self.frequency_begin_p,
                             self.frequency_end_p + self.frequency_delta_p,
                             self.frequency_delta_p)
        else:
            return np.arange(self.frequency_begin,
                             self.frequency_end + self.frequency_delta,
                             self.frequency_delta)

    def _counts_default(self):
        return np.zeros(self.frequency.shape)

    # data acquisition

    def apply_parameters(self):
        """Apply the current parameters and decide whether to keep previous data."""
        if self.pulsed:
            frequency = np.arange(
                self.frequency_begin_p,
                self.frequency_end_p + self.frequency_delta_p,
                self.frequency_delta_p)
        else:
            frequency = np.arange(self.frequency_begin,
                                  self.frequency_end + self.frequency_delta,
                                  self.frequency_delta)

        if not self.keep_data or np.any(frequency != self.frequency):
            self.frequency = frequency
            self.counts = np.zeros(frequency.shape)
            self.run_time = 0.0

        self.keep_data = True  # when job manager stops and starts the job, data should be kept. Only new submission should clear data.

    def _run(self):

        try:
            self.state = 'run'
            self.apply_parameters()

            if self.run_time >= self.stop_time:
                self.state = 'done'
                return

            # if pulsed, turn on sequence
            if self.pulsed:
                ha.PulseGenerator().Sequence([(['laser'], self.laser),
                                              ([], self.wait),
                                              (['mw'], self.t_pi), ([], 15)])
            else:
                ha.PulseGenerator().Open()

            n = len(self.frequency)

            if self.pulsed:
                ha.Microwave().setPower(self.power_p)
                ha.Microwave().initSweep(
                    self.frequency,
                    self.power_p * np.ones(self.frequency.shape))
            else:
                ha.Microwave().setPower(self.power)
                ha.Microwave().initSweep(
                    self.frequency, self.power * np.ones(self.frequency.shape))
            ha.Counter().configure(n, self.seconds_per_point, DutyCycle=0.8)
            time.sleep(0.5)

            while self.run_time < self.stop_time:
                start_time = time.time()
                if threading.currentThread().stop_request.isSet():
                    break
                ha.Microwave().resetListPos()
                counts = ha.Counter().run() / 1e3
                self.run_time += time.time() - start_time
                self.counts += counts
                self.counts_matrix = np.vstack(
                    (counts, self.counts_matrix[:-1, :]))
                self.trait_property_changed('counts', self.counts)
                """
                ha.Microwave().doSweep()
                
                timeout = 3.
                start_time = time.time()
                while not self._count_between_markers.ready():
                    time.sleep(0.1)
                    if time.time() - start_time > timeout:
                        print "count between markers timeout in ODMR"
                        break
                        
                counts = self._count_between_markers.getData(0)
                self._count_between_markers.clean()
                """

            if self.run_time < self.stop_time:
                self.state = 'idle'
            else:
                self.state = 'done'
            if self.pulsed:
                ha.Microwave().setOutput(None, self.frequency_begin_p)
            else:
                ha.Microwave().setOutput(None, self.frequency_begin)
            ha.PulseGenerator().Light()
            ha.Counter().clear()
        except:
            logging.getLogger().exception('Error in odmr.')
            self.state = 'error'
        finally:
            if self.pulsed:
                ha.Microwave().setOutput(None, self.frequency_begin_p)
            else:
                ha.Microwave().setOutput(None, self.frequency_begin)

    # fitting
    def _update_fit(self):
        if self.perform_fit:
            N = self.number_of_resonances
            if N != 'auto':
                N = int(N)
            try:
                p = fitting.fit_multiple_lorentzians(self.frequency,
                                                     self.counts,
                                                     N,
                                                     threshold=self.threshold *
                                                     0.01)
            except Exception:
                logging.getLogger().debug('ODMR fit failed.', exc_info=True)
                p = np.nan * np.empty(4)
        else:
            p = np.nan * np.empty(4)
        self.fit_parameters = p
        self.fit_frequencies = p[1::3]
        self.fit_line_width = p[2::3]
        N = len(p) / 3
        contrast = np.empty(N)
        c = p[0]
        pp = p[1:].reshape((N, 3))
        for i, pn in enumerate(pp):
            a = pn[2]
            g = pn[1]
            A = np.abs(a / (np.pi * g))
            if a > 0:
                contrast[i] = 100 * A / (A + c)
            else:
                contrast[i] = 100 * A / c
        self.fit_contrast = contrast

    # plotting

    def _create_line_plot(self):
        line_data = ArrayPlotData(frequency=np.array((0., 1.)),
                                  counts=np.array((0., 0.)),
                                  fit=np.array((0., 0.)))
        line_plot = Plot(line_data,
                         padding=8,
                         padding_left=64,
                         padding_bottom=32)
        line_plot.plot(('frequency', 'counts'), style='line', color='blue')
        line_plot.index_axis.title = 'Frequency [MHz]'
        line_plot.value_axis.title = 'Fluorescence/k'
        line_label = PlotLabel(text='',
                               hjustify='left',
                               vjustify='bottom',
                               position=[64, 128])
        line_plot.overlays.append(line_label)
        self.line_label = line_label
        self.line_data = line_data
        self.line_plot = line_plot

    def _create_matrix_plot(self):
        matrix_data = ArrayPlotData(image=np.zeros((2, 2)))
        matrix_plot = Plot(matrix_data,
                           padding=8,
                           padding_left=64,
                           padding_bottom=32)
        matrix_plot.index_axis.title = 'Frequency [MHz]'
        matrix_plot.value_axis.title = 'line #'
        matrix_plot.img_plot('image',
                             xbounds=(self.frequency[0], self.frequency[-1]),
                             ybounds=(0, self.n_lines),
                             colormap=Spectral)
        self.matrix_data = matrix_data
        self.matrix_plot = matrix_plot

    def _perform_fit_changed(self, new):
        plot = self.line_plot
        if new:
            plot.plot(('frequency', 'fit'),
                      style='line',
                      color='red',
                      name='fit')
            self.line_label.visible = True
        else:
            plot.delplot('fit')
            self.line_label.visible = False
        plot.request_redraw()

    def _update_line_data_index(self):
        self.line_data.set_data('frequency', self.frequency * 1e-6)
        self.counts_matrix = self._counts_matrix_default()

    def _update_line_data_value(self):
        self.line_data.set_data('counts', self.counts)

    def _update_line_data_fit(self):
        if not np.isnan(self.fit_parameters[0]):
            self.line_data.set_data(
                'fit',
                fitting.NLorentzians(*self.fit_parameters)(self.frequency))
            p = self.fit_parameters
            f = p[1::3]
            w = p[2::3]
            N = len(p) / 3
            contrast = np.empty(N)
            c = p[0]
            pp = p[1:].reshape((N, 3))
            for i, pi in enumerate(pp):
                a = pi[2]
                g = pi[1]
                A = np.abs(a / (np.pi * g))
                if a > 0:
                    contrast[i] = 100 * A / (A + c)
                else:
                    contrast[i] = 100 * A / c
            s = ''
            for i, fi in enumerate(f):
                s += 'f %i: %.6e Hz, HWHM %.3e Hz, contrast %.1f%%\n' % (
                    i + 1, fi, w[i], contrast[i])
            self.line_label.text = s

    def _update_matrix_data_value(self):
        self.matrix_data.set_data('image', self.counts_matrix)

    def _update_matrix_data_index(self):
        if self.n_lines > self.counts_matrix.shape[0]:
            self.counts_matrix = np.vstack(
                (self.counts_matrix,
                 np.zeros((self.n_lines - self.counts_matrix.shape[0],
                           self.counts_matrix.shape[1]))))
        else:
            self.counts_matrix = self.counts_matrix[:self.n_lines]
        self.matrix_plot.components[0].index.set_data(
            (self.frequency[0] * 1e-6, self.frequency[-1] * 1e-6),
            (0.0, float(self.n_lines)))

    # saving data

    def save_line_plot(self, filename):
        self.save_figure(self.line_plot, filename)

    def save_matrix_plot(self, filename):
        self.save_figure(self.matrix_plot, filename)

    def save_all(self, filename):
        self.save_line_plot(filename + '_ODMR_Line_Plot.png')
        self.save_matrix_plot(filename + '_ODMR_Matrix_Plot.png')
        self.save(filename + '_ODMR.pys')

    # react to GUI events

    def submit(self):
        """Submit the job to the JobManager."""
        self.keep_data = False
        ManagedJob.submit(self)
        print threading.currentThread().getName()

    def resubmit(self):
        """Submit the job to the JobManager."""
        self.keep_data = True
        ManagedJob.submit(self)

    def _resubmit_button_fired(self):
        """React to start button. Submit the Job."""
        self.resubmit()

    traits_view = View(VGroup(
        HGroup(
            Item('submit_button', show_label=False),
            Item('remove_button', show_label=False),
            Item('resubmit_button', show_label=False),
            Item('priority', enabled_when='state != "run"'),
            Item('state', style='readonly'),
            Item('run_time', style='readonly', format_str='%.f'),
            Item('stop_time'),
        ),
        Group(
            HGroup(
                Item('pulsed', enabled_when='state != "run"'),
                Item('power_p', width=-40, enabled_when='state != "run"'),
                Item('frequency_begin_p',
                     width=-80,
                     enabled_when='state != "run"'),
                Item('frequency_end_p',
                     width=-80,
                     enabled_when='state != "run"'),
                Item('frequency_delta_p',
                     width=-80,
                     enabled_when='state != "run"'),
                Item('t_pi', width=-50, enabled_when='state != "run"'),
                label='Pulsed Mode',
            ),
            HGroup(
                Item('power', width=-40, enabled_when='state != "run"'),
                Item('frequency_begin',
                     width=-80,
                     enabled_when='state != "run"'),
                Item('frequency_end', width=-80,
                     enabled_when='state != "run"'),
                Item('frequency_delta',
                     width=-80,
                     enabled_when='state != "run"'),
                label='CW Mode',
            ),
            layout='tabbed',
        ),
        HGroup(
            Item('seconds_per_point', width=-40,
                 enabled_when='state != "run"'),
            Item('laser', width=-50, enabled_when='state != "run"'),
            Item('wait', width=-50, enabled_when='state != "run"'),
            Item('mw_source', width=-80, enabled_when='state != "run"')),
        HGroup(
            Item('perform_fit'),
            Item('number_of_resonances', width=-60),
            Item('threshold', width=-60),
            Item('n_lines', width=-60),
        ),
        HGroup(
            Item('fit_contrast', style='readonly'),
            Item('fit_line_width', style='readonly'),
            Item('fit_frequencies', style='readonly'),
        ),
        VSplit(
            Item('line_plot', show_label=False, resizable=True),
            Item('matrix_plot', show_label=False, resizable=True),
        ),
    ),
                       menubar=MenuBar(
                           Menu(Action(action='saveLinePlot',
                                       name='SaveLinePlot (.png)'),
                                Action(action='saveMatrixPlot',
                                       name='SaveMatrixPlot (.png)'),
                                Action(action='save',
                                       name='Save (.pyd or .pys)'),
                                Action(action='saveAll',
                                       name='Save All (.png+.pys)'),
                                Action(action='export',
                                       name='Export as Ascii (.asc)'),
                                Action(action='export',
                                       name='Export as Ascii (.asc)'),
                                Action(action='load', name='Load'),
                                Action(action='_on_close', name='Quit'),
                                name='File')),
                       title='ODMR',
                       width=900,
                       height=800,
                       buttons=[],
                       resizable=True,
                       handler=ODMRHandler)

    get_set_items = [
        'frequency', 'counts', 'counts_matrix', 'fit_parameters',
        'fit_contrast', 'fit_line_width', 'fit_frequencies', 'perform_fit',
        'run_time', 'power', 'frequency_begin', 'frequency_end',
        'frequency_delta', 'power_p', 'frequency_begin_p', 'frequency_end_p',
        'frequency_delta_p', 'laser', 'wait', 'pulsed', 't_pi',
        'seconds_per_point', 'stop_time', 'n_lines', 'number_of_resonances',
        'threshold', '__doc__'
    ]
Beispiel #23
0
class Visualization(HasTraits):

    # Data models
    dipole_data_model = Instance(DataModel)
    signals_data_model = Instance(DataModel)

    # Renderers
    # dipole_renderer = Instance(LinePlot)
    signals_renderer = Instance(MultiLinePlot)

    # Plots
    dipole_plot = Instance(LinePlot)
    signals_plot = Instance(Plot)

    def _signals_renderer_default(self):
        print('_signals_renderer_default')
        """Create the default MultiLinePlot instance."""

        xs = ArrayDataSource(self.signals_data_model.x_index,
                             sort_order='ascending')
        xrange = DataRange1D()
        xrange.add(xs)

        ys = ArrayDataSource(self.signals_data_model.y_index,
                             sort_order='ascending')
        yrange = DataRange1D()
        yrange.add(ys)

        # The data source for the MultiLinePlot.
        ds = MultiArrayDataSource(data=self.signals_data_model.data)

        multi_line_plot_renderer = \
            MultiLinePlot(
                index = xs,
                yindex = ys,
                index_mapper = LinearMapper(range=xrange),
                value_mapper = LinearMapper(range=yrange),
                value=ds,
                global_max = self.signals_data_model.data.max(),
                global_min = self.signals_data_model.data.min(),
                fast_clip = False)

        # Add pan tool
        multi_line_plot_renderer.tools.append(
            PanTool(multi_line_plot_renderer, restrict_to_data=True))

        # Add zoom tool
        multi_line_plot_renderer.overlays.append(
            ZoomTool(multi_line_plot_renderer,
                     tool_mode="range",
                     always_on=False,
                     x_max_zoom_factor=20.0,
                     y_max_zoom_factor=20.0,
                     x_min_zoom_factor=1.0,
                     y_min_zoom_factor=1.0,
                     zoom_to_mouse=True))
        #multi_line_plot_renderer.overlays.append(LineInspector(multi_line_plot_renderer, axis="index",write_metadata=True,is_listener=True))
        # multi_line_plot_renderer.overlays.append(LineInspector(multi_line_plot_renderer, axis='value',
        #                                         write_metadata=True,
        #                                         is_listener=True))
        multi_line_plot_renderer.overlays.append(
            LineInspector(multi_line_plot_renderer,
                          axis="index",
                          write_metadata=True,
                          is_listener=True))
        return multi_line_plot_renderer

    # def _dipole_renderer_default(self):
    #     print("_dipole_renderer_default")
    #     xs = ArrayDataSource(self.dipole_data_model.x_index, sort_order='ascending')
    #     xrange = DataRange1D()
    #     xrange.add(xs)
    #     xm = LinearMapper(range = xrange)
    #
    #     ys = ArrayDataSource(self.dipole_data_model.data, sort_order='ascending')
    #     yrange = DataRange1D()
    #     yrange.add(ys)
    #     ym = LinearMapper(range=yrange)
    #
    #     #pd = ArrayPlotData(index = self.dipole_data_model.x_index)
    #     pd = ArrayDataSource(data = self.dipole_data_model.data)
    #     #pd.set_data("y", self.dipole_data_model.data)
    #
    #     line_plot_renderer = LinePlot(index = xs,
    #                                   value=pd,
    #                                   index_mapper = LinearMapper(range=xrange),
    #                                   value_mapper = LinearMapper(range=yrange),
    #                                   global_max = self.dipole_data_model.data.max(),
    #                                   global_min = self.dipole_data_model.data.min(),
    #                                   fast_clip = False)
    #     return line_plot_renderer

    def _signals_plot_default(self):
        print('_signals_plot_default')
        """Create the Plot instance."""

        plot = Plot()

        plot.add(self.signals_renderer)

        x_axis = PlotAxis(component=plot,
                          mapper=self.signals_renderer.index_mapper,
                          orientation='bottom')
        # y_axis = PlotAxis(component=plot,
        #                     mapper=self.signals_renderer.value_mapper,
        #                     orientation='left')
        plot.overlays.extend([x_axis])

        plot.origin_axis_visible = False
        plot.padding_top = 0
        plot.padding_left = 0
        plot.padding_right = 0
        plot.padding_bottom = 50
        plot.border_visible = False
        plot.bgcolor = "white"
        plot.use_downsampling = True
        return plot

    def _dipole_plot_default(self):
        print('_dipole_plot_default')
        """Create the Plot instance."""

        #pd = ArrayPlotData(index = self.dipole_data_model.x_index)
        #pd.set_data("y", self.dipole_data_model.data)

        plot = create_line_plot(
            (self.dipole_data_model.x_index, self.dipole_data_model.data),
            color='black')
        #plot.add(self.dipole_renderer)
        #plot.plot(("index", "y"))

        x_axis = PlotAxis(component=plot,
                          mapper=plot.index_mapper,
                          orientation='bottom')
        # # y_axis = PlotAxis(component=plot,
        # #                     mapper=self.signals_renderer.value_mapper,
        # #                     orientation='left')
        plot.overlays.extend([x_axis])
        plot.index = self.signals_renderer.index
        plot.overlays.append(
            LineInspector(plot, write_metadata=True, is_listener=True))
        # plot.overlays.append(LineInspector(plot, axis="value",
        #                           is_listener=True))

        plot.origin_axis_visible = False
        plot.padding_top = 0
        plot.padding_left = 0
        plot.padding_right = 0
        plot.padding_bottom = 50
        plot.border_visible = False
        plot.bgcolor = "white"
        plot.use_downsampling = True
        return plot

    def _signals_data_model_changed(self, old, new):
        print('model_changed')

        xs = ArrayDataSource(self.signals_data_model.x_index,
                             sort_order='ascending')
        xrange = DataRange1D()
        xrange.add(xs)

        ys = ArrayDataSource(self.signals_data_model.y_index,
                             sort_order='ascending')
        yrange = DataRange1D()
        yrange.add(ys)

        # The data source for the MultiLinePlot.
        print('ds')
        ds = MultiArrayDataSource(data=self.signals_data_model.data)

        self.signals_renderer.set(
            index=xs,
            yindex=ys,
            #index_mapper = LinearMapper(range=xrange), value_mapper = LinearMapper(range=yrange),
            value=ds,
            global_max=self.signals_data_model.data.max(),
            global_min=self.signals_data_model.data.min())
        self.signals_renderer.index_mapper.range = xrange
        self.signals_renderer.value_mapper.range = yrange
        self.signals_renderer.request_redraw()

    def _dipole_data_model_changed(self, old, new):
        print('dipole_data_model_changed')
        #self.dipole_plot.index_range = self.signals_renderer.index_range
        #self.dipole_plot.index = self.signals_renderer.index
        print(dir(self.dipole_data_model.x_index))
        xs = ArrayDataSource(self.dipole_data_model.x_index,
                             sort_order='ascending')
        xrange = DataRange1D()
        xrange.add(xs)

        self.dipole_plot.index.set_data(self.dipole_data_model.x_index)
        self.dipole_plot.value.set_data(self.dipole_data_model.data)

        self.dipole_plot.index_mapper.range = xrange

        self.dipole_plot.request_redraw()

    # def _time_default(self):
    #     numpoints = 1000.0
    #     low = -5
    #     high = 15
    #     time = np.arange(low, high, (high-low)/numpoints).tolist()
    #     return time
    #
    # def _dipole_signal_default(self):
    #     signal = jn(10, self.time)
    #     return signal
    #
    # def _signals_default(self):
    #     numpoints = 1000
    #     signals = [] #np.zeros((10, numpoints))
    #     for i in range(10):
    #         signals.append(jn(i, self.time))
    #     return signals
    #
    # def _dipole_plot_default(self):
    #     plot = create_line_plot((self.time, self.dipole_signal), color = 'black')
    #     plot.origin_axis_visible = False
    #     plot.origin = "top left"
    #     plot.border_visible = False
    #     plot.bgcolor = "white"
    #     return plot
    #
    # def _plots_container_default(self):
    #     container = VPlotContainer()
    #     # Plot some bessel functions
    #     value_range = None
    #     for i in range(10):
    #         plot = create_line_plot((self.time,self.signals[i,:]), width=2.0)#color=tuple(COLOR_PALETTE[i]), width=2.0)
    #         plot.origin_axis_visible = False
    #         plot.origin = "top left"
    #         plot.border_visible = False
    #         plot.bgcolor = "white"
    #         if value_range is None:
    #             value_range = plot.value_mapper.range
    #         else:
    #             plot.value_range = value_range
    #             value_range.add(plot.value)
    #         # if i%2 == 1:
    #         #     plot.line_style = "dash"
    #         container.add(plot)
    #     return container
    #
    # def _signals_changed(self, old, new):
    #     #self.signals.values = new
    #     print("_signals_changed")
    #     print(dir(self.plots_container))
    #
    # def _dipole_signal_changed(self, old, new):
    #     #self.signals.values = new
    #     print("_signals_changed")
    #     self.dipole_plot.set(y_values = new)
    #     self.dipole_plot.draw()
    #     #print(dir(self.dipole_plot))
    # #     self.dipole_plot.
    #
    # def zoom_in(self, zoom_factor = 1.0):
    #     print('zoom')
    #     #for i,s in enumerate(self.plots_container):
    #         #self.plots_container.

    # @on_trait_change('scene.activated')
    # def update_plot(self):
    #     # This function is called when the view is opened. We don't
    #     # populate the scene when the view is not yet open, as some
    #     # VTK features require a GLContext.
    #
    #     # We can do normal mlab calls on the embedded scene.
    #     self.scene.mlab.test_points3d()

    # Drives multi_line_plot_renderer.normalized_amplitude
    amplitude = Range(0.0, 3.0, value=1.0)

    # Drives multi_line_plot_renderer.offset
    offset = Range(-1.0, 1.0, value=0)

    # Drives multi_line_plot_renderer.scaler
    scale = Range(0.0, 2.0, value=1.0)

    #-----------------------------------------------------------------------
    # Trait change handlers
    #-----------------------------------------------------------------------

    def _amplitude_changed(self, amp):
        self.signals_renderer.normalized_amplitude = amp

    def _offset_changed(self, off):
        self.signals_renderer.offset = off
        # FIXME:  The change does not trigger a redraw.  Force a redraw by
        # faking an amplitude change.
        self.signals_renderer._amplitude_changed()

    def _scale_changed(self, sca):
        self.signals_renderer.scale = sca
        self.signals_renderer._amplitude_changed()

    # the layout of the dialog screated
    view = View(
        VSplit(
            Item('dipole_plot',
                 editor=ComponentEditor(),
                 show_label=False,
                 height=75),
            Item('signals_plot', editor=ComponentEditor(), show_label=False)),
        #HGroup(
        Item('amplitude'),
        Item('offset'),
        Item('scale'),
        #                    springy=True,
        #),
        width=500,
        height=500,
        resizable=True)
class CounterTimeTrace(FreeJob, GetSetItemsMixin):

    trace_length = Range(low=10,
                         high=10000,
                         value=100,
                         desc='Length of Count Trace',
                         label='Trace Length')
    seconds_per_point = Range(low=0.001,
                              high=1,
                              value=0.1,
                              desc='Seconds per point [s]',
                              label='Seconds per point [s]')
    refresh_interval = Range(low=0.01,
                             high=1,
                             value=0.1,
                             desc='Refresh interval [s]',
                             label='Refresh interval [s]')

    # trace data
    C = Array()
    T = Array()

    trace_plot = Instance(Plot)
    trace_data = Instance(ArrayPlotData)

    def __init__(self):
        super(CounterTimeTrace, self).__init__()
        self.on_trait_change(self.update_T, 'T', dispatch='ui')
        self.on_trait_change(self.update_C, 'C', dispatch='ui')

    def _C_default(self):
        return np.zeros((self.trace_length, ))

    def _T_default(self):
        return self.seconds_per_point * np.arange(self.trace_length)

    def update_T(self):
        self.trace_data.set_data('t', self.T)

    def update_C(self):
        self.trace_data.set_data('y', self.C)

    def _trace_length_changed(self):
        self.C = self._C_default()
        self.T = self._T_default()

    def _seconds_per_point_changed(self):
        self.T = self._T_default()

    def _trace_data_default(self):
        return ArrayPlotData(t=self.T, y=self.C)

    def _trace_plot_default(self):
        plot = Plot(self.trace_data, width=500, height=500, resizable='hv')
        plot.plot(('t', 'y'), type='line', color='blue')
        return plot

    def _run(self):
        """Acquire Count Trace"""
        try:
            self.state = 'run'
            counter = ha.CountTask(self.seconds_per_point, self.trace_length)
        except Exception as e:
            logging.getLogger().exception(e)
            raise
        else:
            while True:
                threading.current_thread().stop_request.wait(
                    self.refresh_interval)
                if threading.current_thread().stop_request.isSet():
                    break
                try:
                    self.C = counter.getData() / self.seconds_per_point
                except Exception as e:
                    logging.getLogger().exception(e)
                    raise
        finally:
            self.state = 'idle'

    traits_view = View(VGroup(
        HGroup(
            Item('start_button', show_label=False),
            Item('stop_button', show_label=False),
            Item('priority'),
            Item('state', style='readonly'),
        ),
        Item('trace_plot', editor=ComponentEditor(), show_label=False),
        HGroup(
            Item('trace_length'),
            Item('seconds_per_point'),
            Item('refresh_interval'),
        ),
    ),
                       title='Counter Time Trace',
                       width=800,
                       height=600,
                       buttons=[],
                       resizable=True,
                       handler=GetSetItemsHandler())
Beispiel #25
0
class SolutionView(HasTraits):
    python_console_cmds = Dict()
    # we need to doubleup on Lists to store the psuedo absolutes separately
    # without rewriting everything
    """
  logging_v : toggle logging for velocity files
  directory_name_v : location and name of velocity files
  logging_p : toggle logging for position files
  directory_name_p : location and name of velocity files
  """
    plot_history_max = Int(1000)
    logging_v = Bool(False)
    directory_name_v = File

    logging_p = Bool(False)
    directory_name_p = File

    lats_psuedo_abs = List()
    lngs_psuedo_abs = List()
    alts_psuedo_abs = List()

    table = List()
    dops_table = List()
    pos_table = List()
    vel_table = List()

    rtk_pos_note = Str(
        "It is necessary to enter the \"Surveyed Position\" settings for the base station in order to view the RTK Positions in this tab."
    )

    plot = Instance(Plot)
    plot_data = Instance(ArrayPlotData)
    # Store plots we care about for legend

    running = Bool(True)
    zoomall = Bool(False)
    position_centered = Bool(False)

    clear_button = SVGButton(
        label='',
        tooltip='Clear',
        filename=resource_filename('console/images/iconic/x.svg'),
        width=16,
        height=16)
    zoomall_button = SVGButton(
        label='',
        tooltip='Zoom All',
        toggle=True,
        filename=resource_filename('console/images/iconic/fullscreen.svg'),
        width=16,
        height=16)
    center_button = SVGButton(
        label='',
        tooltip='Center on Solution',
        toggle=True,
        filename=resource_filename('console/images/iconic/target.svg'),
        width=16,
        height=16)
    paused_button = SVGButton(
        label='',
        tooltip='Pause',
        toggle_tooltip='Run',
        toggle=True,
        filename=resource_filename('console/images/iconic/pause.svg'),
        toggle_filename=resource_filename('console/images/iconic/play.svg'),
        width=16,
        height=16)

    traits_view = View(
        HSplit(
            VGroup(
                Item('table',
                     style='readonly',
                     editor=TabularEditor(adapter=SimpleAdapter()),
                     show_label=False,
                     width=0.3),
                Item('rtk_pos_note',
                     show_label=False,
                     resizable=True,
                     editor=MultilineTextEditor(TextEditor(multi_line=True)),
                     style='readonly',
                     width=0.3,
                     height=-40),
            ),
            VGroup(
                HGroup(
                    Item('paused_button', show_label=False),
                    Item('clear_button', show_label=False),
                    Item('zoomall_button', show_label=False),
                    Item('center_button', show_label=False),
                ),
                Item('plot',
                     show_label=False,
                     editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8))),
            )))

    def _zoomall_button_fired(self):
        self.zoomall = not self.zoomall

    def _center_button_fired(self):
        self.position_centered = not self.position_centered

    def _paused_button_fired(self):
        self.running = not self.running

    def _reset_remove_current(self):
        self.plot_data.set_data('cur_lat_spp', [])
        self.plot_data.set_data('cur_lng_spp', [])
        self.plot_data.set_data('cur_alt_spp', [])
        self.plot_data.set_data('cur_lat_dgnss', [])
        self.plot_data.set_data('cur_lng_dgnss', [])
        self.plot_data.set_data('cur_alt_dgnss', [])
        self.plot_data.set_data('cur_lat_float', [])
        self.plot_data.set_data('cur_lng_float', [])
        self.plot_data.set_data('cur_alt_float', [])
        self.plot_data.set_data('cur_lat_fixed', [])
        self.plot_data.set_data('cur_lng_fixed', [])
        self.plot_data.set_data('cur_alt_fixed', [])

    def _clear_history(self):
        self.plot_data.set_data('lat_spp', [])
        self.plot_data.set_data('lng_spp', [])
        self.plot_data.set_data('alt_spp', [])
        self.plot_data.set_data('lat_dgnss', [])
        self.plot_data.set_data('lng_dgnss', [])
        self.plot_data.set_data('alt_dgnss', [])
        self.plot_data.set_data('lat_float', [])
        self.plot_data.set_data('lng_float', [])
        self.plot_data.set_data('alt_float', [])
        self.plot_data.set_data('lat_fixed', [])
        self.plot_data.set_data('lng_fixed', [])
        self.plot_data.set_data('alt_fixed', [])

    def _clear_button_fired(self):
        self.tows = np.empty(self.plot_history_max)
        self.lats = np.empty(self.plot_history_max)
        self.lngs = np.empty(self.plot_history_max)
        self.alts = np.empty(self.plot_history_max)
        self.modes = np.empty(self.plot_history_max)
        self._clear_history()
        self._reset_remove_current()

    def _pos_llh_callback(self, sbp_msg, **metadata):
        # Updating an ArrayPlotData isn't thread safe (see chaco issue #9), so
        # actually perform the update in the UI thread.
        if self.running:
            GUI.invoke_later(self.pos_llh_callback, sbp_msg)

    def age_corrections_callback(self, sbp_msg, **metadata):
        age_msg = MsgAgeCorrections(sbp_msg)
        if age_msg.age != 0xFFFF:
            self.age_corrections = age_msg.age / 10.0
        else:
            self.age_corrections = None

    def update_table(self):
        self.table = self.pos_table + self.vel_table + self.dops_table

    def auto_survey(self):
        if self.last_soln.flags != 0:
            self.latitude_list.append(self.last_soln.lat)
            self.longitude_list.append(self.last_soln.lon)
            self.altitude_list.append(self.last_soln.height)
        if len(self.latitude_list) > 1000:
            self.latitude_list = self.latitude_list[-1000:]
            self.longitude_list = self.longitude_list[-1000:]
            self.altitude_list = self.altitude_list[-1000:]
        if len(self.latitude_list) != 0:
            self.latitude = sum(self.latitude_list) / len(self.latitude_list)
            self.altitude = sum(self.altitude_list) / len(self.latitude_list)
            self.longitude = sum(self.longitude_list) / len(self.latitude_list)

    def pos_llh_callback(self, sbp_msg, **metadata):
        if sbp_msg.msg_type == SBP_MSG_POS_LLH_DEP_A:
            soln = MsgPosLLHDepA(sbp_msg)
        else:
            soln = MsgPosLLH(sbp_msg)
        self.last_soln = soln

        self.last_pos_mode = get_mode(soln)
        pos_table = []
        soln.h_accuracy *= 1e-3
        soln.v_accuracy *= 1e-3

        tow = soln.tow * 1e-3
        if self.nsec is not None:
            tow += self.nsec * 1e-9

        # Return the best estimate of my local and receiver time in convenient
        # format that allows changing precision of the seconds
        ((tloc, secloc), (tgps, secgps)) = log_time_strings(self.week, tow)
        if self.utc_time:
            ((tutc, secutc)) = datetime_2_str(self.utc_time)

        if (self.directory_name_p == ''):
            filepath_p = time.strftime("position_log_%Y%m%d-%H%M%S.csv")
        else:
            filepath_p = os.path.join(
                self.directory_name_p,
                time.strftime("position_log_%Y%m%d-%H%M%S.csv"))

        if not self.logging_p:
            self.log_file = None

        if self.logging_p:
            if self.log_file is None:
                self.log_file = sopen(filepath_p, 'w')
                self.log_file.write(
                    "pc_time,gps_time,tow(sec),latitude(degrees),longitude(degrees),altitude(meters),"
                    "h_accuracy(meters),v_accuracy(meters),n_sats,flags\n")
            log_str_gps = ""
            if tgps != "" and secgps != 0:
                log_str_gps = "{0}:{1:06.6f}".format(tgps, float(secgps))
            self.log_file.write(
                '%s,%s,%.3f,%.10f,%.10f,%.4f,%.4f,%.4f,%d,%d\n' %
                ("{0}:{1:06.6f}".format(tloc, float(secloc)), log_str_gps, tow,
                 soln.lat, soln.lon, soln.height, soln.h_accuracy,
                 soln.v_accuracy, soln.n_sats, soln.flags))
            self.log_file.flush()

        if self.last_pos_mode == 0:
            pos_table.append(('GPS Week', EMPTY_STR))
            pos_table.append(('GPS TOW', EMPTY_STR))
            pos_table.append(('GPS Time', EMPTY_STR))
            pos_table.append(('Num. Signals', EMPTY_STR))
            pos_table.append(('Lat', EMPTY_STR))
            pos_table.append(('Lng', EMPTY_STR))
            pos_table.append(('Height', EMPTY_STR))
            pos_table.append(('Horiz Acc', EMPTY_STR))
            pos_table.append(('Vert Acc', EMPTY_STR))
        else:
            self.last_stime_update = time.time()

            if self.week is not None:
                pos_table.append(('GPS Week', str(self.week)))
            pos_table.append(('GPS TOW', "{:.3f}".format(tow)))

            if self.week is not None:
                pos_table.append(
                    ('GPS Time', "{0}:{1:06.3f}".format(tgps, float(secgps))))
            if self.utc_time is not None:
                pos_table.append(
                    ('UTC Time', "{0}:{1:06.3f}".format(tutc, float(secutc))))
                pos_table.append(('UTC Src', self.utc_source))
            if self.utc_time is None:
                pos_table.append(('UTC Time', EMPTY_STR))
                pos_table.append(('UTC Src', EMPTY_STR))

            pos_table.append(('Sats Used', soln.n_sats))
            pos_table.append(('Lat', soln.lat))
            pos_table.append(('Lng', soln.lon))
            pos_table.append(('Height', "{0:.3f}".format(soln.height)))
            pos_table.append(('Horiz Acc', soln.h_accuracy))
            pos_table.append(('Vert Acc', soln.v_accuracy))

        pos_table.append(('Pos Flags', '0x%03x' % soln.flags))
        pos_table.append(('Pos Fix Mode', mode_dict[self.last_pos_mode]))
        if self.age_corrections is not None:
            pos_table.append(('Corr. Age [s]', self.age_corrections))

        self.auto_survey()

        # set-up table variables
        self.pos_table = pos_table
        self.update_table()
        # setup_plot variables
        self.lats[1:] = self.lats[:-1]
        self.lngs[1:] = self.lngs[:-1]
        self.alts[1:] = self.alts[:-1]
        self.tows[1:] = self.tows[:-1]
        self.modes[1:] = self.modes[:-1]

        self.lats[0] = soln.lat
        self.lngs[0] = soln.lon
        self.alts[0] = soln.height
        self.tows[0] = soln.tow
        self.modes[0] = self.last_pos_mode

        self.lats = self.lats[-self.plot_history_max:]
        self.lngs = self.lngs[-self.plot_history_max:]
        self.alts = self.alts[-self.plot_history_max:]
        self.tows = self.tows[-self.plot_history_max:]
        self.modes = self.modes[-self.plot_history_max:]

    def solution_draw(self):
        if self.running:
            GUI.invoke_later(self._solution_draw)

    def _solution_draw(self):
        spp_indexer, dgnss_indexer, float_indexer, fixed_indexer = None, None, None, None
        self._clear_history()
        soln = self.last_soln
        if np.any(self.modes):
            spp_indexer = (self.modes == SPP_MODE)
            dgnss_indexer = (self.modes == DGNSS_MODE)
            float_indexer = (self.modes == FLOAT_MODE)
            fixed_indexer = (self.modes == FIXED_MODE)

            # make sure that there is at least one true in indexer before setting
            if any(spp_indexer):
                self.plot_data.set_data('lat_spp', self.lats[spp_indexer])
                self.plot_data.set_data('lng_spp', self.lngs[spp_indexer])
                self.plot_data.set_data('alt_spp', self.alts[spp_indexer])
            if any(dgnss_indexer):
                self.plot_data.set_data('lat_dgnss', self.lats[dgnss_indexer])
                self.plot_data.set_data('lng_dgnss', self.lngs[dgnss_indexer])
                self.plot_data.set_data('alt_dgnss', self.alts[dgnss_indexer])
            if any(float_indexer):
                self.plot_data.set_data('lat_float', self.lats[float_indexer])
                self.plot_data.set_data('lng_float', self.lngs[float_indexer])
                self.plot_data.set_data('alt_float', self.alts[float_indexer])
            if any(fixed_indexer):
                self.plot_data.set_data('lat_fixed', self.lats[fixed_indexer])
                self.plot_data.set_data('lng_fixed', self.lngs[fixed_indexer])
                self.plot_data.set_data('alt_fixed', self.alts[fixed_indexer])

            # update our "current solution" icon
            if self.last_pos_mode == SPP_MODE:
                self._reset_remove_current()
                self.plot_data.set_data('cur_lat_spp', [soln.lat])
                self.plot_data.set_data('cur_lng_spp', [soln.lon])
            elif self.last_pos_mode == DGNSS_MODE:
                self._reset_remove_current()
                self.plot_data.set_data('cur_lat_dgnss', [soln.lat])
                self.plot_data.set_data('cur_lng_dgnss', [soln.lon])
            elif self.last_pos_mode == FLOAT_MODE:
                self._reset_remove_current()
                self.plot_data.set_data('cur_lat_float', [soln.lat])
                self.plot_data.set_data('cur_lng_float', [soln.lon])
            elif self.last_pos_mode == FIXED_MODE:
                self._reset_remove_current()
                self.plot_data.set_data('cur_lat_fixed', [soln.lat])
                self.plot_data.set_data('cur_lng_fixed', [soln.lon])
            else:
                pass

        # TODO: figure out how to center the graph now that we have two separate messages
        # when we selectively send only SPP, the centering function won't work anymore

        if not self.zoomall and self.position_centered:
            d = (self.plot.index_range.high - self.plot.index_range.low) / 2.
            self.plot.index_range.set_bounds(soln.lon - d, soln.lon + d)
            d = (self.plot.value_range.high - self.plot.value_range.low) / 2.
            self.plot.value_range.set_bounds(soln.lat - d, soln.lat + d)
        if self.zoomall:
            plot_square_axes(
                self.plot, ('lng_spp', 'lng_dgnss', 'lng_float', 'lng_fixed'),
                ('lat_spp', 'lat_dgnss', 'lat_float', 'lat_fixed'))

    def dops_callback(self, sbp_msg, **metadata):
        flags = 0
        if sbp_msg.msg_type == SBP_MSG_DOPS_DEP_A:
            dops = MsgDopsDepA(sbp_msg)
            flags = 1
        else:
            dops = MsgDops(sbp_msg)
            flags = dops.flags
        if flags != 0:
            self.dops_table = [('PDOP', '%.1f' % (dops.pdop * 0.01)),
                               ('GDOP', '%.1f' % (dops.gdop * 0.01)),
                               ('TDOP', '%.1f' % (dops.tdop * 0.01)),
                               ('HDOP', '%.1f' % (dops.hdop * 0.01)),
                               ('VDOP', '%.1f' % (dops.vdop * 0.01))]
        else:
            self.dops_table = [('PDOP', EMPTY_STR), ('GDOP', EMPTY_STR),
                               ('TDOP', EMPTY_STR), ('HDOP', EMPTY_STR),
                               ('VDOP', EMPTY_STR)]

        self.dops_table.append(('DOPS Flags', '0x%03x' % flags))

    def vel_ned_callback(self, sbp_msg, **metadata):
        flags = 0
        if sbp_msg.msg_type == SBP_MSG_VEL_NED_DEP_A:
            vel_ned = MsgVelNEDDepA(sbp_msg)
            flags = 1
        else:
            vel_ned = MsgVelNED(sbp_msg)
            flags = vel_ned.flags
        tow = vel_ned.tow * 1e-3
        if self.nsec is not None:
            tow += self.nsec * 1e-9

        ((tloc, secloc), (tgps, secgps)) = log_time_strings(self.week, tow)

        if self.directory_name_v == '':
            filepath_v = time.strftime("velocity_log_%Y%m%d-%H%M%S.csv")
        else:
            filepath_v = os.path.join(
                self.directory_name_v,
                time.strftime("velocity_log_%Y%m%d-%H%M%S.csv"))

        if not self.logging_v:
            self.vel_log_file = None

        if self.logging_v:
            if self.vel_log_file is None:
                self.vel_log_file = sopen(filepath_v, 'w')
                self.vel_log_file.write(
                    'pc_time,gps_time,tow(sec),north(m/s),east(m/s),down(m/s),speed(m/s),flags,num_signals\n'
                )
            log_str_gps = ''
            if tgps != "" and secgps != 0:
                log_str_gps = "{0}:{1:06.6f}".format(tgps, float(secgps))
            self.vel_log_file.write(
                '%s,%s,%.3f,%.6f,%.6f,%.6f,%.6f,%d,%d\n' %
                ("{0}:{1:06.6f}".format(tloc, float(secloc)), log_str_gps, tow,
                 vel_ned.n * 1e-3, vel_ned.e * 1e-3, vel_ned.d * 1e-3,
                 math.sqrt(vel_ned.n * vel_ned.n + vel_ned.e * vel_ned.e) *
                 1e-3, flags, vel_ned.n_sats))
            self.vel_log_file.flush()
        if flags != 0:
            self.vel_table = [
                ('Vel. N', '% 8.4f' % (vel_ned.n * 1e-3)),
                ('Vel. E', '% 8.4f' % (vel_ned.e * 1e-3)),
                ('Vel. D', '% 8.4f' % (vel_ned.d * 1e-3)),
            ]
        else:
            self.vel_table = [
                ('Vel. N', EMPTY_STR),
                ('Vel. E', EMPTY_STR),
                ('Vel. D', EMPTY_STR),
            ]
        self.vel_table.append(('Vel Flags', '0x%03x' % flags))
        self.update_table()

    def gps_time_callback(self, sbp_msg, **metadata):
        if sbp_msg.msg_type == SBP_MSG_GPS_TIME_DEP_A:
            time_msg = MsgGPSTimeDepA(sbp_msg)
            flags = 1
        elif sbp_msg.msg_type == SBP_MSG_GPS_TIME:
            time_msg = MsgGPSTime(sbp_msg)
            flags = time_msg.flags
            if flags != 0:
                self.week = time_msg.wn
                self.nsec = time_msg.ns_residual

    def utc_time_callback(self, sbp_msg, **metadata):
        tmsg = MsgUtcTime(sbp_msg)
        seconds = math.floor(tmsg.seconds)
        microseconds = int(tmsg.ns / 1000.00)
        if tmsg.flags & 0x1 == 1:
            dt = datetime.datetime(tmsg.year, tmsg.month, tmsg.day, tmsg.hours,
                                   tmsg.minutes, tmsg.seconds, microseconds)
            self.utc_time = dt
            self.utc_time_flags = tmsg.flags
            if (tmsg.flags >> 3) & 0x3 == 0:
                self.utc_source = "Factory Default"
            elif (tmsg.flags >> 3) & 0x3 == 1:
                self.utc_source = "Non Volatile Memory"
            elif (tmsg.flags >> 3) & 0x3 == 2:
                self.utc_source = "Decoded this Session"
            else:
                self.utc_source = "Unknown"
        else:
            self.utc_time = None
            self.utc_source = None

    def __init__(self, link, dirname=''):
        super(SolutionView, self).__init__()

        self.lats = np.zeros(self.plot_history_max)
        self.lngs = np.zeros(self.plot_history_max)
        self.alts = np.zeros(self.plot_history_max)
        self.tows = np.zeros(self.plot_history_max)
        self.modes = np.zeros(self.plot_history_max)
        self.log_file = None
        self.directory_name_v = dirname
        self.directory_name_p = dirname
        self.vel_log_file = None
        self.last_stime_update = 0
        self.last_soln = None

        self.counter = 0
        self.latitude_list = []
        self.longitude_list = []
        self.altitude_list = []
        self.altitude = 0
        self.longitude = 0
        self.latitude = 0
        self.last_pos_mode = 0

        self.plot_data = ArrayPlotData(lat_spp=[],
                                       lng_spp=[],
                                       alt_spp=[],
                                       cur_lat_spp=[],
                                       cur_lng_spp=[],
                                       lat_dgnss=[],
                                       lng_dgnss=[],
                                       alt_dgnss=[],
                                       cur_lat_dgnss=[],
                                       cur_lng_dgnss=[],
                                       lat_float=[],
                                       lng_float=[],
                                       alt_float=[],
                                       cur_lat_float=[],
                                       cur_lng_float=[],
                                       lat_fixed=[],
                                       lng_fixed=[],
                                       alt_fixed=[],
                                       cur_lat_fixed=[],
                                       cur_lng_fixed=[])
        self.plot = Plot(self.plot_data)

        # 1000 point buffer
        self.plot.plot(('lng_spp', 'lat_spp'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[SPP_MODE])
        self.plot.plot(('lng_spp', 'lat_spp'),
                       type='scatter',
                       name='',
                       color=color_dict[SPP_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        self.plot.plot(('lng_dgnss', 'lat_dgnss'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[DGNSS_MODE])
        self.plot.plot(('lng_dgnss', 'lat_dgnss'),
                       type='scatter',
                       name='',
                       color=color_dict[DGNSS_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        self.plot.plot(('lng_float', 'lat_float'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[FLOAT_MODE])
        self.plot.plot(('lng_float', 'lat_float'),
                       type='scatter',
                       name='',
                       color=color_dict[FLOAT_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        self.plot.plot(('lng_fixed', 'lat_fixed'),
                       type='line',
                       line_width=0.1,
                       name='',
                       color=color_dict[FIXED_MODE])
        self.plot.plot(('lng_fixed', 'lat_fixed'),
                       type='scatter',
                       name='',
                       color=color_dict[FIXED_MODE],
                       marker='dot',
                       line_width=0.0,
                       marker_size=1.0)
        # current values
        spp = self.plot.plot(('cur_lng_spp', 'cur_lat_spp'),
                             type='scatter',
                             name=mode_dict[SPP_MODE],
                             color=color_dict[SPP_MODE],
                             marker='plus',
                             line_width=1.5,
                             marker_size=5.0)
        dgnss = self.plot.plot(('cur_lng_dgnss', 'cur_lat_dgnss'),
                               type='scatter',
                               name=mode_dict[DGNSS_MODE],
                               color=color_dict[DGNSS_MODE],
                               marker='plus',
                               line_width=1.5,
                               marker_size=5.0)
        rtkfloat = self.plot.plot(('cur_lng_float', 'cur_lat_float'),
                                  type='scatter',
                                  name=mode_dict[FLOAT_MODE],
                                  color=color_dict[FLOAT_MODE],
                                  marker='plus',
                                  line_width=1.5,
                                  marker_size=5.0)
        rtkfix = self.plot.plot(('cur_lng_fixed', 'cur_lat_fixed'),
                                type='scatter',
                                name=mode_dict[FIXED_MODE],
                                color=color_dict[FIXED_MODE],
                                marker='plus',
                                line_width=1.5,
                                marker_size=5.0)
        plot_labels = ['SPP', 'DGPS', "RTK float", "RTK fixed"]
        plots_legend = dict(zip(plot_labels, [spp, dgnss, rtkfloat, rtkfix]))
        self.plot.legend.plots = plots_legend
        self.plot.legend.labels = plot_labels  # sets order
        self.plot.legend.visible = True

        self.plot.index_axis.tick_label_position = 'inside'
        self.plot.index_axis.tick_label_color = 'gray'
        self.plot.index_axis.tick_color = 'gray'
        self.plot.index_axis.title = 'Longitude (degrees)'
        self.plot.index_axis.title_spacing = 5
        self.plot.value_axis.tick_label_position = 'inside'
        self.plot.value_axis.tick_label_color = 'gray'
        self.plot.value_axis.tick_color = 'gray'
        self.plot.value_axis.title = 'Latitude (degrees)'
        self.plot.value_axis.title_spacing = 5
        self.plot.padding = (25, 25, 25, 25)

        self.plot.tools.append(PanTool(self.plot))
        zt = ZoomTool(self.plot,
                      zoom_factor=1.1,
                      tool_mode="box",
                      always_on=False)
        self.plot.overlays.append(zt)

        self.link = link
        self.link.add_callback(self.pos_llh_callback,
                               [SBP_MSG_POS_LLH_DEP_A, SBP_MSG_POS_LLH])
        self.link.add_callback(self.vel_ned_callback,
                               [SBP_MSG_VEL_NED_DEP_A, SBP_MSG_VEL_NED])
        self.link.add_callback(self.dops_callback,
                               [SBP_MSG_DOPS_DEP_A, SBP_MSG_DOPS])
        self.link.add_callback(self.gps_time_callback,
                               [SBP_MSG_GPS_TIME_DEP_A, SBP_MSG_GPS_TIME])
        self.link.add_callback(self.utc_time_callback, [SBP_MSG_UTC_TIME])
        self.link.add_callback(self.age_corrections_callback,
                               SBP_MSG_AGE_CORRECTIONS)
        call_repeatedly(0.2, self.solution_draw)

        self.week = None
        self.utc_time = None
        self.age_corrections = None
        self.nsec = 0

        self.python_console_cmds = {
            'solution': self,
        }
Beispiel #26
0
class SpectrumAnalyzerView(HasTraits):
    python_console_cmds = Dict()
    plot = Instance(Plot)
    plot_data = Instance(ArrayPlotData)
    which_plot = Str("Channel 1")
    hint = Str("Enable with setting in \"System Monitor\" group.")
    traits_view = View(
        Item('plot',
             editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8)),
             show_label=False),
        HGroup(
            Spring(width=20, springy=False),
            Item('', label='Channel Selection:', emphasized=True),
            Item(
                name='which_plot',
                show_label=False,
                tooltip=
                'Select the RF Channel for which to display Spectrum Analyzer',
                editor=EnumEditor(values=[
                    "Channel 1", "Channel 2", "Channel 3", "Channel 4"
                ])), Spring(width=20, springy=True),
            Item('hint',
                 show_label=False,
                 style='readonly',
                 style_sheet='*{font-style:italic}'),
            Spring(width=20, springy=True)))

    def parse_payload(self, raw_payload):
        """
        Params
        ======
        payload: is an array of ints representing bytes from the SBP_MSG_USER_DATA message 'contents'

        Returns
        =======
        JSON dict of a payload based on this format, except all N of the diff_amplitude
        are together in a list under 'diff_amplitudes' and rx_time is split into TOW and week

        Frequency is in Hz, Amplitude is in dB

        FIELD               TYPE    OFFSET  SHORT EXPLANATION

        user_msg_tag        u16     0       bespoke preamble for spectrum message

        rx_time             struct  2       struct gps_time_t defined as double TOW + s16 WEEK

        starting_frequency  float  12       starting frequency for this packet

        frequency_step      float  16       frequency step for points in this packet

        min_amplitude       float  20       minimum level of amplitude

        amplitude_step      float  24       amplitude unit

        diff_amplitude      u8     28       N values in the above units
        """
        # Turn the array of ints representing uint8 bytes back to binary, so you can use struct
        # formatting to unpack it. Otherwise you would have to manually parse each byte.
        pack_fmt_str = 'B' * len(raw_payload)
        payload = struct.pack(pack_fmt_str, *raw_payload)
        payload_header_fmt_str = '<Hdhffff'
        payload_header_bytes = struct.calcsize(payload_header_fmt_str)
        diff_amplitude_n = (len(raw_payload) - payload_header_bytes)
        diff_amplitude_fmt_str = 'B' * diff_amplitude_n
        fmt_str = payload_header_fmt_str + diff_amplitude_fmt_str
        parsed_payload = struct.unpack(fmt_str, payload)
        fft_msg_header = [
            'user_msg_tag', 'TOW', 'week', 'starting_frequency',
            'frequency_step', 'min_amplitude', 'amplitude_step'
        ]
        payload_json = dict(
            zip(fft_msg_header, parsed_payload[:len(fft_msg_header)]))
        fft_msg_payload = parsed_payload[len(fft_msg_header):]
        payload_json['diff_amplitudes'] = fft_msg_payload
        return payload_json

    def _which_plot_changed(self):
        channel = int(self.which_plot[-1:])
        self.fftmonitor.enable_channel(channel)
        self.fftmonitor.disable_channel(
            [ch for ch in CHANNELS if ch != channel])

    def spectrum_analyzer_state_callback(self, sbp_msg, **metadata):
        '''
        Params
        ======
        sbp_msg: sbp.msg.SBP object

        Updates the view's data for use in self.update_plot
        '''
        self.fftmonitor.capture_fft(sbp_msg, **metadata)
        channel = int(self.which_plot[-1:])
        if self.fftmonitor.num_ffts(channel) > 0:
            most_recent_fft = self.fftmonitor.get_ffts(channel).pop()
            self.fftmonitor.clear_ffts()
            self.most_recent_complete_data['frequencies'] = most_recent_fft[
                'frequencies']
            self.most_recent_complete_data['amplitudes'] = most_recent_fft[
                'amplitudes']
            GUI.invoke_later(self.update_plot)

    def update_plot(self):
        most_recent_fft = self.most_recent_complete_data
        if len(most_recent_fft['frequencies']) != 0:
            self.plot_data.set_data('frequency',
                                    most_recent_fft['frequencies'])
            self.plot_data.set_data('amplitude', most_recent_fft['amplitudes'])
            self.plot.value_mapper.range.low = min(
                most_recent_fft['amplitudes'])
            self.plot.value_mapper.range.high = max(
                most_recent_fft['amplitudes'])

    def __init__(self, link):
        super(SpectrumAnalyzerView, self).__init__()
        self.link = link
        self.link.add_callback(self.spectrum_analyzer_state_callback,
                               [SBP_MSG_SPECAN, SBP_MSG_SPECAN_DEP])
        self.python_console_cmds = {'spectrum': self}

        self.fftmonitor = FFTMonitor()
        self.fftmonitor.enable_channel(int(self.which_plot[-1:]))

        self.most_recent_complete_data = {
            'frequencies': np.array([]),
            'amplitudes': np.array([])
        }

        self.plot_data = ArrayPlotData()
        self.plot = Plot(self.plot_data, emphasized=True)

        self.plot.title = 'Spectrum Analyzer'
        self.plot.title_color = [0, 0, 0.43]

        self.plot.value_axis.orientation = 'right'
        self.plot.value_axis.title_spacing = 30
        self.plot.value_axis.title = 'Amplitude (dB)'

        self.plot.index_axis.title = 'Frequency (MHz)'
        self.plot_data.set_data('frequency', [0])
        self.plot_data.set_data('amplitude', [0])
        self.plot.plot(('frequency', 'amplitude'),
                       type='line',
                       name='spectrum')
Beispiel #27
0
class AutoFocus( ManagedJob, GetSetItemsMixin ):

    # overwrite default priority from ManagedJob (default 0)
    priority = 10

    confocal = Instance( Confocal )
    odmr = Instance( ODMR )
    #counter_trace = Instance ( CounterTrace )

    size_xy                 = Range(low=0.5, high=10., value=0.8,   desc='Size of XY Scan',                 label='Size XY [micron]',           mode='slider',  auto_set=False, enter_set=True)
    size_z                  = Range(low=0.5, high=10., value=1.5,    desc='Size of Z Scan',                  label='Size Z [micron]',            mode='slider',  auto_set=False, enter_set=True)
    step_xy                 = Range(low=0.01, high=10., value=0.04,  desc='Step of XY Scan',                 label='Step XY [micron]',           mode='slider',  auto_set=False, enter_set=True)
    step_z                  = Range(low=0.01, high=10., value=0.15,  desc='Step of Z Scan',                  label='Step Z [micron]',            mode='slider',  auto_set=False, enter_set=True)
    seconds_per_point_xy    = Range(low=1e-3, high=10, value=0.03,  desc='Seconds per point for XY Scan',   label='seconds per point XY [s]',   mode='text',    auto_set=False, enter_set=True)
    seconds_per_point_z     = Range(low=1e-3, high=10, value=0.05,   desc='Seconds per point for Z Scan',    label='seconds per point Z  [s]',    mode='text',    auto_set=False, enter_set=True)

    fit_method_xy = Enum('Maximum', 'Gaussian', desc='Fit Method for XY Scan',    label='XY Fit Method')
    fit_method_z  = Enum('Maximum', 'Gaussian', desc='Fit Method for Z Scan',     label='Z Fit Method')

    X = Array(value=np.array((0.,1.)) )
    Y = Array(value=np.array((0.,1.)) )
    Z = Array(value=np.array((-1.,1.)) )

    data_xy = Array( )
    data_z = Array( value=np.array((0,0)) )

    targets         = Instance( {}.__class__, factory={}.__class__ ) # Dict traits are no good for pickling, therefore we have to do it with an ordinary dictionary and take care about the notification manually 
    target_list     = Instance( list, factory=list, args=([None],) ) # list of targets that are selectable in current_target editor
    current_target  = Enum(values='target_list')
        
    drift               = Array( value=np.array(((0,0,0,),)) )
    drift_time          = Array( value=np.array((0,)) )
    current_drift       = Array( value=np.array((0,0,0)) )

    focus_interval    = Range(low=1, high=6000, value=10, desc='Time interval between automatic focus events', label='Interval [m]', auto_set=False, enter_set=True)
    periodic_focus    = Bool(False, label='Periodic focusing')
    periodic_freq_feedback  = Bool(False, label='Periodic freq feedback')
    threshold = Range(low=1, high=6000, value=1000, desc='ignore oil junks', label='threshold kcs/s', auto_set=False, enter_set=True)

    target_name = Str(label='name', desc='name to use when adding or removing targets')
    add_target_button       = Button(label='Add Target', desc='add target with given name')
    remove_current_target_button    = Button(label='Remove Current', desc='remove current target')
    next_target_button      = Button(label='Next Target', desc='switch to next available target')
    undo_button       = Button(label='undo', desc='undo the movement of the stage')
    
    previous_state = Instance( () )
    
    plot_data_image = Instance( ArrayPlotData )
    plot_data_line  = Instance( ArrayPlotData )
    plot_data_drift = Instance( ArrayPlotData )
    figure_image    = Instance( HPlotContainer, editor=ComponentEditor() )
    figure_line     = Instance( Plot, editor=ComponentEditor() )
    figure_drift    = Instance( Plot, editor=ComponentEditor() )
    image_plot      = Instance( CMapImagePlot )

    def __init__(self, confocal, odmr):
        super(AutoFocus, self).__init__()
        self.confocal = confocal
        self.odmr = odmr
        #self.counter_trace = counter_trace
        self.on_trait_change(self.update_plot_image, 'data_xy', dispatch='ui')
        self.on_trait_change(self.update_plot_line_value, 'data_z', dispatch='ui')
        self.on_trait_change(self.update_plot_line_index, 'Z', dispatch='ui')
        self.on_trait_change(self.update_plot_drift_value, 'drift', dispatch='ui')
        self.on_trait_change(self.update_plot_drift_index, 'drift_time', dispatch='ui')
        

    @on_trait_change('next_target_button')
    def next_target(self):
        """Convenience method to switch to the next available target."""
        keys = self.targets.keys()
        key = self.current_target
        if len(keys) == 0:
            logging.getLogger().info('No target available. Add a target and try again!')
        elif not key in keys:
            self.current_target = keys[0]
        else:
            self.current_target = keys[(keys.index(self.current_target)+1)%len(keys)]

    def _targets_changed(self, name, old, new):
        l = new.keys() + [None]      # rebuild target_list for Enum trait
        l.sort()
        self.target_list = l
        self._draw_targets()    # redraw target labels

    def _current_target_changed(self):
        self._draw_targets()    # redraw target labels

    def _draw_targets(self):
        c = self.confocal
        c.remove_all_labels()
        c.show_labels=True
        for key, coordinates in self.targets.iteritems():
            if key == self.current_target:
                c.set_label(key, coordinates, marker_color='red')
            else:
                c.set_label(key, coordinates)

    def _periodic_focus_changed(self, new):
        if not new and hasattr(self, 'cron_event'):
            CronDaemon().remove(self.cron_event)
        if new:
            self.cron_event = CronEvent(self.submit, min=range(0,60,self.focus_interval))
            CronDaemon().register(self.cron_event)

    def fit_xy(self):
        if self.fit_method_xy == 'Maximum':
            index = self.data_xy.argmax()
            xp = self.X[index%len(self.X)]
            yp = self.Y[index/len(self.X)]
            self.XYFitParameters = [xp, yp]
            self.xfit = xp
            self.yfit = yp
            return xp, yp
        else:
            print 'Not Implemented! Fix Me!'

    def fit_z(self):
        if self.fit_method_z == 'Maximum':
            zp = self.Z[self.data_z.argmax()]
            self.zfit = zp
            return zp
        else:
            print 'Not Implemented! Fix Me!'

    def add_target(self, key, coordinates=None):
        if coordinates is None:
            c = self.confocal
            coordinates = np.array((c.x,c.y,c.z))
        if self.targets == {}:
            self.forget_drift()
        if self.targets.has_key(key):
            if warning('A target with this name already exists.\nOverwriting will move all targets.\nDo you want to continue?'):
                self.current_drift = coordinates - self.targets[key]
                self.forget_drift()
            else:
                return
        else:
            coordinates = coordinates - self.current_drift
            self.targets[key] = coordinates
        self.trait_property_changed('targets', self.targets)    # trigger event such that Enum is updated and Labels are redrawn
        self.confocal.show_labels=True

    def remove_target(self, key):
        if not key in self.targets:
            logging.getLogger().info('Target cannot be removed. Target does not exist.')
            return
        self.targets.pop(key)        # remove target from dictionary
        self.trait_property_changed('targets', self.targets)    # trigger event such that Enum is updated and Labels are redrawn
        
    def remove_all_targets(self):
        self.targets = {}

    def forget_drift(self):
        targets = self.targets
        # reset coordinates of all targets according to current drift
        for key in targets:
            targets[key] += self.current_drift
        # trigger event such that target labels are redrawn
        self.trait_property_changed('targets', self.targets)
        # set current_drift to 0 and clear plot
        self.current_drift = np.array((0., 0., 0.))
        self.drift_time = np.array((time.time(),))
        self.drift = np.array(((0,0,0),))
        
    def _add_target_button_fired(self):
        self.add_target( self.target_name )
        
    def _remove_current_target_button_fired(self):
        self.remove_target( self.current_target )

    def _run(self):
        
        logging.getLogger().debug("trying run.")
        
        try:
            self.state='run'
            #ha.PulseGenerator().Light()
            
           
            if self.current_target is None:
                self.focus()
                if np.amax(self.data_xy)<10:
                    self._undo_button_fired()
                    pg.Light()
                    self.focus()
                # if self.periodic_freq_feedback: 
                    # self.odmr.submit()
                   
            else: # focus target
                coordinates = self.targets[self.current_target]
                confocal = self.confocal
                confocal.x, confocal.y, confocal.z = coordinates + self.current_drift
                current_coordinates = self.focus()
                self.current_drift = current_coordinates - coordinates  
                self.drift = np.append(self.drift, (self.current_drift,), axis=0)
                self.drift_time = np.append(self.drift_time, time.time())
                logging.getLogger().debug('Drift: %.2f, %.2f, %.2f'%tuple(self.current_drift))
                # if self.periodic_freq_feedback: 
                    # self.odmr.submit()
                    
        finally:
            self.state = 'idle'

    def focus(self):
            """
            Focuses around current position in x, y, and z-direction.
            """
            xp = self.confocal.x
            yp = self.confocal.y
            zp = self.confocal.z
            self.previous_state = ((xp,yp,zp), self.current_target)
            ##+scanner.getXRange()[1]
            safety = 0 #distance to keep from the ends of scan range
            xmin = np.clip(xp-0.5*self.size_xy, scanner.getXRange()[0]+safety, scanner.getXRange()[1]-safety)
            xmax = np.clip(xp+0.5*self.size_xy, scanner.getXRange()[0]+safety, scanner.getXRange()[1]-safety)
            ymin = np.clip(yp-0.5*self.size_xy, scanner.getYRange()[0]+safety, scanner.getYRange()[1]-safety)
            ymax = np.clip(yp+0.5*self.size_xy, scanner.getYRange()[0]+safety, scanner.getYRange()[1]-safety)
            
            X = np.arange(xmin, xmax, self.step_xy)
            Y = np.arange(ymin, ymax, self.step_xy)

            self.X = X
            self.Y = Y

            XP = X[::-1]

            self.data_xy=np.zeros((len(Y),len(X)))
            #self.image_plot.index.set_data(X, Y)  
                        
            for i,y in enumerate(Y):
                if threading.current_thread().stop_request.isSet():
                    self.confocal.x = xp
                    self.confocal.y = yp
                    self.confocal.z = zp
                    return xp, yp, zp                    
                if i%2 != 0:
                    XL = XP
                else:
                    XL = X
                YL = y * np.ones(X.shape)
                ZL = zp * np.ones(X.shape)
                Line = np.vstack( (XL, YL, ZL) )
                
                c = scanner.scanLine(Line, self.seconds_per_point_xy)/1e3
                if i%2 == 0:
                    self.data_xy[i,:] = c[:]
                else:
                    self.data_xy[i,:] = c[-1::-1]
                
                self.trait_property_changed('data_xy', self.data_xy)
                
            for i in range(self.data_xy.shape[0]):
                for j in range(self.data_xy.shape[1]):
                    if self.data_xy[i][j]>self.threshold:
                        self.data_xy[i][j]=0
            
            xp, yp = self.fit_xy()
                        
            self.confocal.x = xp
            self.confocal.y = yp

            Z = np.hstack( ( np.arange(zp, zp-0.5*self.size_z, -self.step_z),
                                np.arange(zp-0.5*self.size_z, zp+0.5*self.size_z, self.step_z),
                                np.arange(zp+0.5*self.size_z, zp, -self.step_z) ) )
            Z = np.clip(Z, scanner.getZRange()[0]+safety, scanner.getZRange()[1]-safety)

            X = xp * np.ones(Z.shape)
            Y = yp * np.ones(Z.shape)

            if not threading.current_thread().stop_request.isSet():
                Line = np.vstack( (X, Y, Z) )
                data_z = scanner.scanLine(Line, self.seconds_per_point_z)/1e3

                self.Z = Z
                self.data_z = data_z
                
            for i in range(self.data_z.shape[0]):
                if self.data_z[i]>self.threshold:
                        self.data_z[i]=0

                zp = self.fit_z()

            self.confocal.z = zp

            logging.getLogger().info('Focus: %.2f, %.2f, %.2f' %(xp, yp, zp))
            return xp, yp, zp

    def undo(self):
        if self.previous_state is not None:
            coordinates, target = self.previous_state
            self.confocal.x, self.confocal.y, self.confocal.z = coordinates
            if target is not None:
                self.drift_time = np.delete(self.drift_time, -1)
                self.current_drift = self.drift[-2]
                self.drift = np.delete(self.drift, -1, axis=0)
            self.previous_state = None
        else:
            logging.getLogger().info('Can undo only once.')

    def _undo_button_fired(self):
        self.remove()
        self.undo()
    
    def _plot_data_image_default(self):
        return ArrayPlotData(image=np.zeros((2,2)))
    def _plot_data_line_default(self):
        return ArrayPlotData(x=self.Z, y=self.data_z)
    def _plot_data_drift_default(self):
        return ArrayPlotData(t=self.drift_time, x=self.drift[:,0], y=self.drift[:,1], z=self.drift[:,2])

    def _figure_image_default(self):
        plot = Plot(self.plot_data_image, width=180, height=180, padding=3, padding_left=48, padding_bottom=32)
        plot.img_plot('image', colormap=jet, name='image')
        plot.aspect_ratio=1
        #plot.value_mapper.domain_limits = (scanner.getYRange()[0],scanner.getYRange()[1])
        #plot.index_mapper.domain_limits = (scanner.getXRange()[0],scanner.getXRange()[1])
        plot.value_mapper.domain_limits = (0,self.size_xy)
        plot.index_mapper.domain_limits = (0,self.size_xy)

        container = HPlotContainer()
        image = plot.plots['image'][0]
        colormap = image.color_mapper
        colorbar = ColorBar(index_mapper=LinearMapper(range=colormap.range),
                            color_mapper=colormap,
                            plot=plot,
                            orientation='v',
                            resizable='v',
                            width=20,
                            height=200,
                            padding=8,
                            padding_left=20)
        container = HPlotContainer()
        container.add(plot)
        container.add(colorbar)
        return container
    def _figure_line_default(self):
        plot = Plot(self.plot_data_line, width=70, height=40, padding=8, padding_left=64, padding_bottom=32)
        plot.plot(('x','y'), color='blue')
        plot.index_axis.title = 'z [um]'
        plot.value_axis.title = 'Fluorescence [ k / s ]'
        return plot
    def _figure_drift_default(self):
        plot = Plot(self.plot_data_drift, width=70, height=40, padding=8, padding_left=64, padding_bottom=32)
        plot.plot(('t','x'), type='line', color='blue', name='x')
        plot.plot(('t','y'), type='line', color='red', name='y')
        plot.plot(('t','z'), type='line', color='green', name='z')
        bottom_axis = PlotAxis(plot,
                               orientation="bottom",
                               tick_generator=ScalesTickGenerator(scale=CalendarScaleSystem()))
        plot.index_axis=bottom_axis
        plot.index_axis.title = 'time'
        plot.value_axis.title = 'drift [um]'
        plot.legend.visible=True
        return plot        

    def _image_plot_default(self):
        return self.figure_image.components[0].plots['image'][0]

    def update_plot_image(self):
        self.plot_data_image.set_data('image', self.data_xy)
    def update_plot_line_value(self):
        self.plot_data_line.set_data('y', self.data_z)        
    def update_plot_line_index(self):
        self.plot_data_line.set_data('x', self.Z)
    def update_plot_drift_value(self):
        if len(self.drift) == 1:
            self.plot_data_drift.set_data('x', np.array(()))
            self.plot_data_drift.set_data('y', np.array(()))
            self.plot_data_drift.set_data('z', np.array(()))            
        else:
            self.plot_data_drift.set_data('x', self.drift[:,0])
            self.plot_data_drift.set_data('y', self.drift[:,1])
            self.plot_data_drift.set_data('z', self.drift[:,2])
    def update_plot_drift_index(self):
        if len(self.drift_time) == 0:
            self.plot_data_drift.set_data('t', np.array(()))
        else:
            self.plot_data_drift.set_data('t', self.drift_time - self.drift_time[0])

    traits_view = View(VGroup(HGroup(Item('submit_button', show_label=False),
                                     Item('remove_button', show_label=False),
                                     Item('priority'),
                                     Item('state', style='readonly'),
                                     Item('undo_button', show_label=False),
                                     ),
                              Group(VGroup(HGroup(Item('target_name'),
                                                  Item('add_target_button', show_label=False),
                                                  ),
                                           HGroup(Item('current_target'),
                                                  Item('next_target_button', show_label=False),
                                                  Item('remove_current_target_button', show_label=False),
                                                  ),
                                           HGroup(Item('periodic_focus'),
                                                  Item('focus_interval', enabled_when='not periodic_focus'),
                                                  ),
                                           HGroup(Item('periodic_freq_feedback'),
                                                  Item('threshold')
                                                  ),       
                                           label='tracking',
                                           ),
                                    VGroup(Item('size_xy'),
                                           Item('step_xy'),
                                           Item('size_z'),
                                           Item('step_z'),
                                           HGroup(Item('seconds_per_point_xy'),
                                                  Item('seconds_per_point_z'),
                                                  ),
                                           label='Settings',
                                           springy=True,
                                           ),
                                    layout='tabbed'
                                    ),
                              VSplit(Item('figure_image', show_label=False, resizable=True)),
                              HGroup(Item('figure_line', show_label=False, resizable=True),
                                     Item('figure_drift', show_label=False, resizable=True),
                                    ),
                              ),
                       menubar = MenuBar(Menu(Action(action='save', name='Save (.pyd or .pys)'),
                                              Action(action='load', name='Load'),
                                              Action(action='_on_close', name='Quit'),
                                              name='File'),
                                         Menu(Action(action='remove_all_targets', name='Remove All'),
                                              Action(action='forget_drift', name='Forget Drift'),
                                              name='Target'),),
                       title='Auto Focus', width=500, height=700, buttons=[], resizable=True,
                       handler=AutoFocusHandler)

    get_set_items=['confocal','targets','current_target','current_drift','drift','drift_time','periodic_focus',
                   'size_xy', 'size_z', 'step_xy', 'step_z', 'seconds_per_point_xy', 'seconds_per_point_z',
                   'data_xy', 'data_z', 'X', 'Y', 'Z', 'focus_interval', 'threshold' ]
    get_set_order=['confocal','targets']
Beispiel #28
0
class PlotExample(HasTraits):
    plot = Instance(Component)

    traits_view = View(Item('plot', editor=ComponentEditor(),
                            show_label=False),
                       resizable=True,
                       title="Tornado Plot",
                       width=800,
                       height=600)

    def _plot_default(self):
        container = OverlayPlotContainer(bgcolor="white")
        plots = self._make_curves()
        for plot in plots:
            plot.padding = 60
            container.add(plot)

        bottom_axis = PlotAxis(plot, orientation='bottom')

        label_list = [
            'var a', 'var b', 'var c', 'var d', 'var e', 'var f', 'var g',
            'var h', 'var i'
        ]
        vertical_axis = LabelAxis(plot,
                                  orientation='left',
                                  title='Categories',
                                  positions=range(1, 10),
                                  labels=label_list)
        vertical2_axis = LabelAxis(plot,
                                   orientation='right',
                                   positions=range(1, 10),
                                   labels=label_list)

        plot.underlays.append(vertical_axis)
        plot.underlays.append(vertical2_axis)
        plot.underlays.append(bottom_axis)

        return container

    def _get_points(self):
        index = linspace(pi / 4, 3 * pi / 2, 9)
        data = sin(index) + 2
        return (range(1, 10), data)

    def _make_curves(self):
        (index_points, value_points) = self._get_points()
        size = len(index_points)

        middle_value = 2500000.0
        mid_values = middle_value * ones(size)
        low_values = mid_values - 10000.0 * value_points
        high_values = mid_values + 20000.0 * value_points

        idx = ArrayDataSource(index_points)
        vals = ArrayDataSource(low_values, sort_order="none")

        idx2 = ArrayDataSource(index_points)
        vals2 = ArrayDataSource(high_values, sort_order="none")

        starting_vals = ArrayDataSource(mid_values, sort_order="none")

        # Create the index range
        index_range = DataRange1D(idx, low=0.5, high=9.5)
        index_mapper = LinearMapper(range=index_range)

        # Create the value range
        value_range = DataRange1D(vals,
                                  vals2,
                                  low_setting='auto',
                                  high_setting='auto',
                                  tight_bounds=False)
        value_mapper = LinearMapper(range=value_range, tight_bounds=False)

        # Create the plot
        plot1 = BarPlot(index=idx,
                        value=vals,
                        value_mapper=value_mapper,
                        index_mapper=index_mapper,
                        starting_value=starting_vals,
                        line_color='black',
                        orientation='v',
                        fill_color=tuple(COLOR_PALETTE[6]),
                        bar_width=0.8,
                        antialias=False)

        plot2 = BarPlot(index=idx2,
                        value=vals2,
                        value_mapper=value_mapper,
                        index_mapper=index_mapper,
                        starting_value=starting_vals,
                        line_color='black',
                        orientation='v',
                        fill_color=tuple(COLOR_PALETTE[1]),
                        bar_width=0.8,
                        antialias=False)

        return [plot1, plot2]
Beispiel #29
0
class SpectrumAnalyzerView(HasTraits):
    python_console_cmds = Dict()
    plot = Instance(Plot)
    plot_data = Instance(ArrayPlotData)
    which_plot = Str("Channel 1")
    hint = Str("Enable with setting in \"System Monitor\" group.")
    traits_view = View(
        Item('plot',
             editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8)),
             show_label=False),
        HGroup(
            Spring(width=20, springy=False),
            Item('', label='Channel Selection:', emphasized=True),
            Item(
                name='which_plot',
                show_label=False,
                tooltip=
                'Select the RF Channel for which to display Spectrum Analyzer',
                editor=EnumEditor(values=[
                    "Channel 1", "Channel 2", "Channel 3", "Channel 4"
                ])), Spring(width=20, springy=True),
            Item('hint',
                 show_label=False,
                 style='readonly',
                 style_sheet='*{font-style:italic}'),
            Spring(width=20, springy=True)))

    def parse_payload(self, raw_payload):
        """
        Params
        ======
        payload: is an array of ints representing bytes from the SBP_MSG_USER_DATA message 'contents'

        Returns
        =======
        JSON dict of a payload based on this format, except all N of the diff_amplitude
        are together in a list under 'diff_amplitudes' and rx_time is split into TOW and week

        Frequency is in Hz, Amplitude is in dB

        FIELD               TYPE    OFFSET  SHORT EXPLANATION

        user_msg_tag        u16     0       bespoke preamble for spectrum message

        rx_time             struct  2       struct gps_time_t defined as double TOW + s16 WEEK

        starting_frequency  float  12       starting frequency for this packet

        frequency_step      float  16       frequency step for points in this packet

        min_amplitude       float  20       minimum level of amplitude

        amplitude_step      float  24       amplitude unit

        diff_amplitude      u8     28       N values in the above units
        """
        # Turn the array of ints representing uint8 bytes back to binary, so you can use struct
        # formatting to unpack it. Otherwise you would have to manually parse each byte.
        pack_fmt_str = 'B' * len(raw_payload)
        payload = struct.pack(pack_fmt_str, *raw_payload)
        payload_header_fmt_str = '<Hdhffff'
        payload_header_bytes = struct.calcsize(payload_header_fmt_str)
        diff_amplitude_n = (len(raw_payload) - payload_header_bytes)
        diff_amplitude_fmt_str = 'B' * diff_amplitude_n
        fmt_str = payload_header_fmt_str + diff_amplitude_fmt_str
        parsed_payload = struct.unpack(fmt_str, payload)
        fft_msg_header = [
            'user_msg_tag', 'TOW', 'week', 'starting_frequency',
            'frequency_step', 'min_amplitude', 'amplitude_step'
        ]
        payload_json = dict(
            zip(fft_msg_header, parsed_payload[:len(fft_msg_header)]))
        fft_msg_payload = parsed_payload[len(fft_msg_header):]
        payload_json['diff_amplitudes'] = fft_msg_payload
        return payload_json

    def get_frequencies(self, start_freq, freq_step, n):
        '''
        start_freq: float (Hz)
        freq_step: float (Hz)
        n: int
        '''
        return np.array([start_freq + freq_step * i for i in range(n)])

    def get_amplitudes(self, min_amplitude, diffs, unit):
        '''
        min_amplitude: float (dB)
        diffs: tuple of floats (dB)
        unit: float (dB)
        '''
        return np.array([min_amplitude + diff * unit for diff in diffs])

    def spectrum_analyzer_state_callback(self, sbp_msg, **metadata):
        '''
        Params
        ======
        sbp_msg: sbp.msg.SBP object

        Updates the view's data for use in self.update_plot
        '''
        # Need to figure out which user_msg_tag means it's an FFT message
        # for now assume that all SBP_MSG_USER_DATA is relevant
        fft = MsgSpecan(sbp_msg)
        frequencies = self.get_frequencies(fft.freq_ref, fft.freq_step,
                                           len(fft.amplitude_value))
        amplitudes = self.get_amplitudes(fft.amplitude_ref,
                                         fft.amplitude_value,
                                         fft.amplitude_unit)

        tag = fft.channel_tag
        if (tag == 1 and self.which_plot != "Channel 1"):
            return
        if (tag == 2 and self.which_plot != "Channel 2"):
            return
        if (tag == 3 and self.which_plot != "Channel 3"):
            return
        if (tag == 4 and self.which_plot != "Channel 4"):
            return
        timestamp = GpsTime(fft.t.wn, fft.t.tow)
        if len(self.incomplete_data[timestamp]['frequencies']) + len(
                frequencies) == NUM_POINTS:
            self.most_recent_complete_data['frequencies'] = np.append(
                self.incomplete_data[timestamp]['frequencies'],
                frequencies,
                axis=0)
            self.most_recent_complete_data['amplitudes'] = np.append(
                self.incomplete_data[timestamp]['amplitudes'],
                amplitudes,
                axis=0)
            self.incomplete_data.pop(timestamp)
            if timestamp is None or timestamp > self.most_recent:
                self.most_recent = timestamp
            GUI.invoke_later(self.update_plot)
        else:
            self.incomplete_data[timestamp]['frequencies'] = np.append(
                self.incomplete_data[timestamp]['frequencies'],
                frequencies,
                axis=0)
            self.incomplete_data[timestamp]['amplitudes'] = np.append(
                self.incomplete_data[timestamp]['amplitudes'],
                amplitudes,
                axis=0)

    def update_plot(self):
        most_recent_fft = self.most_recent_complete_data
        if len(most_recent_fft['frequencies']) != 0:
            self.plot_data.set_data('frequency',
                                    most_recent_fft['frequencies'])
            self.plot_data.set_data('amplitude', most_recent_fft['amplitudes'])
            self.plot.value_mapper.range.low = min(
                most_recent_fft['amplitudes'])
            self.plot.value_mapper.range.high = max(
                most_recent_fft['amplitudes'])

    def __init__(self, link):
        super(SpectrumAnalyzerView, self).__init__()
        self.link = link
        self.link.add_callback(self.spectrum_analyzer_state_callback,
                               SBP_MSG_SPECAN)
        self.python_console_cmds = {'spectrum': self}

        # keys are GpsTime
        self.incomplete_data = defaultdict(lambda: {
            'frequencies': np.array([]),
            'amplitudes': np.array([])
        })
        self.most_recent_complete_data = {
            'frequencies': np.array([]),
            'amplitudes': np.array([])
        }
        self.most_recent = None

        self.plot_data = ArrayPlotData()
        self.plot = Plot(self.plot_data, emphasized=True)

        self.plot.title = 'Spectrum Analyzer'
        self.plot.title_color = [0, 0, 0.43]

        self.plot.value_axis.orientation = 'right'
        self.plot.value_axis.title_spacing = 30
        self.plot.value_axis.title = 'Amplitude (dB)'

        self.plot.index_axis.title = 'Frequency (MHz)'
        self.plot_data.set_data('frequency', [0])
        self.plot_data.set_data('amplitude', [0])
        self.plot.plot(('frequency', 'amplitude'),
                       type='line',
                       name='spectrum')
Beispiel #30
0
class TrackingView(CodeFiltered):
    python_console_cmds = Dict()
    legend_visible = Bool()
    plot = Instance(Plot)
    plots = List()
    plot_data = Instance(ArrayPlotData)

    traits_view = View(
        VGroup(
            Item(
                'plot',
                editor=ComponentEditor(bgcolor=(0.8, 0.8, 0.8)),
                show_label=False, ),
            HGroup(
                Spring(width=8, springy=False),
                Item('legend_visible', label="Show Legend:"),
                CodeFiltered.get_filter_group(), )))

    def clean_cn0(self, t):
        assert self.CN0_lock.locked()
        for k in list(self.CN0_dict.keys()):
            if self.CN0_age[k] < self.time[0]:
                del self.CN0_dict[k]
                del self.CN0_age[k]

    def measurement_state_callback(self, sbp_msg, **metadata):
        with self.CN0_lock:
            codes_that_came = []
            t = monotonic() - self.t_init
            self.time.append(t)
            # first we loop over all the SIDs / channel keys we have stored and set 0 in for CN0
            for i, s in enumerate(sbp_msg.states):
                if code_is_glo(s.mesid.code):
                    # for Glonass satellites, store in two dictionaries FCN and SLOT
                    # so that they can both be retrieved when displaying the channel
                    if (s.mesid.sat > 90):
                        self.glo_fcn_dict[i] = s.mesid.sat - 100
                    sat = self.glo_fcn_dict.get(i, 0)
                    if (s.mesid.sat <= 90):
                        self.glo_slot_dict[sat] = s.mesid.sat
                else:
                    sat = s.mesid.sat
                key = (s.mesid.code, sat)
                codes_that_came.append(key)
                if s.cn0 != 0:
                    self.CN0_dict[key].append(s.cn0 / 4.0)
                    self.CN0_age[key] = t
                received_code_list = getattr(self, "received_codes", [])
                if s.mesid.code not in received_code_list:
                    received_code_list.append(s.mesid.code)
                    self.received_codes = received_code_list
            for key, cno_array in list(self.CN0_dict.items()):
                if key not in codes_that_came:
                    cno_array.append(0)
            self.clean_cn0(t)
        self.update_scheduler.schedule_update('update_plot', self.update_plot)

    def tracking_state_callback(self, sbp_msg, **metadata):
        with self.CN0_lock:
            codes_that_came = []
            t = monotonic() - self.t_init
            self.time.append(t)
            # first we loop over all the SIDs / channel keys we have stored and set 0 in for CN0
            # for each SID, an array of size MAX PLOT with the history of CN0's stored
            # If there is no CN0 or not tracking for an epoch, 0 will be used
            # each array can be plotted against host_time, t
            for i, s in enumerate(sbp_msg.states):
                if code_is_glo(s.sid.code):
                    if (s.sid.sat > 90):
                        sat = s.sid.sat - 100
                    else:
                        sat = s.fcn - GLO_FCN_OFFSET
                    self.glo_slot_dict[sat] = s.sid.sat
                else:
                    sat = s.sid.sat
                key = (s.sid.code, sat)
                codes_that_came.append(key)
                if s.cn0 != 0:
                    self.CN0_dict[key].append(s.cn0 / 4.0)
                    self.CN0_age[key] = t
                received_code_list = getattr(self, "received_codes", [])
                if s.sid.code not in received_code_list:
                    received_code_list.append(s.sid.code)
                    self.received_codes = received_code_list
            for key, cno_array in list(self.CN0_dict.items()):
                if key not in codes_that_came:
                    cno_array.append(0)
            self.clean_cn0(t)
        self.update_scheduler.schedule_update('update_plot', self.update_plot)

    def update_plot(self):
        with self.CN0_lock:
            plot_labels = []
            plots = []
            # Update the underlying plot data from the CN0_dict for selected items
            new_plot_data = {'t': self.time}
            for k, cno_array in self.CN0_dict.items():
                key = str(k)
                # set plot data
                if (getattr(self, 'show_{}'.format(int(k[0])), True)):
                    new_plot_data[key] = cno_array
            self.plot_data.update_data(new_plot_data)
            # Remove any stale plots that got removed from the dictionary
            for each in list(self.plot.plots.keys()):
                if each not in [str(a) for a in self.CN0_dict.keys()] and each != 't':
                    try:
                        self.plot.delplot(each)
                    except KeyError:
                        pass
                    try:
                        self.plot_data.del_data(each)
                    except KeyError:
                        pass
            # add/remove plot as neccesary and build legend
            for k, cno_array in self.CN0_dict.items():
                key = str(k)
                if (getattr(self, 'show_{}'.format(int(k[0])), True) and
                   not cno_array.count(0) == NUM_POINTS):
                    if key not in self.plot.plots.keys():
                        pl = self.plot.plot(('t', key), type='line',
                                            color=get_color(k), name=key)
                    else:
                        pl = self.plot.plots[key]
                    plots.append(pl)
                    plot_labels.append(get_label(k, self.glo_slot_dict))
                # if not selected or all 0, remove
                else:
                    if key in list(self.plot.plots.keys()):
                        self.plot.delplot(key)
            plots = dict(list(zip(plot_labels, plots)))
            self.plot.legend.plots = plots

    def _legend_visible_changed(self):
        if self.plot:
            if not self.legend_visible:
                self.plot.legend.visible = False
            else:
                self.plot.legend.visible = True
            self.plot.legend.tools.append(
                LegendTool(self.plot.legend, drag_button="right"))

    def __init__(self, link):
        super(TrackingView, self).__init__()
        self.t_init = monotonic()
        self.time = deque([x * 1 / TRK_RATE for x in range(-NUM_POINTS, 0, 1)], maxlen=NUM_POINTS)
        self.CN0_lock = threading.Lock()
        self.CN0_dict = defaultdict(lambda: deque([0] * NUM_POINTS, maxlen=NUM_POINTS))
        self.CN0_age = defaultdict(lambda: -1)
        self.glo_fcn_dict = {}
        self.glo_slot_dict = {}
        self.n_channels = None
        self.plot_data = ArrayPlotData(t=[0.0])
        self.plot = Plot(self.plot_data, emphasized=True)
        self.plot.title = 'Tracking C/N0'
        self.plot.title_color = [0, 0, 0.43]
        self.ylim = self.plot.value_mapper.range
        self.ylim.low = SNR_THRESHOLD
        self.ylim.high = 60
        self.plot.value_range.bounds_func = lambda l, h, m, tb: (0, h * (1 + m))
        self.plot.value_axis.orientation = 'right'
        self.plot.value_axis.axis_line_visible = False
        self.plot.value_axis.title = 'dB-Hz'
        self.plot_data.set_data('t', self.time)
        self.plot.index_axis.title = 'seconds'
        self.plot.index_range.bounds_func = lambda l, h, m, tb: (h - 100, h)
        self.legend_visible = True
        self.plot.legend.visible = True
        self.plot.legend.align = 'll'
        self.plot.legend.line_spacing = 1
        self.plot.legend.font = 'monospace 8'
        self.plot.legend.draw_layer = 'overlay'
        self.plot.legend.tools.append(
            LegendTool(self.plot.legend, drag_button="right"))
        self.link = link
        self.link.add_callback(self.measurement_state_callback,
                               SBP_MSG_MEASUREMENT_STATE)
        self.link.add_callback(self.tracking_state_callback,
                               SBP_MSG_TRACKING_STATE)
        self.python_console_cmds = {'track': self}
        self.update_scheduler = UpdateScheduler()