class PychronTasksPlugin(BasePlugin): id = 'pychron.tasks.plugin' name = 'Tasks' preferences_panes = List( contributes_to='envisage.ui.tasks.preferences_panes') task_extensions = List(contributes_to='envisage.ui.tasks.task_extensions') actions = ExtensionPoint(List, id='pychron.actions') file_defaults = ExtensionPoint(List(Tuple), id='pychron.plugin.file_defaults') help_tips = ExtensionPoint(List, id='pychron.plugin.help_tips') available_task_extensions = ExtensionPoint(List, id='pychron.available_task_extensions') my_tips = List(contributes_to='pychron.plugin.help_tips') # def _application_changed(self): # # defaults = (('use_advanced_ui', False), ('show_random_tip', True)) # defaults = (('show_random_tip', True),) # try: # self._set_preference_defaults(defaults, 'pychron.general') # except AttributeError, e: # print 'exception', e def start(self): self.info('Writing plugin file defaults') paths.write_file_defaults(self.file_defaults) self._random_tip() def _random_tip(self): if globalv.random_tip_enabled and to_bool(self.application.preferences.get('pychron.general.show_random_tip')): from pychron.envisage.tasks.tip_view import TipView t = random.choice(self.help_tips) tv = TipView(text=t) tv.edit_traits() def _my_tips_default(self): return ["Use <b>Help>What's New</b> to view the official ChangeLog for the current version", 'Turn Off Random Tip two ways:<br><b>1. Preferences>General></b> Uncheck "Random Tip".</b><br>' '<b>2.</b> Set the flag <i>random_tip_enabled</i> to False in the initialization file'] def _preferences_panes_default(self): return [GeneralPreferencesPane, BrowserPreferencesPane] def _task_extensions_default(self): actions = [SchemaAddition(factory=EditInitializationAction, id='edit_plugins', path='MenuBar/help.menu')] return [TaskExtension(actions=actions)]
class PychronTasksPlugin(BasePlugin): id = 'pychron.tasks.plugin' name = 'Tasks' preferences_panes = List( contributes_to='envisage.ui.tasks.preferences_panes') task_extensions = List(contributes_to='envisage.ui.tasks.task_extensions') actions = ExtensionPoint(List, id='pychron.actions') file_defaults = ExtensionPoint(List(Tuple), id='pychron.plugin.file_defaults') help_tips = ExtensionPoint(List, id='pychron.plugin.help_tips') available_task_extensions = ExtensionPoint( List, id='pychron.available_task_extensions') my_tips = List(contributes_to='pychron.plugin.help_tips') def _application_changed(self): # defaults = (('use_advanced_ui', False), ('show_random_tip', True)) defaults = (('show_random_tip', True), ) try: self._set_preference_defaults(defaults, 'pychron.general') except AttributeError, e: print 'exception', e
class VideoPlugin(BaseTaskPlugin): ''' a list of name, url (file:///abs/path or pvs://host[:port=8080]) tuples if file then should be a path to an image if pvs than should be address to a Pychron Video Server ''' id = 'pychron.video' sources = ExtensionPoint(List, id='pychron.video.sources') def _tasks_default(self): ts = [ TaskFactory(id='pychron.video', name='Video Display', factory=self._video_task_factory, task_group='hardware') ] return ts def _video_task_factory(self): t = VideoTask(available_connections=self.sources) return t
class BaseTasksApplication(TasksApplication, Loggable): about_dialog = Instance(Dialog) startup_tester = Instance(StartupTester) uis = List available_task_extensions = ExtensionPoint( id='pychron.available_task_extensions') def _started_fired(self): st = self.startup_tester if st.results: v = ResultsView(model=st) open_view(v) if globalv.use_testbot: from pychron.testbot.testbot import TestBot testbot = TestBot(application=self) testbot.run() def get_task_extensions(self, pid): import yaml p = paths.task_extensions_file with open(p, 'r') as rfile: yl = yaml.load(rfile) for yi in yl: # print yi['plugin_id'], pid if yi['plugin_id'].startswith(pid): tid = yi.get('task_id', '') for ai in yi['actions']: a, e = ai.split(',') # print tid, a, e if to_bool(e): yield tid, a def about(self): self.about_dialog.open() def start(self): if globalv.open_logger_on_launch: self._load_state() self.open_task('pychron.logger') self.startup_tester = StartupTester() return super(BaseTasksApplication, self).start() def get_open_task(self, tid): for win in self.windows: if win.active_task: if win.active_task.id == tid: return win, win.active_task, True else: win = self.create_window(TaskWindowLayout(tid)) return win, win.active_task, False def task_is_open(self, tid): for win in self.windows: if win.active_task and win.active_task.id == tid: return win.active_task def is_open(self, win): return win in self.windows def get_task(self, tid, activate=True): for win in self.windows: if win.active_task: if win.active_task.id == tid: if activate and win.control: win.activate() break else: w = TaskWindowLayout(tid) win = self.create_window(w) if activate: win.open() if win: win.active_task.window = win return win.active_task def open_task(self, tid, **kw): return self.get_task(tid, True, **kw) # def add_view(self, ui): # self.uis.append(weakref.ref(ui)()) # def open_view(self, obj, **kw): # open_view(obj, **kw) # info = obj.edit_traits(**kw) # self.add_view(info) # return info def exit(self, **kw): report_view_stats() close_views() self._cleanup_services() super(BaseTasksApplication, self).exit() def _cleanup_services(self): for si in self.get_services(ICoreDevice): si.close()
class CorePlugin(Plugin): """ The Envisage core plugin. The core plugin offers facilities that are generally useful when building extensible applications such as adapters and hooks etc. It does not contain anything to do with user interfaces! The core plugin should be started before any other plugin. It is up to the plugin manager to do this. """ #: Extension point ID for preferences PREFERENCES = "envisage.preferences" #: Extension point ID for service offers SERVICE_OFFERS = "envisage.service_offers" #### 'IPlugin' interface ################################################## #: The plugin's unique identifier. id = "envisage.core" #: The plugin's name (suitable for displaying to the user). name = "Core" #### Extension points offered by this plugin ############################## #: preferences ExtensionPoint preferences = ExtensionPoint( List(Str), id=PREFERENCES, desc=""" Preferences files allow plugins to contribute default values for user preferences. Each contributed string must be the URL of a file-like object that contains preferences values. e.g. 'pkgfile://envisage/preferences.ini' - this looks for the 'preferences.ini' file in the 'envisage' package. 'file://*****:*****@on_trait_change("preferences_items") def _preferences_changed(self, event): """ React to new preferencess being *added*. Note that we don't currently do anything if preferences are *removed*. """ self._load_preferences(event.added) return #: service offers ExtensionPoint service_offers = ExtensionPoint( List(ServiceOffer), id=SERVICE_OFFERS, desc=""" Services are simply objects that a plugin wants to make available to other plugins. This extension point allows you to offer services that are created 'on-demand'. e.g. my_service_offer = ServiceOffer( protocol = 'acme.IMyService', factory = an_object_or_a_callable_that_creates_one, properties = {'a dictionary' : 'that is passed to the factory'} ) See the documentation for 'ServiceOffer' for more details. """, ) @on_trait_change("service_offers_items") def _service_offers_changed(self, event): """ React to new service offers being *added*. Note that we don't currently do anything if services are *removed* as we have no facility to let users of the service know that the offer has been retracted. """ for service in event.added: self._register_service_offer(service) return #### Contributions to extension points made by this plugin ################ # None. ########################################################################### # 'IPlugin' interface. ########################################################################### def start(self): """ Start the plugin. """ # Load all contributed preferences files into the application's root # preferences node. self._load_preferences(self.preferences) # Register all service offers. # # These services are unregistered by the default plugin activation # strategy (due to the fact that we store the service ids in this # specific trait!). self._service_ids = self._register_service_offers(self.service_offers) return ########################################################################### # Private interface. ########################################################################### def _load_preferences(self, preferences): """ Load all contributed preferences into a preferences node. """ # Enthought library imports. from envisage.resource.api import ResourceManager # We add the plugin preferences to the default scope. The default scope # is a transient scope which means that (quite nicely ;^) we never # save the actual default plugin preference values. They will only get # saved if a value has been set in another (persistent) scope - which # is exactly what happens in the preferences UI. default = self.application.preferences.node("default/") # The resource manager is used to find the preferences files. resource_manager = ResourceManager() for resource_name in preferences: f = resource_manager.file(resource_name) try: default.load(f) finally: f.close() return def _register_service_offers(self, service_offers): """ Register a list of service offers. """ return list(map(self._register_service_offer, service_offers)) def _register_service_offer(self, service_offer): """ Register a service offer. """ service_id = self.application.register_service( protocol=service_offer.protocol, obj=service_offer.factory, properties=service_offer.properties, ) return service_id
class PychronTasksPlugin(BasePlugin): id = 'pychron.tasks.plugin' name = 'Tasks' preferences_panes = List( contributes_to='envisage.ui.tasks.preferences_panes') task_extensions = List(contributes_to='envisage.ui.tasks.task_extensions') actions = ExtensionPoint(List, id='pychron.actions') file_defaults = ExtensionPoint(List(Tuple), id='pychron.plugin.file_defaults') help_tips = ExtensionPoint(List, id='pychron.plugin.help_tips') available_task_extensions = ExtensionPoint(List, id='pychron.available_task_extensions') my_tips = List(contributes_to='pychron.plugin.help_tips') background_processes = ExtensionPoint(List, id='pychron.background_processes') def start(self): self.info('Writing plugin file defaults') paths.write_file_defaults(self.file_defaults) self._set_user() self._random_tip() self._start_background_processes() def _start_background_processes(self): self.info('starting background processes disabled') return for i, p in enumerate(self.background_processes): if isinstance(p, tuple): name, func = p else: func = p name = 'Background{:02n}'.format(i) if hasattr(func, '__call__'): t = Thread(target=func, name=name) t.setDaemon(True) t.start() def _set_user(self): self.application.preferences.set('pychron.general.username', globalv.username) self.application.preferences.save() def _random_tip(self): if globalv.random_tip_enabled and self.application.get_boolean_preference('pychron.general.show_random_tip'): from pychron.envisage.tasks.tip_view import TipView t = random.choice(self.help_tips) tv = TipView(text=t) tv.edit_traits() def _my_tips_default(self): return ["Use <b>Help>What's New</b> to view the official ChangeLog for the current version", 'Turn Off Random Tip two ways:<br><b>1. Preferences>General></b> Uncheck "Random Tip".</b><br>' '<b>2.</b> Set the flag <i>random_tip_enabled</i> to False in the initialization file', 'Use <b>Window/Reset Layout</b> to change the current window back to its default "Look"', 'Submit bugs or issues to the developers manually using <b>Help/Add Request/Report Bug</b>', 'The current version of Pychron contains over 156K lines of code in 1676 files', 'If menu actions are missing first check that the desired "Plugin" is enabled using <b>Help/Edit ' 'Initialization</b>. If "Plugin" is enabled, check that the desired action is enabled using ' '<b>Help/Edit UI</b>.'] def _preferences_panes_default(self): return [GeneralPreferencesPane, BrowserPreferencesPane] def _task_extensions_default(self): actions = [SchemaAddition(factory=EditInitializationAction, id='edit_plugins', path='MenuBar/help.menu')] return [TaskExtension(actions=actions)]
class EntryPlugin(BaseTaskPlugin): id = 'pychron.entry.plugin' data_sources = ExtensionPoint(List, id='pychron.entry.data_sources') def _help_tips_default(self): return [ 'Use <b>Entry>Labnumber</b> to add/edit irradiation information including ' 'Irradiation, Level, Sample, Project, Labnumber, etc...', 'Use <b>Entry>Sensitivity</b> to add/edit the sensitivity table.', 'Once the Labnumber window is activated additional Menu actions are available including, ' 'Transfer J and Generate Labbook.' ] def _actions_default(self): return [ ('pychron.labnumber_entry', 'Ctrl+Shift+l', 'Open Labnumber Entry Window'), ('pychron.sensitivity', 'Ctrl+Shift+\\', 'Open Sensistivity Window'), ] def _service_offers_default(self): def factory2(): dvc = self.application.get_service(DVC_PROTOCOL) e = FluxMonitorEditor(dvc=dvc) return e so2 = self.service_offer_factory(factory=factory2, protocol=FluxMonitorEditor) return [so2] def _task_extensions_default(self): extensions = [ TaskExtension(actions=actions, task_id=eid) for eid, actions in self._get_extensions() ] additions = [ SchemaAddition( id='entry', factory=lambda: SMenu(id='entry.menu', name='Entry'), path='MenuBar', before='tools.menu', after='view.menu') ] eflag = False eeflag = False for eid, actions in self._get_extensions(): # print 'b', eid, len(actions) for ai in actions: # print 'c',ai,ai.id if not eflag and ai.id.startswith('pychron.entry1'): eflag = True additions.append( SchemaAddition( id='entry_group', factory=lambda: SGroup(id='entry.group'), path='MenuBar/entry.menu')) additions.append( SchemaAddition( id='entry_sample_group', absolute_position='first', factory=lambda: SGroup(id='entry.sample.group'), path='MenuBar/entry.menu')) elif not eeflag and ai.id.startswith('pychron.entry2'): eeflag = True additions.append( SchemaAddition( id='entry_group2', factory=lambda: SGroup(id='entry.group2'), after='entry_group', path='MenuBar/entry.menu'), ) extensions.append(TaskExtension(actions=additions)) return extensions def _available_task_extensions_default(self): g2path = 'MenuBar/entry.menu/entry.group2' gpath = 'MenuBar/entry.menu/entry.group' spath = 'MenuBar/entry.menu/entry.sample.group' return [ ('{}.entry2'.format(self.id), 'pychron.entry.irradiation.task', 'Entry Tools', [ SchemaAddition(id='pychron.entry2.transfer_j', factory=TransferJAction, path=g2path), SchemaAddition(id='pychron.entry2.get_igsns', factory=GetIGSNAction, path=g2path), SchemaAddition(id='pychron.entry2.export_irradiation', factory=ExportIrradiationAction, path=g2path), SchemaAddition(id='pychron.entry2.import_samples_from_file', factory=ImportSamplesAction, path=g2path), SchemaAddition( id='pychron.entry2.import_irradiations_from_file', factory=ImportIrradiationFileAction, path=g2path), SchemaAddition(id='pychron.entry2.generate_tray', factory=GenerateTrayAction, path=g2path), SchemaAddition(id='pychron.entry2.run_report', factory=GenerateStatusReportAction, path=gpath), SchemaAddition(id='pychron.entry2.save_labbook', factory=MakeIrradiationBookPDFAction, path=g2path) ]), ( self.id, '', 'Entry', [ SchemaAddition(id='pychron.entry1.sample_entry', factory=SampleEntryAction, path=spath, absolute_position='first'), SchemaAddition(id='pychron.entry1.sample_prep', factory=SamplePrepAction, path=spath, after='pychron.entry1.sample_edit'), SchemaAddition(id='pychron.entry1.labnumber_entry', factory=LabnumberEntryAction, path=spath, after='pychron.entry1.sample_prep'), SchemaAddition(id='pychron.entry1.project', factory=ProjectAction, path=gpath), SchemaAddition(id='pychron.entry2.import_analyses', factory=ImportAnalysesAction, path=g2path), SchemaAddition(id='pychron.entry2.import_irradiation', factory=ImportIrradiationAction, path=g2path), SchemaAddition(id='pychron.entry1.make_template', factory=MakeIrradiationTemplateAction, path=g2path), SchemaAddition( id='pychron.entry1.generate_irradiation_table', factory=GenerateIrradiationTableAction, path=gpath), SchemaAddition(id='pychron.entry1.import_irradiation_geom', factory=ImportIrradiationGeometryAction, path=gpath), SchemaAddition(id='pychron.entry1.edit_irradiation_geom', factory=EditIrradiationGeometryAction, path=gpath), SchemaAddition(id='pychron.entry1.sensitivity_entry', factory=SensitivityEntryAction, path=gpath), # SchemaAddition(id='pychron.entry1.molecular_weight_entry', factory=AddMolecularWeightAction, # path=gpath), SchemaAddition(id='pychron.entry1.flux_monitor', factory=AddFluxMonitorAction, path=gpath) ]) ] def _tasks_default(self): return [ TaskFactory(id='pychron.entry.irradiation.task', factory=self._labnumber_entry_task_factory, include_view_menu=False), TaskFactory(id='pychron.entry.sensitivity.task', factory=self._sensitivity_entry_task_factory, include_view_menu=False), TaskFactory(id='pychron.entry.sample.task', factory=self._sample_entry_task_factory, include_view_menu=False), TaskFactory(id='pychron.entry.sample.prep.task', factory=self._sample_prep_task_factory, include_view_menu=False), TaskFactory(id='pychron.entry.project.task', factory=self._project_task_factory, include_view_menu=False) ] def _project_task_factory(self): from pychron.entry.tasks.project.task import ProjectTask return ProjectTask(application=self.application) def _sample_prep_task_factory(self): from pychron.entry.tasks.sample_prep.task import SamplePrepTask return SamplePrepTask(application=self.application) def _sample_entry_task_factory(self): from pychron.entry.tasks.sample.task import SampleEntryTask return SampleEntryTask(application=self.application) def _labnumber_entry_task_factory(self): from pychron.entry.tasks.labnumber.task import LabnumberEntryTask return LabnumberEntryTask(application=self.application) def _sensitivity_entry_task_factory(self): from pychron.entry.tasks.sensitivity.task import SensitivityEntryTask return SensitivityEntryTask(application=self.application) def _preferences_panes_default(self): return [ LabnumberEntryPreferencesPane, SamplePrepPreferencesPane, SampleEntryPreferencesPane ]
class BaseTasksApplication(TasksApplication, Loggable): about_dialog = Instance(Dialog) startup_tester = Instance(StartupTester) uis = List available_task_extensions = ExtensionPoint(id='pychron.available_task_extensions') def __init__(self, *args, **kw): super().__init__(*args, **kw) self.init_logger() def _application_initialized_fired(self): if globalv.use_startup_tests: st = StartupTester() for plugin in iter(self.plugin_manager): st.test_plugin(plugin) if st.results: if globalv.show_startup_results or not st.all_passed: v = ResultsView(model=st) open_view(v) if globalv.use_testbot: from pychron.testbot.testbot import TestBot testbot = TestBot(application=self) testbot.run() def get_boolean_preference(self, pid, default=None): return to_bool(self.preferences.get(pid, default)) def get_task_extensions(self, pid): import yaml p = paths.task_extensions_file with open(p, 'r') as rfile: yl = yaml.load(rfile) for yi in yl: # print yi['plugin_id'], pid if yi['plugin_id'].startswith(pid): tid = yi.get('task_id', '') for ai in yi['actions']: a, e = ai.split(',') # print tid, a, e if to_bool(e): yield tid, a def about(self): self.about_dialog.open() # def start(self): # # if globalv.open_logger_on_launch: # # self.debug('load_state') # # self._load_state() # # self.debug('open logger') # # self.open_task('pychron.logger') # # self.startup_tester = StartupTester() # # return super(BaseTasksApplication, self).start() def get_open_task(self, tid): for win in self.windows: if win.active_task: if win.active_task.id == tid: return win, win.active_task, True else: win = self.create_window(TaskWindowLayout(tid)) return win, win.active_task, False def task_is_open(self, tid): for win in self.windows: if win.active_task and win.active_task.id == tid: return win.active_task def is_open(self, win): return win in self.windows def get_task(self, tid, activate=True): for win in self.windows: if win.active_task: if win.active_task.id == tid: if activate and win.control: win.activate() break else: w = TaskWindowLayout(tid) win = self.create_window(w) if activate: win.open() if win: if win.active_task: win.active_task.window = win return win.active_task def open_task(self, tid, **kw): return self.get_task(tid, True, **kw) # def add_view(self, ui): # self.uis.append(weakref.ref(ui)()) # def open_view(self, obj, **kw): # open_view(obj, **kw) # info = obj.edit_traits(**kw) # self.add_view(info) # return info def exit(self, **kw): report_view_stats() close_views() self._cleanup_services() super(BaseTasksApplication, self).exit(**kw) def _cleanup_services(self): for si in self.get_services(ICoreDevice): si.close() def _load_state(self): """ Loads saved application state, if possible. """ state = TasksApplicationState() filename = os.path.join(self.state_location, 'application_memento') if os.path.exists(filename): # Attempt to unpickle the saved application state. try: with open(filename, 'rb') as f: try: restored_state = pickle.load(f) if state.version == restored_state.version: state = restored_state else: logger.warn('Discarding outdated application layout') except EOFError: logger.exception('EOFerror: Restoring application layout from %s', filename) except: # If anything goes wrong, log the error and continue. logger.exception('Restoring application layout from %s', filename) self._state = state def _save_state(self): """ Saves the application state. """ # Grab the current window layouts. window_layouts = [w.get_window_layout() for w in self.windows] self._state.previous_window_layouts = window_layouts # Attempt to pickle the application state. filename = os.path.join(self.state_location, 'application_memento') try: with open(filename, 'wb') as f: pickle.dump(self._state, f) except: # If anything goes wrong, log the error and continue. logger.exception('Saving application layout') def _on_window_closing(self, window, trait_name, event): # Event notification. self.window_closing = window_event = VetoableTaskWindowEvent( window=window) if window_event.veto: event.veto = True else: # Store the layout of the window. window_layout = window.get_window_layout() self._state.push_window_layout(window_layout) # If we're exiting implicitly and this is the last window, save # state, because we won't get another chance. if globalv.quit_on_last_window: if len(self.windows) == 1 and not self._explicit_exit: self._prepare_exit() else: if len(self.windows) == 1: if not self.confirmation_dialog('Closing the last open window will quit Pychron. ' 'Are you sure you want to continue?'): window_event.veto = True event.veto = True else: self._prepare_exit() def _on_window_closed(self, window, trait_name, event): self.windows.remove(window) # Event notification. self.window_closed = TaskWindowEvent(window=window) # Was this the last window? if len(self.windows) == 0: self.stop()
class PipelinePlugin(BaseTaskPlugin): name = 'Pipeline' id = 'pychron.pipeline.plugin' nodes = ExtensionPoint(List, id='pychron.pipeline.nodes') node_factories = ExtensionPoint(List, id='pychron.pipeline.node_factories') predefined_templates = ExtensionPoint( List, id='pychron.pipeline.predefined_templates') def _help_tips_default(self): return [] def _file_defaults_default(self): files = [('flux_constants', 'FLUX_CONSTANTS_DEFAULT', False)] return files def _pipeline_factory(self): model = self.application.get_service(SampleBrowserModel) iamodel = self.application.get_service(InterpretedAgeBrowserModel) dvc = self.application.get_service(DVC) from pychron.pipeline.tasks.task import PipelineTask t = PipelineTask(browser_model=model, dvc=dvc, interpreted_age_browser_model=iamodel, application=self.application) t.engine.nodes = self.nodes t.engine.node_factories = self.node_factories t.engine.predefined_templates = self.predefined_templates t.engine.load_predefined_templates() return t def _browser_model_factory(self): return SampleBrowserModel(application=self.application) def _interpreted_age_browser_model_factory(self): dvc = self.application.get_service(DVC) return InterpretedAgeBrowserModel(application=self.application, dvc=dvc) # defaults def _service_offers_default(self): so = self.service_offer_factory(protocol=SampleBrowserModel, factory=self._browser_model_factory) so1 = self.service_offer_factory( protocol=InterpretedAgeBrowserModel, factory=self._interpreted_age_browser_model_factory) return [so, so1] def _preferences_panes_default(self): return [PipelinePreferencesPane] def _task_extensions_default(self): def data_menu(): return SMenu(id='data.menu', name='Data') def ideogram_menu(): return SMenu(id='ideogram.menu', name='Ideogram') def plot_group(): return SGroup(id='plot.group') def reduction_group(): return SGroup(id='reduction.group') def recall_group(): return SGroup(id='recall.group') exts = self._get_extensions() extensions = [ TaskExtension(actions=actions, task_id=eid) for eid, actions in exts ] additions = [ SchemaAddition( factory=data_menu, path='MenuBar', before='tools.menu', after='view.menu', ) ] for s, f, p in (('ideogram', ideogram_menu, 'MenuBar/data.menu/plot.group'), ('plot', plot_group, 'MenuBar/data.menu'), ('fit', reduction_group, 'MenuBar/data.menu'), ('recall', recall_group, 'MenuBar/data.menu')): for eid, actions in exts: for ai in actions: if ai.id.startswith('pychron.pipeline.{}'.format(s)): additions.append(SchemaAddition(factory=f, path=p)) break extensions.append(TaskExtension(actions=additions)) return extensions def _available_task_extensions_default(self): def idformat(tag): return 'pychron.pipeline.{}'.format(tag) pg = 'MenuBar/data.menu/plot.group' rg = 'MenuBar/data.menu/reduction.group' ig = 'MenuBar/data.menu/plot.group/ideogram.menu' reg = 'MenuBar/data.menu/recall.group' fit_actions = [] for f, t in ((IsoEvolutionAction, 'iso_evo'), (BlanksAction, 'blanks'), (ICFactorAction, 'icfactor'), (FluxAction, 'flux'), (AnalysisTableAction, 'analysis_table'), (FreezeProductionRatios, 'freeze_production'), (MassSpecReducedAction, 'mass_spec_reduced')): fit_actions.append( SchemaAddition(factory=f, id='pychron.pipeline.fit.{}'.format(t), path=rg)) plot_actions = [] for f, t in ((IdeogramAction, 'ideogram'), (SubgroupIdeogramAction, 'subgroup_ideogram'), (HybridIdeogramAction, 'hybrid_ideogram'), (HistoryIdeogramAction, 'history_ideogram')): plot_actions.append( SchemaAddition(factory=f, id='pychron.pipeline.ideogram.{}'.format(t), path=ig)) for f, t in ((SpectrumAction, 'spectrum'), (InverseIsochronAction, 'inverse_isochron'), (SeriesAction, 'series'), (ExtractionAction, 'extraction')): plot_actions.append( SchemaAddition(factory=f, id='pychron.pipeline.plot.{}'.format(t), path=pg)) recall_actions = [ SchemaAddition(factory=ConfigureRecallAction, id='pychron.pipeline.recall.configure', path='MenuBar/edit.menu') ] for f, t in ((RecallAction, 'recall'), (InterpretedAgeRecallAction, 'interpreted_age_recall')): recall_actions.append( SchemaAddition(factory=f, id='pychron.pipeline.recall.{}'.format(t), path=reg)) return [ (self.id, '', 'Pipeline Tools', [ SchemaAddition(id=idformat('reset_factory_defaults'), factory=ResetFactoryDefaultsAction, path='MenuBar/help.menu'), SchemaAddition(id=idformat('clear_analysis_sets'), factory=ClearAnalysisSetsAction, path='MenuBar/help.menu') ]), ('{}.plot'.format(self.id), '', 'Plot', plot_actions), ('{}.fit'.format(self.id), '', 'Fit', fit_actions), ('{}.recall'.format(self.id), '', 'Recall', recall_actions), ] def _tasks_default(self): return [ TaskFactory(id='pychron.pipeline.task', name='Pipeline', accelerator='Ctrl+p', factory=self._pipeline_factory) ]
class HardwarePlugin(BaseTaskPlugin): id = 'pychron.hardware.plugin' managers = ExtensionPoint(List(Dict), id='pychron.hardware.managers') my_managers = List(contributes_to='pychron.hardware.managers') sources = List(contributes_to='pychron.video.sources') def _sources_default(self): return [('pvs://localhost:1081', 'Hardware')] def _my_task_extensions_default(self): return [ TaskExtension(actions=[ SchemaAddition(id='Flag Manager', factory=OpenFlagManagerAction, path='MenuBar/Tools'), ]) ] def _tasks_default(self): return [ TaskFactory(id='tasks.hardware', name='Hardware', factory=self._factory, task_group='hardware') ] def _factory(self): man = self.application.get_service(HardwareManager) task = HardwareTask(manager=man) return task def _service_offers_default(self): so_hm = self.service_offer_factory( protocol=HardwareManager, factory=self._hardware_manager_factory) so_rhm = self.service_offer_factory( protocol=RemoteHardwareManager, factory=self._remote_hardware_manager_factory) so_fm = self.service_offer_factory(protocol=FlagManager, factory=self._flag_manager_factory) # return [so, so1, so2] return [so_hm, so_rhm, so_fm] def _flag_manager_factory(self): return FlagManager(application=self.application) def _hardware_manager_factory(self): return HardwareManager(application=self.application) def _remote_hardware_manager_factory(self): return RemoteHardwareManager(application=self.application) def _preferences_panes_default(self): return [HardwarePreferencesPane] def _my_managers_default(self): return [ dict(name='hardware', manager=self._hardware_manager_factory()) ] # def _system_lock_manager_factory(self): # return SystemLockManager(application=self.application) def start(self): # if self.managers: from pychron.initializer import Initializer dp = DevicePreferences() afh = self.application.preferences.get( 'pychron.hardware.auto_find_handle') awh = self.application.preferences.get( 'pychron.hardware.auto_write_handle') if afh is not None: toBool = lambda x: True if x == 'True' else False dp.serial_preference.auto_find_handle = toBool(afh) dp.serial_preference.auto_write_handle = toBool(awh) ini = Initializer(device_prefs=dp) for m in self.managers: ini.add_initialization(m) # any loaded managers will be registered as services if not ini.run(application=self.application): self.application.exit() return # create the hardware server rhm = self.application.get_service(RemoteHardwareManager) bind_preference(rhm, 'enable_hardware_server', 'pychron.hardware.enable_hardware_server') bind_preference(rhm, 'enable_directory_server', 'pychron.hardware.enable_directory_server') rhm.bootstrap() def stop(self): # rhm = self.application.get_service(RemoteHardwareManager) # rhm.stop() if self.managers: for m in self.managers: man = m['manager'] if man: man.kill() man.close_ui() for s in self.application.get_services(ICoreDevice): if s.is_scanable: s.stop_scan()
class ExperimentPlugin(BaseTaskPlugin): id = 'pychron.experiment.plugin' events = ExtensionPoint(List(ExperimentEventAddition), id='pychron.experiment.events') dock_pane_factories = ExtensionPoint( List, id='pychron.experiment.dock_pane_factories') activations = ExtensionPoint(List(Callable), id='pychron.experiment.activations') deactivations = ExtensionPoint(List(Callable), id='pychron.experiment.deactivations') def _signal_calculator_factory(self, *args, **kw): return SignalCalculator() def _sens_selector_factory(self, *args, **kw): return SensitivitySelector() def _run_history_factory(self, *args, **kw): dvc = self.application.get_service('pychron.dvc.dvc.DVC') rhm = RunHistoryModel(dvc=dvc) rhm.load() rh = RunHistoryView(model=rhm) return rh def _tasks_default(self): return [ TaskFactory(id='pychron.experiment.task', factory=self._task_factory, name='Experiment', image='applications-science', task_group='experiment') ] def _task_factory(self): return ExperimentEditorTask( application=self.application, events=self.events, dock_pane_factories=self.dock_pane_factories, activations=self.activations, deactivations=self.deactivations) def _preferences_default(self): return self._preferences_factory('experiment') def _preferences_panes_default(self): return [ ExperimentPreferencesPane, ConsolePreferencesPane, UserNotifierPreferencesPane, HumanErrorCheckerPreferencesPane ] def _file_defaults_default(self): return [('experiment_defaults', 'EXPERIMENT_DEFAULTS', False), ('ratio_change_detection', 'RATIO_CHANGE_DETECTION', False)] # def _actions_default(self): # return [('pychron.open_experiment', 'Ctrl+O', 'Open Experiment'), # ('pychron.new_experiment', 'Ctrl+N', 'New Experiment'), # ('pychron.deselect', 'Ctrl+Shift+D', 'Deselect'), # ('pychron.open_last_experiment', 'Alt+Ctrl+O', 'Open Last Experiment')] def _help_tips_default(self): return [ 'You can set the Analysis State colors in Preferences>Experiment', 'You can set the color for Sniff, Signal, and Baseline datapoints in Preferences>Experiment', 'If the last analysis fails to save you can recover it using Tools/Recover Last Analysis' ] def _task_extensions_default(self): exts = self._get_extensions() extensions = [ TaskExtension(actions=actions, task_id=eid) for eid, actions in exts ] additions = [] # eflag = False for eid, actions in exts: for ai in actions: # if not eflag and ai.id.startswith('pychron.experiment.edit'): if ai.id.startswith('pychron.experiment.edit'): # eflag = True additions.append( SchemaAddition( id='experiment.edit', factory=lambda: SGroup(id='experiment.group'), path='MenuBar/edit.menu'), ) break if additions: extensions.append(TaskExtension(actions=additions, task_id='')) sr_actions = [ SchemaAddition(id='experiment.acquire_spectrometer', factory=AcquireSpectrometerAction, path='MenuBar/Tools'), SchemaAddition(id='experiment.release_spectrometer', factory=ReleaseSpectrometerAction, path='MenuBar/Tools') ] extensions.append(TaskExtension(actions=sr_actions, task_id='')) return extensions def _available_task_extensions_default(self): def idformat(t): return 'pychron.experiment.{}'.format(t) def eidformat(t): return 'pychron.experiment.edit.{}'.format(t) actions = [] for path, fs in (('edit.menu', ((QueueConditionalsAction, 'open_queue_conditionals'), (SystemConditionalsAction, 'open_system_conditionals'))), ('file.menu/Open', ((OpenExperimentQueueAction, 'open_experiment'), (OpenCurrentExperimentQueueAction, 'open_current_experiment'), (OpenLastExperimentQueueAction, 'open_last_experiment'), (OpenPatternAction, 'open_pattern'))), ('file.menu/New', ((NewExperimentQueueAction, 'new_experiment'), (NewPatternAction, 'new_pattern'))), ('tools.menu', ((OpenExperimentHistoryAction, 'launch_history'), (SignalCalculatorAction, 'signal_calculator'), (LastAnalysisRecoveryAction, 'last_analysis_recovery'), (RunHistoryAction, 'run_history_view'), (MeltingPointCalibrationAction, 'melting_point_calibrator')))): path = 'MenuBar/{}'.format(path) for f, t in fs: actions.append( SchemaAddition(id=idformat(t), factory=f, path=path)) eactions = [] for path, fs in (('edit.menu/experiment.group', ((DeselectAction, 'deselect'), (ResetQueuesAction, 'reset'), (SyncQueueAction, 'sync'), (UndoAction, 'undo'), (ConfigureEditorTableAction, 'configure'))), ('file.menu/Save', ((SaveAsCurrentExperimentAction, 'save_as_current_experiment'), ))): for f, t in fs: eactions.append( SchemaAddition(id=eidformat(t), factory=f, path=path)) return [(self.id, '', 'Experiment', actions), ('{}.edit'.format(self.id), 'pychron.experiment.task', 'Experiment Edit', eactions)] def _service_offers_default(self): so_signal_calculator = self.service_offer_factory( protocol=SignalCalculator, factory=self._signal_calculator_factory) # so_image_browser = self.service_offer_factory( # protocol=ImageBrowser, # factory=self._image_browser_factory) so_sens_selector = self.service_offer_factory( protocol=SensitivitySelector, factory=self._sens_selector_factory) so_run_history = self.service_offer_factory( protocol=RunHistoryView, factory=self._run_history_factory) return [ so_signal_calculator, # so_image_browser, so_sens_selector, so_run_history ]
class PychronTasksPlugin(BasePlugin): id = 'pychron.tasks.plugin' name = 'Tasks' preferences_panes = List( contributes_to='envisage.ui.tasks.preferences_panes') task_extensions = List(contributes_to='envisage.ui.tasks.task_extensions') actions = ExtensionPoint(List, id='pychron.actions') file_defaults = ExtensionPoint(List(Tuple), id='pychron.plugin.file_defaults') help_tips = ExtensionPoint(List, id='pychron.plugin.help_tips') available_task_extensions = ExtensionPoint( List, id='pychron.available_task_extensions') my_tips = List(contributes_to='pychron.plugin.help_tips') # def _application_changed(self): # # defaults = (('use_advanced_ui', False), ('show_random_tip', True)) # defaults = (('show_random_tip', True),) # try: # self._set_preference_defaults(defaults, 'pychron.general') # except AttributeError, e: # print 'exception', e def start(self): self.info('Writing plugin file defaults') paths.write_file_defaults(self.file_defaults) self._set_user() self._random_tip() def _set_user(self): self.application.preferences.set('pychron.general.username', globalv.username) self.application.preferences.save() def _random_tip(self): if globalv.random_tip_enabled and to_bool( self.application.preferences.get( 'pychron.general.show_random_tip')): from pychron.envisage.tasks.tip_view import TipView t = random.choice(self.help_tips) tv = TipView(text=t) tv.edit_traits() def _my_tips_default(self): return [ "Use <b>Help>What's New</b> to view the official ChangeLog for the current version", 'Turn Off Random Tip two ways:<br><b>1. Preferences>General></b> Uncheck "Random Tip".</b><br>' '<b>2.</b> Set the flag <i>random_tip_enabled</i> to False in the initialization file', 'Use <b>Window/Reset Layout</b> to change the current window back to its default "Look"', 'Submit bugs or issues to the developers manually using <b>Help/Add Request/Report Bug</b>', 'The current version of Pychron contains over 147K lines of code', 'If menu actions are missing first check that the desired "Plugin" is enabled using <b>Help/Edit ' 'Initialization</b>. If "Plugin" is enabled, check that the desired action is enabled using ' '<b>Help/Edit UI</b>.' ] def _preferences_panes_default(self): return [GeneralPreferencesPane, BrowserPreferencesPane] def _task_extensions_default(self): actions = [ SchemaAddition(factory=EditInitializationAction, id='edit_plugins', path='MenuBar/help.menu') ] return [TaskExtension(actions=actions)]
class HardwarePlugin(BaseTaskPlugin): id = 'pychron.hardware.plugin' managers = ExtensionPoint(List(Dict), id='pychron.hardware.managers') # my_managers = List(contributes_to='pychron.hardware.managers') sources = List(contributes_to='pychron.video.sources') # def _my_managers_default(self): # return [dict(name='hardware', manager=self._hardware_manager_factory())] # def _system_lock_manager_factory(self): # return SystemLockManager(application=self.application) _remote_hardware_manager = None # _remote_hardware_manager = Instance('pychron.remote_hardware.remote_hardware_manager.RemoteHardwareManager') # _hardware_manager = Instance('pychron.managers.hardware_manager.HardwareManager') def start(self): # if self.managers: from pychron.envisage.initialization.initializer import Initializer dp = DevicePreferences() afh = self.application.preferences.get('pychron.hardware.auto_find_handle') awh = self.application.preferences.get('pychron.hardware.auto_write_handle') if afh is not None: dp.serial_preference.auto_find_handle = to_bool(afh) dp.serial_preference.auto_write_handle = to_bool(awh) ini = Initializer(device_prefs=dp) for m in self.managers: ini.add_initialization(m) # any loaded managers will be registered as services if not ini.run(application=self.application): self.application.exit() # self.application.starting return # create the hardware proxy server ehs = to_bool(self.application.preferences.get('pychron.hardware.enable_hardware_server')) if ehs: # use_tx = to_bool(self.application.preferences.get('pychron.hardware.use_twisted', True)) use_tx = True if use_tx: from pychron.tx.server import TxServer rhm = TxServer() node = self.application.preferences.node('pychron.hardware') ports = eval(node.get('ports', '[]')) factories = eval(node.get('factories', '[]')) for protocol in eval(node.get('pnames', '[]')): factory = import_klass(factories[protocol]) port = int(ports[protocol]) exc = rhm.add_endpoint(port, factory(self.application)) if exc: msg = 'Failed starting Command Server for "{}:{}". Please check that multiple ' \ 'instances of pychron are not running on this computer. ' \ 'Exception: {}'.format(protocol, port, exc) self.warning_dialog(msg) else: self.info('Added Pychron Proxy Service: {}:{}'.format(protocol, port)) # else: # from pychron.remote_hardware.remote_hardware_manager import RemoteHardwareManager # rhm = RemoteHardwareManager(application=self.application) self._remote_hardware_manager = rhm rhm.bootstrap() def stop(self): if self._remote_hardware_manager: self._remote_hardware_manager.kill() if self.managers: for m in self.managers: man = m['manager'] if man: man.kill() for s in self.application.get_services(ICoreDevice): if s.is_scanable: s.stop_scan() def _factory(self): task = HardwareTask(application=self.application) return task def _flag_manager_factory(self): return FlagManager(application=self.application) # def _hardware_manager_factory(self): # return HardwareManager(application=self.application) # def _remote_hardware_manager_factory(self): # return RemoteHardwareManager(application=self.application) def _service_offers_default(self): # so_hm = self.service_offer_factory( # protocol=HardwareManager, # factory=self._hardware_manager_factory) # # so_rhm = self.service_offer_factory( # protocol=RemoteHardwareManager, # factory=self._remote_hardware_manager_factory) so_fm = self.service_offer_factory( protocol=FlagManager, factory=self._flag_manager_factory) # return [so, so1, so2] # return [so_hm, so_rhm, so_fm] # return [so_hm, so_fm] return [so_fm] def _preferences_panes_default(self): return [HardwarePreferencesPane] def _sources_default(self): return [('pvs://localhost:1081', 'Hardware')] def _task_extensions_default(self): return [TaskExtension(actions=[SchemaAddition(id='Flag Manager', factory=OpenFlagManagerAction, path='MenuBar/tools.menu'), ])] def _tasks_default(self): return [TaskFactory(id='tasks.hardware', name='Hardware', factory=self._factory, image='configure-2', task_group='hardware')]
class ExtractionLinePlugin(BaseTaskPlugin): id = 'pychron.extraction_line' name = 'ExtractionLine' extraction_line_manager_klass = ExtractionLineManager plugin_canvases = ExtensionPoint( List(Dict), id='pychron.extraction_line.plugin_canvases') def _preferences_default(self): return self._preferences_factory('extractionline') # def set_preference_defaults(self): # self._set_preference_defaults((('canvas_path', os.path.join(paths.canvas2D_dir, 'canvas.xml')), # ('canvas_config_path', os.path.join(paths.canvas2D_dir, 'canvas_config.xml')), # ('valves_path', os.path.join(paths.extraction_line_dir, 'valves.xml'))), # 'pychron.extraction_line') def test_gauge_communication(self): return self._test('test_gauge_communication') def test_valve_communication(self): return self._test('test_valve_communication') def _test(self, func): man = self.application.get_service(ExtractionLineManager) return getattr(man, func)() def _factory(self): elm = self.extraction_line_manager_klass(application=self.application) elm.bind_preferences() elm.plugin_canvases = self.plugin_canvases return elm def _runner_factory(self): runner = PyScriptRunner() return runner # defaults def _task_extensions_default(self): ex = [ TaskExtension(actions=[ SchemaAddition(id='refresh_canvas', factory=RefreshCanvasAction, path='MenuBar/tools.menu') ]) ] if self.application.get_plugin('pychron.pyscript.plugin'): actions = [] for f in list_directory2(paths.procedures_dir, extension='.py', remove_extension=True): actions.append( SchemaAddition(id='procedure.{}'.format(f), factory=procedure_action( f, self.application), path='MenuBar/procedures.menu')) if actions: actions.insert( 0, SchemaAddition(id='procedures.menu', before='window.menu', after='tools.menu', factory=lambda: SMenu(name='Procedures', id='procedures.menu'), path='MenuBar')) ex.append(TaskExtension(actions=actions)) else: self.warning('no procedure scripts located in "{}"'.format( paths.procedures_dir)) return ex def _service_offers_default(self): """ """ so = self.service_offer_factory(protocol=ExtractionLineManager, factory=self._factory) so1 = self.service_offer_factory(protocol=IPyScriptRunner, factory=self._runner_factory) return [so, so1] def _managers_default(self): """ """ return [ dict(name='extraction_line', plugin_name=self.name, manager=self.application.get_service(ExtractionLineManager)) ] def _tasks_default(self): ts = [ TaskFactory(id='pychron.extraction_line', name='Extraction Line', factory=self._task_factory, accelerator='Ctrl+E', task_group='hardware') ] return ts def _task_factory(self): elm = self.application.get_service(ExtractionLineManager) t = ExtractionLineTask(manager=elm) return t def _preferences_panes_default(self): return [ExtractionLinePreferencesPane, ConsolePreferencesPane]