<commit_before># ===============================================================================
# Copyright 2013 Jake Ross
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ===============================================================================

# ============= enthought library imports =======================

from traits.api import HasTraits, List, Any, Bool, Int, Instance, Enum, \
    Event, Str, Callable, Button, Property
from traits.trait_errors import TraitError
from traitsui.api import View, Item, UItem, CheckListEditor, VGroup, Handler, HGroup, Tabbed
import apptools.sweet_pickle as pickle
# ============= standard library imports ========================
from datetime import datetime
import os
# ============= local library imports  ==========================
from traitsui.tabular_adapter import TabularAdapter
from pychron.paths import paths

SIZES = (6, 8, 9, 10, 11, 12, 14, 15, 18, 24, 36)

class TableConfigurerHandler(Handler):
    def closed(self, info, is_ok):
        if is_ok:
            info.object.closed(is_ok)
            # info.object.dump()
            # info.object.set_columns()

class TableConfigurer(HasTraits):
    columns = List
    children = List(TabularAdapter)
    available_columns = List
    sparse_columns = List
    adapter = Instance(TabularAdapter)
    id = 'table'
    font = Enum(*SIZES)
    auto_set = Bool(False)
    fontsize_enabled = Bool(True)
    # refresh_table_needed = Event
    title = Str('Configure Table')
    refresh_func = Callable
    show_all = Button('Show All')

    set_sparse = Button('Define Sparse')
    toggle_sparse = Button('Toggle Sparse')

    sparse_enabled = Property(depends_on='columns[]')

    _toggle_sparse_enabled = Bool(False)

    default_button = Button('Default')
    defaults_path = Str

    def _get_sparse_enabled(self):
        return self.sparse_columns != self.columns and len(self.columns) < 5

    def __init__(self, *args, **kw):
        super(TableConfigurer, self).__init__(*args, **kw)
        if self.auto_set:
            self.on_trait_change(self.update, 'font, columns[]')
        self._load_state()

    def closed(self, is_ok):
        if is_ok:
            self.dump()
            self.set_columns()
            self.set_font()

    def load(self):
        self._load_state()

    def dump(self):
        self._dump_state()

    def update(self):
        self.set_font()
        self.set_columns()

    def set_font(self):
        if self.adapter:
            self.adapter.font = 'arial {}'.format(self.font)
            if self.refresh_func:
                self.refresh_func()

                # self.refresh_table_needed = True

    def set_columns(self):
        # def _columns_changed(self):
        if self.adapter:
            cols = self._assemble_columns()
            for ci in self.children:
                ci.columns = cols

            self.adapter.columns = cols

    def _set_font(self, f):
        s = f.pointSize()
        self.font = s

    def _load_state(self):
        p = os.path.join(paths.hidden_dir, self.id)
        if os.path.isfile(p):
            try:
                with open(p, 'rb') as rfile:
                    state = pickle.load(rfile)

            except (pickle.PickleError, OSError, EOFError, TraitError):
                return

            try:
                self.sparse_columns = state.get('sparse_columns')
            except:
                pass

            cols = state.get('columns')
            if cols:
                ncols = []
                for ai in self.available_columns:
                    if ai in cols:
                        ncols.append(ai)

                self.columns = ncols

            font = state.get('font', None)
            if font:
                self.font = font

            self._load_hook(state)
            self.set_columns()

    def _dump_state(self):
        p = os.path.join(paths.hidden_dir, self.id)
        obj = self._get_dump()

        with open(p, 'wb') as wfile:
            try:
                pickle.dump(obj, wfile)
            except pickle.PickleError:
                pass

    def _get_dump(self):
        obj = dict(columns=self.columns,
                   font=self.font,
                   sparse_columns=self.sparse_columns)
        return obj

    def _load_hook(self, state):
        pass

    def _assemble_columns(self):
        d = self.adapter.all_columns_dict
        return [(k, d[k]) for k, v in self.adapter.all_columns if k in self.columns]

    def _get_columns_grp(self):
        return

    def _set_defaults(self):
        p = self.defaults_path
        if os.path.isfile(p):
            import yaml

            with open(p, 'r') as rfile:
                yd = yaml.load(rfile)
                try:
                    self.columns = yd['columns']
                except KeyError:
                    pass
            self.set_columns()

    def _default_button_fired(self):
        self._set_defaults()

    def _set_sparse_fired(self):
        self.sparse_columns = self.columns

    def _toggle_sparse_fired(self):
        if self._toggle_sparse_enabled:
            columns = self._prev_columns
        else:
            self._prev_columns = self.columns
            columns = self.sparse_columns

        self.columns = columns
        self.set_columns()

        self._toggle_sparse_enabled = not self._toggle_sparse_enabled

    def _show_all_fired(self):
        self.columns = self.available_columns
        self.set_columns()

    def _adapter_changed(self, adp):
        if adp:
            acols = [c for c, _ in adp.all_columns]

            # set currently visible columns
            t = [c for c, _ in adp.columns]

            cols = [c for c in acols if c in t]
            self.trait_setq(columns=cols)

            # set all available columns
            self.available_columns = acols

            self._set_font(adp.font)
            self._load_state()

    def traits_view(self):
        v = View(VGroup(HGroup(UItem('show_all', tooltip='Show all columns'),
                               UItem('set_sparse',
                                     tooltip='Set the current set of columns to the Sparse Column Set',
                                     enabled_when='sparse_enabled'),
                               UItem('toggle_sparse',
                                     tooltip='Display only Sparse Column Set'),
                               UItem('default_button',
                                     tooltip='Set to Laboratory defaults. File located at '
                                             '[root]/experiments/experiment_defaults.yaml')),
                        VGroup(UItem('columns',
                                     style='custom',
                                     editor=CheckListEditor(name='available_columns', cols=3)),
                               Item('font', enabled_when='fontsize_enabled'),
                               show_border=True)),
                 handler=TableConfigurerHandler(),
                 title=self.title,
                 buttons=['OK', 'Cancel'], )
        return v

def str_to_time(lp):
    lp = lp.replace('/', '-')
    if lp.count('-') == 2:
        y = lp.split('-')[-1]
        y = 'y' if len(y) == 2 else 'Y'

        fmt = '%m-%d-%{}'.format(y)
    elif lp.count('-') == 1:
        y = lp.split('-')[-1]
        y = 'y' if len(y) == 2 else 'Y'

        fmt = '%m-%{}'.format(y)
    else:
        fmt = '%Y' if len(lp) == 4 else '%y'

    return datetime.strptime(lp, fmt)

class ExperimentTableConfigurer(TableConfigurer):
    defaults_path = paths.experiment_defaults

class AnalysisTableConfigurer(TableConfigurer):
    id = 'analysis.table'
    limit = Int
    omit_invalid = Bool(True)

    def _get_dump(self):
        obj = super(AnalysisTableConfigurer, self)._get_dump()
        obj['limit'] = self.limit
        obj['omit_invalid'] = self.omit_invalid

        return obj

    def _load_hook(self, obj):
        self.limit = obj.get('limit', 500)
        self.omit_invalid = obj.get('omit_invalid', True)

    def traits_view(self):
        v = View(VGroup(VGroup(UItem('columns',
                                     style='custom',
                                     editor=CheckListEditor(name='available_columns', cols=3)),
                               label='Columns', show_border=True),
                        # Group(
                        # VGroup(HGroup(Heading('Lower Bound'), UItem('use_low_post')),
                        # UItem('low_post', style='custom', enabled_when='use_low_post')),
                        # VGroup(HGroup(Heading('Upper Bound'), UItem('use_high_post')),
                        #            UItem('high_post', style='custom', enabled_when='use_high_post')),
                        #     VGroup(HGroup(Heading('Named Range'), UItem('use_named_date_range')),
                        #            UItem('named_date_range', enabled_when='use_named_date_range'))),
                        Item('omit_invalid'),
                        Item('limit',
                             tooltip='Limit number of displayed analyses',
                             label='Limit'),
                        show_border=True,
                        label='Limiting'),
                 buttons=['OK', 'Cancel', 'Revert'],
                 # kind='modal',
                 title=self.title,
                 handler=TableConfigurerHandler,
                 resizable=True,
                 width=300)
        return v

class SampleTableConfigurer(TableConfigurer):
    title = 'Configure Sample Table'
    # parent = Any
    id = 'sample.table'
    filter_non_run_samples = Bool(True)

    def _get_dump(self):
        obj = super(SampleTableConfigurer, self)._get_dump()
        obj['filter_non_run_samples'] = self.filter_non_run_samples

        return obj

    def _load_hook(self, obj):
        self.filter_non_run_samples = obj.get('filter_non_run_samples', True)

    def traits_view(self):
        v = View(VGroup(
            VGroup(UItem('columns',
                         style='custom',
                         editor=CheckListEditor(name='available_columns', cols=3)),
                   label='Columns', show_border=True),
            # Item('filter_non_run_samples',
            # tooltip='Omit samples that have not been analyzed to date',
            #      label='Exclude Non-Run')
        ),
                 buttons=['OK', 'Cancel', 'Revert'],
                 # kind='modal',
                 title=self.title,
                 handler=TableConfigurerHandler,
                 resizable=True,
                 width=300)
        return v

