def timed_update():
    from pyface.timer.api import Timer

    def update_loop(line_plot):
        line_plot.update_data()
        # shouldn't need this
        # line_plot.autoscale_axis()

    def log_memory():
        # log memory usage
        usage = float(psutil.Process(os.getpid()).memory_info().rss) * 1e-6
        info = '#[{}] MB:{:f}'.format(-1, usage)
        logger.warning(info)

    plot = LinePlot()
    millisecs = int(1000.0 / 30.0)  # ~30Hz
    update_timer = Timer(millisecs, update_loop, plot)
    log_timer = Timer(int(1000.0 * 10.0), log_memory)
    update_timer.Start()
    log_timer.Start()
    plot.configure_traits()
예제 #2
0
class MainWindow(ApplicationWindow):
    """ The main application window. """

    # The pyface Timer.
    my_timer = Any()

    # Count each time the timer task executes.
    counter = Int

    def __init__(self, **traits):
        """ Creates a new application window. """

        # Base class constructor.
        super(MainWindow, self).__init__(**traits)

        # Add a menu bar.
        self.menu_bar_manager = MenuBarManager(
            MenuManager(
                Action(name='Start Timer', on_perform=self._start_timer),
                Action(name='Stop Timer', on_perform=self._stop_timer),
                Action(name='E&xit', on_perform=self.close),
                name = '&File',
            )
        )

        return

    def _start_timer(self):
        """Called when the user selects "Start Timer" from the menu."""

        if self.my_timer is None:
            # First call, so create a Timer.  It starts automatically.
            self.my_timer = Timer(500, self._timer_task)
        else:
            self.my_timer.Start()

    def _stop_timer(self):
        """Called when the user selecte "Stop Timer" from the menu."""

        if self.my_timer is not None:
            self.my_timer.Stop()


    def _timer_task(self):
        """The method run periodically by the timer."""

        self.counter += 1
        print "counter = %d" % self.counter
예제 #3
0
class Animator(HasTraits):
    """ Convenience class to manage a timer and present a convenient
        UI.  This is based on the code in `tvtk.tools.visual`.
        Here is a simple example of using this class::

            >>> from mayavi import mlab
            >>> def anim():
            ...     f = mlab.gcf()
            ...     while 1:
            ...         f.scene.camera.azimuth(10)
            ...         f.scene.render()
            ...         yield
            ...
            >>> anim = anim()
            >>> t = Animator(500, anim.next)
            >>> t.edit_traits()

        This makes it very easy to animate your visualizations and control
        it from a simple UI.

        **Notes**

        If you want to modify the data plotted by an `mlab` function call,
        please refer to the section on: :ref:`mlab-animating-data`
    """

    ########################################
    # Traits.

    start = Button('Start Animation')
    stop = Button('Stop Animation')
    delay = Range(10, 100000, 500,
                  desc='frequency with which timer is called')

    # The internal timer we manage.
    timer = Instance(Timer)

    ######################################################################
    # User interface view

    traits_view = View(Group(Item('start'),
                             Item('stop'),
                             show_labels=False),
                       Item('_'),
                       Item(name='delay'),
                       title='Animation Controller',
                       buttons=['OK'])

    ######################################################################
    # Initialize object
    def __init__(self, millisec, callable, *args, **kwargs):
        """Constructor.

        **Parameters**

          :millisec: int specifying the delay in milliseconds
                     between calls to the callable.

          :callable: callable function to call after the specified
                     delay.

          :\*args: optional arguments to be passed to the callable.

          :\*\*kwargs: optional keyword arguments to be passed to the callable.

        """
        HasTraits.__init__(self)
        self.delay = millisec
        self.timer = Timer(millisec, callable, *args, **kwargs)

    ######################################################################
    # Non-public methods, Event handlers
    def _start_fired(self):
        self.timer.Start(self.delay)

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

    def _delay_changed(self, value):
        t = self.timer
        if t is None:
            return
        if t.IsRunning():
            t.Stop()
            t.Start(value)
