Beispiel #1
0
class Pipe(Operation):
    """ An operation that extrudes a profile along a spline, wire, or path.
    
    Attributes
    ----------
    
    spline: Edge or Wire
        The spline to extrude along.
    profile: Wire
        The profile to extrude.
    fill_mode: String, optional
        The fill mode to use.
    
        
    Examples
    --------
    
    See examples/pipes.enaml
        
    """
    #: Reference to the implementation control
    proxy = Typed(ProxyPipe)

    #: Spline to make the pipe along
    spline = d_(Instance(Shape))

    #: Profile to make the pipe from
    profile = d_(ForwardInstance(WireFactory))

    #: Fill mode
    fill_mode = d_(
        Enum(None, 'corrected_frenet', 'fixed', 'frenet', 'constant_normal',
             'darboux', 'guide_ac', 'guide_plan', 'guide_ac_contact',
             'guide_plan_contact', 'discrete_trihedron')).tag(view=True,
                                                              group='Pipe')

    @observe('spline', 'profile', 'fill_mode')
    def _update_proxy(self, change):
        super(Pipe, self)._update_proxy(change)
Beispiel #2
0
class Splitter(ConstraintsWidget):
    """ A widget which displays its children in separate resizable
    compartments that are connected with a resizing bar.

    A Splitter can have an arbitrary number of Container children.

    """
    #: The orientation of the Splitter. 'horizontal' means the children
    #: are laid out left to right, 'vertical' means top to bottom.
    orientation = d_(Enum('horizontal', 'vertical'))

    #: Whether the child widgets resize as a splitter is being dragged
    #: (True), or if a simple indicator is drawn until the drag handle
    #: is released (False). The default is True.
    live_drag = d_(Bool(True))

    #: A splitter expands freely in height and width by default.
    hug_width = set_default('ignore')
    hug_height = set_default('ignore')

    #: A reference to the ProxySplitter object.
    proxy = Typed(ProxySplitter)

    def split_items(self):
        """ Get the split item children defined on the splitter.

        """
        return [c for c in self.children if isinstance(c, SplitItem)]

    #--------------------------------------------------------------------------
    # Observers
    #--------------------------------------------------------------------------
    @observe('orientation', 'live_drag')
    def _update_proxy(self, change):
        """ An observer which sends state change to the proxy.

        """
        # The superclass handler implementation is sufficient.
        super(Splitter, self)._update_proxy(change)
Beispiel #3
0
class EditText(TextView):
    """A simple control for displaying read-only text."""

    #: Text selection
    selection = d_(Tuple(int))

    #: Make editable by default
    input_type = set_default("text")

    #: Placeholder text
    placeholder = d_(Str())

    #: Style (iOS)
    style = d_(Enum("", "line", "bezel", "rounded_rect"))

    #: A reference to the ProxyLabel object.
    proxy = Typed(ProxyEditText)

    @observe("selection", "placeholder", "style")
    def _update_proxy(self, change):

        super()._update_proxy(change)
Beispiel #4
0
class InsertTab(DockLayoutOp):
    """ A layout operation which inserts a tab into a tab group.

    This operation will remove an item from the current layout and
    insert it into a tab group in a dock area. If the item does not
    exist, the operation is a no-op.

    If the target -

    - is a normally docked item
        The target and item will be merged into a new tab group
        using the default tab position.

    - is docked in a tab group
        The item will be inserted into the tab group.

    - is docked in a dock bar
        The item will be appended to the dock bar.

    - is a floating dock item
        A new dock area will be created and the target and item will
        be merged into a new tab group.

    - does not exist
        The item is inserted into the left border of the primary dock
        area.

    """
    #: The name of the dock item to insert into the tab group.
    item = Unicode()

    #: The name of an existing dock item in the tab group of interest.
    target = Unicode()

    #: The index at which to insert the dock item.
    index = Int(-1)

    #: The position of the tabs for a newly created tab group.
    tab_position = Enum('default', 'top', 'bottom', 'left', 'right')
Beispiel #5
0
class SplitLayout(LayoutNode):
    """ A layout object for defining split dock layouts.

    """
    #: The orientation of the split layout.
    orientation = Enum('horizontal', 'vertical')

    #: The default sizes to apply to the items in the splitter. If
    #: provided, the length must be equal to the number of items.
    sizes = List(Int())

    #: This list of split layout items to include in the split layout.
    items = List(Coerced(_SplitLayoutItem))

    def __init__(self, *items, **kwargs):
        super(SplitLayout, self).__init__(items=list(items), **kwargs)

    def children(self):
        """ Get the list of children of the split layout.

        """
        return self.items[:]
Beispiel #6
0
class Material_Parameters(Check):
    c_eta = Float(c_eta).tag(
        desc="The element factor",
        check_value=0.8,
        unit="for 50% metallization (Datta assuming sqrt(2) cancellation)",
        latex='c_\eta')

    material = Enum(*sorted(material_dict.keys()))

    def _default_material(self):
        return material

    Dvv = FloatRange(0.00001, 10 / 100.0,
                     Dvv).tag(label="Dvv",
                              unit=None,
                              LiNb=2.4 / 100.0,
                              reference="Morgan pg 9",
                              desc="Piezoelectric coupling constant",
                              aka="K^2/2")

    epsinf = FloatRange(0.0001 * 1.0e-12, 500 * 8.85e-12,
                        epsinf).tag(label="epsilon_infty",
                                    unit="F/m",
                                    LiNb=46.0 * 8.85e-12,
                                    reference="Morgan pg 9",
                                    aka="C_S in Datta (50% metalization)",
                                    desc="Capacitance for one finger pair")

    v = FloatRange(1000.0, 10000.0, v).tag(
        label="v",
        unit="m/s",
        desc="propagation velocity of SAW (free surface)"
    )  # propagation velocity for YZ lithium niobate --- page 9 Morgan's Book

    def _observe_material(self, change):
        self.Dvv = material_dict[self.material]['Dvv']
        self.epsinf = material_dict[self.material]['epsinf']
        self.v = material_dict[self.material]['v']
Beispiel #7
0
class InstrUser(Declarative):
    """Extension to the 'ecpy.instruments.users' extensions point.

    """
    #: Plugin id associated with this use of instrument. This allow the manager
    #: to know what part of the application requested the right to use some
    #: drivers.
    id = d_(Unicode())

    #: Is the plugin susceptible to release the profiles it is currently using
    #: if the manager asks it to do so.
    policy = d_(Enum('releasable', 'unreleasable'))

    @d_func
    def release_profiles(self, workbench, profiles):
        """Release the specified profiles or some of them.

        This call can block until the profiles can be released (if it is likely
        to happen in a relatively short time). The
        'ecpy.instruments.notify_profiles_released' command should not be
        called (the manager knows what profiles it requested and will handle
        the tracking of the current user for each profile itself).

        Parameters
        ----------
        workbench :
            Application workbench.

        profiles : list[unicode]
            List of profiles the manager is requesting the user to release.

        Returns
        -------
        released_profiles : list[unicode]
            List of the profiles that have been released.

        """
        raise NotImplementedError()
