Esempio n. 1
0
class CalibrationObject(HasTraits):
    tweak_dict = Dict
    cx = Float
    cy = Float
    rx = Float
    ry = Float

    rotation = Property(depends_on='rx,ry,_rotation')
    _rotation = Float
    center = Property(depends_on='cx,cy')
    scale = Float(1)

    def _set_rotation(self, rot):
        self._rotation = rot

    def _get_rotation(self):
        # if not (self.rx and self.rx):
        #     return self._rotation
        rot = self._rotation
        if not rot:
            rot = self.calculate_rotation(self.rx, self.ry)
        return rot

    def _get_center(self):
        return self.cx, self.cy

    def set_right(self, x, y):
        self.rx = x
        self.ry = y
        self._rotation = 0

    def set_center(self, x, y):
        self.cx = x
        self.cy = y

    def calculate_rotation(self, x, y, sense='east'):
        def rotation(a, b):
            return calc_rotation(self.cx, self.cy, a, b)

        if sense == 'west':
            print('x={}, y={}, cx={}, cy={}'.format(x, y, self.cx, self.cy))
            if y > self.cy:
                rot = calc_rotation(self.cx, self.cy, x, y) - 180
            else:
                rot = calc_rotation(self.cx, self.cy, x, y) + 180
        elif sense == 'north':
            if x > self.cx:
                rot = rotation(x, -y)
            else:
                rot = rotation(y, -x)
        elif sense == 'south':
            rot = rotation(-y, x)
        else:
            rot = rotation(x, y)

        return rot
Esempio n. 2
0
class PadEntry(HasTraits):
    pad = Float
    olow_post = Date
    ohigh_post = Date

    low_post = Property(depends_on='low_post_data, low_post_time')
    low_post_date = Date
    low_post_time = Time

    high_post = Property(depends_on='high_post_data, high_post_time')
    high_post_date = Date
    high_post_time = Time

    def update_pad(self):
        self._pad_changed(self.pad)

    def _pad_changed(self, pad):
        if self.olow_post and self.ohigh_post:
            td = timedelta(hours=pad)
            lp, hp = self.olow_post, self.ohigh_post

            lp -= td
            hp += td

            self.low_post, self.high_post = lp, hp

    def _set_high_post(self, v):
        self.high_post_date = v.date()
        self.high_post_time = v.time()

    def _set_low_post(self, v):
        self.low_post_date = v.date()
        self.low_post_time = v.time()

    def _get_high_post(self):
        return datetime.combine(self.high_post_date, self.high_post_time)

    def _get_low_post(self):
        return datetime.combine(self.low_post_date, self.low_post_time)

    def traits_view(self):
        l = VGroup(UItem('low_post_time'),
                   UItem('low_post_date', style='custom'))
        h = VGroup(UItem('high_post_time'),
                   UItem('high_post_date', style='custom'))

        v = View(UItem('pad'),
                 HGroup(l, h),
                 kind='livemodal',
                 width=500,
                 resizable=True,
                 buttons=['OK', 'Cancel'])
        return v
Esempio n. 3
0
class PadEntry(HasTraits):
    pad = Float
    olow_post = Date
    ohigh_post = Date

    low_post = Property(depends_on='low_post_data, low_post_time')
    low_post_date = Date
    low_post_time = Time

    high_post = Property(depends_on='high_post_data, high_post_time')
    high_post_date = Date
    high_post_time = Time

    def update_pad(self):
        self._pad_changed(self.pad)

    def _pad_changed(self, pad):
        if self.olow_post and self.ohigh_post:
            td = timedelta(hours=pad)
            lp, hp = self.olow_post, self.ohigh_post

            lp -= td
            hp += td

            self.low_post, self.high_post = lp, hp

    def _set_high_post(self, v):
        self.high_post_date = v.date()
        self.high_post_time = v.time()

    def _set_low_post(self, v):
        self.low_post_date = v.date()
        self.low_post_time = v.time()

    def _get_high_post(self):
        return datetime.combine(self.high_post_date, self.high_post_time)

    def _get_low_post(self):
        return datetime.combine(self.low_post_date, self.low_post_time)

    def traits_view(self):
        l = VGroup(UItem('low_post_time'),
                   UItem('low_post_date', style='custom'))
        h = VGroup(UItem('high_post_time'),
                   UItem('high_post_date', style='custom'))

        v = okcancel_view(Item('pad', label='Pad (hrs)'),
                          HGroup(l, h),
                          width=500)
        return v