예제 #4
0
class MainWindow(HasTraits):
    scene = Instance(MlabSceneModel, ())

    view = View(Item('scene', editor=SceneEditor(), resizable=True,
                    show_label=False),
                    resizable=True, height=500.00, width=750.0)

    def __init__(self, config, server):
        HasTraits.__init__(self)
        self.mayavi_view = PlotHead(self, config, server)
        self.tail_data = np.zeros((2,3))
        self.head_data = np.zeros((2,3))
        self.reset = False
        self.init_plot()
        self.timer = Timer(2000, self.update_plot)
        self.timer.Start()
        
    def init_plot(self):
        # create a window with 14 plots (7 rows x 2 columns)
        ## create a window with 8 plots (4 rows x 2 columns)

        reader = tvtk.OBJReader()
        reader.file_name = self.mayavi_view.filename
        mapper = tvtk.PolyDataMapper()
        mapper.input = reader.output
        actor = tvtk.Actor()
        mapper.color_mode = 0x000000
        actor.mapper = mapper
        actor.orientation = (180,0,90)
        self.scene.add_actor(actor)

        mlab.points3d(11.5, -1.3, -14)
        mlab.points3d(-6.6, -1.3, -13.5)
        mlab.points3d(3,-2,2)
        mlab.points3d(2, 9.5, -9.5)
        self.arrows = mlab.quiver3d(self.tail_data[:,0], self.tail_data[:,1], self.tail_data[:,2],
                        self.head_data[:,0], self.head_data[:,1], self.head_data[:,2], scale_mode='vector', scale_factor=1.0)
        self.dots = mlab.points3d(self.tail_data[:,0], self.tail_data[:,1], self.tail_data[:,2],
        color=(1,1,0),opacity=0.5,scale_mode='vector', scale_factor=1.0)
        self.ar = self.arrows.mlab_source
        self.dot_source = self.dots.mlab_source
        '''
        x_arrows = np.ones((300, 6))
        y_arrows = np.ones((300, 6))
        z_arrows = np.ones((300, 6))
        arrows = np.ones((300, 6))
        for i, pos in enumerate(arrows):
            x_arrows[i, 0] = pos[0] + i
            y_arrows[i, 1] = pos[1] + i
            z_arrows[i, 2] = pos[2] + i
        arrows = np.vstack((x_arrows, y_arrows, z_arrows, np.zeros((1,6))))
        self.tail_data = np.vstack((self.tail_data, arrows[:,:3]))
        mlab.points3d(x_arrows[:,0], x_arrows[:,1], x_arrows[:,2], scale_factor = 0.5)
        mlab.quiver3d(x_arrows[:,0], x_arrows[:,1], x_arrows[:,2],
                       x_arrows[:,3], x_arrows[:,4], x_arrows[:,5], scale_factor = 0.5)
          #  z=arrows[:,2]
        
        self.head_data = np.vstack((self.head_data, arrows[:, -3:]))
        self.ar.reset(x=arrows[:,0] +  self.mayavi_view.plot_vertex_vec[0], y=arrows[:,1] + self.mayavi_view.plot_vertex_vec[1], 
           z=arrows[:,2] + self.mayavi_view.plot_vertex_vec[2], u=arrows[:,3]+10, v=arrows[:,4]+10,w=arrows[:,5]+10)
        '''
         
    def update_plot(self):
        print 'started updating'
        if self.reset:
            while not queue.empty():
                queue.get()
            self.head_data = np.zeros((2,3))
            self.tail_data = np.zeros((2,3))
            self.reset = False
        else:
            while not queue.empty():
                new_values = queue.get()
                print new_values.shape
                self.tail_data = np.vstack((self.tail_data, new_values[1]))
                print 'updated position'
                self.head_data = np.vstack((self.head_data, new_values[0]))
                print 'updated rotation'
        print self.head_data
        print self.tail_data
        self.ar.reset(x=self.tail_data[:,0], y=self.tail_data[:,1], z=self.tail_data[:,2],
                        u=self.head_data[:,0], v=self.head_data[:,1], w=self.head_data[:,2], scale_mode='vector', scale_factor=1.0)
        self.dot_source.reset(x=self.tail_data[:,0], y=self.tail_data[:,1], z=self.tail_data[:,2],
        color=(1,1,0),opacity=0.5,scale_mode='vector', scale_factor=1.0)
        print 'finished'