class IsotopeTableConfigurer(TableConfigurer):
    id = 'recall.isotopes'

    def traits_view(self):
        v = View(VGroup(UItem('columns',
                              style='custom',
                              editor=CheckListEditor(name='available_columns', cols=3)),
                        Item('font', enabled_when='fontsize_enabled'),
                        show_border=True,
                        label='Isotopes'))
        return v

class IntermediateTableConfigurer(TableConfigurer):
    id = 'recall.intermediate'

class RecallTableConfigurer(TableConfigurer):
    isotope_table_configurer = Instance(IsotopeTableConfigurer, ())
    intermediate_table_configurer = Instance(IntermediateTableConfigurer, ())
    show_intermediate = Bool
    experiment_fontsize = Enum(*SIZES)
    measurement_fontsize = Enum(*SIZES)
    extraction_fontsize = Enum(*SIZES)
    main_measurement_fontsize = Enum(*SIZES)
    main_extraction_fontsize = Enum(*SIZES)
    main_computed_fontsize = Enum(*SIZES)

    subview_names = ('experiment', 'measurement', 'extraction')
    main_names = ('measurement', 'extraction', 'computed')
    bind_fontsizes = Bool(False)
    global_fontsize = Enum(*SIZES)

    # def closed(self):
    # super(RecallTableConfigurer, self).closed()
    # self.experiment_view

    def _get_dump(self):
        obj = super(RecallTableConfigurer, self)._get_dump()
        obj['show_intermediate'] = self.show_intermediate
        for a in self.subview_names:
            a = '{}_fontsize'.format(a)
            obj[a] = getattr(self, a)

        for a in self.main_names:
            a = 'main_{}_fontsize'.format(a)
            obj[a] = getattr(self, a)

        for attr in ('global_fontsize', 'bind_fontsizes'):
            obj[attr] = getattr(self, attr)

        return obj

    def _load_hook(self, obj):
        self.show_intermediate = obj.get('show_intermediate', True)
        self.isotope_table_configurer.load()
        self.intermediate_table_configurer.load()

        for a in self.subview_names:
            a = '{}_fontsize'.format(a)
            setattr(self, a, obj.get(a, 10))

        for a in self.main_names:
            a = 'main_{}_fontsize'.format(a)
            setattr(self, a, obj.get(a, 10))

        for attr in ('global_fontsize', 'bind_fontsizes'):
            try:
                setattr(self, attr, obj[attr])
            except KeyError:
                pass

    def dump(self):
        super(RecallTableConfigurer, self).dump()
        self.intermediate_table_configurer.dump()
        self.isotope_table_configurer.dump()

    def set_columns(self):
        self.isotope_table_configurer.set_columns()
        self.intermediate_table_configurer.set_columns()

        self.isotope_table_configurer.update()
        self.intermediate_table_configurer.update()

    def set_font(self):
        self.isotope_table_configurer.set_font()
        self.intermediate_table_configurer.set_font()

    def set_fonts(self, av):
        self.set_font()

        for a in self.subview_names:
            s = getattr(self, '{}_fontsize'.format(a))
            av.update_fontsize(a, s)

        for a in self.main_names:
            av.update_fontsize('main.{}'.format(a),
                               getattr(self, 'main_{}_fontsize'.format(a)))

        av.main_view.refresh_needed = True

    def _bind_fontsizes_changed(self, new):
        if new:
            self._global_fontsize_changed()
        self.isotope_table_configurer.fontsize_enabled = not new
        self.intermediate_table_configurer.fontsize_enabled = not new

    def _global_fontsize_changed(self):
        gf = self.global_fontsize
        self.isotope_table_configurer.font = gf
        self.intermediate_table_configurer.font = gf

        self.main_measurement_fontsize = gf
        self.main_extraction_fontsize = gf
        self.main_computed_fontsize = gf

    def traits_view(self):
        main_grp = VGroup(HGroup(Item('bind_fontsizes'),
                                 Item('global_fontsize', enabled_when='bind_fontsizes')),
                          Item('main_extraction_fontsize', enabled_when='not bind_fontsizes'),
                          Item('main_measurement_fontsize', enabled_when='not bind_fontsizes'),
                          Item('main_computed_fontsize', enabled_when='not bind_fontsizes'))

        main_view = VGroup(main_grp,
                           UItem('isotope_table_configurer', style='custom'),
                           HGroup(Item('show_intermediate', label='Show Intermediate Table')),
                           UItem('intermediate_table_configurer', style='custom', enabled_when='show_intermediate'),
                           label='Main')

        experiment_view = VGroup(Item('experiment_fontsize', label='Size'),
                                 show_border=True,
                                 label='Experiment')
        measurement_view = VGroup(Item('measurement_fontsize', label='Size'),
                                  show_border=True,
                                  label='Measurement')
        extraction_view = VGroup(Item('extraction_fontsize', label='Size'),
                                 show_border=True,
                                 label='Extraction')
        v = View(Tabbed(main_view,
                        VGroup(experiment_view,
                               measurement_view,
                               extraction_view, label='Scripts')),

                 buttons=['OK', 'Cancel', 'Revert'],
                 kind='livemodal',
                 title='Configure Table',
                 handler=TableConfigurerHandler,
                 resizable=True,
                 width=300)
        return v

# ============= EOF =============================================
<commit_msg>fixed experiment table config<commit_after># ===============================================================================
# Copyright 2013 Jake Ross
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# ===============================================================================

# ============= enthought library imports =======================

from traits.api import HasTraits, List, Bool, Int, Instance, Enum, \
    Str, Callable, Button, Property
from traits.trait_errors import TraitError
from traitsui.api import View, Item, UItem, CheckListEditor, VGroup, Handler, HGroup, Tabbed
import apptools.sweet_pickle as pickle
# ============= standard library imports ========================
from datetime import datetime
import os
# ============= local library imports  ==========================
from traitsui.tabular_adapter import TabularAdapter
from pychron.paths import paths

SIZES = (6, 8, 9, 10, 11, 12, 14, 15, 18, 24, 36)

class TableConfigurerHandler(Handler):
    def closed(self, info, is_ok):
        if is_ok:
            info.object.closed(is_ok)
            # info.object.dump()
            # info.object.set_columns()

class TableConfigurer(HasTraits):
    columns = List
    children = List(TabularAdapter)
    available_columns = List
    sparse_columns = List
    adapter = Instance(TabularAdapter)
    id = 'table'
    font = Enum(*SIZES)
    auto_set = Bool(False)
    fontsize_enabled = Bool(True)
    # refresh_table_needed = Event
    title = Str('Configure Table')
    refresh_func = Callable
    show_all = Button('Show All')

    set_sparse = Button('Define Sparse')
    toggle_sparse = Button('Toggle Sparse')

    sparse_enabled = Property(depends_on='columns[]')

    _toggle_sparse_enabled = Bool(False)

    default_button = Button('Default')
    defaults_path = Str

    def _get_sparse_enabled(self):
        return self.sparse_columns != self.columns and len(self.columns) < 5

    def __init__(self, *args, **kw):
        super(TableConfigurer, self).__init__(*args, **kw)
        if self.auto_set:
            self.on_trait_change(self.update, 'font, columns[]')
        self._load_state()

    def closed(self, is_ok):
        if is_ok:
            self.dump()
            self.set_columns()
            self.set_font()

    def load(self):
        self._load_state()

    def dump(self):
        self._dump_state()

    def update(self):
        self.set_font()
        self.set_columns()

    def set_font(self):
        if self.adapter:
            font = 'arial {}'.format(self.font)
            self.adapter.font = font
            for ci in self.children:
                ci.font = font

            if self.refresh_func:
                self.refresh_func()

                # self.refresh_table_needed = True

    def set_columns(self):
        # def _columns_changed(self):
        if self.adapter:
            cols = self._assemble_columns()
            for ci in self.children:
                ci.columns = cols

            self.adapter.columns = cols

    def _set_font(self, f):
        s = f.pointSize()
        self.font = s

    def _load_state(self):
        p = os.path.join(paths.hidden_dir, self.id)
        if os.path.isfile(p):
            try:
                with open(p, 'rb') as rfile:
                    state = pickle.load(rfile)

            except (pickle.PickleError, OSError, EOFError, TraitError):
                return

            try:
                self.sparse_columns = state.get('sparse_columns')
            except:
                pass

            cols = state.get('columns')
            if cols:
                ncols = []
                for ai in self.available_columns:
                    if ai in cols:
                        ncols.append(ai)

                self.columns = ncols

            font = state.get('font', None)
            if font:
                self.font = font

            self._load_hook(state)
            self.set_columns()

    def _dump_state(self):
        p = os.path.join(paths.hidden_dir, self.id)
        obj = self._get_dump()

        with open(p, 'wb') as wfile:
            try:
                pickle.dump(obj, wfile)
            except pickle.PickleError:
                pass

    def _get_dump(self):
        obj = dict(columns=self.columns,
                   font=self.font,
                   sparse_columns=self.sparse_columns)
        return obj

    def _load_hook(self, state):
        pass

    def _assemble_columns(self):
        d = self.adapter.all_columns_dict
        return [(k, d[k]) for k, v in self.adapter.all_columns if k in self.columns]

    def _get_columns_grp(self):
        return

    def _set_defaults(self):
        p = self.defaults_path
        if os.path.isfile(p):
            import yaml

            with open(p, 'r') as rfile:
                yd = yaml.load(rfile)
                try:
                    self.columns = yd['columns']
                except KeyError:
                    pass
            self.set_columns()

    def _default_button_fired(self):
        self._set_defaults()

    def _set_sparse_fired(self):
        self.sparse_columns = self.columns

    def _toggle_sparse_fired(self):
        if self._toggle_sparse_enabled:
            columns = self._prev_columns
        else:
            self._prev_columns = self.columns
            columns = self.sparse_columns

        self.columns = columns
        self.set_columns()

        self._toggle_sparse_enabled = not self._toggle_sparse_enabled

    def _show_all_fired(self):
        self.columns = self.available_columns
        self.set_columns()

    def _adapter_changed(self, adp):
        if adp:
            acols = [c for c, _ in adp.all_columns]

            # set currently visible columns
            t = [c for c, _ in adp.columns]

            cols = [c for c in acols if c in t]
            self.trait_setq(columns=cols)

            # set all available columns
            self.available_columns = acols

            self._set_font(adp.font)
            self._load_state()

    def traits_view(self):
        v = View(VGroup(HGroup(UItem('show_all', tooltip='Show all columns'),
                               UItem('set_sparse',
                                     tooltip='Set the current set of columns to the Sparse Column Set',
                                     enabled_when='sparse_enabled'),
                               UItem('toggle_sparse',
                                     tooltip='Display only Sparse Column Set'),
                               UItem('default_button',
                                     tooltip='Set to Laboratory defaults. File located at '
                                             '[root]/experiments/experiment_defaults.yaml')),
                        VGroup(UItem('columns',
                                     style='custom',
                                     editor=CheckListEditor(name='available_columns', cols=3)),
                               Item('font', enabled_when='fontsize_enabled'),
                               show_border=True)),
                 handler=TableConfigurerHandler(),
                 title=self.title,
                 buttons=['OK', 'Cancel'], )
        return v