class MandelbrotParameters(HasTraits):
    """ Stores the parameters needed to visualize the Mandelbrot set.
    """

    # The number of points on each dimension of the grid.
    grid_size = Int(500)

    # Left limit for the x coordinates.
    xmin = Float(-2.0)

    # Right limit for the x coordinates.
    xmax = Float(1.0, auto_set=False)

    # Bottom limit for the y coordinates.
    ymin = Float(-1.5, auto_set=False)

    # Upper limit for the y coordinates.
    ymax = Float(1.5, auto_set=False)

    # Convenience property that returns a tuple with the bounds on the x axis.
    x_bounds = Property
    def _get_x_bounds(self):
        return (self.xmin, self.xmax)

    # 1D array with the x coordinates of the boundaries of the grid element.
    x_coords = Property
    def _get_x_coords(self):
        # The coordinates have 1 more element than the number of points in
        # the grid, because they represent the locations of pixel boundaries.
        return numpy.linspace(self.xmin, self.xmax, self.grid_size+1)

    # Convenience property that returns a tuple with the bounds on the y axis.
    y_bounds = Property(depends_on='ymin,ymax')
    def _get_y_bounds(self):
        return (self.ymin, self.ymax)

    # 1D array with the y coordinates of the boundaries of the grid element.
    y_coords = Property(depends_on='ymin,ymax')
    def _get_y_coords(self):
        # The coordinates have 1 more element than the number of points in
        # the grid, because they represent the locations of pixel boundaries.
        return numpy.linspace(self.ymin, self.ymax, self.grid_size+1)
Esempio n. 5
0
class FluxTool(HasTraits):
    calculate_button = Button('Calculate')
    monitor_age = Property(depends_on='monitor')
    color_map_name = Str('jet')
    levels = Int(10, auto_set=False, enter_set=True)
    model_kind = Str('Plane')

    data_source = Str('database')
    # plot_kind = Str('Contour')
    plot_kind=Enum('Contour','Hole vs J')

    # def _plot_kind_default(self,):
    monitor=Any
    monitors=List

    group_positions=Bool(False)
    def _monitor_default(self):
        return DummyFluxMonitor()

    def _get_monitor_age(self):
        ma = 28.02e6
        if self.monitor:
            ma=self.monitor.age

        return ma

    def traits_view(self):
        contour_grp = VGroup(Item('color_map_name',
                                  label='Color Map',
                                  editor=EnumEditor(values=sorted(color_map_name_dict.keys()))),
                             Item('levels'),
                             visible_when='plot_kind=="Contour"')
        monitor_grp=Item('monitor', editor=EnumEditor(name='monitors'))
        v = View(
            VGroup(HGroup(UItem('calculate_button'),
                          UItem('data_source', editor=EnumEditor(values=['database', 'file'])),
                          monitor_grp),
                   HGroup(Item('group_positions'), Item('object.monitor.sample', style='readonly',label='Sample')),
                   HGroup(UItem('plot_kind'),
                          Item('model_kind', label='Fit Model',
                            editor=EnumEditor(values=['Bowl', 'Plane']))),
                          # UItem('plot_kind', editor=EnumEditor(values=['Contour', 'Hole vs J']))),
                   contour_grp))
        return v
Esempio n. 6
0
class NewBranchView(HasTraits):
    name = Property(depends_on='_name')
    branches = Any
    _name = Str

    def traits_view(self):
        v = okcancel_view(UItem('name'), width=200, title='New Branch')
        return v

    def _get_name(self):
        return self._name

    def _set_name(self, v):
        self._name = v

    def _validate_name(self, v):
        if v not in self.branches:
            if ' ' not in v:
                return v