예제 #5
0
class Animator(HasTraits):
    start = Button('Start Animation')
    stop = Button('Stop Animation')
    next_frame = Button('+')
    prev_frame = Button('-')
    delay = Range(10, 100000, 500)
    loop = Bool(True)

    current_frame = Int(-1)
    _last_frame = Int()

    # TODO use Range(high="trait name")
    render_from_frame = Int()
    render_to_frame = Int()
    render_animation = Button()
    is_rendering = Bool(False) # indicator bool is True when rendering
    is_rendering_animation = Bool(False)

    render_directory = Directory("/tmp", exists=False)
    render_name_pattern = String("frame_%05d.png")

    magnification = Range(1, 128)
    fix_image_size = Bool(False)
    image_size = Tuple(Int(1280), Int(720))

    render = Event()

    enable_cameraman = Bool(False)
    set_keyframe = Button()
    remove_keyframe = Button()

    timer = Instance(Timer)

    traits_view = View( Tabbed(
            Group(
                HGroup(
                    Item('start', show_label=False),
                    Item('stop', show_label=False),
                    Item('next_frame', show_label=False, enabled_when='current_frame < _last_frame'),
                    Item('prev_frame', show_label=False, enabled_when='current_frame > 0'),
                ),
                HGroup(
                    Item(name = 'loop'),
                    Item(name = 'delay'),
                ),
                Item(name = 'current_frame', 
                     editor=RangeEditor(is_float=False, high_name='_last_frame', mode='slider')),
                Group(
                    HGroup(
                        Item(name = 'enable_cameraman', label='enabled'),
                        Item(name = 'set_keyframe', show_label=False),
                        Item(name = 'remove_keyframe', show_label=False),
                        Item(name = 'interpolation_type', object='object._camera_interpolator'),
                    ),
                label = 'Cameraman',
                ),
            label = 'Timeline',
            ),
            Group(
                HGroup(
                    Item('fix_image_size', label="Set Image Size"),
                    Item('magnification', visible_when='not fix_image_size', label='Magnification'),
                    Item('image_size', visible_when='fix_image_size', show_label=False, editor=TupleEditor(cols=2, labels=['W', 'H'])),
                ),
                Item("_"),
                Item("render_directory", label="Target Dir"),
                Item("render_name_pattern", label="Filename Pattern"),
                Item("_"),
                HGroup(
                    Item("render_from_frame", label="from",
                         editor=RangeEditor(is_float=False, low=0, high_name='render_to_frame')),
                    Item("render_to_frame", label="to",
                         editor=RangeEditor(is_float=False, low_name='render_from_frame', high_name='_last_frame')),
                ),
                Item("render_animation", show_label=False),
                label = "Render",
            ),
        ),
        title = 'Animation Controller', 
        buttons = [])


    def __init__(self, num_frames, callable, millisec=40, figure=None, play=True, *args, **kwargs):
        HasTraits.__init__(self)
        self.delay = millisec
        self._last_frame = num_frames - 1
        self._callable = callable
        if figure is None:
            figure = mlab.gcf()
        self._figure = figure
        self._camera_interpolator = tvtk.CameraInterpolator(interpolation_type='spline')
        self._t_keyframes = {}
        self.render_to_frame = self._last_frame
        self.timer = Timer(millisec, self._on_timer, *args, **kwargs)
        if not play:
            self.stop = True
        self._internal_generator = None
        self.current_frame = 0
        self.on_trait_change(self._render, "render, current_frame", dispatch="ui")

    def _render(self):
        self.is_rendering = True
        if self._internal_generator is not None:
            try:
                next(self._internal_generator)
            except StopIteration: # is ok since generator should yield just once to render
                pass 
            except: # catch and re-raise other errors
                raise
            else:
                raise "The render function should be either a simple function or a generator that yields just once to render"
        # before we call the user function, we want to disallow rendering
        # this speeds up animations that use mlab functions
        scene = self._figure.scene
        scene.disable_render = True
        r = self._callable(self.current_frame)
        if isinstance(r, types.GeneratorType):
            next(r)
            # save away generator to yield when another frame has to be displayed
            self._internal_generator = r
        # render scene without dumb hourglass cursor, 
        # can be prevented by setting _interacting before calling render
        old_interacting = scene._interacting
        if self._camera_interpolator.number_of_cameras >= 2 and self.enable_cameraman:
            t = self.current_frame / float(self._last_frame)
            self._camera_interpolator.interpolate_camera(t, mlab.get_engine().current_scene.scene.camera)
            mlab.gcf().scene.renderer.reset_camera_clipping_range()
        scene._interacting = True
        scene.disable_render = False
        scene.render()
        scene._interacting = old_interacting
        self.is_rendering = False

    @on_trait_change('set_keyframe')
    def _set_keyframe(self):
        t = self.current_frame / float(self._last_frame)
        self._camera_interpolator.add_camera(t, mlab.get_engine().current_scene.scene.camera)
        self._t_keyframes[self.current_frame] = t

    def _next_frame_fired(self):
        self.current_frame += 1

    def _prev_frame_fired(self):
        self.current_frame -= 1

    @on_trait_change('remove_keyframe')
    def _remove_keyframe(self):
        if self.current_frame in self._t_keyframes:
            self._camera_interpolator.remove_last_keyframe(self._t_keyframes[self.current_frame])

    def _on_timer(self, *args, **kwargs):
        if self.loop or self.current_frame != self._last_frame:
            self.current_frame = (self.current_frame + 1) % (self._last_frame + 1)
        else:
            self.stop = True

    def _delay_changed(self, value):
        t = self.timer
        if t is None:
            return
        if t.IsRunning():
            t.Stop()
            t.Start(value)

    def _start_fired(self):
        if not self.loop and self.current_frame == self._last_frame:
            self.current_frame = 0
        self.timer.Start(self.delay) 

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

    def _render_animation_fired(self):
        self.stop = True
        n_frames_render = self.render_to_frame - self.render_from_frame
        # prepare the render window
        renwin = self._figure.scene.render_window
        aa_frames = renwin.aa_frames
        renwin.aa_frames = 8
        renwin.alpha_bit_planes = 1
        # turn on off screen rendering
        #renwin.off_screen_rendering = True
        # set size of window
        if self.fix_image_size:
            orig_size = renwin.size
            renwin.size = self.image_size
        # render the frames
        progress = ProgressDialog(title="Rendering", max=n_frames_render, 
                                  show_time=True, can_cancel=True)
        progress.open()
        self.is_rendering_animation = True
        for frame in range(self.render_from_frame, self.render_to_frame + 1):
            # move animation to desired frame, this will also render the scene
            self.current_frame = frame
            # prepare window to image writer
            render = tvtk.WindowToImageFilter(input=renwin, magnification=1)#, input_buffer_type='rgba')
            if not self.fix_image_size:
                render.magnification = self.magnification
            exporter = tvtk.PNGWriter(file_name=path.join(self.render_directory, self.render_name_pattern % frame))

            configure_input(exporter,render)
            exporter.write()
            do_continue, skip = progress.update(frame - self.render_from_frame)
            if not do_continue:
                break
        # reset the render window to old values
        renwin.aa_frames = aa_frames
        if self.fix_image_size:
            renwin.size = orig_size
        #renwin.off_screen_rendering = False
        self.is_rendering_animation = False
        progress.close()