Beispiel #8
0
class RejectEpochs(EpochInput):
    '''
    Rejects epochs whose amplitude exceeds a specified threshold.

    Attributes
    ----------
    threshold : float
        Reject threshold
    mode : {'absolute value', 'amplitude'}
        If absolute value, rejects epoch if the minimum or maximum exceeds the
        reject threshold. If amplitude, rejects epoch if the difference between
        the minimum and maximum exceeds the reject threshold.
    '''
    threshold = d_(Float()).tag(metadata=True)
    mode = d_(Enum('absolute value', 'amplitude')).tag(metadata=True)

    total = Int()
    rejects = Int()
    reject_ratio = Float()

    def configure_callback(self):
        valid_cb = super().configure_callback()
        return reject_epochs(self.threshold, self.mode, self, valid_cb).send
Beispiel #9
0
class Button(TextView):
    """ A simple control for displaying a button.

    """
    #: Button is clickable by default
    clickable = set_default(True)

    #: Styles
    style = d_(Enum('', 'borderless', 'inset', 'small'))

    #: A reference to the proxy object.
    proxy = Typed(ProxyButton)

    # -------------------------------------------------------------------------
    # Observers
    # -------------------------------------------------------------------------
    @observe('style')
    def _update_proxy(self, change):
        """ An observer which sends the state change to the proxy.

        """
        # The superclass implementation is sufficient.
        super(Button, self)._update_proxy(change)
Beispiel #10
0
class LorentzianFitter(LeastSqFitter):
    """Atom wrapper for Lorentzian least square fitting"""
    fit_type = Enum("lorentzian", "refl_lorentzian")
    gamma = Float(1.0).tag(desc="width of peak for initial guess")
    end_indices = Int(10).tag(desc="indices to average for background guess")

    fit_func_dict = {
        "lorentzian": lorentzian,
        "refl_lorentzian": refl_lorentzian
    }

    p_guess_dict = {
        "lorentzian": lorentzian_p_guess,
        "refl_lorentzian": refl_lorentzian_p_guess
    }

    @private_property
    def fit_func(self):
        return self.fit_func_dict[self.fit_type]

    @private_property
    def p_guess_func(self):
        return self.p_guess_dict[self.fit_type]
Beispiel #11
0
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",
        ])).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("xhtml1", "xhtml5", "xhtml", "html4", "html5",
             "html")).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 Parameter(ContextItem):
    '''
    A context item that can be evaluated dynamically, but cannot be included as
    part of a selector.  This is typically used for settings that must be
    determined before values are drawn from the selectors (e.g., probability of
    a go trial).
    '''
    # Default value of the context item when used as part of a selector.
    default = d_(Value())

    expression = d_(Str()).tag(preference=True)

    # Defines the span over which the item's value does not change:
    # * experiment - the value cannot change once the experiment begins
    # * trial - The value cannot change once a trial begins. This is the only
    #   type of item that can be roved using a selector.
    # * arbitrary - The value can be changd at any time but it does not make
    #   sense for it to be a roving item.
    scope = d_(Enum('trial', 'experiment', 'arbitrary'))

    # Is the value of this item managed by a selector?
    rove = d_(Bool()).tag(preference=True)

    def _default_expression(self):
        return str(self.default)

    def _default_dtype(self):
        return np.array(self.default).dtype.str

    def _default_label(self):
        return self.name

    def to_expression(self, value):
        return str(value)

    def set_value(self, value):
        self.expression = self.to_expression(value)
Beispiel #13
0
class InsertBorderItem(DockLayoutOp):
    """ A layout operation which inserts an item into an area border.

    This operation will remove an item from the current layout and
    insert it into the border of a dock area. If the item does not
    exist, the operation is a no-op.

    If the target -

    - is a normally docked item
        The item is inserted into the border of the dock area containing
        the target.

    - is docked in a tab group
        The item is inserted into the border of the dock area containing
        the tab group.

    - is docked in a dock bar
        The item is inserted into the border of the dock area containing
        the dock bar.

    - is a floating dock item
        A new dock area will be created and the item will be inserted
        into the border of the new dock area.

    - does not exist
        The item is inserted into the border of the primary dock area.

    """
    #: The name of the dock item to insert into the layout.
    item = Unicode()

    #: The name of the dock item to use as the target location.
    target = Unicode()

    #: The border position at which to insert the item.
    position = Enum('left', 'top', 'right', 'bottom')
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)
Beispiel #15
0
class RejectEpochs(EpochInput):
    '''
    Rejects epochs whose amplitude exceeds a specified threshold.

    Attributes
    ----------
    threshold : float
        Reject threshold
    mode : {'absolute value', 'amplitude'}
        If absolute value, rejects epoch if the minimum or maximum exceeds the
        reject threshold. If amplitude, rejects epoch if the difference between
        the minimum and maximum exceeds the reject threshold.
    '''
    threshold = d_(Float()).tag(metadata=True)
    mode = d_(Enum('absolute value', 'amplitude')).tag(metadata=True)

    total = Int()
    rejects = Int()
    reject_percent = Float()

    def status_cb(self, n_total, n_accepted):
        def update():
            # Update the status. Must be wrapped in a deferred call to ensure
            # that the update occurs on the GUI thread.
            nonlocal self
            nonlocal n_total
            nonlocal n_accepted
            self.total += n_total
            self.rejects += n_total - n_accepted
            self.reject_percent = self.rejects / self.total * 100

        deferred_call(update)

    def configure_callback(self):
        valid_cb = super().configure_callback()
        return pipeline.reject_epochs(self.threshold, self.mode,
                                      self.status_cb, valid_cb).send
Beispiel #16
0
class Text_Editor(Atom):
    view = Enum("Text_Editor")
    name = Unicode("Text_Editor")
    main_file = Unicode("idt.jdf").tag(private=True)
    dir_path = Unicode("/Users/thomasaref/Dropbox/Current stuff/TA_software"
                       ).tag(private=True)
    data = Str().tag(discard=True,
                     log=False,
                     no_spacer=True,
                     label="",
                     spec="multiline")
    read_file = Typed(Read_TXT).tag(no_spacer=True)
    save_file = Typed(Save_TXT).tag(no_spacer=True)

    @observe('read_file.read_event')
    def obs_read_event(self, change):
        self.data = "".join(self.read_file.data["data"])

    @observe('save_file.save_event')
    def obs_save_event(self, change):
        self.save_file.direct_save(self.data, write_mode='w')

    def _default_read_file(self):
        return Read_TXT(main_file=self.main_file, dir_path=self.dir_path)

    def _default_save_file(self):
        return Save_TXT(main_file=self.read_file.main_file,
                        dir_path=self.read_file.dir_path)

    def data_list(self):
        return self.data.split("\n")

    @property
    def view_window(self):
        with imports():
            from e_UserTemps import TextEditorWindow
        return TextEditorWindow(instr=self)
Beispiel #17
0
class StorageDefConstruct(ConstructNode):
    """ A construct node for a storage definition.

    """
    #: The kind of the state definition.
    kind = Enum('attr', 'event')

    #: The name of the state object being defined.
    name = Str()

    #: The typename of the allowed values for the state object.
    typename = Str()

    #: The resolved type class for using with the state def. This is
    #: updated during the resolution passes over the tree.
    typeclass = Typed(type)

    @classmethod
    def from_dict(cls, dct):
        self = super(StorageDefConstruct, cls).from_dict(dct)
        self.kind = dct['kind']
        self.name = dct['name']
        self.typename = dct['typename']
        return self