Esempio n. 7
0
class FitSelector(HasTraits):
    fits = List(Fit)
    update_needed = Event
    suppress_refresh_unknowns = Bool
    save_event = Event

    fit_klass = Fit
    command_key = Bool
    auto_update = Bool(True)

    plot_button = Button('Plot')
    default_error_type = 'SD'

    show_all_button = Event
    show_state = Bool
    show_all_label = Property(depends_on='show_state')

    use_all_button = Button('Toggle Save')
    use_state = Bool
    global_fit = Str('Fit')
    global_error_type = Str('Error')

    fit_types = List(['Fit', ''] + FIT_TYPES)
    error_types = List(['Error', ''] + FIT_ERROR_TYPES)

    selected = Any

    def _get_show_all_label(self):
        return 'Hide All' if self.show_state else 'Show All'

    def _plot_button_fired(self):
        self.update_needed = True

    def _auto_update_changed(self):
        self.update_needed = True

    def _get_fits(self):
        fs = self.selected
        if not fs:
            fs = self.fits
        return fs

    def _show_all_button_fired(self):
        self.show_state = not self.show_state
        fs = self._get_fits()
        for fi in fs:
            fi.show = self.show_state

    def _use_all_button_fired(self):
        self.use_state = not self.use_state
        fs = self._get_fits()
        for fi in fs:
            fi.use = self.use_state

    def _global_fit_changed(self):
        if self.global_fit in self.fit_types:
            fs = self._get_fits()
            for fi in fs:
                fi.fit = self.global_fit

    def _global_error_type_changed(self):
        if self.global_error_type in FIT_ERROR_TYPES:
            fs = self._get_fits()
            for fi in fs:
                fi.error_type = self.global_error_type

    def _get_auto_group(self):
        return VGroup(
            HGroup(
                icon_button_editor(
                    'plot_button',
                    'refresh',
                    tooltip='Replot the isotope evolutions. '
                    'This may take awhile if many analyses are selected'),
                icon_button_editor('save_event',
                                   'database_save',
                                   tooltip='Save fits to database'),
                Item(
                    'auto_update',
                    label='Auto Plot',
                    tooltip=
                    'Should the plot refresh after each change ie. "fit" or "show". '
                    'It is not advisable to use this option with many analyses'
                )),
            HGroup(
                UItem('global_fit', editor=EnumEditor(name='fit_types')),
                UItem('global_error_type',
                      editor=EnumEditor(name='error_types'))))

    def traits_view(self):
        v = View(
            VGroup(self._get_auto_group(), self._get_toggle_group(),
                   self._get_fit_group()))
        return v

    def _get_toggle_group(self):
        g = HGroup(
            # UItem('global_fit',editor=EnumEditor(name='fit_types')),
            # UItem('global_error_type', editor=EnumEditor(name='error_types')),
            UItem('show_all_button',
                  editor=ButtonEditor(label_value='show_all_label')),
            UItem('use_all_button'))
        return g

    def _get_columns(self):
        cols = [
            ObjectColumn(name='name', editable=False),
            CheckboxColumn(name='show'),
            CheckboxColumn(name='use', label='Save'),
            ObjectColumn(name='fit',
                         editor=EnumEditor(name='fit_types'),
                         width=150),
            ObjectColumn(name='error_type',
                         editor=EnumEditor(name='error_types'),
                         width=50)
        ]

        return cols

    def _get_fit_group(self):
        cols = self._get_columns()
        editor = myTableEditor(columns=cols,
                               selected='selected',
                               selection_mode='rows',
                               sortable=False,
                               edit_on_first_click=False,
                               clear_selection_on_dclicked=True,
                               on_command_key=self._update_command_key,
                               cell_bg_color='red',
                               cell_font='modern 10')
        grp = UItem('fits', style='custom', editor=editor)
        return grp

    @on_trait_change('fits:[show, fit, use]')
    def _fit_changed(self, obj, name, old, new):
        if self.command_key:
            for fi in self.fits:
                fi.trait_set(**{name: new})
            self.command_key = False

        if self.auto_update:
            if name in ('show', 'fit'):
                self.update_needed = True

    def load_fits(self, keys, fits):

        nfs = []
        for ki, fi in zip(keys, fits):
            pf = next((fa for fa in self.fits if fa.name == ki), None)
            fit, et, fod = fi
            if pf is None:
                pf = self.fit_klass(name=ki)

            pf.fit = fit
            pf.filter_outliers = fod.get('filter_outliers', False)

            pf.filter_iterations = fod.get('iterations', 0)
            pf.filter_std_devs = fod.get('std_devs', 0)
            pf.error_type = et

            nfs.append(pf)

        self.fits = nfs

    # def load_baseline_fits(self, keys):
    # fits = self.fits
    # if not fits:
    # fits = []
    #
    #     fs = [
    #         self.fit_klass(name='{}bs'.format(ki), fit='average')
    #         for ki in keys]
    #
    #     fits.extend(fs)
    #     self.fits = fits

    # def add_peak_center_fit(self):
    #     fits = self.fits
    #     if not fits:
    #         fits = []
    #
    #     fs = self.fit_klass(name='PC', fit='average')
    #
    #     fits.append(fs)
    #     self.fits = fits
    #
    # def add_derivated_fits(self, keys):
    #     fits = self.fits
    #     if not fits:
    #         fits = []
    #
    #     fs = [
    #         self.fit_klass(name='{}E'.format(ki), fit='average')
    #         for ki in keys
    #     ]
    #
    #     fits.extend(fs)
    #     self.fits = fits

    def _update_command_key(self, new):
        self.command_key = new