def str_to_time(lp):
    lp = lp.replace('/', '-')
    if lp.count('-') == 2:
        y = lp.split('-')[-1]
        y = 'y' if len(y) == 2 else 'Y'

        fmt = '%m-%d-%{}'.format(y)
    elif lp.count('-') == 1:
        y = lp.split('-')[-1]
        y = 'y' if len(y) == 2 else 'Y'

        fmt = '%m-%{}'.format(y)
    else:
        fmt = '%Y' if len(lp) == 4 else '%y'

    return datetime.strptime(lp, fmt)

class ExperimentTableConfigurer(TableConfigurer):
    defaults_path = paths.experiment_defaults

class AnalysisTableConfigurer(TableConfigurer):
    id = 'analysis.table'
    limit = Int
    omit_invalid = Bool(True)

    def _get_dump(self):
        obj = super(AnalysisTableConfigurer, self)._get_dump()
        obj['limit'] = self.limit
        obj['omit_invalid'] = self.omit_invalid

        return obj

    def _load_hook(self, obj):
        self.limit = obj.get('limit', 500)
        self.omit_invalid = obj.get('omit_invalid', True)

    def traits_view(self):
        v = View(VGroup(VGroup(UItem('columns',
                                     style='custom',
                                     editor=CheckListEditor(name='available_columns', cols=3)),
                               label='Columns', show_border=True),
                        # Group(
                        # VGroup(HGroup(Heading('Lower Bound'), UItem('use_low_post')),
                        # UItem('low_post', style='custom', enabled_when='use_low_post')),
                        # VGroup(HGroup(Heading('Upper Bound'), UItem('use_high_post')),
                        #            UItem('high_post', style='custom', enabled_when='use_high_post')),
                        #     VGroup(HGroup(Heading('Named Range'), UItem('use_named_date_range')),
                        #            UItem('named_date_range', enabled_when='use_named_date_range'))),
                        Item('omit_invalid'),
                        Item('limit',
                             tooltip='Limit number of displayed analyses',
                             label='Limit'),
                        show_border=True,
                        label='Limiting'),
                 buttons=['OK', 'Cancel', 'Revert'],
                 # kind='modal',
                 title=self.title,
                 handler=TableConfigurerHandler,
                 resizable=True,
                 width=300)
        return v

class SampleTableConfigurer(TableConfigurer):
    title = 'Configure Sample Table'
    # parent = Any
    id = 'sample.table'
    filter_non_run_samples = Bool(True)

    def _get_dump(self):
        obj = super(SampleTableConfigurer, self)._get_dump()
        obj['filter_non_run_samples'] = self.filter_non_run_samples

        return obj

    def _load_hook(self, obj):
        self.filter_non_run_samples = obj.get('filter_non_run_samples', True)

    def traits_view(self):
        v = View(VGroup(
            VGroup(UItem('columns',
                         style='custom',
                         editor=CheckListEditor(name='available_columns', cols=3)),
                   label='Columns', show_border=True),
            # Item('filter_non_run_samples',
            # tooltip='Omit samples that have not been analyzed to date',
            #      label='Exclude Non-Run')
        ),
                 buttons=['OK', 'Cancel', 'Revert'],
                 # kind='modal',
                 title=self.title,
                 handler=TableConfigurerHandler,
                 resizable=True,
                 width=300)
        return v

class IsotopeTableConfigurer(TableConfigurer):
    id = 'recall.isotopes'

    def traits_view(self):
        v = View(VGroup(UItem('columns',
                              style='custom',
                              editor=CheckListEditor(name='available_columns', cols=3)),
                        Item('font', enabled_when='fontsize_enabled'),
                        show_border=True,
                        label='Isotopes'))
        return v

class IntermediateTableConfigurer(TableConfigurer):
    id = 'recall.intermediate'

class RecallTableConfigurer(TableConfigurer):
    isotope_table_configurer = Instance(IsotopeTableConfigurer, ())
    intermediate_table_configurer = Instance(IntermediateTableConfigurer, ())
    show_intermediate = Bool
    experiment_fontsize = Enum(*SIZES)
    measurement_fontsize = Enum(*SIZES)
    extraction_fontsize = Enum(*SIZES)
    main_measurement_fontsize = Enum(*SIZES)
    main_extraction_fontsize = Enum(*SIZES)
    main_computed_fontsize = Enum(*SIZES)

    subview_names = ('experiment', 'measurement', 'extraction')
    main_names = ('measurement', 'extraction', 'computed')
    bind_fontsizes = Bool(False)
    global_fontsize = Enum(*SIZES)

    # def closed(self):
    # super(RecallTableConfigurer, self).closed()
    # self.experiment_view

    def _get_dump(self):
        obj = super(RecallTableConfigurer, self)._get_dump()
        obj['show_intermediate'] = self.show_intermediate
        for a in self.subview_names:
            a = '{}_fontsize'.format(a)
            obj[a] = getattr(self, a)

        for a in self.main_names:
            a = 'main_{}_fontsize'.format(a)
            obj[a] = getattr(self, a)

        for attr in ('global_fontsize', 'bind_fontsizes'):
            obj[attr] = getattr(self, attr)

        return obj

    def _load_hook(self, obj):
        self.show_intermediate = obj.get('show_intermediate', True)
        self.isotope_table_configurer.load()
        self.intermediate_table_configurer.load()

        for a in self.subview_names:
            a = '{}_fontsize'.format(a)
            setattr(self, a, obj.get(a, 10))

        for a in self.main_names:
            a = 'main_{}_fontsize'.format(a)
            setattr(self, a, obj.get(a, 10))

        for attr in ('global_fontsize', 'bind_fontsizes'):
            try:
                setattr(self, attr, obj[attr])
            except KeyError:
                pass

    def dump(self):
        super(RecallTableConfigurer, self).dump()
        self.intermediate_table_configurer.dump()
        self.isotope_table_configurer.dump()

    def set_columns(self):
        self.isotope_table_configurer.set_columns()
        self.intermediate_table_configurer.set_columns()

        self.isotope_table_configurer.update()
        self.intermediate_table_configurer.update()

    def set_font(self):
        self.isotope_table_configurer.set_font()
        self.intermediate_table_configurer.set_font()

    def set_fonts(self, av):
        self.set_font()

        for a in self.subview_names:
            s = getattr(self, '{}_fontsize'.format(a))
            av.update_fontsize(a, s)

        for a in self.main_names:
            av.update_fontsize('main.{}'.format(a),
                               getattr(self, 'main_{}_fontsize'.format(a)))

        av.main_view.refresh_needed = True

    def _bind_fontsizes_changed(self, new):
        if new:
            self._global_fontsize_changed()
        self.isotope_table_configurer.fontsize_enabled = not new
        self.intermediate_table_configurer.fontsize_enabled = not new

    def _global_fontsize_changed(self):
        gf = self.global_fontsize
        self.isotope_table_configurer.font = gf
        self.intermediate_table_configurer.font = gf

        self.main_measurement_fontsize = gf
        self.main_extraction_fontsize = gf
        self.main_computed_fontsize = gf

    def traits_view(self):
        main_grp = VGroup(HGroup(Item('bind_fontsizes'),
                                 Item('global_fontsize', enabled_when='bind_fontsizes')),
                          Item('main_extraction_fontsize', enabled_when='not bind_fontsizes'),
                          Item('main_measurement_fontsize', enabled_when='not bind_fontsizes'),
                          Item('main_computed_fontsize', enabled_when='not bind_fontsizes'))

        main_view = VGroup(main_grp,
                           UItem('isotope_table_configurer', style='custom'),
                           HGroup(Item('show_intermediate', label='Show Intermediate Table')),
                           UItem('intermediate_table_configurer', style='custom', enabled_when='show_intermediate'),
                           label='Main')

        experiment_view = VGroup(Item('experiment_fontsize', label='Size'),
                                 show_border=True,
                                 label='Experiment')
        measurement_view = VGroup(Item('measurement_fontsize', label='Size'),
                                  show_border=True,
                                  label='Measurement')
        extraction_view = VGroup(Item('extraction_fontsize', label='Size'),
                                 show_border=True,
                                 label='Extraction')
        v = View(Tabbed(main_view,
                        VGroup(experiment_view,
                               measurement_view,
                               extraction_view, label='Scripts')),

                 buttons=['OK', 'Cancel', 'Revert'],
                 kind='livemodal',
                 title='Configure Table',
                 handler=TableConfigurerHandler,
                 resizable=True,
                 width=300)
        return v