Beispiel #18
0
class Table(Control):
    """ Enaml declarative control for giving a Table grid widget.
    """

    rows = d_(List())
    columns = d_(List())
    selected_rows = d_(List())
    alternate_row_colors = d_(Bool(default=True))
    stretch_last_column = d_(Bool())
    select_mode = d_(
        Enum("single_row", "multi_rows", "single_cell", "multi_cells", "none"))

    row_style_callback = d_(Value())
    double_click_action = d_(Value())

    #: A reference to the ProxyTable implementation.
    proxy = Typed(ProxyTable)

    hug_height = "weak"
    hug_width = "weak"

    # Observers ---------------------------------------------------------------
    @observe(
        "rows",
        "columns",
        "alternate_row_colors",
        "select_mode",
        "stretch_last_column",
        "selected_rows",
        "row_style_callback",
    )
    def _update_proxy(self, change):
        """ An observer which sends the state change to the proxy.
        """
        # The superclass implementation is sufficient.
        super(Table, self)._update_proxy(change)
class ActivityIndicator(View):
    """ A simple control for displaying an ActivityIndicator.

    """

    #: Style for indeterminate
    size = d_(Enum('normal', 'small', 'large'))

    #: Sets the color of the indicator.
    color = d_(Unicode())

    #: A reference to the ProxyActivityIndicator object.
    proxy = Typed(ProxyActivityIndicator)

    # -------------------------------------------------------------------------
    # Observers
    # -------------------------------------------------------------------------
    @observe('size', 'color')
    def _update_proxy(self, change):
        """ An observer which sends the state change to the proxy.

        """
        # The superclass implementation is sufficient.
        super(ActivityIndicator, self)._update_proxy(change)
Beispiel #20
0
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[:]
Beispiel #21
0
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((
        "*",
        "+",
    ))
Beispiel #22
0
 class XYFormat(Atom):
     rend_list=List(default=[None, None, None]) #First is line, second is scatter #Typed(BaseXYPlot)
     name=Unicode()
     xname=Unicode()
     yname=Unicode()
     zname=Unicode()
     colormap=Enum("jet")
 
     line_color=Enum(*mycolors) #'blue', 'red', 'green', 'purple',  'black', 'darkgray', 'cyan', 'magenta', 'orange')
     plot_type=Enum('line', 'scatter', 'line+scatter')
     line_width=Float(1.0)
     marker = Enum('square', 'circle', 'triangle', 'inverted_triangle', 'plus', 'cross', 'diamond', 'dot', 'pixel')
     marker_size = Float(3.0)
     outline_color=Enum(*mycolors)
     outline_width=Float(1.0)
     inside_color=Enum(*mycolors)
     line_style=Enum('solid', 'dot dash', 'dash', 'dot', 'long dash')
     render_style=Enum('connectedpoints', 'hold', 'connectedhold')
     plotter=ForwardTyped(lambda: Plotter)
 
 
     def _default_name(self):
         return self.yname
 
     def set_param(self, param, change, index=-1):
         if change['type']!='create':
           #  if self.rend_list[index]!=None:
                 setattr(self.rend_list[index], param, change['value'])
                 #print self.rend_list
 
     def set_line_param(self, param, change):
         self.set_param(param, change, index=0)
     def set_scatter_param(self, param, change):
         self.set_param(param, change, index=1)
 
     def _observe_line_color(self, change):
         self.set_line_param('color', change)
 
     def _observe_marker_size(self, change):
         self.set_scatter_param('marker_size', change)
 
     def _observe_marker(self, change):
         self.set_scatter_param('marker', change)
 
     def _observe_line_width(self, change):
         self.set_line_param('line_width', change)
 
     def _observe_outline_width(self, change):
         self.set_scatter_param('line_width', change)
 
     def _observe_outline_color(self, change):
         self.set_scatter_param('outline_color', change)
 
     def _observe_inside_color(self, change):
         self.set_scatter_param('color', change)
 
     def _observe_line_style(self, change):
         self.set_line_param('line_style', change)
 
     def redraw_plot(self):
         self.draw_plot(name=self.name, zname=self.zname, xname=self.xname)
 
     def draw_img_plot(self, name, zname, xname=None, yname=None):
         self.plotter.delete_all_plots()
         self.name=name
         self.zname=zname
         #self.plotter.pd.set_data(zname, z)
         img_plot = self.plotter.plot.img_plot(self.zname,
                                               name="img_plot",
                     colormap=self.colormap)[0]
 #        z_shape=shape(self.plotter.pd.get_data(self.zname))
         #xdata=img_plot.index.get_data()[0].get_data()
         #ydata=img_plot.index.get_data()[1].get_data()
         if xname!=None:
             xdata=self.plotter.get_data(xname)
         else:
             xdata=img_plot.index.get_data()[0].get_data()
         if yname!=None:
             ydata=self.plotter.get_data(yname)
         else:
             ydata=img_plot.index.get_data()[1].get_data()
         img_plot.index.set_data(xdata,ydata)
         img_plot.request_redraw()
         self.rend_list[2]=img_plot
 
     def draw_plot(self, name, zname, zdata=None, xname='', xdata=None):
         if "img_plot" in self.plotter.plot.plots.keys():
             self.plotter.delete_all_plots()
         if "{0}_line".format(name) in self.plotter.plot.plots.keys():
             self.plotter.plot.delplot("{0}_line".format(name))
         if "{0}_scatter".format(name) in self.plotter.plot.plots.keys():
             self.plotter.plot.delplot("{0}_scatter".format(name))
         #if xname==None:
         #    xname="{0}_x0".format(zname)
         #    self.plotter.pd.set_data(xname, arange(len(self.plotter.pd.arrays[zname])))
         self.xname=xname
         self.zname=zname
         self.name=name
         if self.plot_type=='line':
             self.draw_line_plot()
         elif self.plot_type=='scatter':
             self.draw_scatter_plot()
         elif self.plot_type=='line+scatter':
             self.draw_line_plot()
             self.draw_scatter_plot()
 
 #        if data.x_unit:
 #            x_label = "{} [{}]".format(data.x_label, data.x_unit)
 #        else:
 #            x_label = data.x_label
 #        if data.y_unit:
 #            y_label = "{} [{}]".format(data.y_label, data.y_unit)
 #        else:
 #            y_label = data.y_label
 #        plot.x_axis.title = x_label
 #        plot.y_axis.title = y_label
 #        plot.x_axis.tick_label_formatter = lambda x: '%.e'%x
 #        plot.y_axis.tick_label_formatter = lambda x: '%.e'%x
 
 
     def draw_line_plot(self):
         renderer=self.plotter.plot.plot( self.zname ,
            name="{0}_line".format(self.name),
            type="line",
            line_width=self.line_width,
            color=self.line_color,
            render_style=self.render_style,
            value_scale=self.plotter.value_scale,
            index_scale=self.plotter.index_scale
            )[0]
         xdata=self.plotter.get_data(self.xname)   
         if xdata!=None:
                 renderer.index.set_data(xdata)
         renderer.request_redraw()
         self.rend_list[0]=renderer
 
     def draw_scatter_plot(self):
         renderer=self.plotter.plot.plot(self.zname,
            name="{0}_scatter".format(self.name), #self.zname,
            type="scatter", #self.xyformat.plot_type,
            line_width=self.line_width,
            color=self.inside_color,
            outline_color=self.outline_color,
            marker = self.marker,
            marker_size = self.marker_size,
            value_scale=self.plotter.value_scale,
            index_scale=self.plotter.index_scale
            )[0]
         xdata=self.plotter.get_data(self.xname)   
         if xdata!=None:
                 renderer.index.set_data(xdata)
         renderer.request_redraw()
         self.rend_list[1]=renderer