Esempio n. 8
0
class MarkerLabel(Label):
    rotate_angle = 0

    zero_y = 0
    xoffset = 10
    indicator_width = 4
    indicator_height = 10
    visible = Bool(True)
    component_height = 100
    x = Float
    y = Float
    data_y = Float
    vertical = False
    horizontal_line_visible = False
    label_with_intensity = False

    text = Property(depends_on='_text, label_with_intensity')
    _text = Str

    def _set_text(self, text):
        self._text = text

    def _get_text(self):
        if self.label_with_intensity:
            return '{:0.4f}'.format(self.data_y)
        else:
            return self._text

    def draw(self, gc, component_height):
        if not self.text:
            self.text = ''

        if self.bgcolor != "transparent":
            gc.set_fill_color(self.bgcolor_)

        #draw tag border
        with gc:
            if self.vertical:
                self.rotate_angle = 90
                width, height = self.get_bounding_box(gc)
                gc.translate_ctm(self.x, self.zero_y_vert - 35 - height)
            else:
                if self.horizontal_line_visible:
                    self._draw_horizontal_line(gc)

                gc.translate_ctm(self.x + self.xoffset, self.y)
                self._draw_tag_border(gc)

            super(MarkerLabel, self).draw(gc)

        with gc:
            gc.translate_ctm(self.x - self.indicator_width / 2.0, self.zero_y)
            self._draw_index_indicator(gc, component_height)

    def _draw_horizontal_line(self, gc):
        with gc:
            # print self.x, self.y
            gc.set_stroke_color((0, 0, 0, 1))
            gc.set_line_width(2)
            oy = 7 if self.text else 4
            y = self.y + oy
            gc.move_to(0, y)
            gc.line_to(self.x, y)
            gc.stroke_path()

    def _draw_index_indicator(self, gc, component_height):
        # gc.set_fill_color((1, 0, 0, 1))
        w, h = self.indicator_width, self.indicator_height
        gc.draw_rect((0, 0, w, h), FILL)

        gc.draw_rect((0, component_height, w, h), FILL)

    def _draw_tag_border(self, gc):
        gc.set_stroke_color((0, 0, 0, 1))
        gc.set_line_width(2)

        # gc.set_fill_color((1, 1, 1, 1))
        bb_width, bb_height = self.get_bounding_box(gc)

        offset = 2
        xoffset = self.xoffset
        gc.lines([(-xoffset, (bb_height + offset) / 2.0),
                  (0, bb_height + 2 * offset),
                  (bb_width + offset, bb_height + 2 * offset),
                  (bb_width + offset, -offset), (0, -offset),
                  (-xoffset, (bb_height + offset) / 2.0)])

        gc.draw_path()
Esempio n. 9
0
class BaseTemplater(HasTraits):
    formatter = Property(depends_on='label')
    clear_button = Button
    keywords = List
    non_keywords = List
    label = String
    activated = Any
    example = Property(depends_on='label')
    view_title = Str

    predefined_label = Str
    predefined_labels = Property(depends_on='user_predefined_labels')
    base_predefined_labels = List([''])
    user_predefined_labels = List

    add_enabled = Property(depends_on='label')
    delete_enabled = Property(depends_on='label')
    add_label_button = Button
    delete_label_button = Button

    attribute_keys = Property(depends_on='label')

    persistence_name = ''

    attributes = List
    example_context = Dict
    attribute_formats = Dict

    def __init__(self, *args, **kw):
        super(BaseTemplater, self).__init__(*args, **kw)
        self.load()

    #persistence
    def load(self):
        p = os.path.join(paths.hidden_dir, self.persistence_name)
        if os.path.isfile(p):
            with open(p, 'r') as rfile:
                try:
                    self.user_predefined_labels = pickle.load(rfile)
                except BaseException:
                    pass

    def dump(self):
        p = os.path.join(paths.hidden_dir, self.persistence_name)
        with open(p, 'w') as wfile:
            try:
                pickle.dump(self.user_predefined_labels, wfile)
            except BaseException:
                pass

    def _get_attribute_keys(self):
        ks = []
        for k in self.label.split(' '):
            if k in self.attributes:
                ks.append(k.lower())

        return ks

    def _get_formatter(self):
        ns = []
        for k in self.label.split(' '):
            if k in self.attributes:
                if k == '<SPACE>':
                    k = ' '
                else:
                    k = k.lower()
                    try:
                        f = self.attribute_formats[k]
                    except KeyError:
                        f = 's'

                    k = '{{{}:{}}}'.format(k, f)
            ns.append(k)
        s = ''.join(ns)
        return s

    def _get_example(self):
        f = self.formatter
        return f.format(**self.example_context)

    def _get_predefined_labels(self):
        return self.base_predefined_labels + self.user_predefined_labels

    def _get_add_enabled(self):
        return self.label and self.label not in self.predefined_labels

    def _get_delete_enabled(self):
        return self.label in self.user_predefined_labels

    def _delete_label_button_fired(self):
        if self.label in self.user_predefined_labels:
            self.user_predefined_labels.remove(self.label)
            self.dump()
            self.load()
            self.label = ''

    #handlers
    def _add_label_button_fired(self):
        if self.label not in self.predefined_labels:
            self.user_predefined_labels.append(self.label)
            self.dump()
            self.load()

    def _clear_button_fired(self):
        self.label = ''
        self.predefined_label = ''

    def _activated_changed(self, new):
        if new:
            self.keywords.append(new)
            if self.label:
                self.label += ' {}'.format(new)
            else:
                self.label = new

            self.activated = None

    def _predefined_label_changed(self, new):
        self.label = new