예제 #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.1,
                              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(200, 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,
    )
예제 #7
0
class DACChannel(traits.HasTraits):
    def __init__(self, setchannelName, port, connection, rpiADC):
        self.channelName = setchannelName
        self.x = ad.ADEvalBC()
        self.port = port
        self.connection = connection
        self.rpiADC = rpiADC
        self.wmLockTimer = Timer(1000, self.wmLock2)
        self.wmLockTimer.Stop()
#        time.sleep(5)
#        self.start_timer()

    update = traits.Button()
    set = traits.Button()

    pinMode = '0'
    relockMode = traits.Enum("Manual Mode", "Doubling cavity Relock",
                             "Wavemeter Relock", "Wavemeter Lock")
    #set_Relock = traits.Button()

    #---- MANUAL MODE ----#

    voltage = traits.Float(desc="Voltage of the Channel")
    setVoltage = traits.Float(desc="set Voltage")
    powerModeMult = 0
    channelName = traits.Str(desc="Name")
    channelDescription = traits.Str(desc="Description")
    powerMode = traits.Enum(
        5,
        10,
        10.8,
        desc="power Mode",
    )
    bipolar = traits.Bool(desc="Bipolarity")
    channelMessage = traits.Str()
    bytecode = traits.Str()
    port = traits.Str()

    def pinSet(self, channel, mode):
        cmd = "pin=" + channel + mode
        self.connection.send(cmd)
        #print cmd

    def _update_fired(self):
        if self.bipolar == True:
            a = "bipolar"
            bip = True
            self.powerModeMult = -1
        else:
            a = "unipolar"
            bip = False
            self.powerModeMult = 0

        cmd = "cmd=" + self.x.setMaxValue(self.port, self.powerMode, bip)
        #print cmd
        self.connection.send(cmd)
        b = "Mode set to %.1f" % self.powerMode
        self.channelMessage = b + ' ' + a
        self._set_fired()

    def _set_fired(self):
        if ((self.setVoltage > self.powerMode) and (self.bipolar == False)):
            print "setVoltage out of bounds. Not sending."
        elif ((abs(self.setVoltage) > self.powerMode)
              and (self.bipolar == True)):
            print "setVoltage out of bounds. Not sending."
        else:
            cmd = "cmd=" + self.x.generate_voltage(
                self.port, self.powerMode, self.powerModeMult * self.powerMode,
                self.setVoltage)
            self.connection.send(cmd)
            self.bytecode = self.x.generate_voltage(
                self.port, self.powerMode, self.powerModeMult * self.powerMode,
                self.setVoltage)
            self.voltage = self.setVoltage