Beispiel #23
0
 class Plotter(Atom):
      name=Unicode()
      title=Unicode("yoyoyoyoyo")
      xlabel=Unicode()
      ylabel=Unicode()
 
      xyfs=Dict()
      #pd=Typed(ArrayPlotData, ())
      plot= ForwardTyped(lambda: Plot)
      color_index=Int()
      clts=Dict()
      fig=Typed(Figure)
      axe=Typed(Axes)
      #clt=Typed(PolyCollection)
      plottables=Dict()
 
      overall_plot_type=Enum("XY", "img", "polygon")
      value_scale=Enum('linear', 'log')
      index_scale=Enum('linear', 'log')
 
      #def _default_clt(self):
      #    return PolyCollection([((0,0), (0,0))], alpha=0.6, antialiased=True)#, rasterized=False, antialiased=False)
      
      def _default_axe(self):
          axe=self.fig.add_subplot(111)
          axe.autoscale_view(True)
          return axe
          
      def _default_fig(self):
          return Figure()
 
      def _observe_value_scale(self, change):
          if self.overall_plot_type=="XY plot":
              self.plot.value_scale=self.value_scale
              self.plot.request_redraw()
 
      def _observe_index_scale(self, change):
          if self.overall_plot_type=="XY plot":
              self.plot.index_scale=self.index_scale
              self.plot.request_redraw()
 
      def _default_plottables(self):
          return dict(plotted=[None])
 
      def _observe_title(self, change):
          self.axe.set_title(self.title)
          #self.plot.request_redraw()
 
      def _observe_xlabel(self, change):
          self.axe.set_xlabel(self.xlabel)
          #self.plot.x_axis.title=self.xlabel
          #self.plot.request_redraw()
 
      def _observe_ylabel(self, change):
          self.axe.set_ylabel(self.ylabel)
 #         self.plot.request_redraw()
 
      def _default_xyfs(self):
          xyf=AllXYFormat(plotter=self)
          return {"All":xyf}
 
      def delete_all_plots(self):
          for key in self.plot.plots.keys():
                 self.plot.delplot(key)
          self.color_index=0
 
      def _save(self):
          global PlotGraphicsContext
          if PlotGraphicsContext==None:
              from chaco.plot_graphics_context import PlotGraphicsContext
          win_size = self.plot.outer_bounds
          plot_gc = PlotGraphicsContext(win_size)#, dpi=300)
          plot_gc.render_component(self.plot)
          plot_gc.save("image_test.png")
 
      def set_data(self, zname, zdata, zcolor):
          if zdata!=None:
              if self.overall_plot_type=="polygon":
                 if zname not in self.clts: #plottables['plotted']:#self.pd.list_data():
                     clt=PolyCollection(zdata, alpha=0.5, antialiased=True)#, rasterized=False, antialiased=False)
                     clt.set_color(colorConverter.to_rgba(zcolor))                
                     self.clts[zname]=clt
                     self.axe.add_collection(self.clts[zname], autolim=True)
                 else:                
                     self.clts[zname].set_verts(zdata)
              if self.overall_plot_type=="XY":
                  if zname not in self.clts:
                      clt = LineCollection(zdata)#, offsets=offs)
                      clt.set_color(colors)
                      #print dir(clt)
                      self.clts[zname]=clt
                      self.axe.add_collection(self.clts[zname], autolim=True)
                      self.axe.autoscale_view()
                  else:
                      self.clts[zname].set_segments(zdata)
              if self.overall_plot_type=="img":
                  if zname not in self.clts:
                      axeimg=self.axe.imshow( Magvec, 
                                             vmin=amin(Magvec),
                                             vmax=0.001, #amax(Magvec), 
                                             aspect="auto", origin="lower",
                                      extent=[amin(yoko),amax(yoko), amin(freq),amax(freq)],
                                      #cmap='RdBu'
                                      )
                      self.fig.colorbar(axeimg)
      def draw(self):
          if self.fig.canvas!=None:
              #trans = transforms.Affine2D().scale(self.fig.dpi/72.0)
              #self.clt.set_transform(trans)  # the points to pixels transform
              #self.clt.set_color(colors)
          
              #self.axe.autoscale_view(True)
              self.fig.canvas.draw()
 
      def set_xlim(self, xmin, xmax):
          self.axe.set_xlim(xmin, xmax)
 
      def set_ylim(self, ymin, ymax):
          self.axe.set_ylim(ymin, ymax)
          
      def get_data(self, zname, index=None, axis=0):
         data=[c.to_polygons() for c in self.clt.get_paths()]
         if index==None:
             return data
         if axis==0:
             return atleast_2d(data)[index, :]
         return atleast_2d(data)[:, index]
         
      def add_poly_plot_old(self, n, verts, cn="green", polyname=""):
          nxarray, nyarray = transpose(verts)
          xname=polyname+"x" + str(n)
          yname=polyname+"y" + str(n)
          self.pd.set_data(xname, nxarray, coord='x') #coord='x' is likely redundant or a metadata tag
          self.pd.set_data(yname, nyarray, coord='y')
          self.plot.plot((xname, yname),
                           type="polygon",
                           face_color=cn, #colors[nsides],
                           hittest_type="poly")[0]
 
      def add_poly_plot(self, n, verts, cn="green", polyname=""):
         #for n,p in enumerate(self.polylist):
             log_debug("drawing polygon #: {0}".format(n))
             #npoints = p.verts #n_gon(center=p, r=2, nsides=nsides)
             nxarray, nyarray = transpose(verts)
             self.pd.set_data("x" + str(n), nxarray)
             self.pd.set_data("y" + str(n), nyarray)
             log_debug("data set")            
             self.plot.plot(("x"+str(n), "y"+str(n)),
                           type="polygon",
                           face_color=cn, #colors[nsides],
                           hittest_type="poly"
                           )[0]
             log_debug("plot occured")
 
      def add_img_plot(self, zname, zdata, xname=None, xdata=None, yname=None,  ydata=None):
          self.add_data(zname=zname, zdata=zdata, xname=xname, xdata=xdata, yname=yname, ydata=ydata, overwrite=True, concat=False)
          print self.pd.get_data(zname)
          xyf=XYFormat(plotter=self)
          xyf.draw_img_plot(name='img_plot', zname=zname, xname=xname, yname=yname)
          self.xyfs.update(**{xyf.name: xyf})
          self.overall_plot_type="img plot"
 
      def add_line_plot(self, name, zname, zdata, xname='', xdata=None):
         #self.add_data(zname=zname, zdata=zdata, xname=xname, xdata=xdata, overwrite=True)
         self.set_data(zname, zdata)
         self.set_data(xname, xdata)
         xyf=XYFormat(plotter=self)
         zdata=self.get_data(zname)
         #if 1: #zdata.ndim>1:
         #    for i, arr in enumerate(self.splitMultiD(zdata, 0)):
         #        self.add_line_plot(name+str(i), zname+str(i), squeeze(arr), xname, xdata )
         #else:
             #self.set_data(zname, zdata)
             #if xname!=None and xdata!=None:
             #    self.set_data(xname, xdata, coord='x')
         xyf.draw_plot(name=name, zname=zname, xname=xname)
         self.xyfs.update(**{xyf.name: xyf})
         self.overall_plot_type="XY plot"
 
 #     def append_data(self, name, zpoint, xpoint=None):
 #         xyf=self.xyfs[name]
 #         zdata=self.pd.get_data(xyf.zname)
 #         zdata=append(zdata, zpoint)
 #         self.pd.set_data(xyf.zname, zdata)
 #         xdata=self.pd.get_data(xyf.xname)
 #         if xpoint==None:
 #             xpoint=max(xdata)+range(len(zpoint))+1
 #         xdata=append(xdata, xpoint)
 #         self.pd.set_data(xyf.xname, xdata)
 
 #     def _default_plot(self):
 #        global Plot, PanTool, ZoomTool, LegendTool
 #        if Plot==None:
 #            from chaco.plot import Plot
 #        if PanTool==None or ZoomTool==None or LegendTool==None:
 #            from chaco.tools.api import PanTool, ZoomTool,  LegendTool #, LineInspector
 #
 #        plot=Plot(self.pd, padding=50, fill_padding=True,
 #                        bgcolor="white", use_backbuffer=True,  unified_draw=True)#, use_downsampling=True)
 #        plot.tools.append(PanTool(plot, constrain_key="shift"))
 #        plot.overlays.append(ZoomTool(component=plot, tool_mode="box", always_on=False))
 #        plot.legend.tools.append(LegendTool(plot.legend, drag_button="right"))
 #        return plot
 
      def splitMultiD(self, arr, axis=0):
         if arr.ndim<2:
             return atleast_2d(arr)
         else:
             return split(arr, arr.shape[axis], axis=axis)
 
      def gatherMultiD(self, name, arrs, appen=None, concat=True, overwrite=False):
          if not isinstance(arrs, tuple):
              arrs=(arrs,)
          if appen==None:
              if shape(arrs)==(1,):
                  appen=True
              else:
                  appen=False             
          orig=self.get_data(name)
          if orig!=None and not overwrite:
              arrs=(orig,)+arrs
          if appen:
              axis=1
          else:
              axis=0
          print arrs[0]==atleast_2d(*arrs)
          #if ndim(arrs[0])>1:
          #    concat=False
 
          if concat:             
              data=concatenate(atleast_2d(*arrs), axis)
          self.set_data(name, data)
  
      def add_data(self, zname, zdata, xname=None, xdata=None, yname=None, ydata=None, appen=None, concat=True, overwrite=False):
          if xname!=None:
              self.gatherMultiD(xname, xdata, appen=appen, overwrite=overwrite, concat=concat)
          if yname!=None:
              self.gatherMultiD(yname, ydata, appen=appen, overwrite=overwrite, concat=concat)
          self.gatherMultiD(zname, zdata, appen=appen, overwrite=overwrite, concat=concat)
          
      def show(self):
         with imports():
             from e_Plotter import PlotMain
         app = QtApplication()
         view = PlotMain(plotr=self)
         view.show()
         app.start()