class PyannoApplication(HasTraits):

    database = Instance(PyannoDatabase)

    main_window = Instance(ModelDataView)

    database_window = Instance(DatabaseView)

    database_ui = Instance(UI)

    logging_level = Int(logging.INFO)

    pyanno_pathname = Str

    db_window_open = Property(Bool)

    def _get_db_window_open(self):
        return (self.database_ui is not None
                and self.database_ui.control is not None)

    def open(self):
        self._start_logging()
        self._open_pyanno_database()
        self._open_main_window()

    def close(self):
        self.database.close()
        logger.info('Closing pyAnno -- Goodbye!')

    def _start_logging(self):
        logging.basicConfig(level=self.logging_level)
        logger.info('Starting pyAnno')

    def _create_pyanno_directory(self):
        """Create a pyanno directort in the user's home if it is missing."""
        home_dir = os.getenv('HOME') or os.getenv('HOMEPATH')
        logger.debug('Found home directory at ' + str(home_dir))

        self.pyanno_pathname = os.path.join(home_dir, PYANNO_PATH_NAME)

        try:
            logger.debug('Creating pyAnno directory at ' +
                         self.pyanno_pathname)
            os.makedirs(self.pyanno_pathname)
        except OSError as e:
            logger.debug('pyAnno directory already existing')
            if e.errno != errno.EEXIST:
                raise

    def _open_pyanno_database(self):
        # database filename
        self._create_pyanno_directory()
        db_filename = os.path.join(self.pyanno_pathname, DATABASE_FILENAME)
        self.database = PyannoDatabase(db_filename)

    def _open_main_window(self):
        self.main_window = ModelDataView(application=self)

        model = ModelBt.create_initial_state(5, 8)
        self.main_window.set_model(model=model)

        self.main_window.configure_traits()

    def open_database_window(self):
        if self.db_window_open:
            # windows exists, raise
            self.database_ui.control.Raise()
        else:
            # window was closed or not existent
            logger.debug('Open database window')
            database_window = DatabaseView(database=self.database,
                                           application=self)
            database_ui = database_window.edit_traits(kind='live')

            self.database_window = database_window
            self.database_ui = database_ui

    def close_database_window(self):
        # wx specific
        self.database_ui.control.Close()

    def update_window_from_database_record(self, record):
        """Update main window from pyanno database record.
        """
        self.main_window.set_from_database_record(record)

    def add_current_state_to_database(self):
        mdv = self.main_window

        # file name may contain unicode characters
        data_id = mdv.annotations_view.annotations_container.name
        if data_id is '':
            data_id = 'anonymous_annotations'
        elif type(data_id) is unicode:
            u_data_id = unicodedata.normalize('NFKD', data_id)
            data_id = u_data_id.encode('ascii', 'ignore')

        try:
            self.database.store_result(
                data_id, mdv.annotations_view.annotations_container, mdv.model,
                mdv.log_likelihood)
        except PyannoValueError as e:
            logger.info(e)
            errmsg = e.args[0]
            error('Error: ' + errmsg)

        if self.db_window_open:
            self.database_window.db_updated = True

    def _create_debug_database(self):
        """Create and populate a test database in a temporary file.
        """

        from tempfile import mktemp
        from pyanno.modelA import ModelA
        from pyanno.modelB import ModelB
        from pyanno.annotations import AnnotationsContainer

        # database filename
        tmp_filename = mktemp(prefix='tmp_pyanno_db_')
        db = PyannoDatabase(tmp_filename)

        def _create_new_entry(model, annotations, id):
            value = model.log_likelihood(annotations)
            ac = AnnotationsContainer.from_array(annotations, name=id)
            db.store_result(id, ac, model, value)

        # populate database
        model = ModelA.create_initial_state(5)
        annotations = model.generate_annotations(100)
        _create_new_entry(model, annotations, 'test_id')

        modelb = ModelB.create_initial_state(5, 8)
        _create_new_entry(modelb, annotations, 'test_id')

        annotations = model.generate_annotations(100)
        _create_new_entry(modelb, annotations, 'test_id2')

        self.database = db