# ============= EOF =============================================
<|endoftext|>


<commit_before>DISCONNCTING_VCENERT = 'disconnecting from vcenter: {0}'
COMMAND_ERROR = 'error has occurred while executing command: {0} error: {1}'
DEBUG_COMMAND_RESULT = 'finished executing with the result: {0}'
FINISHED_EXECUTING_COMMAND = 'finished executing command: {0}'
DEBUG_COMMAND_PARAMS = 'command params: {0}'
COMMA = ','
EXECUTING_COMMAND = 'executing command: {0}'
CONNECTED_TO_CENTER = 'connected to vcenter: {0}'
DEBUG_CONNECTION_INFO = 'connection params: host: {0} username: {1} password: {2} port: {3}'
LOGGER_CANNOT_BE_NONE = 'logger cannot be None'
COMMAND_CANNOT_BE_NONE = 'command cannot be None'
INFO_CONNECTING_TO_VCENTER = 'connecting to vcenter: {0}'
START = 'START'
END = 'END'
LOG_FORMAT = 'action:{0} command_name:{0}'

class CommandWrapper:
    def __init__(self, logger, pv_service):
        self.pv_service = pv_service
        self.logger = logger

    def execute_command(self, command, *args):
        return self.execute_command_with_connection(None, command, *args)

    def execute_command_with_connection(self, connection_details, command, *args):
        if not self.logger:
            self.logger.error(LOGGER_CANNOT_BE_NONE)
            raise Exception(LOGGER_CANNOT_BE_NONE)
        if not command:
            self.logger.error(COMMAND_CANNOT_BE_NONE)
            raise Exception(COMMAND_CANNOT_BE_NONE)

        try:
            command_name = command.__name__
            self.logger.info(LOG_FORMAT.format(START, command_name))
            command_args = []
            si = None

            if connection_details:
                self.logger.info(INFO_CONNECTING_TO_VCENTER.format(connection_details.host))
                self.logger.debug(
                    DEBUG_CONNECTION_INFO.format(connection_details.host,
                                                 connection_details.username,
                                                 connection_details.password,
                                                 connection_details.port))

                si = self.pv_service.connect(connection_details)
            if si:
                self.logger.info(CONNECTED_TO_CENTER.format(connection_details.host))

                command_args.append(si)

            command_args.extend(args)

            self.logger.info(EXECUTING_COMMAND.format(command_name))
            self.logger.debug(DEBUG_COMMAND_PARAMS.format(COMMA.join([str(x) for x in command_args])))

            results = command(*tuple(command_args))

            self.logger.info(FINISHED_EXECUTING_COMMAND.format(command_name))
            self.logger.debug(DEBUG_COMMAND_RESULT.format(str(results)))

            return results
        except Exception as e:
            self.logger.error(COMMAND_ERROR.format(command_name, e))
            raise
        finally:
            if si:
                self.logger.info(DISCONNCTING_VCENERT.format(connection_details.host))
                self.pv_service.disconnect(si)
            self.logger.info(LOG_FORMAT.format(END, command_name))
<commit_msg>fixing logging bug<commit_after>DISCONNCTING_VCENERT = 'disconnecting from vcenter: {0}'
COMMAND_ERROR = 'error has occurred while executing command: {0} error: {1}'
DEBUG_COMMAND_RESULT = 'finished executing with the result: {0}'
FINISHED_EXECUTING_COMMAND = 'finished executing command: {0}'
DEBUG_COMMAND_PARAMS = 'command params: {0}'
COMMA = ','
EXECUTING_COMMAND = 'executing command: {0}'
CONNECTED_TO_CENTER = 'connected to vcenter: {0}'
DEBUG_CONNECTION_INFO = 'connection params: host: {0} username: {1} password: {2} port: {3}'
LOGGER_CANNOT_BE_NONE = 'logger cannot be None'
COMMAND_CANNOT_BE_NONE = 'command cannot be None'
INFO_CONNECTING_TO_VCENTER = 'connecting to vcenter: {0}'
START = 'START'
END = 'END'
LOG_FORMAT = 'action:{0} command_name:{0}'

class CommandWrapper:
    def __init__(self, logger, pv_service):
        self.pv_service = pv_service
        self.logger = logger

    def execute_command(self, command, *args):
        return self.execute_command_with_connection(None, command, *args)

    def execute_command_with_connection(self, connection_details, command, *args):
        if not self.logger:
            print LOGGER_CANNOT_BE_NONE
            raise Exception(LOGGER_CANNOT_BE_NONE)
        if not command:
            self.logger.error(COMMAND_CANNOT_BE_NONE)
            raise Exception(COMMAND_CANNOT_BE_NONE)

        try:
            command_name = command.__name__
            self.logger.info(LOG_FORMAT.format(START, command_name))
            command_args = []
            si = None

            if connection_details:
                self.logger.info(INFO_CONNECTING_TO_VCENTER.format(connection_details.host))
                self.logger.debug(
                    DEBUG_CONNECTION_INFO.format(connection_details.host,
                                                 connection_details.username,
                                                 connection_details.password,
                                                 connection_details.port))

                si = self.pv_service.connect(connection_details)
            if si:
                self.logger.info(CONNECTED_TO_CENTER.format(connection_details.host))

                command_args.append(si)

            command_args.extend(args)

            self.logger.info(EXECUTING_COMMAND.format(command_name))
            self.logger.debug(DEBUG_COMMAND_PARAMS.format(COMMA.join([str(x) for x in command_args])))

            results = command(*tuple(command_args))

            self.logger.info(FINISHED_EXECUTING_COMMAND.format(command_name))
            self.logger.debug(DEBUG_COMMAND_RESULT.format(str(results)))

            return results
        except Exception as e:
            self.logger.error(COMMAND_ERROR.format(command_name, e))
            raise
        finally:
            if si:
                self.logger.info(DISCONNCTING_VCENERT.format(connection_details.host))
                self.pv_service.disconnect(si)
            self.logger.info(LOG_FORMAT.format(END, command_name))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright 2017 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo.tests import common

class TestAlignFollowers(common.TransactionCase):

    def setUp(self):
        super(TestAlignFollowers, self).setUp()

        AnalyticAccount = self.env['account.analytic.account']
        Project = self.env['project.project']
        Follower = self.env['mail.followers']

        self.aa_1 = AnalyticAccount.create({
            'name': 'Analytic Account 1',
        })

        self.proj_1 = Project.create({
            'name': 'Project 1',
            'analytic_account_id': self.aa_1.id,
        })

        self.foll_1 = Follower.create({
            'res_model': 'account.analytic.account',
            'res_id': self.aa_1.id,
            'partner_id': self.env.user.partner_id.id,
        })

        self.foll_2 = Follower.create({
            'res_model': 'project.project',
            'res_id': self.proj_1.id,
            'partner_id': self.env.user.partner_id.id,
        })

    def test_01_unlink_proj(self):
        self.proj_1.unlink()

    def test_02_unlink_aa(self):
        self.aa_1.unlink()
<commit_msg>Unit tests for module project_analytic_align_follower<commit_after># -*- coding: utf-8 -*-
# Copyright 2017 Onestein (<http://www.onestein.eu>)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).

from odoo.tests import common