#---- MANUAL MODE GUI ----#

    voltageGroup = traitsui.HGroup(traitsui.VGroup(
        traitsui.Item('voltage',
                      label="Measured Voltage",
                      style_sheet='* { font-size: 18px;  }',
                      style="readonly"),
        traitsui.Item('setVoltage', label="Set Value"),
    ),
                                   traitsui.Item('set', show_label=False),
                                   show_border=True)

    powerGroup = traitsui.VGroup(traitsui.HGroup(
        traitsui.Item('powerMode', label="Power Mode"),
        traitsui.Item('bipolar'),
    ),
                                 traitsui.HGroup(
                                     traitsui.Item('update', show_label=False),
                                     traitsui.Item('channelMessage',
                                                   show_label=False,
                                                   style="readonly"),
                                 ),
                                 traitsui.Item('bytecode',
                                               show_label=False,
                                               style="readonly"),
                                 traitsui.Item('switch_Lock'),
                                 show_border=True)

    manualGroup = traitsui.VGroup(traitsui.Item('channelName',
                                                label="Channel Name",
                                                style="readonly"),
                                  voltageGroup,
                                  show_border=True,
                                  visible_when='relockMode == "Manual Mode"')

    #---- DOUBLING CAVITY MODE GUI----#

    adcChannel = traits.Enum(0,
                             1,
                             2,
                             3,
                             4,
                             5,
                             6,
                             7,
                             8,
                             9,
                             10,
                             11,
                             12,
                             desc="Channel of the rpiADC")
    adcVoltage = traits.Float(desc="Voltage on rpiADC Channel")
    DCscan_and_lock = traits.Button()
    switch_Lock = traits.Button()
    DCconnect = traits.Bool()
    DCautolock = traits.Button()
    DCadcVoltages = None
    DCadcVoltagesMean = None
    DCtolerance = 0.01  #Volt
    DCmistakeCounter = 0
    DCminBoundary = traits.Float()
    DCmaxBoundary = traits.Float()
    DCnoOfSteps = traits.Int()

    #Updates voltage of the selected channel"
    def _adcVoltage_update(self):
        self.adcVoltage = self._adcVoltage_get()

#Gets voltage of the selected channel via rpiADC Client

    def _adcVoltage_get(self):
        return self.rpiADC.getResults()[self.adcChannel]
#        print "latest results = %s " % self.rpiADC.latestResults
#        self.rpiADC.getResults()
#        print "latest results = %s " % self.rpiADC.latestResults
#        if self.adcChannel in self.rpiADC.latestResults:
#            return self.rpiADC.latestResults[self.adcChannel]
#        else:
#            return -999

#As soon as the connect button is checked, automatic updating of the adc voltage is initiated.
#When it is unchecked, the update stops

    def _DCconnect_changed(self):

        if self.DCconnect == True:
            self._start_PD_timer()
        else:
            self.PDtimer.stop()
            self.adcVoltage = -999
            print "PD timer stopped."

#Starts the timer, that only updates the displayed voltage

    def _start_PD_timer(self):
        self.PDtimer = Timer(1000.0, self._adcVoltage_update)

    #Starts a timer, that updates the displayed voltage, as well as does the "in lock" checking
    def _start_PD_lock_timer(self):
        self.PDtimer = Timer(1000.0, self.update_PD_and_Lock)

#Controls if everything is still in lock. Also updates displayed voltage. It counts still in lock, when the measured frequency
#is within DC tolerance of the mean of the last five measured frequencies.

    def update_PD_and_Lock(self):
        self._adcVoltage_update()  #still display Voltage
        pdVoltage = self._adcVoltage_get()
        #print "Updated Frequency"
        #mistakeCounter = 0
        if len(self.DCadcVoltages
               ) < 5:  #number of Measurements that will be compared
            print "Getting Data for Lock. Do not unlock!"
            self.DCadcVoltages = np.append(self.DCadcVoltages, pdVoltage)
        else:
            self.DCadcVoltagesMean = np.mean(
                self.DCadcVoltages)  #Mean Frequency to compare to
            if (abs(pdVoltage - self.DCadcVoltagesMean) < self.DCtolerance):
                self.DCadcVoltages = np.append(self.DCadcVoltages, pdVoltage)
                self.DCadcVoltages = np.delete(
                    self.DCadcVoltages, 0)  #keep Array at constant length
                print "Still locked."
                if self.DCmistakeCounter > 0:
                    self.DCmistakeCounter = 0
            else:
                self.DCmistakeCounter += 1
                if self.DCmistakeCounter > 5:
                    self.PDtimer.stop()
                    self._start_PD_timer()  #keep Frequency on display..
                    self._DCscan_and_lock_fired()
                    self._DCautolock_fired()
                else:
                    print self.DCmistakeCounter

    #This button is used, when everything is already locked. It prepares the voltage mean array, stops the PD timer and starts the update_PD_and_Lock timer routine
    def _DCautolock_fired(self):
        if self.DCconnect == True:
            self.DCadcVoltages = np.array([])
            self.PDtimer.stop()
            self._start_PD_lock_timer()
        else:
            print "No adcRPi connected."