Esempio n. 11
0
class AnnotationsContainer(HasStrictTraits):
    """Translate from general annotations files and arrays to pyAnno's format.

    This class exposes a few methods to import data from files and arrays, and
    converts them to pyAnno's format:

    * annotations are 2D integer arrays; rows index items, and columns
      annotators

    * label classes are numbered 0 to :attr:`nclasses`-1 . The attribute
      :attr:`labels` defines a mapping from label tokens to label classes

    * missing values are defined as :attr:`pyanno.util.MISSING_VALUE`. The
      attribute :attr:`missing_values` contains the missing values tokens
      found in the original, raw data

    The converted data can be accessed through the :attr:`annotations` property.

    The `AnnotationsContainer` is also used as the format to store annotations
    in :class:`~pyanno.database.PyannoDatabase` objects.
    """

    DEFAULT_MISSING_VALUES_STR = ['-1', 'NA', 'None', '*']
    DEFAULT_MISSING_VALUES_NUM = [-1, np.nan, None]
    DEFAULT_MISSING_VALUES_ALL = (DEFAULT_MISSING_VALUES_STR +
                                  DEFAULT_MISSING_VALUES_NUM)

    #: raw annotations, as they are imported from file or array
    raw_annotations = List(List)

    #: name of file or array from which the annotations were imported
    name = Str

    #: list of all labels found in file/array
    labels = List

    #: labels corresponding to a missing value
    missing_values = List

    #: number of classes found in the annotations
    nclasses = Property(Int, depends_on='labels')

    def _get_nclasses(self):
        return len(self.labels)

    #: number of annotators
    nannotators = Property(Int, depends_on='raw_annotations')

    def _get_nannotators(self):
        return len(self.raw_annotations[0])

    #: number of annotations
    nitems = Property(Int, depends_on='raw_annotations')

    def _get_nitems(self):
        return len(self.raw_annotations)

    #: annotations in pyAnno format
    annotations = Property(Array, depends_on='raw_annotations')

    @cached_property
    def _get_annotations(self):
        nitems, nannotators = len(self.raw_annotations), self.nannotators
        anno = np.empty((nitems, nannotators), dtype=int)

        # build map from labels and missing values to annotation values
        raw2val = dict(list(zip(self.labels, list(range(self.nclasses)))))
        raw2val.update([(mv, MISSING_VALUE) for mv in self.missing_values])

        # translate
        nan_in_missing_values = _is_nan_in_list(self.missing_values)
        for i, row in enumerate(self.raw_annotations):
            for j, lbl in enumerate(row):
                if nan_in_missing_values and _robust_isnan(lbl):
                    # workaround for the fact that np.nan cannot be used as
                    # the key to a dictionary, since np.nan != np.nan
                    anno[i, j] = MISSING_VALUE
                else:
                    anno[i, j] = raw2val[lbl]

        return anno

    @staticmethod
    def _from_generator(rows_generator, missing_values, name=''):

        missing_set = set(missing_values)
        labels_set = set()

        raw_annotations = []
        nannotators = None
        for n, row in enumerate(rows_generator):

            # verify that number of lines is consistent in the whole file
            if nannotators is None: nannotators = len(row)
            else:
                if len(row) != nannotators:
                    raise PyannoValueError(
                        'File has inconsistent number of entries '
                        'on separate lines (line {})'.format(n))

            raw_annotations.append(row)
            labels_set.update(row)

        # remove missing values from set of labels
        all_labels = sorted(list(labels_set - missing_set))
        missing_values = sorted(list(missing_set & labels_set))

        # workaround for np.nan != np.nan, so intersection does not work
        if _is_nan_in_list(all_labels):
            # uses fact that np.nan < x, for every x
            all_labels = all_labels[1:]
            missing_values.insert(0, np.nan)

        # create annotations object
        anno = AnnotationsContainer(raw_annotations=raw_annotations,
                                    labels=all_labels,
                                    missing_values=missing_values,
                                    name=name)

        return anno

    @staticmethod
    def _from_file_object(fobj, missing_values=None, name=''):
        """Useful for testing, as it can be called using a StringIO object.
        """

        if missing_values is None:
            missing_values = AnnotationsContainer.DEFAULT_MISSING_VALUES_STR

        # generator for rows of file-like object
        def file_row_generator():
            for line in fobj.readlines():
                # remove commas and split in individual tokens
                line = line.strip().replace(',', ' ')

                # ignore empty lines
                if len(line) == 0: continue

                labels = line.split()
                yield labels

        return AnnotationsContainer._from_generator(file_row_generator(),
                                                    missing_values,
                                                    name=name)

    @staticmethod
    def from_file(filename, missing_values=None):
        """Load annotations from a file.

        The file is a text file with a columns separated by spaces and/or
        commas, and rows on different lines.

        Arguments
        ---------
        filename : string
            File name

        missing_values : list
            List of labels that are considered missing values.
            Default is :attr:`DEFAULT_MISSING_VALUES_STR`
        """

        if missing_values is None:
            missing_values = AnnotationsContainer.DEFAULT_MISSING_VALUES_STR

        with open(filename) as fh:
            anno = AnnotationsContainer._from_file_object(
                fh, missing_values=missing_values, name=filename)

        return anno

    @staticmethod
    def from_array(x, missing_values=None, name=''):
        """Create an annotations object from an array or list-of-lists.

        Arguments
        ---------
        x : ndarray or list-of-lists
            Array or list-of-lists containing numerical or string annotations

        missing_values : list
            List of values that are considered missing values.
            Default is :attr:`DEFAULT_MISSING_VALUES_ALL`

        name : string
            Name of the annotations (for user interaction and used as key in
            databases).
        """

        if missing_values is None:
            missing_values = AnnotationsContainer.DEFAULT_MISSING_VALUES_ALL

        # generator for array objects
        def array_rows_generator():
            for row in x:
                yield list(row)

        return AnnotationsContainer._from_generator(array_rows_generator(),
                                                    missing_values,
                                                    name=name)

    def save_to(self, filename, set_name=False):
        """Save raw annotations to file.

        Arguments
        ---------
        filename : string
            File name

        set_name : bool
            Set the :attr:`name` of the annotation container to the file name
        """
        if set_name:
            self.name = filename
        with open(filename, 'w') as f:
            f.writelines((' '.join(map(str, row)) + '\n'
                          for row in self.raw_annotations))
