class DSCUSBUILog(DSCUSBUI): """Same as :class:`.DSCUSBUI` except that it adds a logger facility. It defines an :attr:`~.DSCUSBUILog.data` that hold the measured data. Examples -------- For a display with a logger ... >>> dsc = DSCUSBUILog() >>> ok = dsc.configure_traits() %(skip)s """ #: this holds the measured data data = Instance(StructArrayData, ()) log_timer = Any _data = [] #: set to False to stop writing to :attr:`~.DSCUSBUILog.data` do_log = Bool(True, desc='whether logging is activated or not') view = dscusbui_log_view def _data_default(self): return StructArrayData(width=420, height=230, dtype=[('time', 'float'), ('force', 'float'), ('temperature', 'float')]) def _timer_function(self): value_temp = super(DSCUSBUILog, self)._timer_function() if self.do_log and value_temp is not None: value, temp = value_temp self._data.append((time.time(), value, temp)) def _log_timer_function(self): if len(self._data) != 0: data, self._data = self._data, [] self.data.append(data) def start_readout(self, interval=1.): """Starts readout process. GUI must be running for this to work... """ super(DSCUSBUILog, self).start_readout(interval) try: self.log_timer.Start(1000) except AttributeError: #self._timer_function() self.log_timer = Timer(1000, self._log_timer_function) def stop_readout(self): """Stops readout process """ super(DSCUSBUILog, self).stop_readout() self.log_timer.Stop()
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
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)
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()
class Application(HasStrictTraits): """ Main GUI application which allows user to set global, Openfoam and Liggghts parameters of the computation and visualize it with Mayavi """ #: The global settings for the calculation global_settings = Instance(GlobalParametersModel) #: The Liggghts settings for the calculation liggghts_settings = Instance(LiggghtsModel) #: The Openfoam settings for the calculation openfoam_settings = Instance(OpenfoamModel) # The mayavi sources, associated to the following datasets: # first element is the openfoam mesh, second and third are # the flow and walls particles, respectively. # It is an invariant. The cuds gets changed as we select different # frames. sources = Tuple(Instance(CUDSSource), Instance(CUDSSource), Instance(CUDSSource)) # All the frames resulting from the execution of our computation. frames = List(Tuple(VTKMesh, VTKParticles, VTKParticles)) # The frame to visualize current_frame_index = Int() # The physical current frame, for practicality _current_frame = Either( None, Tuple(VTKMesh, VTKParticles, VTKParticles) ) #: The button on which the user will click to run the # calculation run_button = Button("Run") first_button = Button("First") previous_button = Button("Previous") play_stop_button = Button() play_stop_label = Str("Play") next_button = Button("Next") last_button = Button("Last") save_button = Button("Save...") play_timer = Instance(Timer) #: The pop up dialog which will show the status of the # calculation progress_dialog = Instance(ProgressDialog) #: Boolean representing if the application should allow # operations or not interactive = Bool(True) #: The Mayavi traits model which contains the scene and engine mlab_model = Instance(MlabSceneModel, ()) #: Event object which will be useful for error dialog calculation_error_event = Event(Str) #: True if the calculation can be safely run, False otherwise valid = Bool(False) #: Dictionary of the namespace associated to the shell editor shell = Dict() # Private traits. #: Executor for the threaded action. _executor = Instance(futures.ThreadPoolExecutor) # Lock to synchronize the execution loop and the storage of the Datasets # from application specific cuds to VTK Datasets. We need to do so because # the computational engine can change the datasets, so we need to hold # the computational engine until we are done "copying and storing" each # frame _event_lock = Instance(threading.Event, ()) traits_view = View( HSplit( VSplit( VGroup( Tabbed( UItem('global_settings', style='custom'), UItem('liggghts_settings', style='custom'), UItem('openfoam_settings', label='OpenFOAM settings', style="custom"), ), UItem( name='run_button', enabled_when='valid' ), enabled_when='interactive', ), UItem('shell', editor=ShellEditor()) ), VGroup( UItem( name='mlab_model', editor=SceneEditor(scene_class=MayaviScene) ), HGroup( UItem( name="first_button", enabled_when=( "current_frame_index > 0 and play_timer is None"), ), UItem( name="previous_button", enabled_when=( "current_frame_index > 0 and play_timer is None"), ), UItem( name="play_stop_button", editor=ButtonEditor(label_value="play_stop_label") ), UItem( name="next_button", enabled_when=( "current_frame_index < len(frames) " "and play_timer is None"), ), UItem( name="last_button", enabled_when=( "current_frame_index < len(frames) " "and play_timer is None"), ), Item(name="current_frame_index", style="readonly"), UItem(name="save_button"), enabled_when=( 'interactive and len(frames) > 0') ) ), ), title='Simphony UI', resizable=True, width=1.0, height=1.0 ) @on_trait_change('calculation_error_event', dispatch='ui') def show_error(self, error_message): error( None, 'Oups ! Something went bad...\n\n{}'.format(error_message), 'Error' ) @on_trait_change('openfoam_settings:valid,' 'liggghts_settings:valid') def update_valid(self): self.valid = (self.openfoam_settings.valid and self.liggghts_settings.valid) @on_trait_change('run_button') def run_calc(self): """ Function which will start the calculation on a secondary thread on run button click Raises ------ RuntimeError If the calculation is already running """ if not self.interactive: raise RuntimeError('Unable to start calculation. Another ' 'operation is already in progress') self.frames = [] self.interactive = False self.progress_dialog.title = 'Calculation running...' self.progress_dialog.open() future = self._executor.submit(self._run_calc_threaded) future.add_done_callback(self._calculation_done) def _add_sources_to_scene(self): """Add the sources to the main scene.""" mayavi_engine = self.mlab_model.engine mayavi_engine.add_source(self.sources[0]) mayavi_engine.add_module(Surface()) self._add_liggghts_source_to_scene(self.sources[1]) self._add_liggghts_source_to_scene(self.sources[2]) def _add_liggghts_source_to_scene(self, source): """ Function which add to liggghts source to the Mayavi scene Parameters ---------- source : The mayavi source linked to the dataset """ mayavi_engine = self.mlab_model.engine # Create Sphere glyph sphere_glyph_module = Glyph() # Add Liggghts sources mayavi_engine.add_source(source) try: source.point_vectors_name = 'VELOCITY' except TraitError: # The data is not available in the dataset for some reason. # Add the modules anyway, but don't select it. pass # Add sphere glyph module mayavi_engine.add_module(sphere_glyph_module) sphere_glyph_module.glyph.glyph_source.glyph_source = SphereSource() sphere_glyph_module.glyph.scale_mode = 'scale_by_scalar' sphere_glyph_module.glyph.glyph.range = [0.0, 1.0] sphere_glyph_module.glyph.glyph_source.glyph_source.radius = 1.0 # Velocities are in meter/second, this scale factor makes # 1 graphical unit = 1 millimeter/sec arrow_scale_factor = 1.0 arrow_glyph_module = Glyph() mayavi_engine.add_module(arrow_glyph_module) arrow_glyph_module.glyph.scale_mode = 'scale_by_vector' arrow_glyph_module.glyph.color_mode = 'color_by_vector' arrow_glyph_module.glyph.glyph.range = [0.0, 1.0] arrow_glyph_module.glyph.glyph.scale_factor = arrow_scale_factor def _remove_sources_from_scene(self): for source in self.sources: try: self.mlab_model.mayavi_scene.remove_child(source) except ValueError: pass def _run_calc_threaded(self): """ Function which will run the calculation. This function is only run by the secondary thread """ try: return run_calc( self.global_settings, self.openfoam_settings, self.liggghts_settings, self.progress_callback, self._event_lock ) except Exception: self.calculation_error_event = traceback.format_exc() log.exception('Error during the calculation') return None def _calculation_done(self, future): """ Function which will return the result of the computation to the main thread Parameters ---------- future Object containing the result of the calculation """ GUI.invoke_later(self._computation_done, future.result()) def _computation_done(self, datasets): self.progress_dialog.update(100) if datasets is not None: self._append_frame(datasets) self._to_last_frame() self.interactive = True def _append_frame(self, datasets): self.frames.append( ( VTKMesh.from_mesh(datasets[0]), VTKParticles.from_particles(datasets[1]), VTKParticles.from_particles(datasets[2]) ) ) @on_trait_change("current_frame_index,frames[]") def _sync_current_frame(self): """Synchronizes the current frame with the index and the available frames.""" try: self._current_frame = self.frames[self.current_frame_index] except IndexError: self._current_frame = None @on_trait_change("_current_frame") def _update_sources_with_current_frame(self, object, name, old, new): """Called when the current frame is changed, updates the sources with the new data. Parameters are from traits interface.""" scene = self.mlab_model.mayavi_scene scene.scene.disable_render = True if new is None: self._remove_sources_from_scene() else: self._remove_sources_from_scene() for i in xrange(len(self._current_frame)): self.sources[i].cuds = self._current_frame[i] self._add_sources_to_scene() scene.scene.disable_render = False def progress_callback(self, datasets, current_iteration, total_iterations): """ Function called in the secondary thread. It will transfer the progress status of the calculation to the main thread Parameters ---------- progress The progress of the calculation (Integer in the range [0, 100]) """ progress = current_iteration/total_iterations*100 GUI.invoke_later(self._append_frame_and_continue, datasets) GUI.invoke_later(self.progress_dialog.update, progress) def _append_frame_and_continue(self, datasets): self._append_frame(datasets) self._event_lock.set() self.current_frame_index = len(self.frames) - 1 def reset(self): """ Function which reset the Mayavi scene. """ # Clear scene self._remove_sources_from_scene() @on_trait_change('first_button') def _to_first_frame(self): """Goes to the first frame""" self.current_frame_index = 0 @on_trait_change('last_button') def _to_last_frame(self): """Goes to the last frame""" self.current_frame_index = len(self.frames) - 1 @on_trait_change('previous_button') def _to_prev_frame(self): """Goes to the previous frame""" frame = self.current_frame_index - 1 if frame < 0: frame = 0 self.current_frame_index = frame @on_trait_change('next_button') def _to_next_frame(self): """Goes to the next frame""" frame = self.current_frame_index + 1 if frame >= len(self.frames): frame = len(self.frames) - 1 self.current_frame_index = frame @on_trait_change('play_stop_button') def _start_stop_video(self): """Starts the video playing""" if self.play_timer is None: self.play_timer = Timer(500, self._next_frame_looped) else: self.play_timer.Stop() self.play_timer = None @on_trait_change("save_button") def _save_images(self): """Saves the current frames in individual images.""" dialog = DirectoryDialog() if dialog.open() != OK: return self.progress_dialog.title = 'Saving images...' self.progress_dialog.open() dirpath = dialog.path self.interactive = False try: for frame_index in xrange(len(self.frames)): self.current_frame_index = frame_index mlab.savefig(os.path.join( dirpath, "frame-{}.png".format(frame_index) )) progress = 100*frame_index/len(self.frames) self.progress_dialog.update(progress) self.progress_dialog.update(100) except Exception: self.calculation_error_event = traceback.format_exc() log.exception('Error while saving') finally: self.interactive = True @on_trait_change('play_timer') def _change_play_button_label(self): """Changes the label from play to stop and vice-versa""" self.play_stop_label = "Stop" if self.play_timer else "Start" def _next_frame_looped(self): """Goes to the next frame, but loop back to the first when over.""" if len(self.frames) == 0: self.current_frame_index = 0 self.current_frame_index = ( self.current_frame_index + 1 ) % len(self.frames) def __executor_default(self): return futures.ThreadPoolExecutor(max_workers=1) def _progress_dialog_default(self): return ProgressDialog( min=0, max=100, ) def _sources_default(self): return CUDSSource(), CUDSSource(), CUDSSource() def _global_settings_default(self): return GlobalParametersModel() def _liggghts_settings_default(self): return LiggghtsModel() def _openfoam_settings_default(self): return OpenfoamModel()
class BaseSimpleInstrumentUI(HasTraits): """This class serves as a base class for all custom instrument devices. It provides a basic interface with buttons and actions defined. When subclassing you need to define actions for the io_button and settings_button events and make sure that _initialized, _LED, _status_message attributes are in control. You also need to define the report method, which is responsible for a continuous device operation checking, like checking for status, motor positions.. etc. """ #: logger from the logging module. logger = Any _initialized = Bool(False) _LED = Int(desc='device IO status') _status_message = Str(desc='status message') @property def initialized(self): """A bool that determines if the device is active or not""" return self._initialized @property def LED(self): """Determines device LED indicator status, an int of values 0(off),1(on),2(busy),-1(error)""" return self._LED @property def status_message(self): """"Returns device status message""" return self._status_message def _logger_default(self): return logger @display_exception('Could not initialize.') def _init_button_fired(self): if self.initialized: self.stop_timer() self.close() else: self.init() self.start_timer() def _io_button_fired(self): information(None, 'IO parameters not defined for this device.') def _settings_button_fired(self): information(None, 'Settings not defined for this device.') def __initialized_changed(self, value): if value == False: self._LED = 0 self._status_message = '' def start_timer(self, interval=TIMER_INTERVAL): """Starts timer process. It updates status of the instrument with the interval specified, collects data, etc, depending on the defined update method """ self.logger.info('Starting readout.') try: self.timer.Start(interval * 1000) except AttributeError: self.timer = Timer(interval * 1000, self._update) def stop_timer(self): """Stops timer process. """ self.logger.info('Stopping readout.') try: self.timer.Stop() except AttributeError: pass def _update(self): self.logger.debug('Update called.') try: self.update() except Exception as e: self.logger.critical('Error in update. ' + e.message) raise e def update(self): """Does the status checking.. etc. """ report = self.report() self.update_status_message(report) self.update_LED(report) def update_status_message(self, report): self._status_message = report.get('status_message', '') def update_LED(self, report): if report.get('error') == True: self._LED = -1 else: self._LED = self._initialized def report(self): """Gives a device report. This function is called by the update methhod """ return {'status_message': 'OK', 'error': False} def init(self, *args, **kw): """Needs to be defined in a subclass. Opens port, initializes.. """ self._initialized = True def close(self): """Needs to be defined in a subclass. """ self._initialized = False
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, )
class RemoteCommandServer(ConfigLoadable): ''' ''' simulation = False _server = None repeater = Instance(CommandRepeater) processor = Instance(CommandProcessor) host = Str(enter_set=True, auto_set=False) port = Int(enter_set=True, auto_set=False) klass = Str loaded_port = None loaded_host = None packets_received = Int packets_sent = Int repeater_fails = Int cur_rpacket = String cur_spacket = String server_button = Event server_label = Property(depends_on='_running') _running = Bool(False) _connected = Bool(False) save = Button _dirty = Bool(False) run_time = Str led = Instance(LED, ()) use_ipc = True def _repeater_default(self): ''' ''' if globalv.use_ipc: c = CommandRepeater(logger_name='{}_repeater'.format(self.name), name=self.name, configuration_dir_name='servers') if c.bootstrap(): return c def _repeater_fails_changed(self, old, new): if new != 0: self.repeater.led.state = 0 def load(self, *args, **kw): ''' ''' config = self.get_configuration() if config: server_class = self.config_get(config, 'General', 'class') if server_class is None: return if server_class == 'IPCServer': path = self.config_get(config, 'General', 'path') if path is None: self.warning('Path not set. use path config value') return addr = path self.host = path if os.path.exists(path): os.remove(path) else: if LOCAL: host = 'localhost' else: host = self.config_get(config, 'General', 'host', optional=True) port = self.config_get(config, 'General', 'port', cast='int') if host is None: host = socket.gethostbyname(socket.gethostname()) if port is None: self.warning('Host or Port not set {}:{}'.format( host, port)) return elif port < 1024: self.warning('Port Numbers < 1024 not allowed') return addr = (host, port) self.host = host self.port = port if port else 0 self.loaded_host = host self.loaded_port = port self.klass = server_class[:3] ds = None if config.has_option('Requests', 'datasize'): ds = config.getint('Requests', 'datasize') ptype = self.config_get(config, 'Requests', 'type', optional=False) if ptype is None: return self.datasize = ds self.processor_type = ptype self._server = self.server_factory(server_class, addr, ptype, ds) # add links for link in self.config_get_options(config, 'Links'): # note links cannot be stopped self._server.add_link(link, self.config_get(config, 'Links', link)) if self._server is not None and self._server.connected: addr = self._server.server_address # saddr = '({})'.format(','.join(addr if isinstance(addr, tuple) else (addr,))) saddr = '({})'.format(addr) msg = '%s - %s' % (server_class, saddr) self.info(msg) self._connected = True return True else: self._connected = False self.warning('Cannot connect to {}'.format(addr)) def server_factory(self, klass, addr, ptype, ds): ''' ''' # from tcp_server import TCPServer # from udp_server import UDPServer module = __import__('pychron.messaging.{}_server'.format( klass[:3].lower()), fromlist=[klass]) factory = getattr(module, klass) # gdict = globals() # if handler in gdict: # handler_klass = gdict[handler] # server = gdict[server_class] if ds is None: ds = 2**10 # return server(self, ptype, ds, addr, handler_klass) return factory(self, ptype, ds, addr) def open(self): ''' ''' self._running = True # t = threading.Thread(target = self._server.serve_forever) t = threading.Thread(target=self.start_server) t.start() return True def start_server(self): SELECT_TIMEOUT = 1 # THREAD_LIMIT = 15 while self._running: try: readySocket = select.select([self._server.socket], [], [], SELECT_TIMEOUT) if readySocket[0]: self._server.handle_request() # if threading.activeCount() < THREAD_LIMIT: # self._server.handle_request() except: pass # self._server.socket.close() def shutdown(self): ''' ''' self._connected = False if self._server is not None: # self._server.shutdown() self._server.socket.close() self._running = False def traits_view(self): ''' ''' cparams = VGroup( HGroup( Item('led', show_label=False, editor=LEDEditor()), Item('server_button', show_label=False, editor=ButtonEditor(label_value='server_label'), enabled_when='_connected'), ), Item('host', visible_when='not _running'), Item('port', visible_when='not _running'), show_border=True, label='Connection', ) stats = Group(Item('packets_received', style='readonly'), Item('cur_rpacket', label='Received', style='readonly'), Item('packets_sent', style='readonly'), Item('cur_spacket', label='Sent', style='readonly'), Item('repeater_fails', style='readonly'), Item('run_time', style='readonly'), show_border=True, label='Statistics', visible_when='_connected') buttons = HGroup(Item('save', show_label=False, enabled_when='_dirty')) v = View( VGroup(cparams, stats, buttons), handler=RCSHandler, ) return v def _run_time_update(self): ''' ''' # t = datetime.datetime.now() - self.start_time # h = t.seconds / 3600 # m = (t.seconds % 3600) / 60 # s = (t.seconds % 3600) % 60 t, h, m, s = diff_timestamp(datetime.datetime.now(), self.start_time) rt = '{:02n}:{:02n}:{:02n}'.format(h, m, s) if t.days: rt = '{} {:02n}:{:02n}:{:02n}'.format(t.days, h, m, s) self.run_time = rt def __running_changed(self): ''' ''' if self._running: self.start_time = datetime.datetime.now() self.timer = Timer(1000, self._run_time_update) else: self.timer.Stop() def _anytrait_changed(self, name, value): ''' ''' if name in ['host', 'port']: attr = 'loaded_{}'.format(name) a = getattr(self, attr) if value != a and a is not None: self._dirty = True def _save_fired(self): ''' ''' self.shutdown() config = self.get_configuration() for attr in ['host', 'port']: a = getattr(self, attr) setattr(self, 'loaded_{}'.format(attr), a) config.set('General', attr, a) self.write_configuration(config) self.load() self._dirty = False def _server_button_fired(self): ''' ''' if self._running: self.shutdown() else: # reset the stats self.packets_received = 0 self.packets_sent = 0 self.cur_rpacket = '' self.cur_spacket = '' self.repeater_fails = 0 # self._server = self.server_factory('TCPServer', # (self.host, self.port), # self.handler, # self.processor_type, # self.datasize # ) # self.open() self.bootstrap() def _get_server_label(self): ''' ''' return 'Start' if not self._running else 'Stop'
class Progress(HasTraits): """Use this for progress tracking, estimating time to complete and to obtain progress messages. Examples -------- >>> p = Progress() >>> p.start(9) #9 tasks to finish, timer is started >>> p.percentage 0 >>> p.task_add() # 10 tasks to finish >>> p.task_done() # 9 tasks to finish >>> p.tasks_all #10 tasks in total 10 >>> p.tasks_done #one completed 1 >>> p.percentage 10 >>> p.stop() #0 tasks to finish, timer is stopped >>> p.percentage 100 >>> p.task_add() # 1 task to finish, timer is started """ #: integer describing how many tasks have completed in percentage percentage = Property(Int, depends_on='tasks_done,tasks_all') #: descirbes how many tasks have completed. This string is empty when all tasks done message = Property(Str, depends_on='percentage') #: specifies time when start is called start_time = Float() # specifies current time. This gets updated every second by the timer current_time = Float #: specifies total run time (a timedelta) run_time = Property(depends_on='current_time,start_time') #: specifies total run time (a timedelta) run_time_str = Property(depends_on='run_time') #: estimated time to complete (a timedelta) estimated_time = Property(depends_on='start_time,percentage,run_time') #: estimated time string to complete estimated_time_str = Property(Str, depends_on='estimated_time') #: number of all tasks to complete tasks_all = Range(low=0, value=0) #: number of completed tasks tasks_done = Range(low=0, value=0) #: calculated speed of task completion... needed for estimating time to complete speed = Property(depends_on='percentage') #: a timer that updates current time, should have a pyface Timer interface timer = Any def start(self, tasks): """This can be called to start timer and to define unfinished tasks """ self.tasks_all = tasks self.start_time = time.time() try: self.timer.Start(1000) except AttributeError: self.timer = Timer(1000, self._timer_task) def task_done(self): """This must be called when task is finished """ self.tasks_done += 1 if self.percentage == 100: self.stop() def task_add(self): """This can be called either after start function to add a task It can be called without calling start first. """ if self.tasks_all == 0: self.start(1) else: self.tasks_all += 1 def stop(self): """This clears progress and puts everything to initial state """ try: self.timer.Stop() except AttributeError: pass self.tasks_done = 0 self.tasks_all = 0 def _timer_task(self): self.current_time = time.time() @cached_property def _get_run_time(self): return datetime.timedelta( seconds=max(self.current_time - self.start_time, 0)) @cached_property def _get_percentage(self): try: return min(int((100. * self.tasks_done) / self.tasks_all), 100) except ZeroDivisionError: return 100 @cached_property def _get_speed(self): try: return 1.0 * self.percentage / (self.run_time.seconds) except ZeroDivisionError: return 0. @cached_property def _get_message(self): if self.percentage == 100: return '' else: return 'In progress ... %d%% completed.' % self.percentage @cached_property def _get_estimated_time(self): if self.percentage == 100: return else: try: return datetime.timedelta(seconds=int(100. / self.speed - self.run_time.seconds)) except ZeroDivisionError: return @cached_property def _get_estimated_time_str(self): if self.estimated_time: return 'Estimated time: %s' % self.estimated_time else: return '' @cached_property def _get_run_time_str(self): return 'Total time: %s' % self.run_time def __del__(self): self.stop()
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)
class DSCUSBUI(DSCUSB, HasTraits): """An enhanced version of :class:`~.dscusb.DSCUSB`. It defines a traits based user interface. For function definition see :class:`~.dscusb.DSCUSB` .. note:: HasTraits define set and get functions, so these are overridden by DSCUSB's set and get functions. Examples -------- For simple DSCUSB redout display do: >>> dsc = DSCUSBUI() >>> dsc.configure_traits() # doctest: +SKIP %s """ #: DSCUSB settable parameters are defined in this class settings = Instance(DSCUSBSettings, ()) #: station number STN = Range(0, 999, 1, desc='station number') #: serialUI instance serial = Instance(SerialUI, (), transient=True) _initialized = Bool(False, desc='device status') #: a string representing serial number of the device serial_number = Str(' Unknown ', desc='device serial number') #: a stringe representing firmware version of the device firmware_version = Str(' -.-- ', desc='firmware version') #: here the measured data is written for display output = Str(desc='measured output') #: here the measured temperature is written for display temp = Str('', desc='measured temperature') #: defines output mode SYS: Force [mN], MVV: Strain [mV/V], CELL: Cell output output_mode = Trait('Force [mN]', { 'Force [mN]': 'SYS', 'Strain [mV/V]': 'MVV', 'Cell output': 'CELL' }, desc='different output modes. ') #: STAT flag is written here, for status messages stat = Int(desc='STAT flags.') #: status messages are written here status_message = Str #: a bool that determines if there is a problem with output data output_alarm = Bool(False) #: a bool that determines if there is a problem with temperature temp_alarm = Bool(False) timer = Any #: interval for data readout interval = Range(low=READOUT_INTERVAL_MIN, high=READOUT_INTERVAL_MAX, value=READOUT_INTERVAL, desc='data acquisition interval') timer_fast = Any readout = List([]) offset = Float(desc='force measurement offset') port_button = Button('Port', desc='port settings') settings_button = Button('Settings', desc='settings') init_button = Button('On/Off', desc='initialize action') set_offset_button = Button('Set', desc='set offset action') # zero_button = Button('Set zero', desc = 'set force to zero') view = dscusbui_view def _serial_default(self): return DSCSerial(timeout=0.06, baudrate=BAUDRATE_DEFAULT) def __initialized_changed(self, value): if value == True: self.serial_number, self.firmware_version = self.get_info() self._stat_changed(self.stat) #update message self.start_readout(self.interval) else: self.stop_readout() self._reset_output_data() self.status_message = '' def _interval_changed(self, value): if self._initialized: self.stop_readout() self.start_readout(value) def _timer_function(self): try: self.stat = self.get_stat() if self.readout != []: value, self.readout = np.median(self.readout), [] self.output = '%.4f' % value temp = self.get_temp() self.temp = '%.2f' % temp return value, temp except: self.close() raise def _timer_fast_function(self): try: value = self.get(self.output_mode_) if self.output_mode_ == 'SYS': value -= self.offset self.readout.append(value) except: self.close() raise def start_readout(self, interval=1.): """Starts readout process. GUI must be running for this to work... """ try: self.timer.Start(interval * 1000) self.timer_fast.Start(self._interval_min * 1000) except AttributeError: #self._timer_function() self.timer = Timer(interval * 1000, self._timer_function) self.timer_fast = Timer(self._interval_min * 1000, self._timer_fast_function) def stop_readout(self): """Stops readout process """ self.timer.Stop() self.timer_fast.Stop() def _reset_output_data(self): self.status_message = '' self.output = '' self.temp = '' self.serial_number, self.firmware_version = ('Unknown', '-.--') def _stat_changed(self, stat): stat = stat_to_dict(stat) self.output_alarm = stat['ECOMUR'] or stat['ECOMOR'] or \ stat['SYSUR'] or stat['SYSOR'] or \ stat['CRAWUR'] or stat['CRAWOR'] or \ stat['SCALON'] or stat['LCINTEG'] self.temp_alarm = stat['TEMPUR'] or stat['TEMPOR'] self.status_message = get_status_message(stat) @display_on_exception(logger, 'Could not initialize') def _init_button_fired(self): if self._initialized: self.close() else: self.init() @display_on_exception(logger, 'Could not change settings') def _settings_button_fired(self): self.stop_readout() d = self.settings.get() d.pop('_poweruser') for key in d: value = self.get(key) setattr(self.settings, key, value) d[key] = getattr(self.settings, key) self.settings.edit_traits(kind='modal') reset = False STN = self.STN for key in d: value = getattr(self.settings, key) if d[key] != value: if key == 'BAUD': self.set_baudrate(BAUDRATES[baudrate]) else: self.set(key, value) if key in RESET_SETTINGS: reset = True if key == 'STN': if STN != value: STN = value if reset == True: self._initialized = False self.reset() self.STN = STN self.start_readout(self.interval) @display_on_exception(logger, 'Could not change port settings') def _port_button_fired(self): self.close() self.serial.edit_traits(kind='livemodal') @display_on_exception(logger, 'Could not change offset') def _set_offset_button_fired(self): self.calibrate()
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