#This function (button) scans the voltage and reads the RPiADC voltage of the selected channel. It subsequently attempts
#to lock the Cavity at the voltage, where the RPiADC voltage is highest. The Algorithm for the lock is as follows:
#1) It does a coarse DAC voltage scan with the parameters selected in the input (minBoundary etc). This scan is terminated when
#	the adc voltage goes above a threshold (3.2 V - hardcoded, maybe add input), or after scanning the whole range.
#2) A fine scan 0.3V(dac) around the maximum (or around the 3.2V dac voltage) is done. Currently the number of steps is hardcoded to 600,
#	which worked well. This scan terminated either by going to a 3.3V (adc) threshhold or after finishing.
#3) The Cavity is locked at a dac voltage that corresponds to either the maximum after the whole scan or the 3.3V threshold.

    def _DCscan_and_lock_fired(self):
        self.pinSet(self.port, '1')  #Unlock
        time.sleep(
            1
        )  #If the cavity was in lock before we can not directly start scanning, or else it will read 3.3V as first value
        voltages = np.linspace(
            self.DCminBoundary, self.DCmaxBoundary,
            self.DCnoOfSteps)  #Parameters for first scan set by GUI
        diodeVoltages = np.array([])
        for entry in voltages:  #First scan
            self.setVoltage = entry
            self._set_fired()  #update setVoltage
            diodeVoltages = np.append(diodeVoltages, self._adcVoltage_get())
            volt = self._adcVoltage_get()
            print volt
            if volt >= 3.2:  #Threshold for first scan
                break
            time.sleep(
                0.05
            )  #sleep time between every step for adc readout, maybe it is possible to make the scan faster
        self.setVoltage = voltages[diodeVoltages.argmax(
            axis=0)]  #DAC Voltage corresponding to the highest adc voltage
        print "Attempting to reduce scan Range"
        print self.setVoltage
        time.sleep(2.0)
        if self.setVoltage < 0.3:  #make sure we do not scan below zero, as the lock box does not like negative voltages.
            auxSetVolt = 0
        else:
            auxSetVolt = self.setVoltage - 0.3
        voltages = np.linspace(auxSetVolt, self.setVoltage + 0.3,
                               600)  #parameters for second scan
        diodeVoltages = np.array([])
        for entry in voltages:  #Second scan
            if entry > self.powerMode:  #Our voltage can not go above our maximum value
                break
            self.setVoltage = entry
            self._set_fired()
            diodeVoltages = np.append(diodeVoltages, self._adcVoltage_get())
            volt = self._adcVoltage_get()
            print volt
            if volt >= 3.3:  #threshold for second scan
                print self.setVoltage
                self.pinSet(self.port, '0')
                return
            time.sleep(0.1)
        self.setVoltage = voltages[diodeVoltages.argmax(axis=0)]
        print "DAC Voltage set to %f" % voltages[diodeVoltages.argmax(axis=0)]
        print ".. this corresponds to a diode Voltage of %f" % diodeVoltages[
            diodeVoltages.argmax(axis=0)]
        self._set_fired()
        time.sleep(0.2)
        self.pinSet(self.port, '0')  #Lock
        print "Voltage set to %f to attempt relock." % self.setVoltage
        return

    #Changes from lock to dither and other way around
    def _switch_Lock_fired(self):
        if self.pinMode == '0':
            self.pinMode = '1'
            self.pinSet(self.port, self.pinMode)
        else:
            self.pinMode = '0'
            self.pinSet(self.port, self.pinMode)

