class NestedContainerClass(HasTraits): # Used in regression test for changes to nested containers # Nested list list_of_list = List(List) # enthought/traits#281 dict_of_list = Dict(Str, List(Str)) # Similar to enthought/traits#281 dict_of_union_none_or_list = Dict(Str, Union(List(), None)) # Nested dict # enthought/traits#25 list_of_dict = List(Dict) dict_of_dict = Dict(Str, Dict) dict_of_union_none_or_dict = Dict(Str, Union(Dict(), None)) # Nested set list_of_set = List(Set) dict_of_set = Dict(Str, Set) dict_of_union_none_or_set = Dict(Str, Union(Set(), None))
class Example(HasTraits): shapes = List() selection = List() add_random_cylinder = Button() remove_cylinder = Button() view = View(Item('shapes', editor=OCCEditorFactory(selection='selection'), show_label=False), Item('add_random_cylinder', show_label=False), Item('remove_cylinder', show_label=False), width=0.8, height=0.8, resizable=True) def _selection_items_changed(self, name, undefined, list_change): print("selection trait changed", list_change.added) def _add_random_cylinder_fired(self, old, new): brep = BRepPrimAPI_MakeCylinder(random.random() * 50, random.random() * 50).Shape() trsf = gp_Trsf() trsf.SetTranslation( gp_Vec(random.random() * 100, random.random() * 100, random.random() * 100)) brep.Move(TopLoc_Location(trsf)) self.shapes.append(brep) def _remove_cylinder_fired(self, old, new): for s in self.selection: if s is None: continue self.shapes.remove(s)
class A(HasTraits): alist = List(Int, list(range(5))) adict = Dict(Str, Int, dict(a=1, b=2)) aset = Set(Int, set(range(5))) events = List() @on_trait_change("alist_items,adict_items,aset_items") def _receive_events(self, object, name, old, new): self.events.append((name, new))
class BIDSGrabInputSpec(BaseInterfaceInputSpec): # TODO: Check this inteface, why are there 'either file or list'? ~Mateusz fmri_prep_files = List() fmri_prep_aroma_files = Either(List(ImageFile()), File()) conf_raw_files = Either(List(File(exists=True)), File(exists=True)) conf_json_files = Either(List(File(exists=True)), File(exists=True)) subject = Str() task = Str() session = Str() run = Int()
class GroupConfoundsInputSpec(BaseInterfaceInputSpec): conf_summary_json_files = List(File(exists=True), mandatory=True, desc="Confounds summary") output_dir = Directory( # needed to save data in other directory mandatory=True, desc="Output path")
def test_list_editor_default(self): trait = List(Str) editor = list_editor(trait, trait) self.assertIsInstance(editor, traitsui.api.ListEditor) self.assertEqual(editor.trait_handler, trait) self.assertEqual(editor.rows, 5) self.assertFalse(editor.use_notebook) self.assertEqual(editor.page_name, '')
def test_list_editor_options(self): trait = List(Str, rows=10, use_notebook=True, page_name='page') editor = list_editor(trait, trait) self.assertIsInstance(editor, traitsui.api.ListEditor) self.assertEqual(editor.trait_handler, trait) self.assertEqual(editor.rows, 10) self.assertTrue(editor.use_notebook) self.assertEqual(editor.page_name, 'page')
class FlipBvecInputSpec(BaseInterfaceInputSpec): bvecs = File(exists=True, desc="Input diffusion gradient bvec file") flipping_axis = List(desc="List of axis to be flipped") delimiter = Str(desc="Delimiter used in the table") header_lines = Int(0, desc="Line number of table header") orientation = Enum(['v', 'h'], desc="Orientation of the table")
class CorePyFibrePlugin(CorePlugin): """Inherits from the Envisage CorePlugin to include extra extension points for classes that fulfil the IMultiImageFactory interface""" id = 'pyfibre.core.pyfibre_plugin' #: Extension points for IMultiImageFactory multi_image_factories = ExtensionPoint(List(IMultiImageFactory), id=MULTI_IMAGE_FACTORIES)
class ReportCreatorInputSpec(BaseInterfaceInputSpec): pipelines = List(Dict(), mandatory=True) pipelines_names = List(Str(), mandatory=True) group_data_dir = Directory(exists=True) excluded_subjects = List(Str(), value=()) plot_pipeline_edges_density = File( exists=True, desc="Density of edge weights (all subjects)") plot_pipelines_edges_density_no_high_motion = File( exist=True, desc="Density of edge weights (no high motion)") plot_pipelines_fc_fd_pearson = File(exist=True) plot_pipelines_fc_fd_uncorr = File(exist=True) plot_pipelines_distance_dependence = File(exist=True)
class DummyParent(HasTraits): number = Int() number2 = Int() instance = Instance(Dummy, allow_none=True) instance2 = Instance(Dummy) income = Float() dummies = List(Dummy)
class OCCEditor(Editor): shapes = List(Any) selection = List(Any) border_size = Int() layout_style = Int() def init(self, parent): self.control = OCCTraitViewer(parent, editor=self, selection=self.selection) self.sync_value(self.name, 'shapes', 'both', is_list=True) self.sync_value(self.factory.selection, 'selection', 'both', is_list=True) def _shapes_items_changed(self, name, nothing, change): for s in change.added: print(self.control) self.control.add_shape_to_viewer(s) for s in change.removed: self.control.erase_shape_from_viewer(s)
class ProjectInfoUI(cmp.project.ProjectInfo): """Class that extends the :class:`ProjectInfo` with graphical components. It supports graphically the setting of all processing properties / attributes of an :class:`ProjectInfo` instance. Attributes ----------- creation_mode : traits.Enum Mode for loading the dataset. Valid values are 'Load BIDS dataset', 'Install Datalad BIDS dataset' install_datalad_dataset_via_ssh : traits.Bool If set to True install the datalad dataset from a remote server via ssh.(True by default) ssh_user : traits.Str Remote server username. (Required if ``install_datalad_dataset_via_ssh`` is True) ssh_pwd <traits.Password> Remote server password. (Required if ``install_datalad_dataset_via_ssh`` is True) ssh_remote : traits.Str Remote server IP or URL. (Required if ``install_datalad_dataset_via_ssh`` is True) datalad_dataset_path : traits.Directory Path to the datalad dataset on the remote server. (Required if ``install_datalad_dataset_via_ssh`` is True) summary_view_button : traits.ui.Button Button that shows the pipeline processing summary table pipeline_processing_summary_view : traits.ui.VGroup TraitsUI VGroup that contains ``Item('pipeline_processing_summary')`` dataset_view : traits.ui.View TraitsUI View that shows a summary of project settings and modality available for a given subject traits_view : QtView TraitsUI QtView that includes the View 'dataset_view' create_view : traits.ui.View Dialog view to create a BIDS Dataset subject_view : traits.ui.View Dialog view to select of subject subject_session_view : traits.ui.View Dialog view to select the subject session dmri_bids_acq_view : traits.ui.View Dialog view to select the diffusion acquisition model anat_warning_view : traits.ui.View View that displays a warning message regarding the anatomical T1w data anat_config_error_view : traits.ui.View Error view that displays an error message regarding the configuration of the anatomical pipeline dmri_warning_view : traits.ui.View View that displays a warning message regarding the diffusion MRI data dmri_config_error_view : traits.ui.View View that displays an error message regarding the configuration of the diffusion pipeline fmri_warning_view : traits.ui.View View that displays a warning message regarding the functional MRI data fmri_config_error_view : traits.ui.View View that displays an error message regarding the configuration of the fMRI pipeline open_view : traits.ui.View Dialog view to load a BIDS Dataset anat_select_config_to_load : traits.ui.View Dialog view to load the configuration file of the anatomical pipeline diffusion_imaging_model_select_view : traits.ui.View Dialog view to select the diffusion acquisition model dmri_select_config_to_load : traits.ui.View Dialog view to load the configuration file of the diffusion MRI pipeline fmri_select_config_to_load : traits.ui.View Dialog view to load the configuration file of the fMRI pipeline """ creation_mode = Enum("Load BIDS dataset", "Install Datalad BIDS dataset") install_datalad_dataset_via_ssh = Bool(True) ssh_user = String("remote_username") ssh_pwd = Password("") ssh_remote = String("IP address/ Machine name") datalad_dataset_path = Directory( "/shared/path/to/existing/datalad/dataset") anat_runs = List() anat_run = Enum(values="anat_runs") dmri_runs = List() dmri_run = Enum(values="dmri_runs") fmri_runs = List() fmri_run = Enum(values="fmri_runs") summary_view_button = Button("Pipeline processing summary") pipeline_processing_summary_view = VGroup( Item("pipeline_processing_summary")) dataset_view = VGroup( VGroup( HGroup( Item( "base_directory", width=-0.3, style="readonly", label="", resizable=True, ), Item( "number_of_subjects", width=-0.3, style="readonly", label="Number of participants", resizable=True, ), "summary_view_button", ), label="BIDS Dataset", ), spring, HGroup( Group( Item("subject", style="simple", show_label=True, resizable=True)), Group( Item("subject_session", style="simple", label="Session", resizable=True), visible_when='subject_session!=""', ), springy=True, ), spring, Group( Item("t1_available", style="readonly", label="T1", resizable=True), HGroup( Item( "dmri_available", style="readonly", label="Diffusion", resizable=True, ), Item( "diffusion_imaging_model", label="Model", resizable=True, enabled_when="dmri_available", ), ), Item("fmri_available", style="readonly", label="BOLD", resizable=True), label="Modalities", ), spring, Group( Item( "anat_last_date_processed", label="Anatomical pipeline", style="readonly", resizable=True, enabled_when="t1_available", ), Item( "dmri_last_date_processed", label="Diffusion pipeline", style="readonly", resizable=True, enabled_when="dmri_available", ), Item( "fmri_last_date_processed", label="fMRI pipeline", style="readonly", resizable=True, enabled_when="fmri_available", ), label="Last date processed", ), spring, Group(Item("number_of_cores", resizable=True), label="Processing configuration"), "550", spring, springy=True, ) traits_view = QtView(Include("dataset_view")) create_view = View( Item("creation_mode", style="custom"), Group( Group( Item("base_directory", label="BIDS Dataset"), visible_when='creation_mode=="Load BIDS dataset"', ), Group( Item("install_datalad_dataset_via_ssh"), visible_when='creation_mode=="Install Datalad/BIDS dataset"', ), Group( Item( "ssh_remote", label="Remote ssh server", visible_when="install_datalad_dataset_via_ssh", ), Item( "ssh_user", label="Remote username", visible_when="install_datalad_dataset_via_ssh", ), Item( "ssh_pwd", label="Remote password", visible_when="install_datalad_dataset_via_ssh", ), Item( "datalad_dataset_path", label="Datalad/BIDS Dataset Path/URL to be installed", ), Item("base_directory", label="Installation directory"), visible_when='creation_mode=="Install Datalad/BIDS dataset"', ), ), kind="livemodal", title="Data creation: BIDS dataset selection", # style_sheet=style_sheet, width=modal_width, buttons=["OK", "Cancel"], ) subject_view = View( Group(Item("subject", label="Selected Subject")), kind="modal", title="Subject and session selection", # style_sheet=style_sheet, width=modal_width, buttons=["OK", "Cancel"], ) subject_session_view = View( Group( Item("subject", style="readonly", label="Selected Subject"), Item("subject_session", label="Selected Session"), ), kind="modal", title="Session selection", # style_sheet=style_sheet, width=modal_width, buttons=["OK", "Cancel"], ) dmri_bids_acq_view = View( Group(Item("dmri_bids_acq", label="Selected model"), ), kind="modal", title="Selection of diffusion acquisition model", # style_sheet=style_sheet, width=modal_width, buttons=["OK", "Cancel"], ) anat_warning_view = View( Group(Item("anat_warning_msg", style="readonly", show_label=False), ), title="Warning : Anatomical T1w data", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) anat_config_error_view = View( Group( Item("anat_config_error_msg", style="readonly", show_label=False), ), title="Error", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) dmri_warning_view = View( Group(Item("dmri_warning_msg", style="readonly", show_label=False), ), title="Warning : Diffusion MRI data", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) dmri_config_error_view = View( Group( Item("dmri_config_error_msg", style="readonly", show_label=False), ), title="Error", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) fmri_warning_view = View( Group(Item("fmri_warning_msg", style="readonly", show_label=False), ), title="Warning : fMRI data", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) fmri_config_error_view = View( Group( Item("fmri_config_error_msg", style="readonly", show_label=False), ), title="Error", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) open_view = View( Item("creation_mode", label="Mode"), Group( Item("install_datalad_dataset_via_ssh"), Item( "ssh_remote", label="Remote ssh server", visible_when="install_datalad_dataset_via_ssh", ), Item( "ssh_user", label="Remote username", visible_when="install_datalad_dataset_via_ssh", ), Item( "ssh_pwd", label="Remote password", visible_when="install_datalad_dataset_via_ssh", ), Item( "datalad_dataset_path", label="Datalad/BIDS Dataset Path/URL to be installed", ), Item("base_directory", label="Installation directory"), visible_when='creation_mode=="Install Datalad BIDS dataset"', ), Group( Item("base_directory", label="BIDS Dataset"), visible_when='creation_mode=="Load BIDS dataset"', ), kind="livemodal", title="BIDS Dataset Creation/Loading", # style_sheet=style_sheet, width=600, height=250, buttons=["OK", "Cancel"], ) anat_select_config_to_load = View( Group( Item("anat_config_to_load_msg", style="readonly", show_label=False), Item( "anat_config_to_load", style="custom", editor=EnumEditor(name="anat_available_config"), show_label=False, ), ), title="Select configuration for anatomical pipeline", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) anat_custom_map_view = View( Group( Item( "anat_custom_last_stage", editor=EnumEditor(name="anat_stage_names"), style="custom", show_label=False, ), ), title="Select until which stage to process the anatomical pipeline.", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) diffusion_imaging_model_select_view = View( Group(Item("diffusion_imaging_model", label="Diffusion MRI modality"), ), title="Please select diffusion MRI modality", kind="modal", width=modal_width, buttons=["OK", "Cancel"], ) dmri_select_config_to_load = View( Group( Item("dmri_config_to_load_msg", style="readonly", show_label=False), ), Item( "dmri_config_to_load", style="custom", editor=EnumEditor(name="dmri_available_config"), show_label=False, ), title="Select configuration for diffusion pipeline", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) dmri_custom_map_view = View( Group( Item( "dmri_custom_last_stage", editor=EnumEditor(name="dmri_stage_names"), style="custom", show_label=False, ), ), title="Select until which stage to process the diffusion pipeline.", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) fmri_select_config_to_load = View( Group( Item("fmri_config_to_load_msg", style="readonly", show_label=False), ), Item( "fmri_config_to_load", style="custom", editor=EnumEditor(name="fmri_available_config"), show_label=False, ), title="Select configuration for fMRI pipeline", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) fmri_custom_map_view = View( Group( Item( "fmri_custom_last_stage", editor=EnumEditor(name="fmri_stage_names"), style="custom", show_label=False, ), ), title="Select until which stage to process the fMRI pipeline.", kind="modal", width=modal_width, # style_sheet=style_sheet, buttons=["OK", "Cancel"], ) def _summary_view_button_fired(self): self.configure_traits(view="pipeline_processing_summary_view")
class PersonWithPostInt(Person): events = List() @observe("age", post_init=True) def handler(self, event): self.events.append(event)
class BaseClass(HasTraits): events = List() @observe("value") def handler(self, event): self.events.append(event)
class NewPerson(Person): events = List() @observe(expression) def handler(self, event): self.events.append(event)
class PersonWithObserve(Person): events = List() @observe(trait("age")) def handler(self, event): self.events.append(event)
class DatabaseView(HasTraits): # reference to pyanno database database = Instance(PyannoDatabase) # reference to pyanno application application = Any # trait displayed in the TableView, it is synchronized with the actual db results_table = List(DBEntry) # used to track add and delete actions results_table_len = Int # currently selected entry current_selection = Instance(DBEntry) # event raised when the database entries changed db_updated = Event # button that sends the currently selected row to the main window open_to_main = Button('Load results') # button that deletes the currently selected row from the database delete_action = Button('Delete...') # button that closes the database window close_view = Button('Close') @on_trait_change('results_table[]') def _database_content_modified(self): """Track results_table to detect delete events.""" if self.results_table_len > len(self.results_table): logger.debug('delete database entry event' + self.current_selection.data_id) # delete current selection self.database.remove(self.current_selection.data_id, self.current_selection.idx) self.results_table_len = len(self.results_table) @on_trait_change('delete_action') def _delete_action(self): # open dialog asking are you sure msg = 'Remove selected result from database?' result = message(message=msg, title='Delete result from database', buttons=['OK', 'Cancel']) if result: # remove from results_table self.results_table.remove(self.current_selection) self.current_selection = None @on_trait_change('db_updated,database') def _create_results_table(self): db = self.database.database table = [] for data_id in list(db.keys()): results = db[data_id] for idx, result in enumerate(results): table.append(DBEntry.from_result(idx, data_id, result)) # sort entries by hand as the sortable columns in wx TableEditor do # not work table.sort(key=lambda x: (x.data_id, x.value)) self.results_table = table self.results_table_len = len(table) def find_database_record(self, entry): """Given an entry in the results_table, find the corresponding database record.""" return self.database.retrieve_id(entry.data_id)[entry.idx] @on_trait_change('open_to_main') def forward_to_model_data_view(self): # called on double click, it sets the model and the annotations in # the main window if self.application is not None: entry = self.current_selection record = self.find_database_record(entry) self.application.update_window_from_database_record(record) @on_trait_change('close_view') def close_database_view(self): if self.application is not None: self.application.close_database_window() def track_selection(self, entry): # update current selection each time the selection is changes self.current_selection = entry def traits_view(self): db_table_editor = TableEditor( columns=[ ObjectColumn(name='data_id', label='Annotations ID', editable=False, width=0.65), ObjectColumn(name='model_name', editable=False, width=0.20), ObjectColumn(name='value', label='Log likelihood', editable=False, width=0.15) ], search=SearchIDFilter(), editable=True, deletable=True, configurable=False, sortable=True, sort_model=False, auto_size=False, orientation='vertical', show_toolbar=True, selection_mode='row', on_dclick=self.forward_to_model_data_view, on_select=self.track_selection) traits_view = View( VGroup( Item( 'results_table', editor=db_table_editor, show_label=False, ), HGroup( Item('open_to_main', show_label=False, width=100), Item('delete_action', show_label=False, enabled_when='current_selection is not None', width=100), Spring(), Item('close_view', show_label=False, width=100)), ), title='pyAnno results database', width=800, height=400, resizable=True, #buttons = [ 'OK' ], kind='live') return traits_view
def test_list_editor_list_instance(self): trait = List(Instance(HasTraits)) editor = list_editor(trait, trait) self.assertIsInstance(editor, traitsui.api.TableEditor)
class ListOfFloats(HasTraits): data = List(Float)
class TraitObject(HasTraits): list_str = List(Str)
class ListStrEditorWithSelectedIndex(HasTraits): values = List(Str()) selected_index = Int() selected_indices = List(Int()) selected = Str()
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))
class BoardWrapper(HasTraits): pins = List(PinWrapper) digital_pins = List(PinWrapper) analog_pins = List(PinWrapper) defines = List(GuiDefine) port_type = Enum('serial', [ 'none', 'serial', ] ) serial_device = Enum(_auto_detect_serial_unix()) baudrate = Int(115200) sleep_after_connect = Int(2) timeout = Int(1) uptime = Float() tree = None vcc = Float() avr_name = Str() arduino_version = Str() firmware_build_time = Str() gcc_version = Str() libc_version = Str() libc_date = Str() connected = Bool(False) connect = Button() disconnect = Button() def _connect_fired(self): try: connection = SerialManager(device=self.serial_device, baudrate=self.baudrate, sleep_after_connect=self.sleep_after_connect, timeout=self.timeout) connection.open() print ArduinoApi(connection=connection).millis() except Exception as e: traceback.print_exc() message(traceback.format_exc(), buttons=['OK']) return a = self.tree = ArduinoTree(connection=connection) d = a.define.as_dict s = [GuiDefine(name=k, value=str(v)) for k, v in d.items()] s.sort(key=lambda x: x.name) self.defines = s self.digital_pins = [PinWrapper(pin=a.pin.get(x)) for x in a.pin.names_digital] self.analog_pins = [PinWrapper(pin=a.pin.get(x)) for x in a.pin.names_analog] self.pins = self.digital_pins + self.analog_pins fw = a.firmware_info self.arduino_version = fw.get('arduino_version') self.firmware_build_time = str(fw.get('compile_datetime')) self.avr_name = fw.get('avr_name') self.gcc_version = fw.get('gcc_version') self.libc_version = fw.get('libc_version') self.libc_date = str(fw.get('libc_date')) self.connected = True def _disconnect_fired(self): self.digital_pins = [] self.analog_pins = [] self.pins = [] self.defines = [] self.avr_name = '' self.arduino_version = '' self.firmware_build_time = '' self.gcc_version = '' self.libc_version = '' self.libc_date = '' self.tree.connection.close() del self.tree self.tree = None self.connected = False update_interval = Int(1000, desc='interval in msec') update_enable = Bool(True) def update(self): if self.update_enable and self.connected and self.tree: for x in self.pins: x.update() self.uptime = self.tree.api.millis() / 1000.0 self.vcc = self.tree.vcc.read() if self.tree.vcc else -1 time.sleep(self.update_interval / 1000.0) traits_view = View( Tabbed( Group( HGroup( Group( button('connect', enabled_when='not connected'), button('disconnect', enabled_when='connected'), Item( 'port_type', enabled_when='not connected', width=300, ), Group( 'serial_device', 'baudrate', 'sleep_after_connect', 'timeout', visible_when='port_type=="serial"', enabled_when='not connected', ), ), Group( 'avr_name', 'arduino_version', 'firmware_build_time', 'gcc_version', 'libc_version', 'libc_date', # 'baudrate', # 'sleep_after_connect', # visible_when='port_type=="serial"', springy=True, ), ), label='connection', ), Group( 'uptime', 'vcc', label='misc', ), Item(name='digital_pins', editor=ListEditor( style='custom', ), style='readonly', show_label=False, ), Item(name='analog_pins', editor=ListEditor( style='custom', ), style='readonly', show_label=False, ), Group( 'update_enable', Item(name='update_interval', editor=RangeEditor( mode='slider', low=1, high=1000, ), style='custom', ), label='settings', ), Item('defines', show_label=False, editor=ListEditor( # auto_size=False, # editable=False, # configurable=False, style='custom', ), style='readonly', ) ), width=800, height=600, buttons=['Undo', 'Revert', 'OK', 'Cancel'], kind='live', resizable=True, handler=Handler(), )
class ListStrModelRightClick(HasTraits): value = List([]) right_clicked = Str() right_clicked_index = Int()
class EventVisualization(HasTraits): background = (0, 0, 0) normal_barcolor = (153.0 / 255, 204.0 / 255, 255.0 / 255) textcolor = normal_barcolor scene = Instance(MlabSceneModel, ()) def default_traits_view(self): view = View( Item('scene', editor=SceneEditor(scene_class=MayaviScene), height=600, width=600, show_label=False), HGroup( Item("current_time", label="Date"), Item(" "), Item("num_of_shown_days", label="Show"), Item("_home_button", show_label=False), Item("_selected_source_name", show_label=False), Item("_selected_event_name", editor=CheckListEditor(name='_selected_events_list'), show_label=False), Item("_back1", show_label=False), Item( "Relative_Start_Day", show_label=False, editor=RangeEditor(mode="slider", low_name="_low_start_day_number", high_name="_high_start_day_number"), tooltip= "Shows total number of days in data set and the currently selected day", springy=True, full_size=True), Item("_forward1", show_label=False), Item("move_step", show_label=False), Item("play_button", label='Play')), title="Visualization of Events", resizable=True) view.resizable = True return view # Index to the currently selected source. None if no source is selected. selected_source = Trait(None, None, Int) _selected_source_name = Enum(None, [None]) # index to a selected event. None if not selected. selected_event = None _selected_event_name = List _selected_events_list = List(['None', 'None']) # Current (most recent) time, can also be set usinh start day, but then relative to the total number of days. current_time = Date start_day = Trait(None, int, tuple, String, Date) _low_start_day_number = Int(0) # minimum start day = 0 _high_start_day_number = Int( 100) # maximum start day = total number of days # Configures the shown number of days in the visualization. num_of_shown_days = Trait( "30 days", Enum([ "7 days", "14 days", "30 days", "60 days", "90 days", "120 days", "180 days", "365 days" ])) ## Buttons for controlling the visualization _home_button = Button("Unselect>>", width_padding=0, height_padding=0) _back1 = Button("<", width_padding=0, height_padding=0) _forward1 = Button(">", width_padding=0, height_padding=0) # Play button sets the visualization on stepping in the last selected direction, back or forth. play_button = Bool # Configure the number of days the visualization can step. move_step = Trait("1 day", Enum(["1 day", "2 days", "3 days", "7 days"])) # Home button, unselects any selection def __home_button_changed(self): self.selected_source = None _last_clicked_direction = None def move_backward(self): ''' Moves the shown area backward 1 step. :return: ''' if self.Relative_Start_Day >= (self._low_start_day_number + int(self.move_step[0])): self.Relative_Start_Day -= int(self.move_step[0]) def move_forward(self): ''' Moves the shown area forward 1 step. :return: ''' if self.Relative_Start_Day <= (self._high_start_day_number - int(self.move_step[0])): self.Relative_Start_Day += int(self.move_step[0]) def __back1_changed(self): ''' Triggered when back button is pressed :return: ''' self.move_backward() self._last_clicked_direction = self.move_backward def __forward1_changed(self): ''' Triggered when forward button is pressed :return: ''' self.move_forward() self._last_clicked_direction = self.move_forward _play_thread = False def _play_button_changed(self, play_pressed): ''' Triggered when play button is selected :param play_pressed: :return: ''' if play_pressed: if not self._play_thread: self._play_thread = True GUI.invoke_after(1, self._play_func) else: self._play_thread = False def _play_func(self): ''' Called while play button is selected :return: ''' if self._play_thread: if self._last_clicked_direction is not None: self._last_clicked_direction() else: self.move_forward() GUI.invoke_after(1000, self._play_func) @on_trait_change("Relative_Start_Day") def _relative_start_day_changed(self, new_value): self.start_day = new_value def _start_day_changed(self, new_time): if isinstance(new_time, int): self.current_time = datetools.to_datetime(self._data_times.min() + datetools.Day(new_time)) elif isinstance(new_time, str): self.current_time = datetools.to_datetime(new_time) elif isinstance(new_time, datetime.date): self.current_time = datetools.to_datetime(new_time) else: print "Unsupported start day ", new_time return def _selected_source_changed(self, old_source, new_source): #print "Source changed", old_source, new_source if old_source is not new_source: if new_source is not None: self._selected_source_name = self._get_source_name(new_source) self._update_selected_event(None) self._update_selected_event( self._vis_model.get_num_of_selected_events() - 1) else: self._selected_source_name = None self._update_selected_event(None) def __selected_source_name_changed(self, old_source, new_source): if new_source in self.source_names: source_index = self.source_names.index(new_source) else: source_index = -1 if self.selected_source != source_index: if source_index == -1: self.selected_source = None else: self.selected_source = source_index def _current_time_changed(self, old_time, new_time): num_of_days = int( (datetools.to_datetime(new_time) - self._data_times.min()).days) if self.Relative_Start_Day != num_of_days: self.Relative_Start_Day = num_of_days elif old_time != new_time: self.current_time = datetools.to_datetime(self.current_time) self.update() _old_event_name = -1 def _update_selected_event(self, event_index): if event_index > -1: event = self._vis_model.get_selected_event(event_index) else: event = None # if self._old_event_name == event or event is not None and self._old_event_name == event.name: # return # Do nothing self._old_event_name = None if event is None else event.name if event_index > -1: selected_event = self._vis_model.expand_events( event.parent if self.selected_event > -1 and event_index >= self.selected_event else self._vis_model. get_selected_event(event_index)) else: selected_event = self._vis_model.expand_events(None) self.selected_event = selected_event if event is not None: sevents = self._vis_model.get_selected_events_name() names = list( sorted([ pyisc._get_string_value(sevents, i) for i in range( self._vis_model.get_num_of_selected_events()) ])) if event.name in names: self._selected_events_list = names self._selected_event_name = [event.name] else: self._selected_events_list = ['None'] self._selected_event_name = ['None'] self.update() def __selected_event_name_changed(self, oldvalue, newvalue): if self._old_event_name is None or len( self._selected_event_name ) == 1 and self._old_event_name != self._selected_event_name[0]: if len(oldvalue) != len(newvalue) or len( newvalue) == 1 and oldvalue[0] != newvalue[0]: if len(self._selected_event_name ) == 1 and self._selected_event_name[0] != 'None': event_index = self._vis_model.get_event_index( self._selected_event_name[0]) self._update_selected_event(event_index) else: self._update_selected_event(None) def _num_of_shown_days_changed(self): self.used_cache_size = self._num_of_shown_days_to_int( ) * self._num_of_sources self.update() # Used for caching anomaly calculations _cache = dict() # Used for scaling visualizatuion in the z direction _scale_z = Trait(0.1, Range(0.0, 1.0)) # Used for setting a good default view in 3D _last_view = None def __init__(self, visualisation_model, decision_threshold, start_day=3, num_of_shown_days="30 days", precompute_cache=False): ''' :param visualisation_model: an instance of EventDataModel :param decision_threshold: a float larger or equal to 0.0 that is used for deciding when an anomaly score is significantly anomalous :param start_day: an integer >= or an instance of datetime.date or an string, like "2014-10-11" or a tuple, like (2014, 10, 11) :param num_of_shown_days: an integer > 1 that specifies the number of days back in time from start_day that will be shown. :param precompute_cache: boolean that indates whether all anomaly scores should be computed at once or when asked for. :return: ''' assert isinstance(visualisation_model, EventDataModel) assert isinstance( start_day, int) or isinstance(start_day, str) or isinstance( start_day, datetime.date) or (isinstance(start_day, tuple) and len(start_day) == 3) HasTraits.__init__(self) self.used_cache_size = 0 # must be initialized self._data = visualisation_model._event_data_object self.num_of_shown_days = num_of_shown_days # Updates self.used_cache_size self._vis_model = visualisation_model self._anomaly_detector = visualisation_model._anomaly_detector self.anomaly_detection_threshold = decision_threshold dates = visualisation_model._event_data_object.dates_ self._data_times = array([datetools.to_datetime(d) for d in dates]) self.source_names = list( unique(visualisation_model._event_data_object.sources_)) self._data_sources = array([ self.source_names.index(source) for source in visualisation_model._event_data_object.sources_ ]) self._num_of_sources = len(unique( self.source_names)) # number of sources self.barcharts = [] self.barchart_actors = [] self.time_text3ds = [] self.source_text3ds = [] self.xy_positions = [] self._high_start_day_number = int( (self._data_times.max() - self._data_times.min()).days) self.scene.anti_aliasing_frames = 8 # add traits dynamically self.add_trait("Relative_Start_Day", Range(0, self._high_start_day_number)) self.add_trait("_selected_source_name", Enum(None, [None] + self.source_names)) self.configure_traits() self.scene.background = self.background # add the mouse pick handler self.picker = self.scene.mayavi_scene.on_mouse_pick( self.vis_picker, 'cell') self.picker.tolerance = 0.01 #cmap = matplotlib.cm.get_cmap('Reds') #self.severity_color = [cmap(x)[:-1] for x in linspace(0.75, 0.95, self._vis_model.num_of_severity_levels_)] if self._vis_model.num_of_severity_levels_ > 1: self.severity_color = self.severity_color = [ (1, x / 100.0, x / 100.0) for x in range(70, 30, -40 / self._vis_model.num_of_severity_levels_) ] else: self.severity_color = [(255.0 / 255, 51 / 255.0, 51 / 255.0)] # This used for a fix to manage a bug in Mayavi library, an invisible default object self._obj = self.scene.mlab.points3d(0, 0, 0, opacity=0.0) # Cache all anomaly calculations for all data values if precompute_cache: self.used_cache_size = len(self._data) for data_index in xrange(len(self._data)): self._populate_cache(data_index) self.start_day = start_day self.update() def _create_barcharts(self, severities, x, y, z): ''' Creates and shows the 3D bars :param severities: :param x: :param y: :param z: :return: ''' #self.scene.disable_render = True x = array(x) y = array(y) z = array(z) severities = array(severities) for s in set(severities): s_index = (severities == s) color = self.normal_barcolor if s == -1 else self.background if s == -2 else self.severity_color[ s] x0 = x[s_index] y0 = y[s_index] z0 = z[s_index] barchart = self.scene.mlab.barchart(x0, y0, z0, color=color, auto_scale=False, reset_zoom=False) self.barcharts.append(barchart) self.barchart_actors.append(barchart.actor.actors[0]) self.xy_positions.append((x0, y0, z0)) for actor in self.barchart_actors: actor.scale = array([1.0, 1.0, self._scale_z]) #self.scene.disable_render = False def clear_figure(self): ''' Removes the objects from the scene. :return: ''' self.scene.remove_actors(self.barchart_actors) # A bug fix, when there are no objects left in the scene it stops working unless you set a default current_object # It is an invisibale point outside the 3D bar plot region. self.scene.mlab.get_engine().current_object = self._obj self.barchart_actors = [] self.xy_positions = [] def _trim_cache(self, data_index, used_cache_size): ''' Keeps the cache to the defined size. :param data_index: :param used_cache_size: :return: ''' if len(self._cache) > used_cache_size: max_index = max(self._cache.keys()) min_index = min(self._cache.keys()) if data_index > max_index: del self._cache[min_index] elif data_index < min_index: del self._cache[max_index] else: # Remove the one farest away median_index = median(self._cache.keys()) triple_indexes = array([min_index, median_index, max_index]) diffs = abs(data_index - triple_indexes) diff_max_index = diffs.argmax() del self._cache[triple_indexes[diff_max_index]] def update(self): ''' Plots the 3D bars and axis. :return: ''' is_first_update = False if self._last_view is None: self._last_view = (38, 8, 205, array([8, 17.5, 49.25])) self.scene.mlab.view(*self._last_view) is_first_update = True else: self._last_view = self.scene.mlab.view() self.scene.disable_render = True self.clear_figure() #print "Day: %s" % time.ctime(self.current_time) max_z = 0 time_index = ( (self._data_times <= datetools.to_datetime(self.current_time)) & (self._data_times >= (datetools.to_datetime(self.current_time) - self._num_of_shown_days_to_timedelta()))) if self.selected_source is None: # Plot all sources x = [] y = [] z = [] severities = [] for source in range(self._num_of_sources): for data_index in array(range(len(self._data)))[time_index][ self._data_sources[time_index] == source]: if self.used_cache_size > 0 and self._cache.has_key( data_index): devsptr, sevs, expectptr, min2, max2, count = self._cache[ data_index] else: devs, sevs, expect, min2, max2 = self._vis_model.calc_one( data_index) devsptr = pyisc._to_cpp_array(devs) expectptr = pyisc._to_cpp_array(expect) count = None if count is None: self._trim_cache(data_index, self.used_cache_size) vec = self._data._get_intfloat(data_index) count = sum([ pyisc._get_intfloat_value( vec, self._vis_model.get_event_hierarchy(). get_index_value(l)) for l in range( self._vis_model.num_of_severity_levels_) if self._vis_model.get_event_hierarchy(). get_index_value(l) != -1 ]) self._cache[data_index] = (devsptr, sevs, expectptr, min2, max2, count) ztime = self._num_of_shown_days_to_int() - ( self.current_time - self._data_times[data_index]).days x.append(source) y.append(ztime) z.append(count) sev_max = argmax(sevs) sev = (-1 if sevs[sev_max] < self.anomaly_detection_threshold else sev_max) severities.append(sev) self._create_barcharts(severities, x, y, z) max_z = max([max_z] + z) else: # Plot for selected source source_index = self._data_sources[ time_index] == self.selected_source data_indexes = array(range(len( self._data)))[time_index][source_index] x = [] y = [] z = [] severities = [] # Plot selected events for data_index in data_indexes: if self.used_cache_size > 0 and self._cache.has_key( data_index): devsptr, sevs, expectptr, min2, max2, _ = self._cache[ data_index] else: devs, sevs, expect, min2, max2 = self._vis_model.calc_one( data_index) devsptr = pyisc._to_cpp_array(devs) expectptr = pyisc._to_cpp_array(expect) self._trim_cache(data_index, self.used_cache_size) self._cache[data_index] = (devsptr, sevs, expectptr, min2, max2, None) ztime = self._num_of_shown_days_to_int() - ( datetools.to_datetime(self.current_time) - self._data_times[data_index]).days if self._vis_model.get_num_of_selected_events() > 0: for element in range( self._vis_model.get_num_of_selected_events()): x.append(element) y.append(ztime) (dev, sev, count, mexp, maxind) = self._vis_model.summarize_event_children( self._vis_model.get_selected_event(element), devsptr, expectptr, self._data._get_intfloat(data_index), 1 if element >= self.selected_event else 0) z.append(count) if dev < self.anomaly_detection_threshold: severities.append(-1) else: severities.append(sev) self._create_barcharts(severities, x, y, z) max_z = max([max_z] + z) self.scene.disable_render = True datetime.date curr_t = self.current_time time_strs = [ str(t.date()) for t in date_range( curr_t - self._num_of_shown_days_to_timedelta(), curr_t) ] time_max_len = min([len(t) for t in time_strs]) max_x = (self._num_of_sources if self.selected_source is None else self._vis_model.get_num_of_selected_events()) max_y = self._num_of_shown_days_to_int() if len(self.time_text3ds) != len(time_strs): self.scene.remove_actors( [t.actor.actors[0] for t in self.time_text3ds]) self.time_text3ds = [] for slot in range(len(time_strs)): name = time_strs[slot] pos = (max_x + time_max_len / 2 - 1, slot, 0) self.time_text3ds.append( self.scene.mlab.text3d(*pos, text=name, scale=0.5, color=self.textcolor, orient_to_camera=False, orientation=(180, 180, 0))) else: for slot in range(len(time_strs)): name = time_strs[slot] pos = (max_x + time_max_len / 2 - 1, slot, 0) self.time_text3ds[slot].position = pos self.time_text3ds[slot].text = name if self.selected_source is None: source_strs = [ self._get_source_name(source) for source in range(self._num_of_sources) ] num_of_sources = self._num_of_sources else: source_strs = [ self._get_event_name(element) for element in range( self._vis_model.get_num_of_selected_events()) ] num_of_sources = self._vis_model.get_num_of_selected_events() if len(self.source_text3ds ) != num_of_sources or self.selected_source is None: self.scene.remove_actors( [t.actor.actors[0] for t in self.source_text3ds]) self.source_text3ds = [] for source in range(num_of_sources): name = source_strs[source] if self.selected_source is None: self.source_text3ds.append( self.scene.mlab.text3d(source, max_y + 0.5, 0, name, scale=0.6, color=self.textcolor, orient_to_camera=False, orientation=(0, 0, 90))) else: self.source_text3ds.append( self.scene.mlab.text3d( source, max_y + 0.5, 0, name, color=self.textcolor if source < self.selected_event else (192.0 / 255, 192.0 / 255, 192.0 / 255) if source > self.selected_event else (1.0, 1.0, 1.0), scale=0.5, orient_to_camera=False, orientation=(0, 0, 90))) else: for source in range(num_of_sources): name = source_strs[source] self.source_text3ds[source].text = name self.source_text3ds[source].position = (source, max_y + 0.5, 0) if is_first_update: self.scene.reset_zoom() self.scene.disable_render = False return last_picker = None def vis_picker(self, picker): ''' Called when the user clicks in the scene in order to find the object that was selected. :param picker: :return: ''' self.last_picker = picker _source = None if picker.actor is not None: if picker.actor in self.barchart_actors: actor_index = self.barchart_actors.index(picker.actor) _sources, _time_slots, _ = self.xy_positions[actor_index] _source = _sources[picker.point_id / 24] _time_slot = _time_slots[picker.point_id / 24] else: actors = [t.actor.actors[0] for t in self.source_text3ds] if picker.actor in actors: actor_index = actors.index(picker.actor) _source = actor_index if _source is not None: if self.selected_source is None: if _source >= 0 and _source < self._num_of_sources: self.selected_source = _source elif _source >= 0 and _source < self._vis_model.get_num_of_selected_events( ): self._update_selected_event(_source) def _num_of_shown_days_to_timedelta(self): return datetools.to_offset( str(self.num_of_shown_days).split(' ')[0] + "d") def _num_of_shown_days_to_int(self): return int(str(self.num_of_shown_days).split(' ')[0]) def _get_source_name(self, source): return self.source_names[source] def _get_event_name(self, element): return self._vis_model.get_selected_event(element).name def _populate_cache(self, data_index): devs, sevs, expect, min2, max2 = self._vis_model.calc_one(data_index) devsptr = pyisc._to_cpp_array(devs) expectptr = pyisc._to_cpp_array(expect) vec = self._data._get_intfloat(data_index) count = sum([ pyisc._get_intfloat_value( vec, self._vis_model.get_event_hierarchy().get_index_value(l)) for l in xrange(self._vis_model.num_of_severity_levels_) if self._vis_model.get_event_hierarchy().get_index_value(l) != -1 ]) self._cache[data_index] = (devsptr, sevs, expectptr, min2, max2, count)
class BandwidthHighlighter(HasTraits): container = Instance(HPlotContainer) plot = Instance(Component) colormap_name_1 = Str('gray') path = Str # add_band = Button('Add band') highlight_bands = List(Band) def update_path(self, new): self.path = new def delete_band(self): self.highlight_bands.pop(-1) def add_band(self): self.highlight_bands.append(Band()) def _path_changed(self): self._load_image(self.path) @on_trait_change('highlight_bands:[center,threshold,color, use]') def _refresh_highlight_bands(self, obj, name, old, new): if self.path: plot = self.oplot im = Image.open(self.path) rgb_arr = array(im.convert('RGB')) # im_arr=array(im) gray_im = array(im.convert('L')) for band in self.highlight_bands: if band.use: low = band.center - band.threshold high = band.center + band.threshold mask = where((gray_im > low) & (gray_im < high)) # print band.color[:3] rgb_arr[mask] = band.color.toTuple()[:3] imgplot = plot.plots['plot0'][0] tools = imgplot.tools overlays = imgplot.overlays plot.delplot('plot0') plot.data.set_data('img', rgb_arr) img_plot = plot.img_plot('img', colormap=color_map_name_dict[self.colormap_name_1])[0] for ti in tools + overlays: ti.component = img_plot img_plot.tools = tools img_plot.overlays = overlays plot.request_redraw() def _load_image(self, path): self.container = self._container_factory() im = Image.open(path) # oim = array(im) im = im.convert('L') odim = ndim = array(im) pd = ArrayPlotData() pd.set_data('img', odim) plot = Plot(data=pd, padding=[30, 5, 5, 30], default_origin='top left') img_plot = plot.img_plot('img', colormap=color_map_name_dict[self.colormap_name_1] )[0] self.add_inspector(img_plot) self.add_tools(img_plot) self.oplot = plot self.container.add(self.oplot) # self.container.add(self.plot) self.container.request_redraw() def add_inspector(self, img_plot): imgtool = ImageInspectorTool(img_plot) img_plot.tools.append(imgtool) overlay = ImageInspectorOverlay(component=img_plot, image_inspector=imgtool, bgcolor="white", border_visible=True) img_plot.overlays.append(overlay) def add_tools(self, img_plot): zoom = ZoomTool(component=img_plot, tool_mode="box", always_on=False) pan = PanTool(component=img_plot, restrict_to_data=True) img_plot.tools.append(pan) img_plot.overlays.append(zoom) def _highlight_bands_default(self): return [Band(color='red'), Band(color='green'), Band(color='blue')] def traits_view(self): ctrl_grp = VGroup( # HGroup(UItem('add_band')), UItem('highlight_bands', height=115,editor=ListEditor(mutable=False, style='custom', editor=InstanceEditor()))) v = View( VSplit( ctrl_grp, UItem('container', editor=ComponentEditor(height=700)))) return v def _container_factory(self): pc = HPlotContainer(padding=[5, 5, 5, 20]) return pc def _container_default(self): return self._container_factory() #============= EOF =============================================
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 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
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') def _plot_button_fired(self): self.update_needed = True def _auto_update_changed(self): self.update_needed = True def _get_auto_group(self): return HGroup( icon_button_editor( 'plot_button', 'chart_curve_go', 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'), spring, 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')) def traits_view(self): v = View(VGroup(self._get_auto_group(), self._get_fit_group())) return v def _get_columns(self): cols = [ ObjectColumn(name='name', editable=False), CheckboxColumn(name='show'), ObjectColumn(name='fit', editor=EnumEditor(name='fit_types'), width=150), ObjectColumn(name='error_type', editor=EnumEditor(name='error_types'), width=50), CheckboxColumn(name='use', label='Save DB') ] return cols def _get_fit_group(self): cols = self._get_columns() editor = myTableEditor(columns=cols, sortable=False, on_command_key=self._update_command_key) 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(trait_change_notify=False, **{name: new}) 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) if pf is None: pf = self.fit_klass(name=ki, fit=fi) else: pf.fit = fi nfs.append(pf) self.fits = nfs # self.fits = [ # self.fit_klass(name=ki, fit=fi) # for ki, fi in zip(ks, fs) # ] 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