Beispiel #24
0
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)
Beispiel #25
0
class Scintilla(Control):
    """ A Scintilla text editing control.

    Notes
    -----
    The 'background', 'foreground', and 'font' attributes have no effect
    on this widget. All styling is supplied via the 'theme' attribute.

    """
    #: Enable autocompletion
    autocomplete = d_(Enum('none', 'all', 'document', 'apis'))

    #: Autocompletion values and call signatures.
    #: Images can be used by appending "?<image_no>" to the completion value.
    #: The images are defined by passing a list of image paths as the
    #: "autocompletion_images" settings key.
    autocompletions = d_(List(str))

    #: Position of the cursor within the editor in the format (line, column)
    #: This is needed for autocompletion engines to determine the current text
    cursor_position = d_(Tuple(int, default=(0, 0)), writable=False)

    #: The scintilla document buffer to use in the editor. A default
    #: document will be created automatically for each editor. This
    #: value only needs to be supplied when swapping buffers or when
    #: using a single buffer in multiple editors.
    document = d_(Typed(ScintillaDocument, ()))

    #: The language syntax to apply to the document.
    syntax = d_(Enum(*SYNTAXES))

    #: The theme to apply to the widget. See the './THEMES' document
    #: for how to create a theme dict for the widget.
    theme = d_(Typed(dict, ()))

    #: The settings to apply to the widget. See the './SETTINGS'
    #: document for how to create a settings dict for the widget.
    settings = d_(Typed(dict, ()))

    #: The zoom factor for the editor. The value is internally clamped
    #: to the range -10 to 20, inclusive.
    zoom = d_(Int())

    #: An event emitted when the text is changed.
    text_changed = d_(Event(), writable=False)

    #: Text Editors expand freely in height and width by default.
    hug_width = set_default('ignore')
    hug_height = set_default('ignore')

    #: Markers to display.
    markers = d_(List(ScintillaMarker))

    #: Indicators to display.
    indicators = d_(List(ScintillaIndicator))

    #: A reference to the ProxyScintilla object.
    proxy = Typed(ProxyScintilla)

    #--------------------------------------------------------------------------
    # Post Validators
    #--------------------------------------------------------------------------
    def _post_validate_document(self, old, new):
        """ Post validate the text document.

        A new document is created when the existing document is set to
        None. This ensures that the proxy object never receives a null
        document and helps keep the state synchronized.

        """
        return new or ScintillaDocument()

    def _post_validate_theme(self, old, new):
        """" Post validate the theme.

        The theme is reset to an empty dictionary if set to None.

        """
        return new or {}

    def _post_validate_settings(self, old, new):
        """" Post validate the settings.

        The settings are reset to an empty dictionary if set to None.

        """
        return new or {}

    #--------------------------------------------------------------------------
    # Observers
    #--------------------------------------------------------------------------
    @observe('document', 'syntax', 'theme', 'settings', 'zoom', 'autocomplete',
             'autocompletions', 'indicators', 'markers')
    def _update_proxy(self, change):
        """ An observer which sends the document change to the proxy.

        """
        # The superclass implementation is sufficient.
        super(Scintilla, self)._update_proxy(change)

    #--------------------------------------------------------------------------
    # Public API
    #--------------------------------------------------------------------------
    def get_text(self):
        """ Get the text in the current document.

        Returns
        -------
        result : unicode
            The text in the current document.

        """
        if self.proxy_is_active:
            return self.proxy.get_text()
        return u''

    def set_text(self, text):
        """ Set the text in the current document.

        Parameters
        ----------
        text : unicode
            The text to apply to the current document.

        """
        if self.proxy_is_active:
            self.proxy.set_text(text)