#Gui Stuff#

    DCgroup = traitsui.VGroup(
        traitsui.HGroup(
            traitsui.VGroup(
                traitsui.Item('adcChannel'),
                traitsui.Item('adcVoltage', style='readonly'),
            ),
            traitsui.VGroup(
                traitsui.Item('DCmaxBoundary'),
                traitsui.Item('DCminBoundary'),
                traitsui.Item('DCnoOfSteps'),
            ),
        ),
        #traitsui.Item('switch_Lock'),
        traitsui.HGroup(
            traitsui.VGroup(
                traitsui.Item('DCscan_and_lock'),
                traitsui.Item('DCautolock'),
            ), traitsui.Item('DCconnect')),
        visible_when='relockMode == "Doubling cavity Relock"',
        show_border=True,
    )

    #---- WAVEMETER GUI ----#
    wavemeter = traits.Enum("Humphry", "Ion Cavity")
    wmChannel = traits.Enum(1, 2, 3, 4, 5, 6, 7, 8)
    wmFrequency = traits.Float()
    wmConnected = traits.Bool()
    wmHWI = None
    wmIP = None
    wmPort = None
    wmReLock = traits.Button()
    wmFrequencyLog = np.array([])
    wmMeanFrequency = None
    wmTolerance = 0.0000006  #Frequency tolerance in THz, set to 60 MHz in accordance with wm accuracy
    mistakeCounter = 0
    #wmPolarity = traits.Enum("+", "-")
    wmEmptyMemory = traits.Button()

    #When hitting wmConnected, a connection to the wavemeter and readout is established
    def _wmConnected_changed(self):
        if self.wmConnected == True:
            if self.wavemeter == "Humphry":
                self.wmIP = '192.168.0.111'
                self.wmPort = 6101
            elif self.wavemeter == "Ion Cavity":
                self.wmIP = '192.168.32.2'
                self.wmPort = 6100

            self.wmHWI = PyHWI.DECADSClientConnection('WLM', self.wmIP,
                                                      self.wmPort)
            #frequencyArray = wmHWI.getFrequency(True, self.wmChannel)
            self.start_timer()
        else:
            self.wmFrequency = -999
            self.timer.Stop()  #stops either lock_timer or read_timer.
            print "Timer stopped"

    #GUI stuff
    wmGroup = traitsui.VGroup(traitsui.Item('wmFrequency', style='readonly'),
                              traitsui.Item('wmConnected'),
                              traitsui.Item('wmReLock'),
                              traitsui.HGroup(
                                  traitsui.Item('wavemeter'),
                                  traitsui.Item('wmChannel'),
                                  traitsui.Item('wmEmptyMemory',
                                                show_label=False)),
                              visible_when='relockMode == "Wavemeter Relock"')

    #Resets the memory of the lock (the array which saves the last read frequencies)
    def _wmEmptyMemory_fired(self):
        self.wmFrequencyLog = np.array([])
        print "Memory empty."

#starts readout-only timer

    def start_timer(self):
        print "Timer started"
        self.timer = Timer(1000.0, self.update_wm)

#starts readout-and-lock timer, analogue to the doubling cavity case

    def start_lock_timer(self):
        print "Lock timer started"
        self.timer = Timer(1000.0, self.update_wm_and_lock)

#updates the displayed frequency

    def update_wm(self):
        frequencyArray = self.wmHWI.getFrequency(True, self.wmChannel)
        self.wmFrequency = frequencyArray[1]

#updates frequency and checks if its still near the mean of the last five (hardcoded, see below) measured frequencies. If not, it attempts a relock.

    def update_wm_and_lock(self):
        self.update_wm()
        frequencyArray = self.wmHWI.getFrequency(True, self.wmChannel)
        #print "Updated Frequency"
        #mistakeCounter = 0
        if len(self.wmFrequencyLog
               ) < 5:  #number of Measurements that will be compared
            print "Getting Data for Lock. Do not unlock!"
            self.wmFrequencyLog = np.append(self.wmFrequencyLog,
                                            frequencyArray[1])
        else:
            self.wmMeanFrequency = np.mean(
                self.wmFrequencyLog)  #Mean Frequency to compare to
            if (abs(frequencyArray[1] - self.wmMeanFrequency) <
                    self.wmTolerance):
                self.wmFrequencyLog = np.append(self.wmFrequencyLog,
                                                frequencyArray[1])
                self.wmFrequencyLog = np.delete(
                    self.wmFrequencyLog, 0)  #keep Array at constant length
                print "Still locked."
                if self.mistakeCounter > 0:
                    self.mistakeCounter = 0
            else:
                self.mistakeCounter += 1
                if self.mistakeCounter > 5:  #number of measurements that still count as locked, though the frequency is not within boundaries
                    self.timer.stop()
                    self.start_timer()  #keep Frequency on display..
                    self.wmRelock(self.wmMeanFrequency)
                else:
                    print self.mistakeCounter

    #Relock procedure.