Esempio n. 12
0
 def func(fget):
     fget.__name__ = '_get_' + fget.__name__
     fget = cached_property(fget)
     x = Property(depends_on=depends_on, fget=fget, force=True, **kwargs)
     return x
Esempio n. 13
0
class FluxTool(HasTraits):
    calculate_button = Button('Calculate')
    monitor_age = Property(depends_on='monitor')
    color_map_name = Str('jet')
    marker_size = Int(5)
    levels = Int(50, auto_set=False, enter_set=True)
    model_kind = Str('Plane')

    data_source = Str('database')
    # plot_kind = Str('Contour')
    plot_kind = Enum('Contour', 'Hole vs J')

    # def _plot_kind_default(self,):
    monitor = Any
    monitors = List

    group_positions = Bool(False)
    show_labels = Bool(True)

    mean_j_error_type = Enum(*ERROR_TYPES)
    predicted_j_error_type = Enum(*ERROR_TYPES)
    _prev_predicted_j_error_type = Str
    use_weighted_fit = Bool(False)
    use_monte_carlo = Bool(False)
    monte_carlo_ntrials =Int(10000)
    save_mean_j = Bool(False)
    auto_clear_cache = Bool(False)

    def _monitor_default(self):
        return DummyFluxMonitor()

    def _get_monitor_age(self):
        ma = 28.02e6
        if self.monitor:
            ma = self.monitor.age

        return ma

    def _use_weighted_fit_changed(self, new):
        if new:
            self._prev_predicted_j_error_type = self.predicted_j_error_type
            self.predicted_j_error_type = 'SD'
        else:
            self.predicted_j_error_type = self._prev_predicted_j_error_type

    def traits_view(self):
        contour_grp = HGroup(Item('color_map_name',
                                  label='Color Map',
                                  editor=EnumEditor(values=sorted(color_map_name_dict.keys()))),
                             Item('levels'),
                             Item('marker_size'),
                             visible_when='plot_kind=="Contour"')
        monitor_grp = Item('monitor', editor=EnumEditor(name='monitors'))
        v = View(
            VGroup(HGroup(UItem('calculate_button'),
                          UItem('data_source', editor=EnumEditor(values=['database', 'file'])),
                          monitor_grp),
                   HGroup(Item('save_mean_j', label='Save Mean J'),
                          Item('auto_clear_cache', label='Auto Clear Cache')),
                   Item('mean_j_error_type', label='Mean J Error'),
                   HGroup(Item('use_weighted_fit'),
                          Item('use_monte_carlo'),
                          Item('monte_carlo_ntrials',
                               enabled_when='object.use_monte_carlo')),
                   Item('predicted_j_error_type', label='Predicted J Error',
                        enabled_when='not (object.use_weighted_fit or object.use_monte_carlo)'),
                   HGroup(Item('group_positions'),
                          Item('object.monitor.sample',
                               style='readonly', label='Sample')),
                   Item('show_labels',
                        label='Display Labels',
                        tooltip='Display hole labels on plot'),
                   HGroup(UItem('plot_kind'),
                          Item('model_kind', label='Fit Model',
                               editor=EnumEditor(values=['Bowl', 'Plane']))),
                   # UItem('plot_kind', editor=EnumEditor(values=['Contour', 'Hole vs J']))),
                   contour_grp))
        return v