class TestAlignFollowers(common.TransactionCase):

    def setUp(self):
        super(TestAlignFollowers, self).setUp()

        AnalyticAccount = self.env['account.analytic.account']
        Project = self.env['project.project']

        self.aa_1 = AnalyticAccount.create({
            'name': 'Analytic Account 1',
        })

        self.proj_1 = Project.create({
            'name': 'Project 1',
            'analytic_account_id': self.aa_1.id,
        })

    def test_01_unlink_proj(self):
        self.proj_1.unlink()

    def test_02_unlink_aa(self):
        self.aa_1.unlink()

    def test_03_aa_foll_create(self):
        foll_1 = self.env['mail.followers'].create({
            'res_model': 'account.analytic.account',
            'res_id': self.aa_1.id,
            'partner_id': self.env.ref('base.res_partner_2').id,
        })

    def test_04_proj_foll_create(self):
        foll_2 = self.env['mail.followers'].create({
            'res_model': 'project.project',
            'res_id': self.proj_1.id,
            'partner_id': self.env.ref('base.res_partner_2').id,
        })
<|endoftext|>


<commit_before>import numpy as np

class Architecture(object):

    """
    Architecture is a static class that relates genotypes to phenotypes.

    Main Effects
    ------
    For main (i.e non-epistatic) effects, you supply a tuple of
    (chromosome, position) to indicate location. You also supply a dictionary
    of genotype/effect pairs. For example, to add a fully dominant effect of
    allele A  that adds 1 to the trait value at chromosome 4, position 50,
    you would prepare a dictionary in the form:

    effects = {('A','A'): 1, ('A','a'): 1, ('a','a'): 0}
    location = (4,50)

    Then you would add the effect to the trait architecture with:
    t.add_effect_liability(location,effects)

    For convenience, any genotype not found in the effects dictionary has no
    effect on the trait. For example a fully reccessive effect of allele 'a'
    on the trait, giving an effect of 1 could be a dictionary that looks like
    this: {('a','a'): 1}

    Epistatic Effects
    ------
    Pydigree can also simulate epistatic effects. That is, combinations of
    genotypes that add effects non additively. For these the locations are
    given as a list of (chr, pos) tuples (as seen in the main effects section).
    The dictionary of effects is given as the key,value pair of a list of
    genotypes and the effect of that genotype on the trait.

    The list of genotypes reflects the order of the positions. That is, if you
    supply positions 1,2,3, the genotypes should look like:
    [(genotype at position 1), (genotype at position 2),
    (genotype at position 3)]

    Like with the main effects, any genotype combination not in the effect
    dictionary is assumed to have 0 effect on the trait.
    """

    def __init__(self, name, type, chromosomes=None):
        self.name = name
        self.chromosomes = chromosomes
        self.effects = {}
        self.epistatic_effects = {}
        self.noise = None
        if type not in ['quantitative', 'dichotomous']:
            raise ValueError('Not a valid trait type!')
        else:
            self.traittype = type
        self.liability_threshold = None

    def __str__(self):
        return "Trait %s (%s): %s main effects, %s epistatic effects" \
            % (self.name, self.traittype,
               len(self.effects), len(self.epistatic_effects))

    def __transformdict(self, d):
        d2 = {}
        for k in d:
            d2[frozenset(k)] = d[k]
        return d2

    def _geteffect(self, individual, location):
        g = frozenset(individual.get_genotype(location))
        try:
            return self.effects[location][g]
        except KeyError:
            return 0

    def _getepistaticeffects(self, individual, locations):
        locations = tuple(tuple(loc) for loc in locations)
        g = tuple(frozenset(individual.get_genotype(chr, pos)
                            for chr, pos in locations))
        if g not in self.epistatic_effects[locations]:
            return 0

    def set_liability_threshold(self, threshold):
        if self.traittype != 'dichotomous':
            raise ValueError('Thresholds only for dichotomous traits')
        else:
            self.liability_threshold = threshold

    def add_effect(self, location, effects):
        """
        Add a main effect

        Arguments
        ------
        location: a chromosome, index tuple
        effects: a dictionary describing the effect for each genotype. eg:
        Dominance: {(1,1): 1, (0,1): 1, (0,0): 0 }
        Additive: {(1,1): 2, (0,1): 1, (0,0): 0 }

        or

        a numeric variable that will be made into an additive effect
        """
        chrom, marker = location
        if not isinstance(effects, dict):
            try:
                effect = float(effects)
                effects = {(1,1): 0, (1,2): effect, (2,2): 2 * effect}
            except ValueError:
                raise ValueError('Unparsable effect: {}'.format(effects))
        effects = self.__transformdict(effects)
        try:
            self.effects[location].update(effects)
        except KeyError:
            self.effects[(chrom, marker)] = effects

    def add_epistatic_effect(self, locations, effects):
        locations = tuple(tuple(x) for x in locations)
        effects = self.__transformdict(effects)
        self.epistatic_effects[locations] = effects

    def add_noise(self, mean=0, sd=1):
        self.noise = (mean, sd)

    def predict_phenotype(self, individual):
        liability = [self._geteffect(individual, x) for x in self.effects]
        liability += [self._getepistaticeffect(individual, x)
                      for x in self.epistatic_effects]
        liabilitysum = sum(liability)

        if self.noise:
            mu, sigma = self.noise
            liabilitysum += np.random.normal(mu, sigma)

        if self.traittype == 'dichotomous':
            if self.liability_threshold is None:
                raise ValueError('No liability threshold set')
            return 1 if liabilitysum >= self.liability_threshold else 0
        return liabilitysum

    @staticmethod
    def from_file(filename):
        with open(filename) as f:
            type, name = f.readline().strip().split()
            trait = Architecture(type, name)
            for line in f:
                l = line.strip().split()
                if len(l) != 5:
                    # TODO: implement epistatic effects in file
                    raise NotImplementedError(
                        'Epistatic effects not yet implemented')
                chr, pos, allele_a, allele_b, effect = line.strip().split()
                locus = chr, pos
                eff = {(allele_a, allele_b): effect}
                trait.add_effect(locus, eff)
<commit_msg>remove epistatic effects for now<commit_after>import numpy as np

class Architecture(object):

    """
    Architecture is a static class that relates genotypes to phenotypes.

    Main Effects
    ------
    For main (i.e non-epistatic) effects, you supply a tuple of
    (chromosome, position) to indicate location. You also supply a dictionary
    of genotype/effect pairs. For example, to add a fully dominant effect of
    allele A  that adds 1 to the trait value at chromosome 4, position 50,
    you would prepare a dictionary in the form:

    effects = {('A','A'): 1, ('A','a'): 1, ('a','a'): 0}
    location = (4,50)

    Then you would add the effect to the trait architecture with:
    t.add_effect_liability(location,effects)

    For convenience, any genotype not found in the effects dictionary has no
    effect on the trait. For example a fully reccessive effect of allele 'a'
    on the trait, giving an effect of 1 could be a dictionary that looks like
    this: {('a','a'): 1}

    """

    def __init__(self, name, type, chromosomes=None):
        self.name = name
        self.chromosomes = chromosomes
        self.effects = {}
        self.noise = None
        if type not in ['quantitative', 'dichotomous']:
            raise ValueError('Not a valid trait type!')
        else:
            self.traittype = type
        self.liability_threshold = None

    def __str__(self):
        return "Trait {} ({}): {} main effects".format(self.name,
                                                       self.traittype,
                                                       len(self.effects))

    def __transformdict(self, d):
        d2 = {}
        for k in d:
            d2[frozenset(k)] = d[k]
        return d2

    def _geteffect(self, individual, location):
        g = frozenset(individual.get_genotype(location))
        try:
            return self.effects[location][g]
        except KeyError:
            return 0

    def set_liability_threshold(self, threshold):
        if self.traittype != 'dichotomous':
            raise ValueError('Thresholds only for dichotomous traits')
        else:
            self.liability_threshold = threshold

    def add_effect(self, location, effects):
        """
        Add a main effect

        Arguments
        ------
        location: a chromosome, index tuple
        effects: a dictionary describing the effect for each genotype. eg:
        Dominance: {(1,1): 1, (0,1): 1, (0,0): 0 }
        Additive: {(1,1): 2, (0,1): 1, (0,0): 0 }

        or

        a numeric variable that will be made into an additive effect
        """
        chrom, marker = location
        if not isinstance(effects, dict):
            try:
                effect = float(effects)
                effects = {(1,1): 0, (1,2): effect, (2,2): 2 * effect}
            except ValueError:
                raise ValueError('Unparsable effect: {}'.format(effects))
        effects = self.__transformdict(effects)
        try:
            self.effects[location].update(effects)
        except KeyError:
            self.effects[(chrom, marker)] = effects

    def add_noise(self, mean=0, sd=1):
        self.noise = (mean, sd)

    def predict_phenotype(self, individual):
        liability = [self._geteffect(individual, x) for x in self.effects]
        liabilitysum = sum(liability)

        if self.noise:
            mu, sigma = self.noise
            liabilitysum += np.random.normal(mu, sigma)

        if self.traittype == 'dichotomous':
            if self.liability_threshold is None:
                raise ValueError('No liability threshold set')
            return 1 if liabilitysum >= self.liability_threshold else 0
        return liabilitysum

    @staticmethod
    def from_file(filename):
        with open(filename) as f:
            type, name = f.readline().strip().split()
            trait = Architecture(type, name)
            for line in f:
                l = line.strip().split()
                if len(l) != 5:
                    # TODO: implement epistatic effects in file
                    raise NotImplementedError(
                        'Epistatic effects not yet implemented')
                chr, pos, allele_a, allele_b, effect = line.strip().split()
                locus = chr, pos
                eff = {(allele_a, allele_b): effect}
                trait.add_effect(locus, eff)