#For now this scans only one time, with a hardcoded number of steps. It might be worth modifying this to look like the doubling cavity relock procedure.

    def wmRelock(self, wantedFrequency):
        self.pinSet(self.port, '1')
        voltages = np.linspace(self.powerModeMult * self.powerMode,
                               self.powerMode, 10)
        wmRelockTry = 0
        try:
            while (wmRelockTry < 5):  #attempt relock five times
                for entry in voltages:
                    self.setVoltage = entry
                    self._set_fired()
                    time.sleep(1.0)
                    frequencyArray = self.wmHWI.getFrequency(
                        True, self.wmChannel)
                    if (abs(frequencyArray[1] - wantedFrequency) <
                            self.wmTolerance):
                        print "Relock_attempt!"
                        self.pinSet(self.port, '0')
                        self._wmLock_fired()
                        raise GetOutOfLoop  #Opens the function again (inductively). Maybe fix that by going back
                        #to the level above somehow.
                wmRelockTry += 1
                print "Relock try %f not succesful" % wmRelockTry
            print "Was not able to Relock."
        except GetOutOfLoop:
            print "gotOutOfLoop"
            pass

    def _wmReLock_fired(self):
        #self.wmFrequencyLog = np.array([])
        self.mistakeCounter = 0
        if self.wmConnected == True:
            self.timer.Stop(
            )  #Switch from read-only timer to read-and-log timer. If both run at the same time
            self.start_lock_timer()  #we run into timing problems.
        else:
            print "No Wavemeter connected!"

        print "hi"

#---- WAVEMETERLOCK - DE 17092018 GUI ----#

    wavemeter = traits.Enum("Humphry", "Ion Cavity")
    wmChannel = traits.Enum(1, 2, 3, 4, 5, 6, 7, 8)
    wmFrequency = traits.Float()
    wmConnected = traits.Bool()
    wmHWI = None
    wmIP = None
    wmPort = None
    isRunning = traits.Bool(False)
    wmVoltage = 0
    wmLockTimer = traits.Instance(Timer)
    wmLockStart = traits.Button()
    wmLockStop = traits.Button()
    wmFrequencyLog = np.array([])
    wmMeanFrequency = None
    wmTargetFrequency = traits.Float()  #frequency to lock
    wmGain = traits.Float()  #Gain for wavemeterlock
    wmTolerance = 0.0000006  #Frequency tolerance in THz, set to 60 MHz in accordance with wm accuracy
    mistakeCounter = 0
    #wmPolarity = traits.Enum("+", "-")
    wmEmptyMemory = traits.Button()

    #GUI stuff
    wmlockGroup = traitsui.VGroup(
        traitsui.HGroup(traitsui.Item('wavemeter'), traitsui.Item('wmChannel'),
                        traitsui.Item('wmEmptyMemory', show_label=False)),
        traitsui.Item('wmFrequency', style='readonly'),
        traitsui.Item('wmConnected'),
        traitsui.Item('wmTargetFrequency'),
        traitsui.Item('wmGain'),
        traitsui.HGroup(
            traitsui.Item('wmLockStart', visible_when="isRunning == False"),
            traitsui.Item('wmLockStop', visible_when="isRunning == True")),
        visible_when='relockMode == "Wavemeter Lock"')

    def _wmLockStart_fired(self):
        print "Start: Wavemeterlock"
        self.isRunning = True
        self.wmLockTimer.Start()

    def wmLock2(self):
        # Calculate error in MHz
        error = (self.wmFrequency - self.wmTargetFrequency) * 10**3
        if abs(error) < 5000:
            self.wmVoltage = self.wmVoltage + error * self.wmGain
            if self.wmVoltage > 10:
                self.wmVoltage = 10
            elif self.wmVoltage < -10:
                self.wmVoltage = -10

        cmd = "cmd=" + self.x.generate_voltage(
            self.port, self.powerMode, self.powerModeMult * self.powerMode,
            self.wmVoltage)
        self.connection.sendwithoutcomment(cmd)
        self.bytecode = self.x.generate_voltage(
            self.port, self.powerMode, self.powerModeMult * self.powerMode,
            self.wmVoltage)

        #self.saveToFile( "frequency_data.csv" )

    def _wmLockStop_fired(self):
        print "Stop: Wavemeterlock"
        self.isRunning = False

        cmd = "cmd=" + self.x.generate_voltage(
            self.port, self.powerMode, self.powerModeMult * self.powerMode,
            0)  #Spannung wieder auf 0
        self.connection.sendwithoutcomment(cmd)
        self.bytecode = self.x.generate_voltage(
            self.port, self.powerMode, self.powerModeMult * self.powerMode, 0)
        self.wmVoltage = 0

        self.wmLockTimer.Stop()

    def saveToFile(self, fileName):

        f = open(fileName, "a")

        f.write("%f \n" % self.wmFrequency)

        f.close()


#---- PUT TOGETHER CHANNEL ----#

    selectionGroup = traitsui.HGroup(traitsui.Item('relockMode'),
                                     #traitsui.Item('set_Relock'),
                                     )

    channelGroup = traitsui.VGroup(
        selectionGroup,
        powerGroup,
        wmGroup,
        wmlockGroup,
        DCgroup,
        manualGroup,
    )

    traits_view = traitsui.View(channelGroup)