Esempio n. 14
0
class SystemObject(HasStrictTraits):

    """
        Baseclass for Programs, Sensor, Actuators
    """

    #: Names of attributes that accept Callables. If there are custom callables being used, they must be added here.
    #: The purpose of this list is that these Callables will be initialized properly.
    #: :class:`~automate.program.ProgrammableSystemObject` introduces 5 basic callables
    #: (see also :ref:`automate-programs`).
    callables = []

    def get_default_callables(self):
        """ Get a dictionary of default callables, in form {name:callable}. Re-defined in subclasses."""
        return {}

    #: Reference to System object
    system = Instance(SystemBase, transient=True)

    #: Description of the object (shown in WEB interface)
    description = CUnicode

    #: Python Logger instance for this object. System creates each object its own logger instance.
    logger = Instance(logging.Logger, transient=True)

    #: Tags are used for (for example) grouping objects. See :ref:`groups`.
    tags = TagSet(trait=CUnicode)

    #: Name property is determined by System namespace. Can be read/written.
    name = Property(trait=Unicode, depends_on='name_changed_event')

    log_level = Int(logging.INFO)

    def _log_level_changed(self, new_value):
        if self.logger:
            self.logger.setLevel(new_value)

    @cached_property
    def _get_name(self):
        try:
            return self.system.reverse[self]
        except (KeyError, AttributeError):
            return 'System not initialized!'

    def _set_name(self, new_name):
        if not is_valid_variable_name(new_name):
            raise NameError('Illegal name %s' % new_name)
        try:
            if self in list(self.system.namespace.values()):
                del self.system.namespace[self.name]
        except NameError:

            pass
        self.system.namespace[new_name] = self
        self.logger = self.system.logger.getChild('%s.%s' % (self.__class__.__name__, new_name))

    #: If set to *True*, current SystemObject is hidden in the UML diagram of WEB interface.
    hide_in_uml = CBool(False)

    _order = Int
    _count = 0

    #: Attributes that can be edited by user in WEB interface
    view = ['hide_in_uml']

    #: The data type name (as string) of the object. This is written in the initialization, and is used by WEB
    #: interface Django templates.
    data_type = ''

    #: If editable=True, a quick edit widget will appear in the web interface. Define in subclasses.
    editable = False

    # Namespace triggers this event when object name name is changed
    name_changed_event = Event

    _passed_arguments = Tuple(transient=True)
    _postponed_callables = Dict(transient=True)

    @property
    def class_name(self):
        # For Django templates
        return self.__class__.__name__

    @property
    def object_type(self):
        """
            A read-only property that gives the object type as string; sensor, actuator, program, other.
            Used by WEB interface templates.
        """

        from .statusobject import AbstractSensor, AbstractActuator
        from .program import Program
        if isinstance(self, AbstractSensor):
            return 'sensor'
        elif isinstance(self, AbstractActuator):
            return 'actuator'
        elif isinstance(self, Program):
            return 'program'
        else:
            return 'other'

    def __init__(self, name='', **traits):
        # Postpone traits initialization to be launched by System
        self.logger = logging.getLogger('automate.%s' % self.__class__.__name__)
        self._order = SystemObject._count
        SystemObject._count += 1

        self._passed_arguments = name, traits
        if 'system' in traits:
            self.setup_system(traits.pop('system'))
            self.setup_callables()

    def __setstate__(self, state, trait_change_notify=True):
        self.logger = logging.getLogger('automate.%s' % self.__class__.__name__)
        self._order = state.pop('_order')
        self._passed_arguments = None, state

    def get_status_display(self, **kwargs):
        """
            Redefine this in subclasses if status can be represented in human-readable way (units etc.)
        """
        if 'value' in kwargs:
            return str(kwargs['value'])
        return self.class_name

    def get_as_datadict(self):
        """
            Get information about this object as a dictionary.  Used by WebSocket interface to pass some
            relevant information to client applications.
        """
        return dict(type=self.__class__.__name__, tags=list(self.tags))

    def setup(self, *args, **kwargs):
        """
            Initialize necessary services etc. here. Define this in subclasses.
        """
        pass

    def setup_system(self, system, name_from_system='', **kwargs):
        """
            Set system attribute and do some initialization. Used by System.
        """

        if not self.system:
            self.system = system
        name, traits = self._passed_arguments
        new_name = self.system.get_unique_name(self, name, name_from_system)
        if not self in self.system.reverse:
            self.name = new_name
        self.logger = self.system.logger.getChild('%s.%s' % (self.__class__.__name__, self.name))
        self.logger.setLevel(self.log_level)
        if name is None and 'name' in traits:  # Only __setstate__ sets name to None. Default is ''.
            del traits['name']

        for cname in self.callables:
            if cname in traits:
                c = self._postponed_callables[cname] = traits.pop(cname)
                c.setup_callable_system(self.system)
            getattr(self, cname).setup_callable_system(self.system)

        if not self.traits_inited():
            super().__init__(**traits)
        self.name_changed_event = True
        self.setup()

    def setup_callables(self):
        """
            Setup Callable attributes that belong to this object.
        """
        defaults = self.get_default_callables()
        for key, value in list(defaults.items()):
            self._postponed_callables.setdefault(key, value)
        for key in self.callables:
            value = self._postponed_callables.pop(key)
            value.setup_callable_system(self.system, init=True)
            setattr(self, key, value)

    def cleanup(self):
        """
            Write here whatever cleanup actions are needed when object is no longer used.
        """

    def __str__(self):
        return self.name

    def __repr__(self):
        return u"'%s'" % self.name