<|endoftext|>


<commit_before>from pprint import pprint

from django import forms

from base.forms import O2BaseForm
from base.forms import mount_fields

O2FieldModeloForm = mount_fields.MountIntegerFieldForm(
    'modelo',
    attrs={
        'min_value': 1,
        'max_value': 9999,
    },
    widget_attrs={'size': 4},
)

class O2FieldRefForm(forms.Form):
    ref = forms.CharField(
        label='Referência',
        required=False,
        widget=forms.TextInput(attrs={'size': 5}))

    def clean_ref(self):
        return O2BaseForm.cleanner_pad(self, 'ref', 5)

class O2FieldTamanhoForm(forms.Form):
    tamanho = forms.CharField(
        required=False,
        widget=forms.TextInput(attrs={'size': 3}))

    def clean_tamanho(self):
        return O2BaseForm.cleanner(self, 'tamanho')

class O2FieldCorForm(forms.Form):
    cor = forms.CharField(
        required=False,
        widget=forms.TextInput(attrs={'size': 6}))

    def clean_cor(self):
        return O2BaseForm.cleanner_pad(self, 'cor', 6)

class O2FieldGtinForm(forms.Form):
    gtin = forms.CharField(
        label='GTIN', max_length=13, min_length=13, required=False,
        widget=forms.TextInput(attrs={'size': 13}))

    def clean_cor(self):
        return O2BaseForm.cleanner(self, 'gtin')

class O2FieldFiltroForm(forms.Form):
    filtro = forms.CharField(
        required=False,
        help_text='Busca vários valores separados por espaço.',
        widget=forms.TextInput())

    def clean_filtro(self):
        return O2BaseForm.upper(self, 'filtro')

class O2FieldDepositoForm(forms.Form):
    deposito = forms.CharField(
        label='Depósito', required=False,
        widget=forms.NumberInput(attrs={'size': 3}))

O2FieldPedidoForm = mount_fields.MountIntegerFieldForm(
    'pedido', widget_attrs={'size': 6})
<commit_msg>O2FieldPedidoForm passa a tem valores mínimo e máximo<commit_after>from pprint import pprint

from django import forms

from base.forms import O2BaseForm
from base.forms import mount_fields

O2FieldModeloForm = mount_fields.MountIntegerFieldForm(
    'modelo',
    attrs={
        'min_value': 1,
        'max_value': 9999,
    },
    widget_attrs={'size': 4},
)

class O2FieldRefForm(forms.Form):
    ref = forms.CharField(
        label='Referência',
        required=False,
        widget=forms.TextInput(attrs={'size': 5}))

    def clean_ref(self):
        return O2BaseForm.cleanner_pad(self, 'ref', 5)

class O2FieldTamanhoForm(forms.Form):
    tamanho = forms.CharField(
        required=False,
        widget=forms.TextInput(attrs={'size': 3}))

    def clean_tamanho(self):
        return O2BaseForm.cleanner(self, 'tamanho')

class O2FieldCorForm(forms.Form):
    cor = forms.CharField(
        required=False,
        widget=forms.TextInput(attrs={'size': 6}))

    def clean_cor(self):
        return O2BaseForm.cleanner_pad(self, 'cor', 6)

class O2FieldGtinForm(forms.Form):
    gtin = forms.CharField(
        label='GTIN', max_length=13, min_length=13, required=False,
        widget=forms.TextInput(attrs={'size': 13}))

    def clean_cor(self):
        return O2BaseForm.cleanner(self, 'gtin')

class O2FieldFiltroForm(forms.Form):
    filtro = forms.CharField(
        required=False,
        help_text='Busca vários valores separados por espaço.',
        widget=forms.TextInput())

    def clean_filtro(self):
        return O2BaseForm.upper(self, 'filtro')

class O2FieldDepositoForm(forms.Form):
    deposito = forms.CharField(
        label='Depósito', required=False,
        widget=forms.NumberInput(attrs={'size': 3}))

O2FieldPedidoForm = mount_fields.MountIntegerFieldForm(
    'pedido',
    attrs={
        'min_value': 1,
        'max_value': 999999,
    },
    widget_attrs={'size': 6},
)
<|endoftext|>


<commit_before>__author__ = 'noe'

import mdtraj
import numpy as np

__all__ = ['MDFeaturizer']

def _describe_atom(topology, index):
    """
    Returns a string describing the given atom

    :param topology:
    :param index:
    :return:
    """
    at = topology.atom(index)
    return "%s %i %s %i" % (at.residue.name, at.residue.index, at.name, at.index)

class CustomFeature(object):

    """
    A CustomFeature is the base class for all self defined features. You shall
    calculate your quantities in map method and return it as an ndarray.

    If you simply want to call a function with arguments, you do not need to derive.

    Parameters
    ----------
    func : function
        will be invoked with given args and kwargs on mapping traj
    args : list of positional args (optional)
    kwargs : named arguments
    """

    def __init__(self, func=None, *args, **kwargs):
        self._func = func
        self._args = args
        self._kwargs = kwargs

    def describe(self):
        return "override me to get proper description!"

    def map(self, traj):
        feature = self._func(traj, self._args, self._kwargs)
        assert isinstance(feature, np.ndarray)
        return feature

class DistanceFeature:

    def __init__(self, top, distance_indexes):
        self.top = top
        self.distance_indexes = distance_indexes
        self.prefix_label = "DIST:"

    def describe(self):
        labels = []
        for pair in self.distance_indexes:
            labels.append("%s%s - %s" % (self.prefix_label,
                                         _describe_atom(self.top, pair[0]),
                                         _describe_atom(self.top, pair[1])))
        return labels

    def map(self, traj):
        return mdtraj.compute_distances(traj, self.distance_indexes)

class InverseDistanceFeature(DistanceFeature):

    def __init__(self, top, distance_indexes):
        DistanceFeature.__init__(self, top, distance_indexes)
        self.prefix_label = "INVDIST:"

    def map(self, traj):
        return 1.0 / mdtraj.compute_distances(traj, self.distance_indexes)

class BackboneTorsionFeature:

    def __init__(self, topology):
        self.topology = topology

    def _has_atom(self, res_index, name):
        for atom in self.topology.atoms:
            if atom.name.lower() == name.lower():
                return True
        return False

    def _list_phis(self):
        # phi: C-1, N, CA, C
        phis = []
        for ires in range(1, self.topology.n_residues):
            if (self._has_atom(ires - 1, "C") and self._has_atom(ires, "N") and
                    self._has_atom(ires, "CA") and self._has_atom(ires, "C")):
                phis.append(ires)
        return phis

    def _list_psis(self):
        # psi: N, CA, C, N+1
        psis = []
        for ires in range(0, self.topology.n_residues - 1):
            if (self._has_atom(ires, "N") and self._has_atom(ires, "CA") and
                    self._has_atom(ires, "C") and self._has_atom(ires + 1, "N")):
                psis.append(ires)
        return psis

    def describe(self):
        labels = []
        phis = self._list_phis()
        for ires in phis:
            labels.append("PHI: %s %i" %
                          (self.topology.residue(ires).name, ires))
        psis = self._list_psis()
        for ires in psis:
            labels.append("PSI: %s %i" %
                          (self.topology.residue(ires).name, ires))
        return labels

    def map(self, traj):
        y1 = mdtraj.compute_phi(traj)[1].astype(np.float32)
        y2 = mdtraj.compute_psi(traj)[1].astype(np.float32)
        return np.hstack((y1, y2))

