class DummyMonitor(BaseMonitor): """Dummy monitor used for testing. """ running = Bool() monitored_entries = set_default(['default_path']) received_news = List() def start(self): self.running = True def stop(self): self.running = False def refresh_monitored_entries(self, entries=None): """Do nothing when refreshing. """ pass def handle_database_entries_change(self, news): """Add all entries to the monitored ones. """ if news[0] == 'added': self.monitored_entries = self.monitored_entries + [news[1]] def handle_database_nodes_change(self, news): """Simply ignore nodes updates. """ pass def process_news(self, news): self.received_news.append(news)
class Toast(ToolkitObject): """ A toast is a view containing a quick little message for the user. """ #: Text to display #: if this node has a child view this is ignored text = d_(Unicode()) #: Duration to display in ms duration = d_(Int(1000)) #: x position x = d_(Int()) #: y position y = d_(Int()) #: Position gravity = d_(Coerced(int, coercer=coerce_gravity)) #: Show the notification for the given duration show = d_(Bool()) #: A reference to the proxy object. proxy = Typed(ProxyToast) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe('text', 'duration', 'show', 'gravity', 'x', 'y') def _update_proxy(self, change): """ An observer which sends the state change to the proxy. """ # The superclass implementation is sufficient. super(Toast, self)._update_proxy(change)
class StreamInterpolator(Atom): filespec = Typed(StreamFileSpec) is_reference = Bool(False) selector = Enum(*RECORD_SELECTORS) latency = Float(0.0) streamfile = Typed(StreamFile) @property def fieldname(self): return self.filespec.fieldname @property def datatype(self): return self.filespec.datatype @property def is_array(self): return self.filespec.is_array @property def timestamps(self): return self.streamfile.timestamps @property def interval(self): return self.streamfile.interval @property def record_count(self): return self.streamfile.count def _default_streamfile(self): return self.filespec.getStreamFile() def get(self, idx, dts): return self.streamfile.get(idx, dts - self.latency, self.selector)
class HttpResponse(Atom): """ The response object returned to an AsyncHttpClient fetch callback. It is based on the the tornado HttpResponse object. """ #: Request that created this response request = Instance(HttpRequest) #: Numeric HTTP status code code = Int() #: Reason phrase for the status code reason = Unicode() #: Response headers list of strings headers = Dict() #: Result success ok = Bool() #: Response body #: Note: if a streaming_callback is given to the request #: then this is NOT used and will be empty body = Unicode() #: Size content_length = Int() #: Error message error = Instance(HttpError) #: Progress progress = Int() #: Done time request_time = Float()
class Markdown(Raw): """ A block for rendering Markdown source. """ #: Extensions to use when rendering extensions = d_( List(default=[ "markdown.extensions.codehilite", "markdown.extensions.fenced_code", "markdown.extensions.tables", ])).tag(attr=False) #: Configuration for them extension_configs = d_( Dict(default={ 'markdown.extensions.codehilite': { 'css_class': 'highlight' }, })).tag(attr=False) #: Disallow raw HTMl safe_mode = d_(Bool()).tag(attr=False) #: Output format output_format = d_(Enum("xhtml", "html5")).tag(attr=False) #: Tab size tab_length = d_(Int(4)).tag(attr=False) #: Reference to the proxy proxy = Typed(ProxyMarkdown) @observe('extensions', 'extension_configs', 'safe_mode', 'output_format', 'tab_length') def _update_proxy(self, change): """ The superclass implementation is sufficient. """ super(Markdown, self)._update_proxy(change)
class Person(Atom): """A simple class representing a person object.""" last_name = Str() first_name = Str() age = Range(low=0) dob = Value(datetime.date(1970, 1, 1)) debug = Bool(False) @observe("age") def debug_print(self, change): """Prints out a debug message whenever the person's age changes.""" if self.debug: templ = "{first} {last} is {age} years old." s = templ.format( first=self.first_name, last=self.last_name, age=self.age, ) print(s)
class DropFirstMeasurementsFilter(Analysis): """This analysis allows the user to drop the first N measurements in an iteration, to ensure that all measurements are done at equivalent conditions .""" version = '2014.06.12' enable = Bool() filter_level = Int() N = Int() def __init__(self, name, experiment, description=''): super(DropFirstMeasurementsFilter, self).__init__(name, experiment, description) self.properties += ['version', 'enable', 'filter_level', 'N'] def analyzeMeasurement(self, measurementResults, iterationResults, experimentResults): if self.enable: i = measurementResults.attrs['measurement'] if i < self.N: # User chooses whether or not to delete data. # max takes care of ComboBox returning -1 for no selection logger.info('dropping measurement {} of {}'.format(i, self.N)) return max(0, self.filter_level)
class AnalysisWithFigure(Analysis): # matplotlib figures figure = Typed(Figure) backFigure = Typed(Figure) figure1 = Typed(Figure) figure2 = Typed(Figure) draw_fig = Bool(False) # do not draw the figure unless told to def __init__(self, name, experiment, description=''): super(AnalysisWithFigure, self).__init__(name, experiment, description) #set up the matplotlib figures self.figure1 = Figure() self.figure2 = Figure() self.backFigure = self.figure2 self.figure = self.figure1 self.properties += ['draw_fig'] def swapFigures(self): temp = self.backFigure self.backFigure = self.figure self.figure = temp def updateFigure(self): # signal the GUI to redraw figure try: deferred_call(self.swapFigures) except RuntimeError: # application not started yet self.swapFigures() def blankFigure(self): fig = self.backFigure fig.clf() self.updateFigure()
class TabLayout(LayoutNode): """ A layout object for defining tabbed dock layouts. """ #: The position of the tabs in the tab layout. tab_position = Enum('top', 'bottom', 'left', 'right') #: The index of the currently selected tab. index = Int(0) #: Whether or not the tab layout is maximized. maximized = Bool(False) #: The list of item layouts to include in the tab layout. items = List(Coerced(ItemLayout)) def __init__(self, *items, **kwargs): super(TabLayout, self).__init__(items=list(items), **kwargs) def children(self): """ Get the list of children of the tab layout. """ return self.items[:]
class GPIB_tester(GPIB_Instrument): """A useful GPIB tester for random instruments. Input command strings in command and receive strings in response""" #def __init__(self, **kwargs): # super(GPIB_tester, self).__init__(**kwargs) @private_property def main_params(self): return ['output', 'voltage', 'V_range', 'current_limit', 'mode', 'header', 'overload'] def postboot(self): sleep(self.resp_delay) self.synchronize() def _default_resp_delay(self): return 0.05 identify = Unicode().tag(sub=True, get_str="OS", do=True, read_only=True, no_spacer=True) output=Enum("Off", "On").tag(mapping={'Off':0, 'On':1}, set_str="O{output} E", get_cmd=get_status) V_range=Enum('10 mV', '100 mV', '1 V', '10 V', '30 V').tag(mapping={'30 V' : 6, '10 V' : 5, '1 V' : 4, '100 mV' : 3, '10 mV' : 2}, set_str='R{V_range} E', get_cmd=get_voltage) def _default_V_range(self): return '10 V' voltage=Float(0.0).tag(unit2='V', get_cmd=get_voltage, set_cmd=ramp, log=False) sleep_time=Float(0.1).tag(sub=True, unit2=" s", label="Step Time", low=0.0, high=0.5) ramp_steps=Int(100).tag(sub=True, label="Ramp Steps", read_only=True) ramp_rate=Float(0.03).tag(desc='voltage ramp rate per second', sub=True, low=0.0, high=1.0) ramp_time_left=Float(0.0).tag(desc='estimated time before voltage ramp is complete', sub=True, read_only=True, log=False) header=Enum('On', "Off").tag(mapping={'Off':0, 'On':1}, set_str="H{header}", get_cmd=get_voltage) overload=Bool(False).tag(read_only=True, get_cmd=get_voltage) mode=Enum('Voltage').tag(mapping={'Voltage' : 'V'}, get_cmd=get_voltage) current_limit=Int(120).tag(low=5, high=120, desc='current limit in mA', set_str='LA{current_limit}')
class SetRFPowerTask(InterfaceableTaskMixin, InstrumentTask): """Set the power of the signal delivered by the source. """ # Target power (dynamically evaluated) power = Unicode().tag(pref=True, feval=LOOP_REAL) # Whether to start the source if its output is off. auto_start = Bool(False).tag(pref=True) database_entries = set_default({'power': -10}) def i_perform(self, power=None): """ """ if self.auto_start: self.driver.output = 'On' if power is None: power = self.format_and_eval_string(self.power) self.driver.power = power self.write_in_database('power', power)
class SwipeRefreshLayout(ViewGroup): """ SwipeRefreshLayout is a view group that displays child views in relative positions. """ #: Enabled enabled = d_(Bool(True)) #: Must be a indicator_color = d_(Unicode()) #: Must be a indicator_background_color = d_(Unicode()) #: Set the distance to trigger a sync in dips trigger_distance = d_(Int()) #: Triggered when the user swipes refreshed = d_(Event()) #: A reference to the proxy object. proxy = Typed(ProxySwipeRefreshLayout) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe('enabled', 'indicator_color', 'indicator_background_color', 'trigger_distance', 'refeshed') def _update_proxy(self, change): """ An observer which sends the state change to the proxy. """ if change['type'] == 'event': self.proxy.set_refreshed(True) else: super(SwipeRefreshLayout, self)._update_proxy(change)
class RepeatedTimer(Atom): """ """ interval = Float() function = Callable() args = Tuple() kwargs = Dict() is_running = Bool() _timer = Typed(Thread) # the Timer class is not supposed to be accessed to def __init__(self, interval, function, *args, **kwargs): super(RepeatedTimer, self).__init__() self.interval = interval self.function = function self.args = args self.kwargs = kwargs self.start() #---- Public API ---------------------------------------------------------- def start(self): if not self.is_running: self._timer = Timer(self.interval, self._run) self._timer.start() self.is_running = True def cancel(self): self._timer.cancel() self.is_running = False #---- Private API --------------------------------------------------------- def _run(self): self.is_running = False self.start() self.function(*self.args, **self.kwargs)
class RatingBar(ProgressBar): """ A simple control for displaying read-only text. """ #: Whether this rating bar should only be an indicator #: (thus non-changeable by the user). is_indicator = d_(Bool()) #: The number of stars set (via setNumStars(int) or in an XML layout) #: will be shown when the layout width is set to wrap content #: (if another layout width is set, the results may be unpredictable). layout_width = set_default('wrap_content') #: Sets the number of stars to show. num_stars = d_(Int()) #: Sets the rating (the number of stars filled). rating = d_(Float(strict=False)) #: Sets the step size (granularity) of this rating bar. step_size = d_(Float(strict=False)) #: A reference to the RatingBar object. proxy = Typed(ProxyRatingBar) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe('is_indicator', 'num_stars', 'rating', 'step_size') def _update_proxy(self, change): """ An observer which sends the state change to the proxy. """ # The superclass implementation is sufficient. super(RatingBar, self)._update_proxy(change)
class TreeView(AbstractItemView): #: Proxy widget proxy = Typed(ProxyTreeView) #: Show root node show_root = d_(Bool(True)) @observe("show_root") def _update_proxy(self, change): """An observer which sends state change to the proxy.""" # The superclass handler implementation is sufficient. super(TreeView, self)._update_proxy(change) def child_added(self, child): super(TreeView, self).child_added(child) self._update_rows() def child_removed(self, child): super(TreeView, self).child_removed(child) self._update_rows() def _update_rows(self): for r, item in enumerate(self._items): item.row = r
class SeekBar(ProgressBar): """ A simple control for displaying read-only text. """ #: Sets the amount of progress changed via the arrow keys. key_progress_increment = d_(Int()) #: Specifies whether the track should be split by the thumb. split_track = d_(Bool()) #: A reference to the SeekBar object. proxy = Typed(ProxySeekBar) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe('key_progress_increment', 'split_track') def _update_proxy(self, change): """ An observer which sends the state change to the proxy. """ # The superclass implementation is sufficient. super(SeekBar, self)._update_proxy(change)
class PlotElement(Atom): """Element of plot interacting with the backend through a proxy.""" #: Name of the backend to use backend_name = Str() #: Backend specific proxy proxy = Typed(PlotElementProxy) #: Control the visibility of the element. visibility = Bool(True) def initialize(self, resolver): """Initialize the element by creating the proxy.""" proxy = resolver.resolve_proxy(self) proxy.activate() self.observe("visibility", update_proxy) def finalize(self): """Finalize the element by destroying the proxy.""" self.unobserve("visibility", update_proxy) self.proxy.deactivate() del self.proxy.element del self.proxy
class FrameLayout(ViewGroup): """ FrameLayout is a view group that displays child views in relative positions. """ #: Describes how the child views are positioned. #: Defaults to Gravity.START | Gravity.TOP. foreground_gravity = d_(Int()) measure_all_children = d_(Bool()) #: A reference to the ProxyLabel object. proxy = Typed(ProxyFrameLayout) # ------------------------------------------------------------------------- # Observers # ------------------------------------------------------------------------- @observe('foreground_gravity', 'measure_all_children') def _update_proxy(self, change): """ An observer which sends the state change to the proxy. """ # The superclass implementation is sufficient. super(FrameLayout, self)._update_proxy(change)
class Plot1DLine(Plot1D): """""" #: Color of the plot color = ColorMember() #: Weight of the line line_weight = Float(1.0) #: Style of the line line_style = Str() #: Should markers be displayed markers_enabled = Bool() #: Size of the markers markers_size = Float() #: Shape of the marker # FIXME complete marker_shape = Enum(( "*", "+", ))
class Clock(Atom): """ A clock so widgets can observe each field as required. """ year = Int() month = Int() day = Int() hour = Int() minute = Int() second = Int() running = Bool(True) now = Instance(datetime, factory=lambda: datetime.now()) def _observe_running(self, change): if self.running: timed_call(0, self.tick) def _observe_now(self, change): t = self.now self.year, self.month, self.day = t.year, t.month, t.day self.hour, self.minute, self.second = t.hour, t.minute, t.second if self.running: timed_call(1000, self.tick) def tick(self): self.now = datetime.now()
class PopupState(Atom): """ A class which maintains the public state for a popup view. """ #: The mode to use when computing the anchored position. anchor_mode = Typed(AnchorMode, factory=lambda: AnchorMode.Parent) #: The anchor location on the parent. The default anchors #: the top center of the view to the center of the parent. parent_anchor = Typed(QPointF, factory=lambda: QPointF(0.5, 0.5)) #: The anchor location on the view. The default anchors #: the top center of the view to the center of the parent. anchor = Typed(QPointF, factory=lambda: QPointF(0.5, 0.0)) #: The offset of the popup view with respect to the anchor. offset = Typed(QPoint, factory=lambda: QPoint(0, 0)) #: The edge location of the arrow for the view. arrow_edge = Typed(ArrowEdge, factory=lambda: ArrowEdge.Left) #: The size of the arrow for the view. arrow_size = Int(0) #: The timeout value to use when closing the view, in seconds. timeout = Float(0.0) #: The duration for the fade in. fade_in_duration = Int(100) #: The duration for the fade out. fade_out_duration = Int(100) #: The computed path to use when drawing the view. path = Typed(QPainterPath, factory=lambda: QPainterPath()) #: The animator to use when showing the view. fade_in_animator = Typed(QPropertyAnimation, ()) #: The animator to use when hiding the view. fade_out_animator = Typed(QPropertyAnimation, ()) #: The timeout timer to use for closing the view. close_timer = Typed(QTimer, ()) #: Whether or not the view closes on click. close_on_click = Bool(True) #: Whether or not the view is currently in a resize event. in_resize_event = Bool(False) def init(self, widget): """ Initialize the state for the owner widget. """ fade_in = self.fade_in_animator fade_in.setTargetObject(widget) fade_in.setPropertyName('windowOpacity') fade_out = self.fade_out_animator fade_out.setTargetObject(widget) fade_out.setPropertyName('windowOpacity') fade_out.finished.connect(widget.close) close_timer = self.close_timer close_timer.setSingleShot(True) close_timer.timeout.connect(widget.close)
class QtListStrWidget(RawWidget): """A list widget for Enaml displaying objects as strings. Objects that are not string should be convertible to str and hashable. """ #: The list of str being viewed items = d_(List()) #: The list of the currently selected str selected_item = d_(Value()) selected_items = d_(List()) #: Whether or not the user can select multiple lines multiselect = d_(Bool(False)) #: Callable to use to build a unicode representation of the objects #: (one at a time). to_string = d_(Callable(str)) #: Whether or not to sort the items before inserting them. sort = d_(Bool(True)) hug_width = set_default(str("strong")) hug_height = set_default(str("ignore")) # PySide requires weakrefs for using bound methods as slots. # PyQt doesn't, but executes unsafe code if not using weakrefs. __slots__ = "__weakref__" def initialize(self): """Ensures that the selected members always have meaningful values.""" self._build_mapping(self.items) if self.items: self._do_default_selection() super(QtListStrWidget, self).initialize() def refresh_items(self): """Refresh the items displayed in the list. This is useful after an inplace operation on the list which is not notified. """ self._post_setattr_items([], self.items) def clear_selection(self): """Make no item be selected.""" # HINT : this only gives a visual hint to the user the selected value # is not updated. widget = self.get_widget() if widget is not None: widget.clearSelection() def create_widget(self, parent): """Create the QListView widget.""" # Create the list widget. widget = QtWidgets.QListWidget(parent) # Populate the widget. self._set_widget_items(widget) # Set the selection mode. if self.multiselect: mode = QtWidgets.QAbstractItemView.ExtendedSelection selected = self.selected_items else: mode = QtWidgets.QAbstractItemView.SingleSelection selected = [self.selected_item] widget.setSelectionMode(mode) self.proxy.widget = widget # Anticipated so that selection works # Make sure the widget selection reflects the members. if self.items: self._select_on_widget(selected, widget) widget.itemSelectionChanged.connect(self.on_selection) return widget def on_selection(self): """The signal handler for the index changed signal.""" if not self._guard & INDEX_GUARD: self._guard ^= INDEX_GUARD widget = self.get_widget() selected = [ self._rmap[index.row()] for index in widget.selectedIndexes() ] if selected: if self.multiselect: self.selected_items = selected else: self.selected_item = selected[0] self._guard ^= INDEX_GUARD # ========================================================================= # --- Private API --------------------------------------------------------- # ========================================================================= #: Guard bit field. _guard = Int(0) #: Mapping between user list objects and widget list indexes. _map = Dict() #: Mapping between the widget list indexes and the user list objects. _rmap = Dict() #: String representation of the objects in the widget order. _items = List() def _post_setattr_items(self, old, new): """Update the widget content when the items changes.""" self._build_mapping(new) self._set_widget_items(self.get_widget()) if new: self._do_default_selection() else: if self.multiselect: self.selected_items = [] else: self.selected_item = None def _post_setattr_multiselect(self, old, new): """Update the widget selection mode.""" widget = self.get_widget() if widget is None: return if new: mode = QtWidgets.QAbstractItemView.ExtendedSelection if self.items: self.selected_items = [self.selected_item] else: mode = QtWidgets.QAbstractItemView.SingleSelection if self.items: self.selected_item = self.selected_items[0] widget.setSelectionMode(mode) if self.items: self._select_on_widget( self.selected_items if new else [self.selected_item]) def _post_setattr_selected_item(self, old, new): """Update the widget when the selected item is changed externally.""" if not self._guard & INDEX_GUARD and self.items: self._guard ^= INDEX_GUARD self._select_on_widget([new]) self._guard ^= INDEX_GUARD def _post_setattr_selected_items(self, old, new): """Update the widget when the selected items are changed externally.""" if not self._guard & INDEX_GUARD and self.items: self._guard ^= INDEX_GUARD self._select_on_widget(new) self._guard ^= INDEX_GUARD def _build_mapping(self, items): """Build the mapping between user objects and widget indexes.""" items_map = {self.to_string(o): o for o in items} items = sorted(items_map) if self.sort else list(items_map) self._rmap = {i: items_map[item] for i, item in enumerate(items)} self._map = {v: k for k, v in self._rmap.items()} self._items = items def _set_widget_items(self, widget): """Set the list items sorting if necessary.""" if widget is not None: widget.clearSelection() widget.clear() for i in self._items: widget.addItem(i) def _do_default_selection(self): """Determine the items that should be selected. This method also ensures that the widget state reflects the member values. """ items = self.items if not self.multiselect: if self.selected_item not in items: self.selected_item = self._rmap[0] else: self._post_setattr_selected_item(None, self.selected_item) else: if not any(i in items for i in self.selected_items): self.selected_items = [self._rmap[0]] else: items_selected = [i for i in self.selected_items if i in items] if len(items_selected) == len(self.selected_item): self._post_setattr_selected_items(None, items) else: self.selected_items = items_selected def _select_on_widget(self, items, widget=None): """Select the specified items on the widget.""" if widget is None: widget = self.get_widget() if widget is not None: widget.setCurrentItem(widget.item(0), QtCore.QItemSelectionModel.Clear) item_map = self._map for n in items: widget.setCurrentItem(widget.item(item_map[n]), QtCore.QItemSelectionModel.Select)
class Declarator(Declarative): """Base class for extension object which uses a visitor pattern. """ #: Flag indicating whether the declarator has been successfully registered is_registered = Bool() def get_path(self): """Query from parent the path to use for this declarator. Returns ------- path : unicode or None Path declared by the parent. This can be None if no path is declared. """ if isinstance(self.parent, Declarator): return self.parent.get_path() def get_group(self): """Get the group defined by the closest parent. """ if not isinstance(self.parent, Declarator): return group = getattr(self.parent, 'group', None) if group: return group return self.parent.get_group() def register(self, collector, traceback): """Add the contribution of this extension to the plugin. Parameters ---------- collector : DeclaratorCollector Collector in charge handling the registering of declarators. Contributions should be added to the contributions member (Dict). If a declarator cannot be registered because another one need to be registered first it should add itself to the _delayed member (List) traceback : dict Dictionary in which any issue occuring during registration should be recorded. """ raise NotImplementedError() def unregister(self, plugin): """Remove the contribution of this extension to the plugin. Parameters ---------- collector : DeclaratorCollector Collector in charge handling the registering of declarators. """ raise NotImplementedError() def __str__(self): """Provide a nice string representation of the object. """ raise NotImplementedError()
class ViewerProtocol(JSONRRCProtocol): """ Use stdio as a json-rpc interface to communicate with external processes. If --frameless is used, the interface must receive a ping at least every 60 sec or it will assume it's owner has left and will exit. """ view = Instance(ViewerWindow) watch = Bool() _watched_files = Dict() _exit_in_sec = Float(60, strict=False) def connection_made(self, transport): self.send_message({ 'result': self.handle_window_id(), 'id': 'window_id' }) if self.view.frameless: self.schedule_close() def handle_window_id(self): return int(self.view.proxy.widget.winId()) def handle_filename(self, filename): self.view.filename = filename def handle_version(self, version): self.view.version = version def handle_ping(self): self._exit_in_sec = 60 return True def __getattr__(self, name): """ The JSONRRCProtocol tries to invoke 'handle_<attr>' on this class to handle JSON-RPC requests. This is invoked if such a method doesn't exist and attempts to redirect the getattr to the window or viewer. """ if not name.startswith('handle_'): raise AttributeError(name) attr = name[7:] # Strip handle_ # Lookup matching methods on the window and viewer for target in (self.view, self.view.viewer): handler = getattr(target, attr, None) if handler is not None and callable(handler): return handler # Replace any set_<attr> with a setattr if attr.startswith('set_'): attr = attr[len('set_'):] for target in (self.view, self.view.viewer): handler = getattr(target, attr, None) if handler is not None and not callable(handler): def handler(v, target=target, attr=attr): setattr(target, attr, v) return handler raise AttributeError(name) def schedule_close(self): """ A watchdog so if the parent is killed the viewer will automatically exit. Otherwise it will hang around forever. """ if self._exit_in_sec <= 0: # Timeout print("WARNING: Ping timeout expired, closing") sys.exit(1) else: timed_call(self._exit_in_sec * 1000, self.schedule_close) self._exit_in_sec = 0 # Clear timeout def check_for_changes(self): """ A simple poll loop to check if the file changed and if it has reload it by bumping the version. """ if self.watch: timed_call(1000, self.check_for_changes) try: filename = self.view.filename if os.path.exists(filename): try: mtime = os.stat(filename).st_mtime except: return if filename not in self._watched_files: self._watched_files[filename] = mtime elif self._watched_files[filename] != mtime: self._watched_files[filename] = mtime print("%s changed, reloading" % filename) deferred_call(self.handle_version, self.view.version + 1) except Exception as e: print(traceback.format_exc())
class DeclarativeNode(CompilerNode): """ A compiler node which represents a declarative declaration. Instances of this class are generated by the compiler and contain the information needed to create an instance of the hierarchy at runtime. """ #: The declarative type object to instantiate. klass = Typed(type) #: The local identifier to associate with the instance. identifier = Str() #: Whether or not the node should store the locals in the map. store_locals = Bool(False) #: Whether or not the instance intercepts the child nodes. child_intercept = Bool(False) #: The expression engine to associate with the instance. engine = Typed(ExpressionEngine) #: The set of scope keys for the closure scopes. This will be None #: if the node does not require any closure scopes. closure_keys = Typed(set) #: The superclass nodes of this node. This will be None if the #: node represents a raw declarative object vs an enamldef. super_node = ForwardTyped(lambda: EnamlDefNode) def __call__(self, parent): """ Instantiate the type hierarchy. This is invoked by a parent compiler node when the declarative hierarchy is being instantiated. Parameters ---------- parent : Declarative or None The parent declarative object for the hierarchy. Returns ------- result : Declarative The declarative instance created by the node. """ klass = self.klass instance = klass.__new__(klass) self.populate(instance) instance.__init__(parent) return instance def populate(self, instance): """ Populate an instance generated for the node. Parameters ---------- instance : Declarative The declarative instance for this node. """ if self.super_node is not None: self.super_node(instance) f_locals = peek_scope() scope_key = self.scope_key if self.identifier: f_locals[self.identifier] = instance if self.store_locals: instance._d_storage[scope_key] = f_locals if self.engine is not None: instance._d_engine = self.engine if self.closure_keys is not None: for key in self.closure_keys: instance._d_storage[key] = fetch_scope(key) if self.child_intercept: children_copy = self.children[:] instance.child_node_intercept(children_copy, scope_key, f_locals) else: for node in self.children: node(instance) def size(self): """ Return the size of the instantiated node. """ return 1 def update_id_nodes(self, mapping): """ Update the id nodes for this node. Parameters ---------- mapping : sortedmap The mapping to fill with the identifier information. """ if self.identifier: mapping[self.identifier] = self super(DeclarativeNode, self).update_id_nodes(mapping) def copy(self): """ Create a copy of this portion of the node hierarchy. Returns ------- result : DeclarativeNode A copy of the node hierarchy from this node down. """ node = super(DeclarativeNode, self).copy() node.klass = self.klass node.identifier = self.identifier node.store_locals = self.store_locals node.child_intercept = self.child_intercept if self.engine is not None: node.engine = self.engine.copy() if self.super_node is not None: node.super_node = self.super_node.copy() if self.closure_keys is not None: node.closure_keys = self.closure_keys.copy() return node
class CalculatorGraphController(GraphControllerBase): is_active = Bool(False) is_dirty = Bool(False) current_path = Unicode() filename = Unicode() registry = Typed(TypeRegistry) graph = Instance(ExecutableGraph) selectedNodes = List(NodeItem) def default_current_path(self): return os.curdir def _default_registry(self): return TypeRegistry() def _default_graph(self): return ExecutableGraph(controller=self) @observe('view.selectedItems') def filter_selected_items(self, change): self.selectedNodes = [ i for i in change['value'] if isinstance(i, NodeItem) ] @observe('graph.topologyChanged', 'graph.attributesChanged') def mark_dirty(self, change): self.is_dirty = True def create_node(self, typename, **kw): if self.view.scene is None: return nt = self.registry.node_type_name_map.get(typename, None) if nt is not None: node = nt.model_class() kw['model'] = node kw['type_name'] = typename n = nt.widget_class(**kw) self.view.scene.insert_children(None, [n]) node.id = n.id n.name = "%s (%s)" % (nt.name, n.id.split("-")[-1]) self.graph.nodes.append(node) self.graph.topologyChanged() return n def destroy_node(self, id): if self.view.scene is None: return if id in self.view.scene.nodes: if self.view.scene.nodes[id].model in self.graph.nodes: self.graph.nodes.remove(self.graph.node_dict[id]) self.view.scene.nodes[id].destroy() self.graph.topologyChanged() def create_edge(self, typename, **kw): if self.view.scene is None: return et = self.registry.edge_type_name_map.get(typename, None) if et is not None: edge = et.model_class() kw['model'] = edge kw['type_name'] = typename e = et.widget_class(**kw) self.view.scene.insert_children(None, [e]) edge.id = e.id return e def destroy_edge(self, id): if self.view.scene is None: return if id in self.view.scene.edges: if self.view.scene.edges[id].model in self.graph.edges: self.graph.edges.remove(self.view.scene.edges[id].model) self.view.scene.edges[id].destroy() def edge_type_for_start_socket(self, start_node, start_socket): return 'default' def edge_can_connect(self, start_node_id, start_socket_id, end_node_id, end_socket_id): if self.view.scene is None: return False try: start_node = self.graph.node_dict[start_node_id] end_node = self.graph.node_dict[end_node_id] start_socket = start_node.output_dict[start_socket_id] end_socket = end_node.input_dict[end_socket_id] return end_socket.can_connect(start_socket) except KeyError as e: log.exception(e) return False def edge_connected(self, id): if id in self.view.scene.edges: edge_view = self.view.scene.edges[id] edge = edge_view.model ss_view = edge_view.start_socket edge.start_socket = ss_view.parent.model.output_dict[ss_view.name] es_view = edge_view.end_socket edge.end_socket = es_view.parent.model.input_dict[es_view.name] self.graph.edges.append(edge) self.graph.topologyChanged() def edge_disconnect(self, id): if id in self.view.scene.edges: edge = self.view.scene.edges[id].model edge.start_socket = None edge.end_socket = None if edge in self.graph.edges: self.graph.edges.remove(edge) self.graph.topologyChanged() def serialize_graph(self): G = self.graph.nxgraph.copy() G.graph['viewport_transform'] = self.view.getViewportTransform( ).to_list() for node_id in G.nodes(): node_view = self.view.scene.nodes[node_id] node_data = {} self.serialize_node(node_data, node_view) G.nodes[node_id].update(node_data) for start_node_id, end_node_id, key, edge_id in G.edges(data='id', keys=True): if edge_id is None: continue edge_view = self.view.scene.edges[edge_id] edge_data = {} self.serialize_edge(edge_data, edge_view) G.edges[start_node_id, end_node_id, key].update(edge_data) return G def serialize_node(self, archive, node_view): archive['type_name'] = node_view.type_name archive['position'] = node_view.position.to_list() if node_view.model is not None: node_view.model.serialize(archive) def serialize_edge(self, archive, edge_view): archive['type_name'] = edge_view.type_name if edge_view.model is not None: edge_view.model.serialize(archive) def deserialize_graph(self, G, replace=True): if 'viewport_transform' in G.graph: self.view.setViewportTransform( Transform2D.from_list(G.graph['viewport_transform'])) for node_id in G.nodes.keys(): data = G.nodes[node_id] type_name = data.get('type_name', None) if type_name is None: log.error("Invalid Node (missing type_name): %s" % node_id) continue position = Point2D.from_list(data['position']) name = data['name'] n = self.create_node(type_name, id=node_id, name=name, position=position) if n.model is not None: n.model.deserialize(data) for start_node_id, end_node_id, key, edge_id in G.edges(data='id', keys=True): data = G.edges[start_node_id, end_node_id, key] type_name = data.get('type_name', None) if type_name is None: log.error("Invalid Edge (missing type_name): %s" % edge_id) continue source_socket_name = data['source_socket'] target_socket_name = data['target_socket'] source_socket = None target_socket = None for socket in self.view.scene.nodes[start_node_id].output_sockets: if socket.name == source_socket_name: source_socket = socket break for socket in self.view.scene.nodes[end_node_id].input_sockets: if socket.name == target_socket_name: target_socket = socket break if source_socket is None or target_socket is None: log.error("Invalid edge - missing socket: %s" % edge_id) continue e = self.create_edge(type_name, id=edge_id) e.start_socket = source_socket e.end_socket = target_socket if e.model is not None: e.model.deserialize(data) self.edge_connected(edge_id) def file_new(self): self.filename = "" self.view.scene.clear_all() self.is_dirty = False def file_open(self, filename, replace=True): self.current_path = os.path.dirname(filename) self.filename = os.path.basename(filename) if replace: self.view.scene.clear_all() g = nx.node_link_graph( json.load(open(os.path.join(self.current_path, self.filename), 'r'))) self.deserialize_graph(g, replace=replace) self.is_dirty = False def file_save(self, filename): self.current_path = os.path.dirname(filename) self.filename = os.path.basename(filename) g = self.serialize_graph() json.dump(nx.node_link_data(g), open(os.path.join(self.current_path, self.filename), 'w')) self.is_dirty = False
class Instrument(Prop): enable = Bool(False) isInitialized = Bool() isDone = Bool() instruments = Member() data = Member() def __init__(self, name, experiment, description=''): super(Instrument, self).__init__(name, experiment, description) self.instruments = [] self.isInitialized = False self.isDone = True self.data = [] self.properties += ['enable'] def evaluate(self): """Checks to see if the Instrument is enabled, before calling Prop.evaluate()""" if self.enable: logger.debug('{}.evaluate()'.format(self.name)) return super(Instrument, self).evaluate() def toHardware(self): """Checks to see if the Instrument is enabled, before calling Prop.toHardware()""" if self.enable: return super(Instrument, self).toHardware() else: return '<{}><enable>False</enable></{}>'.format(self.name, self.name) def update(self): """Sends current settings to the instrument. This function is run at the beginning of every new iteration. Does not explicitly call evaluate, to avoid duplication of effort. All calls to evaluate should already have been accomplished.""" for i in self.instruments: if i.enable: #check that the instruments are initialized if not i.isInitialized: i.initialize() # reinitialize i.update() # put the settings to where they should be at this iteration #the details of sending to each instrument must be handled in a subclass #first call super(subclass,self).update() to call this method #then do the hardware update, probably involving sending the toXML string via TCP/IP def start(self): """Enables the instrument to begin a measurement. Sent at the beginning of every measurement. Actual output or input from the measurement may yet wait for a signal from another device.""" pass def stop(self): """Stops output as soon as possible. This is not run during the course of a normal instrument.""" pass def initialize(self): """Sends initialization commands to the instrument""" for i in self.instruments: i.initialize() self.isInitialized = True def acquire_data(self): """Instruments that are not aware of the experiment timing can not be programmed to acquire data during start(). Instead they can be programmed to get data in this method, which is called after start() has completed.""" for i in self.instruments: if i.enable: i.acquire_data() def writeResults(self, hdf5): """Write results to the hdf5 file. Must be overwritten in subclass to do anything.""" pass
class TCP_Instrument(Instrument): """ This class inherets from Instrument but has the capability to do TCP communication to an instrument server. This class is generalized from the LabView class. """ port = Member() IP = Str() connected = Member() msg = Str() results = Member() sock = Member() timeout = Typed(FloatProp) error = Bool() log = Str() def __init__(self, name, experiment, description=''): super(TCP_Instrument, self).__init__(name, experiment, description) # defaults self.port = 0 self.connected = False self.error = False self.connected = False self.results = {} self.sock = None self.connected = False self.timeout = FloatProp('timeout', experiment, 'how long before TCP gives up [s]', '1.0') self.properties += ['IP', 'port', 'timeout'] self.doNotSendToHardware += ['IP', 'port', 'timeout'] def openThread(self): thread = threading.Thread(target=self.initialize) thread.daemon = True thread.start() def open(self): if self.enable: logger.debug('Opening {} TCP.'.format(self.name)) # check for an old socket and delete it if self.sock is not None: logger.debug('Closing previously open sock.') try: self.sock.close() except Exception as e: logger.debug('Ignoring exception during sock.close() of previously open sock.\n{}\n'.format(e)) try: del self.sock except Exception as e: logger.debug('Ignoring exception during sock.close() of previously open sock.\n{}\n'.format(e)) # Create a TCP/IP socket logger.debug('{}.open() opening sock'.format(self.name)) try: self.sock = TCP.CsClientSock(self.IP, self.port, parent=self) except Exception as e: logger.warning('Failed to open TCP socket in {}.open():\n{}\n'.format(self.name, e)) raise PauseError logger.debug('{}.open() sock opened'.format(self.name)) self.connected = True def initialize(self): self.open() logger.debug('Initializing LabView instruments.') super(TCP_Instrument, self).initialize() def close(self): if self.sock is not None: self.sock.close() self.connected = False self.isInitialized = False def update(self): """Send the current values to hardware.""" super(TCP_Instrument, self).update() self.send(self.toHardware()) def start(self): self.isDone = True def writeResults(self, hdf5): """Write the previously obtained results to the experiment hdf5 file. hdf5 is an hdf5 group, typically the data group in the appropriate part of the hierarchy for the current measurement.""" for key, value in self.results.iteritems(): # no special protocol try: hdf5[key] = value except Exception as e: logger.error('Exception in {}.writeResults() doing hdf5[key]=value for key={}\n'.format(key, self.name, e)) raise PauseError def send(self, msg): results = {} if self.enable: if not (self.isInitialized and self.connected): logger.debug('TCP is not both initialized and connected. Reinitializing TCP in {}.send().'.format(self.name)) self.initialize() # display message on GUI self.set_dict({'msg': msg}) # send message #logger.info('{} sending message ...'.format(self.name)) #logger.info('msg: `{}`'.format(msg)) try: self.sock.settimeout(self.timeout.value) self.sock.sendmsg(msg) except IOError as e: logger.warning('Timeout while waiting to send data in {}.send():\n{}\n'.format(self.name, e)) self.connected = False raise PauseError except Exception as e: logger.warning('Exception while sending message in {}.send():\n{}\n{}\n'.format(self.name, e, traceback.format_exc())) self.connected = False raise PauseError # wait for response logger.info('{} waiting for response ...'.format(self.name)) try: rawdata = self.sock.receive() except IOError as e: logger.warning('Timeout while waiting for return data in {}.send():\n{}\n'.format(self.name, e)) self.connected = False raise PauseError except: logger.exception('Exception in {}.sock.receive.') self.connected = False raise PauseError # parse results logger.info('Parsing TCP results ...') results = self.sock.parsemsg(rawdata) # for key, value in self.results.iteritems(): # print 'key: {} value: {}'.format(key,str(value)[:40]) # report server errors log = '' if 'log' in results: log = results['log'] self.set_gui({'log': self.log + log}) if 'error' in results: error = toBool(results['error']) self.set_gui({'error': error}) if error: logger.warning('Error returned from {}.send:\n{}\n'.format(self.name, log)) raise PauseError self.results = results self.isDone = True return results
class FFTAlazarTask(InstrumentTask): """ Get the raw or averaged quadratures of the signal. Can also get raw or averaged traces of the signal. Custom shape for demodulation can be used. """ tracetimeaftertrig = Str('0').tag(pref=True, feval=VAL_REAL) tracetimeaftertrigB = Str('0').tag(pref=True, feval=VAL_REAL) traceduration = Str('0').tag(pref=True) tracedurationB = Str('0').tag(pref=True) tracesbuffer = Str('20').tag(pref=True, feval=VAL_INT) tracesnumber = Str('1000').tag(pref=True, feval=VAL_INT) average = Bool(True).tag(pref=True) Npoints = Str('0').tag(pref=True, feval=VAL_INT) trigrange = Enum('2.5V', '5V').tag(pref=True) triglevel = Str('0.3').tag(pref=True, feval=VAL_REAL) powerPhaseA = Bool(False).tag(pref=True) powerPhaseB = Bool(False).tag(pref=True) database_entries = set_default({ 'FFT': {}, 'freq': {}, 'power': {}, 'phase': {} }) def format_string(self, string, factor, n): s = self.format_and_eval_string(string) if isinstance(s, list) or isinstance(s, tuple) or isinstance( s, np.ndarray): return [elem * factor for elem in s] else: return [s * factor] * n def check(self, *args, **kwargs): """ """ test, traceback = super(FFTAlazarTask, self).check(*args, **kwargs) if (self.format_and_eval_string(self.tracesnumber) % self.format_and_eval_string(self.tracesbuffer) != 0): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''The number of traces must be an integer multiple of the number of traces per buffer.''') if not (self.format_and_eval_string(self.tracesnumber) >= 1000): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''At least 1000 traces must be recorded. Please make real measurements and not noisy s***.''') tracetime = self.format_string(self.tracetimeaftertrig, 10**-9, 1) traceduration = self.format_string(self.traceduration, 10**-9, 1) tracetimeB = self.format_string(self.tracetimeaftertrigB, 10**-9, 1) tracedurationB = self.format_string(self.tracedurationB, 10**-9, 1) for t, d in ((tracetime, traceduration), (tracetimeB, tracedurationB)): if len(t) != len(d): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''An equal number of "Start time after trig" and "Duration" should be given.''') else: for tt, dd in zip(t, d): if not (tt >= 0 and dd >= 0): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''Both "Start time after trig" and "Duration" must be >= 0.''') if ((0 in traceduration) and (0 in tracedurationB)): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''All measurements are disabled.''') return test, traceback def perform(self): """ """ if not self.driver: self.start_driver() if self.trigrange == '5V': trigrange = 5 else: trigrange = 2.5 triglevel = self.format_and_eval_string(self.triglevel) self.driver.configure_board(trigrange, triglevel) recordsPerCapture = self.format_and_eval_string(self.tracesnumber) recordsPerBuffer = int(self.format_and_eval_string(self.tracesbuffer)) Npoints = self.format_and_eval_string(self.Npoints) tracetimeA = self.format_string(self.tracetimeaftertrig, 10**-9, 1) tracedurationA = self.format_string(self.traceduration, 10**-9, 1) tracetimeB = self.format_string(self.tracetimeaftertrigB, 10**-9, 1) tracedurationB = self.format_string(self.tracedurationB, 10**-9, 1) NtraceA = len(tracedurationA) if 0 in tracedurationA: NtraceA = 0 tracetimeA = [] tracedurationA = [] NtraceB = len(tracedurationB) if 0 in tracedurationB: NtraceB = 0 tracetimeB = [] tracedurationB = [] startaftertrig = tracetimeA + tracetimeB duration = tracedurationA + tracedurationB powerPhase = [self.powerPhaseA, self.powerPhaseB] answerFFT, answerFreq, answerFFTpower, answerFFTphase = self.driver.get_FFT( startaftertrig, duration, recordsPerCapture, recordsPerBuffer, self.average, NtraceA, NtraceB, Npoints, powerPhase) self.write_in_database('FFT', answerFFT) self.write_in_database('freq', answerFreq) self.write_in_database('power', answerFFTpower) self.write_in_database('phase', answerFFTphase)
class VNAAlazarTask(InstrumentTask): """ Allows to used an Alazar card as a VNA. """ freq = Str('[]').tag(pref=True) freqB = Str('[]').tag(pref=True) timeaftertrig = Str('0').tag(pref=True) timeaftertrigB = Str('0').tag(pref=True) duration = Str('1000').tag(pref=True) durationB = Str('0').tag(pref=True) tracesbuffer = Str('20').tag(pref=True, feval=VAL_INT) tracesnumber = Str('1000').tag(pref=True, feval=VAL_INT) average = Bool(True).tag(pref=True) trigrange = Enum('2.5V', '5V').tag(pref=True) triglevel = Str('0.3').tag(pref=True, feval=VAL_REAL) demodFormFile = Str('[]').tag(pref=True) aux_trig = Bool(False).tag(pref=True) database_entries = set_default({'VNADemod': {}}) def format_string(self, string, factor, n): s = self.format_and_eval_string(string) if isinstance(s, list) or isinstance(s, tuple) or isinstance( s, np.ndarray): return [elem * factor for elem in s] else: return [s * factor] * n def check(self, *args, **kwargs): """ """ test, traceback = super(VNAAlazarTask, self).check(*args, **kwargs) if (self.format_and_eval_string(self.tracesnumber) % self.format_and_eval_string(self.tracesbuffer) != 0): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''The number of traces must be an integer multiple of the number of traces per buffer.''') if not (self.format_and_eval_string(self.tracesnumber) >= 1000): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''At least 1000 traces must be recorded. Please make real measurements and not noisy s***.''') time = self.format_string(self.timeaftertrig, 10**-9, 1) duration = self.format_string(self.duration, 10**-9, 1) timeB = self.format_string(self.timeaftertrigB, 10**-9, 1) durationB = self.format_string(self.durationB, 10**-9, 1) for t, d in ((time, duration), (timeB, durationB)): if len(t) != len(d): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''An equal number of "Start time after trig" and "Duration" should be given.''') else: for tt, dd in zip(t, d): if not (tt >= 0 and dd >= 0): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''Both "Start time after trig" and "Duration" must be >= 0.''') if ((0 in duration) and (0 in durationB)): test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''All measurements are disabled.''') demodFormFile = self.format_and_eval_string(self.demodFormFile) samplesPerSec = 500000000.0 if demodFormFile != []: duration = duration + durationB for d in duration: if len(demodFormFile[0]) > samplesPerSec * d: test = False traceback[self.path + '/' + self.name + '-get_demod'] = \ cleandoc('''Acquisition's duration must be larger than demodulation fonction's duration''') return test, traceback def perform(self): """ """ if not self.driver: self.start_driver() if self.trigrange == '5V': trigrange = 5 else: trigrange = 2.5 triglevel = self.format_and_eval_string(self.triglevel) self.driver.configure_board(trigrange, triglevel) recordsPerCapture = self.format_and_eval_string(self.tracesnumber) recordsPerBuffer = int(self.format_and_eval_string(self.tracesbuffer)) timeA = self.format_string(self.timeaftertrig, 10**-9, 1) durationA = self.format_string(self.duration, 10**-9, 1) timeB = self.format_string(self.timeaftertrigB, 10**-9, 1) durationB = self.format_string(self.durationB, 10**-9, 1) demodFormFile = self.format_and_eval_string(self.demodFormFile) NdemodA = len(durationA) if 0 in durationA: NdemodA = 0 timeA = [] durationA = [] NdemodB = len(durationB) if 0 in durationB: NdemodB = 0 timeB = [] durationB = [] if len(demodFormFile) == 0: demodCosinus = 1 else: demodCosinus = 0 startaftertrig = timeA + timeB duration = durationA + durationB freqA = self.format_string(self.freq, 10**6, NdemodA) freqB = self.format_string(self.freqB, 10**6, NdemodB) freq = freqA + freqB freqA = self.format_string(self.freq, 10**6, 1) if freqA != []: Nfreq = len(freqA) else: Nfreq = len(self.format_string(self.freqB, 10**6, 1)) answerDemod = self.driver.get_VNAdemod(startaftertrig, duration, recordsPerCapture, recordsPerBuffer, freq, self.average, Nfreq, NdemodA, NdemodB, demodFormFile, demodCosinus, self.aux_trig) self.write_in_database('VNADemod', answerDemod)