Beispiel #26
0
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)
Beispiel #27
0
class DemodAlazarTask(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.
    """
    freq = Str('50').tag(pref=True)

    freqB = Str('50').tag(pref=True)

    timeaftertrig = Str('0').tag(pref=True)

    timeaftertrigB = Str('0').tag(pref=True)

    timestep = Str('0').tag(pref=True)

    timestepB = Str('0').tag(pref=True)

    tracetimeaftertrig = Str('0').tag(pref=True)

    tracetimeaftertrigB = Str('0').tag(pref=True)

    duration = Str('1000').tag(pref=True)

    durationB = Str('0').tag(pref=True)

    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)

    IQtracemode = Bool(False).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)

    powerBoolA = Bool(False).tag(pref=True)

    powerBoolB = Bool(False).tag(pref=True)

    aux_trig = Bool(False).tag(pref=True)

    database_entries = set_default({'Demod': {}, 'Trace': {}, 'Power': {}})

    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(DemodAlazarTask, 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)
        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 ((time, duration), (timeB, durationB),
                     (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 duration) and (0 in durationB) and (0 in traceduration)
                and (0 in tracedurationB)):
            test = False
            traceback[self.path + '/' + self.name + '-get_demod'] = \
                           cleandoc('''All measurements are disabled.''')

        timestep = self.format_string(self.timestep, 10**-9, len(time))
        timestepB = self.format_string(self.timestepB, 10**-9, len(timeB))
        freq = self.format_string(self.freq, 10**6, len(time))
        freqB = self.format_string(self.freqB, 10**6, len(timeB))
        samplesPerSec = 500000000.0

        if 0 in duration:
            duration = []
            timestep = []
            freq = []
        if 0 in durationB:
            durationB = []
            timestepB = []
            freqB = []

        for d, ts in zip(duration + durationB, timestep + timestepB):
            if ts and np.mod(int(samplesPerSec * d), int(samplesPerSec * ts)):
                test = False
                traceback[self.path + '/' + self.name + '-get_demod'] = \
                   cleandoc('''The number of samples in "IQ time step" must divide the number of samples in "Duration".''')

        for f, ts in zip(freq + freqB, timestep + timestepB):
            if ts and np.mod(f * int(samplesPerSec * ts), samplesPerSec):
                test = False
                traceback[self.path + '/' + self.name + '-get_demod'] = \
                   cleandoc('''The "IQ time step" does not cover an integer number of demodulation periods.''')

        demodFormFile = self.format_and_eval_string(self.demodFormFile)

        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''')

        #RAM estimation and test

        #Prepare the parameters
        recordsPerCapture = self.format_and_eval_string(self.tracesnumber)
        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)
        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)
        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 = []
        NtraceA = len(tracedurationA)
        if 0 in tracedurationA:
            NtraceA = 0
            tracetimeA = []
            tracedurationA = []
        NtraceB = len(tracedurationB)
        if 0 in tracedurationB:
            NtraceB = 0
            tracetimeB = []
            tracedurationB = []
        if len(demodFormFile) == 0:
            demodCosinus = 1
        else:
            demodCosinus = 0

        startaftertrig = timeA + timeB + tracetimeA + tracetimeB
        duration = durationA + durationB + tracedurationA + tracedurationB
        timestepA = self.format_string(self.timestep, 10**-9, NdemodA)
        timestepB = self.format_string(self.timestepB, 10**-9, NdemodB)
        timestep = timestepA + timestepB
        freqA = self.format_string(self.freq, 10**6, NdemodA)
        freqB = self.format_string(self.freqB, 10**6, NdemodB)
        freq = freqA + freqB
        samplesPerSec = 500000000.0

        #Initialize the RAM quantities
        size_data = 0
        RAM_DEMOD = 0  #RAM coming from demodulations
        RAM_TRACE = 0  #RAM coming from traces
        RAM_list = [
        ]  #storage of the RAM estimations from each demodulation/trace

        #Quantities of reference
        RAM_USAGE_1_REF = 15.265243530273438  #15.265243530273438 MB = deep_getsizeof(data,set())/(1024*1024)
        #where data is generated with NdemodA=1,duration=200e-9,recordsPerCapture=20000 (these are the parameters relevant to the size of data) and timestep=20ns
        #NOTE : the deep_getsizeof function can be found at github.com/the-gigi/deep/blob/master/deeper.py, line 80 (thanks to the author by the way)
        RAM_USAGE_2_REF = 0.1529388427734375  #0.1530609130859375 MB = deepgetsizeof(np.empty((20000,1)),set())/(1024*1024)

        #Calculate the RAM needed
        samplesPerDemod_RAM = []

        #Calculate RAM_DEMOD (in MB) coming from demodulations
        for i in range(NdemodA + NdemodB):
            samplesPerDemod_RAM.append(int(samplesPerSec * duration[i]))

            if timestep[i] or not demodCosinus:
                RAM_DEMOD += RAM_USAGE_1_REF * (duration[i] / 200e-9) * (
                    recordsPerCapture / 20000)
                RAM_list.append(RAM_USAGE_1_REF * (duration[i] / 200e-9) *
                                (recordsPerCapture / 20000))

            else:
                # Check wheter it is possible to cut each record in blocks of size equal
                # to an integer number of periods
                periodsPerBlock = 1
                while (periodsPerBlock * samplesPerSec <
                       freq[i] * samplesPerDemod_RAM[i]
                       and periodsPerBlock * samplesPerSec % freq[i]):
                    periodsPerBlock += 1
                RAM_DEMOD += RAM_USAGE_2_REF * (
                    recordsPerCapture / 20000) * int(
                        np.minimum(periodsPerBlock * samplesPerSec / freq[i],
                                   samplesPerDemod_RAM[i]))
                RAM_list.append(RAM_DEMOD)
                #We make the assumption that the size of np.empty((a,b)) becomes linearly dependent on a and b at sufficiently high vallues
                #of a and b. Here, recordsPerCapture will not be under 1000, which guaranties this assumption

        #Calculate RAM_TRACE (in MB) coming from traces
        for i in (np.arange(NtraceA + NtraceB) + NdemodA + NdemodB):
            RAM_TRACE += RAM_USAGE_1_REF * (duration[i] / 200e-9) * (
                recordsPerCapture / 20000)
            RAM_list.append(RAM_USAGE_1_REF * (duration[i] / 200e-9) *
                            (recordsPerCapture / 20000))

        size_data = RAM_DEMOD + RAM_TRACE  #RAM used by the data array in MB

        #Determine the heights of RAM peaks linked to the wanted demodulations/traces
        RAM_peaks = []
        for k in range(len(RAM_list)):
            RAM_peaks.append(RAM_list[k] * 3 + (size_data - RAM_list[k]))
            #The demodulation/trace being calculated takes 3 times the RAM needed by its
            #data and we still have to take into account the RAM taken by the other demodulation/traces that have been or will be processed.
        estimation = max(
            RAM_peaks
        )  #The higher peak is the one that matters to determine if the calculation is possible or not
        estimation = (estimation / 1024)  #Conversion into GB

        #In the case with no timestep, we have to take into account the RAM used by the buffers
        RAM_BUFFERS_REF = 1.0  #RAM (in GB) used by buffers with following parameters : recordsPerCapture = 1000000 ; duration = 1000ns
        #(it has been measured)
        total_duration_max = np.max(
            np.array(startaftertrig) + np.array(duration))
        RAM_BUFFERS = RAM_BUFFERS_REF * (recordsPerCapture / 1000000) * (
            total_duration_max / 1000e-9)

        if len(timestep) != 0 and not timestep[0]:
            estimation = max(
                estimation, RAM_BUFFERS
            )  #measurements showed that the higher quantity overshadows the other and is the one
            #that matter for the RAM used in the end

        #Retrieval of quantities of available RAM : physical and total (physical+virtual) and conversion into GB
        RAM_physique_dispo = psutil.virtual_memory()[1] / (1024**3)
        RAM_totale_dispo = psutil.swap_memory()[2] / (1024**3)

        if (estimation + 2) > RAM_physique_dispo:
            test = False
            traceback[self.path + '/' + self.name + '-get_demod'] = \
                cleandoc('''Available RAM may be insufficient. RAM needed for this calculation = '''+str(round(estimation,3))+''' (+1/-2) GB VS Available physical RAM = '''+str(round(RAM_physique_dispo,3))+''' GB and Total available RAM (physical and virtual) = '''+str(round(RAM_totale_dispo,3))+''' GB.''')

        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)

        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)
        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)
        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 = []
        NtraceA = len(tracedurationA)
        if 0 in tracedurationA:
            NtraceA = 0
            tracetimeA = []
            tracedurationA = []
        NtraceB = len(tracedurationB)
        if 0 in tracedurationB:
            NtraceB = 0
            tracetimeB = []
            tracedurationB = []
        if len(demodFormFile) == 0:
            demodCosinus = 1
        else:
            demodCosinus = 0

        startaftertrig = timeA + timeB + tracetimeA + tracetimeB
        duration = durationA + durationB + tracedurationA + tracedurationB

        timestepA = self.format_string(self.timestep, 10**-9, NdemodA)
        timestepB = self.format_string(self.timestepB, 10**-9, NdemodB)
        timestep = timestepA + timestepB
        freqA = self.format_string(self.freq, 10**6, NdemodA)
        freqB = self.format_string(self.freqB, 10**6, NdemodB)
        freq = freqA + freqB

        power = [self.powerBoolA, self.powerBoolB]

        answerDemod, answerTrace, answerPower = self.driver.get_demod(
            startaftertrig, duration, recordsPerCapture, recordsPerBuffer,
            timestep, freq, self.average, NdemodA, NdemodB, NtraceA, NtraceB,
            Npoints, demodFormFile, demodCosinus, self.aux_trig, power)

        self.write_in_database('Demod', answerDemod)
        self.write_in_database('Trace', answerTrace)
        self.write_in_database('Power', answerPower)
Beispiel #28
0
class Driver(Declarator):
    """Declarator used to register a new driver for an instrument.

    """
    #: Path to the driver object. Path should be dot separated and the class
    #: name preceded by ':'.
    #: TODO complete : ex: ecpy_hqc_legacy.instruments.
    #: The path of any parent Drivers object will be prepended to it.
    driver = d_(Unicode())

    #: Name identifying the system the driver is built on top of (lantz, hqc,
    #: slave, etc ...). Allow to handle properly multiple drivers declared in
    #: a single extension package for the same instrument.
    architecture = d_(Unicode())

    #: Name of the instrument manufacturer. Can be inferred from parent
    #: Drivers.
    manufacturer = d_(Unicode())

    #: Serie this instrument is part of. This is optional as it does not always
    #: make sense to be specified but in some cases it can help finding a
    #: a driver. Can be inferred from parent Drivers.
    serie = d_(Unicode())

    #: Model of the instrument this driver has been written for.
    model = d_(Unicode())

    #: Kind of the instrument, to ease instrument look up. If no kind match,
    #: leave 'Other' as the kind. Can be inferred from parent
    #: Drivers.
    kind = d_(Enum(None, *INSTRUMENT_KINDS))

    #: Starter to use when initializing/finialzing this driver.
    #: Can be inferred from parent Drivers.
    starter = d_(Unicode())

    #: Supported connections and default values for some parameters. The
    #: admissible values for a given kind can be determined by looking at the
    #: Connection object whose id match.
    #: ex : {'visa_tcpip' : {'port': 7500, 'resource_class': 'SOCKET'}}
    #: Can be inferred from parent Drivers.
    connections = d_(Dict())

    #: Special settings for the driver, not fitting the connections. Multiple
    #: identical connection infos with different settings can co-exist in a
    #: profile. The admissible values for a given kind can be determined by
    #: looking at the Settings object whose id match.
    #: ex : {'lantz': {'resource_manager': '@py'}}
    #: Can be inferred from parent Drivers.
    settings = d_(Dict())

    #: Id of the driver computed from the top-level package and the driver name
    id = Property(cached=True)

    def register(self, collector, traceback):
        """Collect driver and add infos to the DeclaratorCollector
        contributions member.

        """
        # Build the driver id by assembling the package name, the architecture
        # and the class name
        try:
            driver_id = self.id
        except KeyError:  # Handle the lack of architecture
            traceback[self.driver] = format_exc()
            return

        # Determine the path to the driver.
        path = self.get_path()
        try:
            d_path, driver = (path + '.' +
                              self.driver if path else self.driver).split(':')
        except ValueError:
            msg = 'Incorrect %s (%s), path must be of the form a.b.c:Class'
            traceback[driver_id] = msg % (driver_id, self.driver)
            return

        # Check that the driver does not already exist.
        if driver_id in collector.contributions or driver_id in traceback:
            i = 0
            while True:
                i += 1
                err_id = '%s_duplicate%d' % (driver_id, i)
                if err_id not in traceback:
                    break

            msg = 'Duplicate definition of {}, found in {}'
            traceback[err_id] = msg.format(self.architecture + '.' + driver,
                                           d_path)
            return

        try:
            meta_infos = {
                k: getattr(self, k)
                for k in ('architecture', 'manufacturer', 'serie', 'model',
                          'kind')
            }
            infos = DriverInfos(id=driver_id,
                                infos=meta_infos,
                                starter=self.starter,
                                connections=self.connections,
                                settings=self.settings)
        # ValueError catch wrong kind value
        except (KeyError, ValueError):
            traceback[driver_id] = format_exc()
            return

        # Get the driver class.
        d_cls = import_and_get(d_path, driver, traceback, driver_id)
        if d_cls is None:
            return

        try:
            infos.cls = d_cls
        except TypeError:
            msg = '{} should be a callable.\n{}'
            traceback[driver_id] = msg.format(d_cls, format_exc())
            return

        collector.contributions[driver_id] = infos

        self.is_registered = True

    def unregister(self, collector):
        """Remove contributed infos from the collector.

        """
        if self.is_registered:

            # Remove infos.
            driver_id = self.id
            try:
                del collector.contributions[driver_id]
            except KeyError:
                pass

            self.is_registered = False

    def __str__(self):
        """Identify the decl by its members.

        """
        members = ('driver', 'architecture', 'manufacturer', 'serie', 'model',
                   'kind', 'starter', 'connections', 'settings')
        st = '{} whose known members are :\n{}'
        st_m = '\n'.join(' - {} : {}'.format(m, v)
                         for m, v in [(m, getattr(self, m)) for m in members])
        return st.format(type(self).__name__, st_m)

    # =========================================================================
    # --- Private API ---------------------------------------------------------
    # =========================================================================

    def _default_manufacturer(self):
        """Default value grabbed from parent if not provided explicitely.

        """
        return self._get_inherited_member('manufacturer')

    def _default_serie(self):
        """Default value grabbed from parent if not provided explicitely.

        """
        return self._get_inherited_member('serie')

    def _default_kind(self):
        """Default value grabbed from parent if not provided explicitely.

        """
        return self._get_inherited_member('kind')

    def _default_architecture(self):
        """Default value grabbed from parent if not provided explicitely.

        """
        return self._get_inherited_member('architecture')

    def _default_starter(self):
        """Default value grabbed from parent if not provided explicitely.

        """
        return self._get_inherited_member('starter')

    def _default_connections(self):
        """Default value grabbed from parent if not provided explicitely.

        """
        return self._get_inherited_member('connections')

    def _default_settings(self):
        """Default value grabbed from parent if not provided explicitely.

        """
        return self._get_inherited_member('settings')

    def _get_inherited_member(self, member, parent=None):
        """Get the value of a member found in a parent declarator.

        """
        parent = parent or self.parent
        if isinstance(parent, Drivers):
            value = getattr(parent, member)
            if value:
                return value
            else:
                parent = parent.parent
        else:
            parent = None

        if parent is None:
            if member == 'settings':
                return {}  # Settings can be empty
            elif member == 'serie':
                return ''  # An instrument can have no serie
            elif member == 'kind':
                return 'Other'
            raise KeyError('No inherited member was found for %s' % member)

        return self._get_inherited_member(member, parent)

    def _get_id(self):
        """Create the unique identifier of the driver using the top level
        package the architecture and the class name.

        """
        if ':' in self.driver:
            path = self.get_path()
            d_path, d = (path + '.' +
                         self.driver if path else self.driver).split(':')

            # Build the driver id by assembling the package name, architecture
            # and the class name
            return '.'.join((d_path.split('.', 1)[0], self.architecture, d))

        else:
            return self.driver
Beispiel #29
0
class Widget(ToolkitObject):
    """ The base class of visible widgets in Enaml.

    """
    #: Whether or not the widget is enabled.
    enabled = d_(Bool(True))

    #: Whether or not the widget is visible.
    visible = d_(Bool(True))

    #: The background color of the widget.
    background = d_(ColorMember())
    # TODO remove in Enaml version 0.8.0
    bgcolor = _warn_prop('bgcolor', 'background')

    #: The foreground color of the widget.
    foreground = d_(ColorMember())
    # TODO remove in Enaml version 0.8.0
    fgcolor = _warn_prop('fgcolor', 'foreground')

    #: The font used for the widget.
    font = d_(FontMember())

    #: The minimum size for the widget. The default means that the
    #: client should determine an intelligent minimum size.
    minimum_size = d_(Coerced(Size, (-1, -1)))

    #: The maximum size for the widget. The default means that the
    #: client should determine and inteliigent maximum size.
    maximum_size = d_(Coerced(Size, (-1, -1)))

    #: The tool tip to show when the user hovers over the widget.
    tool_tip = d_(Unicode())

    #: The status tip to show when the user hovers over the widget.
    status_tip = d_(Unicode())

    #: A flag indicating whether or not to show the focus rectangle for
    #: the given widget. This is not necessarily support by all widgets
    #: on all clients. A value of None indicates to use the default as
    #: supplied by the client.
    show_focus_rect = d_(Enum(None, True, False))

    #: A reference to the ProxyWidget object.
    proxy = Typed(ProxyWidget)

    #--------------------------------------------------------------------------
    # Observers
    #--------------------------------------------------------------------------
    @observe(('enabled', 'visible', 'background', 'foreground', 'font',
        'minimum_size', 'maximum_size', 'show_focus_rect', 'tool_tip',
        'status_tip'))
    def _update_proxy(self, change):
        """ Update the proxy widget when the Widget data changes.

        This method only updates the proxy when an attribute is updated;
        not when it is created or deleted.

        """
        # The superclass implementation is sufficient.
        super(Widget, self)._update_proxy(change)

    #--------------------------------------------------------------------------
    # Public API
    #--------------------------------------------------------------------------
    def show(self):
        """ Ensure the widget is shown.

        Calling this method will also set the widget visibility to True.

        """
        self.visible = True
        if self.proxy_is_active:
            self.proxy.ensure_visible()

    def hide(self):
        """ Ensure the widget is hidden.

        Calling this method will also set the widget visibility to False.

        """
        self.visible = False
        if self.proxy_is_active:
            self.proxy.ensure_hidden()
Beispiel #30
0
class Field(Control):
    """ A single line editable text widget.

    """
    #: The unicode text to display in the field.
    text = d_(Unicode())

    #: The mask to use for text input:
    #:  http://qt-project.org/doc/qt-4.8/qlineedit.html#inputMask-prop
    #:
    #: The summary of the mask grammar is as follows:
    #: A   ASCII alphabetic character required. A-Z, a-z.
    #: a   ASCII alphabetic character permitted but not required.
    #: N   ASCII alphanumeric character required. A-Z, a-z, 0-9.
    #: n   ASCII alphanumeric character permitted but not required.
    #: X   Any character required.
    #: x   Any character permitted but not required.
    #: 9   ASCII digit required. 0-9.
    #: 0   ASCII digit permitted but not required.
    #: D   ASCII digit required. 1-9.
    #: d   ASCII digit permitted but not required (1-9).
    #: #   ASCII digit or plus/minus sign permitted but not required.
    #: H   Hexadecimal character required. A-F, a-f, 0-9.
    #: h   Hexadecimal character permitted but not required.
    #: B   Binary character required. 0-1.
    #: b   Binary character permitted but not required.
    #: >   All following alphabetic characters are uppercased.
    #: <   All following alphabetic characters are lowercased.
    #: !   Switch off case conversion.
    #: \   Use \ to escape the special characters listed above to use them as separators.
    #:
    #: The mask consists of a string of mask characters and separators, optionally
    #: followed by a semicolon and the character used for blanks
    #: Eg: 9 digit phone number: (999) 999-9999;_
    mask = d_(Unicode())

    #: The validator to use for this field. If the validator provides
    #: a client side validator, then text will only be submitted if it
    #: passes that validator.
    validator = d_(Typed(Validator))

    #: The list of actions which should cause the client to submit its
    #: text to the server for validation and update. The currently
    #: supported values are 'lost_focus', 'return_pressed', and 'auto_sync'.
    #: The 'auto_sync' mode will attempt to validate and synchronize the
    #: text when the user stops typing.
    submit_triggers = d_(
        List(Enum('lost_focus', 'return_pressed', 'auto_sync'),
             ['lost_focus', 'return_pressed']))

    #: The grayed-out text to display if the field is empty and the
    #: widget doesn't have focus. Defaults to the empty string.
    placeholder = d_(Unicode())

    #: How to display the text in the field. Valid values are 'normal'
    #: which displays the text as normal, 'password' which displays the
    #: text with an obscured character, and 'silent' which displays no
    #: text at all but still allows input.
    echo_mode = d_(Enum('normal', 'password', 'silent'))

    #: The maximum length of the field in characters. The default value
    #: is Zero and indicates there is no maximum length.
    max_length = d_(Int(0))

    #: Whether or not the field is read only. Defaults to False.
    read_only = d_(Bool(False))

    #: Alignment for the text inside the field. Defaults to 'left'.
    text_align = d_(Enum('left', 'right', 'center'))

    #: How strongly a component hugs it's contents' width. Fields ignore
    #: the width hug by default, so they expand freely in width.
    hug_width = set_default('ignore')

    #: A reference to the ProxyField object.
    proxy = Typed(ProxyField)

    #--------------------------------------------------------------------------
    # Observers
    #--------------------------------------------------------------------------
    @observe('text', 'mask', 'submit_triggers', 'placeholder', 'echo_mode',
             'max_length', 'read_only', 'text_align')
    def _update_proxy(self, change):
        """ An observer which sends state change to the proxy.

        """
        # The superclass implementation is sufficient.
        super(Field, self)._update_proxy(change)

    #--------------------------------------------------------------------------
    # Public API
    #--------------------------------------------------------------------------
    def field_text(self):
        """ Get the text stored in the field control.

        Depending on the state of the field, this text may be different
        than that stored in the 'text' attribute.

        Returns
        -------
        result : unicode
            The unicode text stored in the field.

        """
        if self.proxy_is_active:
            return self.proxy.field_text()
        return u''