class MDFeaturizer(object):

    """
    Parameters
    ----------

    topfile : str
        a path to a topology file (pdb etc.)
    """

    def __init__(self, topfile):
        self.topology = (mdtraj.load(topfile)).topology

        self.distance_indexes = []
        self.inv_distance_indexes = []
        self.contact_indexes = []
        self.angle_indexes = []

        self.active_features = []
        self.dim = 0

    def describe(self):
        """
        Returns a list of strings, one for each feature selected,
        with human-readable descriptions of the features.

        :return:
        """
        labels = []

        for f in self.active_features:
            labels.append(f.describe())

        return labels

    def select(self, selstring):
        """
        Selects using the given selection string

        :param selstring:
        :return:
        """
        return self.topology.select(selstring)

    def select_Ca(self):
        """
        Selects Ca atoms

        :return:
        """
        return self.topology.select("name CA")

    def select_Backbone(self):
        """
        Selects backbone C, CA and N atoms

        :return:
        """
        return self.topology.select("name C CA N")

    def select_Heavy(self):
        """
        Selects all heavy atoms

        :return:
        """
        return self.topology.select("mass >= 2")

    def pairs(self, sel):
        """
        Creates all pairs between indexes, except for 1 and 2-neighbors

        :return:
        """
        nsel = np.shape(sel)[0]
        npair = ((nsel - 2) * (nsel - 3)) / 2
        pairs = np.zeros((npair, 2))
        s = 0
        for i in range(0, nsel - 3):
            d = nsel - 3 - i
            pairs[s:s + d, 0] = sel[i]
            pairs[s:s + d, 1] = sel[i + 3:nsel]
            s += d

        return pairs

    def distances(self, atom_pairs):
        """
        Adds the set of distances to the feature list
        :param atom_pairs:
        """
        # TODO: shall we instead append here?
        self.distance_indexes = atom_pairs
        f = DistanceFeature(self.topology, distance_indexes=atom_pairs)
        self.active_features.append(f)
        self.dim += np.shape(atom_pairs)[0]

    def distancesCa(self):
        """
        Adds the set of Ca-distances to the feature list
        """
        self.distance_indexes = self.pairs(self.select_Ca())

        f = DistanceFeature(self.topology, atom_pairs=self.distance_indexes)
        self.active_features.append(f)
        self.dim += np.shape(self.distance_indexes)[0]

    def inverse_distances(self, atom_pairs):
        """
        Adds the set of inverse distances to the feature list

        :param atom_pairs:
        """
        self.inv_distance_indexes = atom_pairs

        f = InverseDistanceFeature(atom_pairs=self.inv_distance_indexes)
        self.active_features.append(f)
        self.dim += np.shape(self.distance_indexes)[0]

    def contacts(self, atom_pairs):
        """
        Adds the set of contacts to the feature list
        :param atom_pairs:
        """
        f = CustomFeature(mdtraj.compute_contacts, atom_pairs=atom_pairs)

        def describe():
            labels = []
            for pair in self.contact_indexes:
                labels.append("CONTACT: %s - %s" % (_describe_atom(self.topology, pair[0]),
                                                    _describe_atom(self.topology, pair[1])))
            return labels
        f.describe = describe
        f.topology = self.topology

        self.dim += np.shape(atom_pairs)[0]
        self.active_features.append(f)

    def angles(self, indexes):
        """
        Adds the list of angles to the feature list

        :param indexes:
        """
        f = CustomFeature(mdtraj.compute_angles, indexes=indexes)

        def describe():
            labels = []
            for triple in self.angle_indexes:
                labels.append("ANGLE: %s - %s - %s " %
                              (_describe_atom(self.topology, triple[0]),
                               _describe_atom(self.topology, triple[1]),
                               _describe_atom(self.topology, triple[2])))

            return labels

        f.describe = describe
        f.topology = self.topology

        self.active_features.append(f)
        self.angle_indexes = indexes
        self.dim += np.shape(indexes)[0]

    def backbone_torsions(self):
        """
        Adds all backbone torsions
        """
        f = BackboneTorsionFeature(self.topology)
        self.active_features.append(f)
        self.dim += 2 * self.topology.n_residues

    def add_custom_feature(self, feature, output_dimension):
        """
        Parameters
        ----------
        feature : object
            an object with interface like CustomFeature (map, describe methods)
        output_dimension : int
            a mapped feature coming from has this dimension.
        """
        assert output_dimension > 0, "tried to add empty feature"
        assert hasattr(feature, 'map'), "no map method in given feature"
        assert hasattr(feature, 'describe')

        self.active_features.append(feature)
        self.dim += output_dimension

    def dimension(self):
        return self.dim

    def map(self, traj):
        """
        Computes the features for the given trajectory
        :return:
        """

        feature_vec = []

        for f in self.active_features:
            feature_vec.append(f.map(traj).astype(np.float32))

        return np.hstack(feature_vec)
<commit_msg>dim->_dim; return traj if no feature is selected.<commit_after>__author__ = 'noe'

import mdtraj
import numpy as np

__all__ = ['MDFeaturizer',
           'CustomFeature',
           ]

def _describe_atom(topology, index):
    """
    Returns a string describing the given atom

    :param topology:
    :param index:
    :return:
    """
    at = topology.atom(index)
    return "%s %i %s %i" % (at.residue.name, at.residue.index, at.name, at.index)

class CustomFeature(object):

    """
    A CustomFeature is the base class for all self defined features. You shall
    calculate your quantities in map method and return it as an ndarray.

    If you simply want to call a function with arguments, you do not need to derive.

    Parameters
    ----------
    func : function
        will be invoked with given args and kwargs on mapping traj
    args : list of positional args (optional)
    kwargs : named arguments
    """

    def __init__(self, func=None, *args, **kwargs):
        self._func = func
        self._args = args
        self._kwargs = kwargs

    def describe(self):
        return "override me to get proper description!"

    def map(self, traj):
        feature = self._func(traj, self._args, self._kwargs)
        assert isinstance(feature, np.ndarray)
        return feature

class DistanceFeature:

    def __init__(self, top, distance_indexes):
        self.top = top
        self.distance_indexes = distance_indexes
        self.prefix_label = "DIST:"

    def describe(self):
        labels = []
        for pair in self.distance_indexes:
            labels.append("%s%s - %s" % (self.prefix_label,
                                         _describe_atom(self.top, pair[0]),
                                         _describe_atom(self.top, pair[1])))
        return labels

    def map(self, traj):
        return mdtraj.compute_distances(traj, self.distance_indexes)

class InverseDistanceFeature(DistanceFeature):

    def __init__(self, top, distance_indexes):
        DistanceFeature.__init__(self, top, distance_indexes)
        self.prefix_label = "INVDIST:"

    def map(self, traj):
        return 1.0 / mdtraj.compute_distances(traj, self.distance_indexes)

class BackboneTorsionFeature:

    def __init__(self, topology):
        self.topology = topology

    def _has_atom(self, res_index, name):
        for atom in self.topology.atoms:
            if atom.name.lower() == name.lower():
                return True
        return False

    def _list_phis(self):
        # phi: C-1, N, CA, C
        phis = []
        for ires in range(1, self.topology.n_residues):
            if (self._has_atom(ires - 1, "C") and self._has_atom(ires, "N") and
                    self._has_atom(ires, "CA") and self._has_atom(ires, "C")):
                phis.append(ires)
        return phis

    def _list_psis(self):
        # psi: N, CA, C, N+1
        psis = []
        for ires in range(0, self.topology.n_residues - 1):
            if (self._has_atom(ires, "N") and self._has_atom(ires, "CA") and
                    self._has_atom(ires, "C") and self._has_atom(ires + 1, "N")):
                psis.append(ires)
        return psis

    def describe(self):
        labels = []
        phis = self._list_phis()
        for ires in phis:
            labels.append("PHI: %s %i" %
                          (self.topology.residue(ires).name, ires))
        psis = self._list_psis()
        for ires in psis:
            labels.append("PSI: %s %i" %
                          (self.topology.residue(ires).name, ires))
        return labels

    def map(self, traj):
        y1 = mdtraj.compute_phi(traj)[1].astype(np.float32)
        y2 = mdtraj.compute_psi(traj)[1].astype(np.float32)
        return np.hstack((y1, y2))

class MDFeaturizer(object):

    """
    Parameters
    ----------

    topfile : str
        a path to a topology file (pdb etc.)
    """

    def __init__(self, topfile):
        self.topology = (mdtraj.load(topfile)).topology

        self.distance_indexes = []
        self.inv_distance_indexes = []
        self.contact_indexes = []
        self.angle_indexes = []

        self.active_features = []
        self._dim = 0

    def describe(self):
        """
        Returns a list of strings, one for each feature selected,
        with human-readable descriptions of the features.

        :return:
        """
        labels = []

        for f in self.active_features:
            labels.append(f.describe())

        return labels

    def select(self, selstring):
        """
        Selects using the given selection string

        :param selstring:
        :return:
        """
        return self.topology.select(selstring)

    def select_Ca(self):
        """
        Selects Ca atoms

        :return:
        """
        return self.topology.select("name CA")

    def select_Backbone(self):
        """
        Selects backbone C, CA and N atoms

        :return:
        """
        return self.topology.select("name C CA N")

    def select_Heavy(self):
        """
        Selects all heavy atoms

        :return:
        """
        return self.topology.select("mass >= 2")

    @staticmethod
    def pairs(sel):
        """
        Creates all pairs between indexes, except for 1 and 2-neighbors

        :return:
        """
        nsel = np.shape(sel)[0]
        npair = ((nsel - 2) * (nsel - 3)) / 2
        pairs = np.zeros((npair, 2))
        s = 0
        for i in range(0, nsel - 3):
            d = nsel - 3 - i
            pairs[s:s + d, 0] = sel[i]
            pairs[s:s + d, 1] = sel[i + 3:nsel]
            s += d

        return pairs

    def distances(self, atom_pairs):
        """
        Adds the set of distances to the feature list
        :param atom_pairs:
        """
        # TODO: shall we instead append here?
        self.distance_indexes = atom_pairs
        f = DistanceFeature(self.topology, distance_indexes=atom_pairs)
        self.active_features.append(f)
        self._dim += np.shape(atom_pairs)[0]

    def distancesCa(self):
        """
        Adds the set of Ca-distances to the feature list
        """
        self.distance_indexes = self.pairs(self.select_Ca())

        f = DistanceFeature(self.topology, atom_pairs=self.distance_indexes)
        self.active_features.append(f)
        self._dim += np.shape(self.distance_indexes)[0]

    def inverse_distances(self, atom_pairs):
        """
        Adds the set of inverse distances to the feature list

        :param atom_pairs:
        """
        self.inv_distance_indexes = atom_pairs

        f = InverseDistanceFeature(atom_pairs=self.inv_distance_indexes)
        self.active_features.append(f)
        self._dim += np.shape(self.distance_indexes)[0]

    def contacts(self, atom_pairs):
        """
        Adds the set of contacts to the feature list
        :param atom_pairs:
        """
        f = CustomFeature(mdtraj.compute_contacts, atom_pairs=atom_pairs)

        def describe():
            labels = []
            for pair in self.contact_indexes:
                labels.append("CONTACT: %s - %s" % (_describe_atom(self.topology, pair[0]),
                                                    _describe_atom(self.topology, pair[1])))
            return labels
        f.describe = describe
        f.topology = self.topology

        self._dim += np.shape(atom_pairs)[0]
        self.active_features.append(f)

    def angles(self, indexes):
        """
        Adds the list of angles to the feature list

        :param indexes:
        """
        f = CustomFeature(mdtraj.compute_angles, indexes=indexes)

        def describe():
            labels = []
            for triple in self.angle_indexes:
                labels.append("ANGLE: %s - %s - %s " %
                              (_describe_atom(self.topology, triple[0]),
                               _describe_atom(self.topology, triple[1]),
                               _describe_atom(self.topology, triple[2])))

            return labels

        f.describe = describe
        f.topology = self.topology

        self.active_features.append(f)
        self.angle_indexes = indexes
        self._dim += np.shape(indexes)[0]

    def backbone_torsions(self):
        """
        Adds all backbone torsions
        """
        f = BackboneTorsionFeature(self.topology)
        self.active_features.append(f)
        self._dim += 2 * self.topology.n_residues

    def add_custom_feature(self, feature, output_dimension):
        """
        Parameters
        ----------
        feature : object
            an object with interface like CustomFeature (map, describe methods)
        output_dimension : int
            a mapped feature coming from has this dimension.
        """
        assert output_dimension > 0, "tried to add empty feature"
        assert hasattr(feature, 'map'), "no map method in given feature"
        assert hasattr(feature, 'describe')

        self.active_features.append(feature)
        self._dim += output_dimension

    @property
    def dimension(self):
        return self._dim

    def map(self, traj):
        """
        Computes the features for the given trajectory
        :return:
        """
        # if there are no features selected, return given trajectory
        if self._dim == 0:
            return traj

        feature_vec = []

        for f in self.active_features:
            feature_vec.append(f.map(traj).astype(np.float32))

        return np.hstack(feature_vec)
<|endoftext|>


<commit_before>from pyethapp.eth_protocol import ETHProtocol, TransientBlock
from devp2p.service import WiredService
from devp2p.app import BaseApp
from pyethereum import tester
import rlp
tester.disable_logging()

class PeerMock(object):
    packets = []
    config = dict()

    def send_packet(self, packet):
        self.packets.append(packet)

def setup():
    peer = PeerMock()
    proto = ETHProtocol(peer, WiredService(BaseApp()))
    chain = tester.state()
    cb_data = []

    def cb(proto, data):
        cb_data.append((proto, data))
    return peer, proto, chain, cb_data, cb

def test_status():
    peer, proto, chain, cb_data, cb = setup()
    genesis = head = chain.blocks[-1]

    # test status
    proto.send_status(total_difficulty=head.difficulty, chain_head_hash=head.hash,
                      genesis_hash=genesis.hash)
    packet = peer.packets.pop()
    proto.receive_status_callbacks.append(cb)
    proto._receive_status(packet)

    _p, _d = cb_data.pop()
    assert _p == proto
    assert isinstance(_d, dict)
    assert _d['total_difficulty'] == head.difficulty
    print _d
    assert _d['chain_head_hash'] == head.hash
    assert _d['genesis_hash'] == genesis.hash
    assert 'eth_version' in _d
    assert 'network_id' in _d

def test_blocks():
    peer, proto, chain, cb_data, cb = setup()

    # test blocks
    chain.mine(n=2)
    proto.send_blocks(blocks=chain.blocks)
    packet = peer.packets.pop()
    proto.receive_blocks_callbacks.append(cb)
    proto._receive_blocks(packet)

    _p, _d = cb_data.pop()
    assert 'blocks' in _d
    assert isinstance(_d['blocks'], list)
    for block in _d['blocks']:
        assert isinstance(block, TransientBlock)
        assert isinstance(block.transactions, rlp.LazyList)
        assert isinstance(block.uncles, rlp.LazyList)
        # assert that transactions and uncles have not been decoded
        assert len(block.transactions._elements) == 0
        assert len(block.uncles._elements) == 0

    # newblock
    approximate_difficulty = chain.blocks[-1].difficulty * 3
    proto.send_newblock(block=chain.blocks[-1], total_difficulty=approximate_difficulty)
    packet = peer.packets.pop()
    proto.receive_newblock_callbacks.append(cb)
    proto._receive_newblock(packet)

    _p, _d = cb_data.pop()
    assert 'block' in _d
    assert 'total_difficulty' in _d
    assert _d['total_difficulty'] == approximate_difficulty
    assert _d['block'].header == chain.blocks[-1].header
    assert isinstance(_d['block'].transactions, rlp.LazyList)
    assert isinstance(_d['block'].uncles, rlp.LazyList)
    # assert that transactions and uncles have not been decoded
    assert len(_d['block'].transactions._elements) == 0
    assert len(_d['block'].uncles._elements) == 0
<commit_msg>Fix transaction_list rename<commit_after>from pyethapp.eth_protocol import ETHProtocol, TransientBlock
from devp2p.service import WiredService
from devp2p.app import BaseApp
from pyethereum import tester
import rlp
tester.disable_logging()

class PeerMock(object):
    packets = []
    config = dict()

    def send_packet(self, packet):
        self.packets.append(packet)

def setup():
    peer = PeerMock()
    proto = ETHProtocol(peer, WiredService(BaseApp()))
    chain = tester.state()
    cb_data = []

    def cb(proto, **data):
        cb_data.append((proto, data))
    return peer, proto, chain, cb_data, cb

def test_status():
    peer, proto, chain, cb_data, cb = setup()
    genesis = head = chain.blocks[-1]

    # test status
    proto.send_status(total_difficulty=head.difficulty, chain_head_hash=head.hash,
                      genesis_hash=genesis.hash)
    packet = peer.packets.pop()
    proto.receive_status_callbacks.append(cb)
    proto._receive_status(packet)

    _p, _d = cb_data.pop()
    assert _p == proto
    assert isinstance(_d, dict)
    assert _d['total_difficulty'] == head.difficulty
    print _d
    assert _d['chain_head_hash'] == head.hash
    assert _d['genesis_hash'] == genesis.hash
    assert 'eth_version' in _d
    assert 'network_id' in _d

def test_blocks():
    peer, proto, chain, cb_data, cb = setup()

    # test blocks
    chain.mine(n=2)
    proto.send_blocks(blocks=chain.blocks)
    packet = peer.packets.pop()
    proto.receive_blocks_callbacks.append(cb)
    proto._receive_blocks(packet)

    _p, _d = cb_data.pop()
    assert 'blocks' in _d
    assert isinstance(_d['blocks'], list)
    for block in _d['blocks']:
        assert isinstance(block, TransientBlock)
        assert isinstance(block.transaction_list, rlp.LazyList)
        assert isinstance(block.uncles, rlp.LazyList)
        # assert that transactions and uncles have not been decoded
        assert len(block.transaction_list._elements) == 0
        assert len(block.uncles._elements) == 0

    # newblock
    approximate_difficulty = chain.blocks[-1].difficulty * 3
    proto.send_newblock(block=chain.blocks[-1], total_difficulty=approximate_difficulty)
    packet = peer.packets.pop()
    proto.receive_newblock_callbacks.append(cb)
    proto._receive_newblock(packet)

    _p, _d = cb_data.pop()
    assert 'block' in _d
    assert 'total_difficulty' in _d
    assert _d['total_difficulty'] == approximate_difficulty
    assert _d['block'].header == chain.blocks[-1].header
    assert isinstance(_d['block'].transaction_list, rlp.LazyList)
    assert isinstance(_d['block'].uncles, rlp.LazyList)
    # assert that transactions and uncles have not been decoded
    assert len(_d['block'].transaction_list._elements) == 0
    assert len(_d['block'].uncles._elements) == 0
<|endoftext|>