def _tool_bars_default(self):
        # No accelerators here: they are added to menu entries

        tool_bars = [
            # General action toolbar
            SToolBar(TaskAction(
                name="Open recent projects",
                method="open_recent_projects",
                tooltip="Open recent project(s)",
                image=ImageResource("document-open-recent.png")),
                     TaskAction(name='Open project file',
                                method='open_proj_file',
                                tooltip='Open project file',
                                image=ImageResource('document-open')),
                     TaskAction(name='Save current project',
                                method='save',
                                tooltip='Save current project',
                                image=ImageResource('document-save')),
                     TaskAction(name='Save user data',
                                method='save_user_ds',
                                tooltip='Save user data',
                                image=ImageResource('drive-harddisk')),
                     image_size=ICON_SIZE,
                     show_tool_names=False),
            SToolBar(TaskAction(name='New simulation(s) from experiment(s)',
                                method='new_simulation_from_experiments',
                                tooltip='New simulation(s) from experiment(s)',
                                image=ImageResource('kchart')),
                     TaskAction(name='Run simulation(s)',
                                method='run_simulations',
                                tooltip='Run simulation(s)',
                                enabled_name='simulations_exist',
                                image=ImageResource('arrow-right')),
                     TaskAction(name='Run simulation grid(s)',
                                tooltip='Run simulation grid(s)',
                                method='run_simulation_groups',
                                enabled_name='simulation_groups_exist',
                                image=ImageResource('arrow-right-double')),
                     image_size=ICON_SIZE,
                     show_tool_names=False),

            # Plot action toolbar
            SToolBar(TaskAction(name='Plot all simulations',
                                method='new_model_calibration_plot',
                                tooltip='Plot all simulations',
                                image=ImageResource('office-chart-line')),
                     TaskAction(name='Show/hide plot controls',
                                method='show_hide_plot_controls',
                                tooltip='Show/hide plot controls',
                                image=ImageResource('format-list-unordered'),
                                enabled_name='_central_pane_is_plot'),
                     TaskAction(name='Show/hide plot legend',
                                method='show_hide_legend',
                                tooltip='Show/hide plot legend',
                                image=ImageResource('preferences-activities'),
                                enabled_name='_central_pane_is_plot'),
                     image_size=ICON_SIZE,
                     show_tool_names=False)
        ]
        return tool_bars
Esempio n. 2
0
class ThirdTask(ExampleTask):
    """ A simple task for opening a blank editor.
    """

    #### Task interface #######################################################

    id = 'example.third_task'
    name = 'Third Multi-Tab Editor'

    tool_bars = [ SToolBar(TaskAction(method='new',
                                      tooltip='New file',
                                      image=ImageResource('document_new')),
                           TaskAction(method='new',
                                      tooltip='New file',
                                      image=ImageResource('document_new')),
                           TaskAction(method='new',
                                      tooltip='New file',
                                      image=ImageResource('document_new')),
                           TaskAction(method='new',
                                      tooltip='New file',
                                      image=ImageResource('document_new')),
                           image_size = (32, 32)),
    ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################

    def _default_layout_default(self):
        return TaskLayout(
            right=VSplitter(
                HSplitter(
                    PaneItem('steps.pane1'),
                    PaneItem('steps.pane2')),
                ))
Esempio n. 3
0
class SecondTask(ExampleTask):
    """ A simple task for opening a blank editor.
    """

    #### Task interface #######################################################

    id = 'example.second_task'
    name = 'Second Multi-Tab Editor'

    tool_bars = [ SToolBar(TaskAction(method='new',
                                      tooltip='New file',
                                      image=ImageResource('document_new')),
                           image_size = (32, 32)), ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################
    
    def _menu_bar_default(self):
        return SMenuBar(SMenu(TaskAction(name='New', method='new',
                                         accelerator='Ctrl+N'),
                              id='File', name='&File'),
                        SMenu(DockPaneToggleGroup(),
                              TaskToggleGroup(),
                              id='View', name='&View'),
                        SMenu(TaskAction(name='Item 1', method='item1'),
                              TaskAction(name='Item 2', method='item2'),
                              id='Task2', name='&Task2'),)
class SecondTask(ExampleTask):
    """ A simple task for opening a blank editor.
    """

    #### Task interface #######################################################

    id = 'example.second_task'
    name = 'Second Multi-Tab Editor'

    menu_bar = SMenuBar(
        SMenu(TaskAction(name='New', method='new', accelerator='Ctrl+N'),
              id='File',
              name='&File'),
        SMenu(DockPaneToggleGroup(),
              TaskToggleGroup(),
              id='View',
              name='&View'))

    tool_bars = [
        SToolBar(TaskAction(method='new',
                            tooltip='New file',
                            image=ImageResource('document_new')),
                 image_size=(32, 32)),
    ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################

    def _default_layout_default(self):
        return TaskLayout(left=Tabbed(PaneItem('steps.first_pane'),
                                      PaneItem('steps.second_pane'),
                                      PaneItem('steps.third_pane')))
Esempio n. 5
0
class SecondTask(ExampleTask):
    """ A simple task for opening a blank editor.
    """

    # Task interface -------------------------------------------------------

    id = "example.second_task"
    name = "Second Multi-Tab Editor"

    tool_bars = [
        SToolBar(
            TaskAction(
                method="new",
                tooltip="New file",
                image=ImageResource("document_new"),
            ),
            TaskAction(
                method="new",
                tooltip="New file",
                image=ImageResource("document_new"),
            ),
            image_size=(32, 32),
        )
    ]

    # ------------------------------------------------------------------------
    # 'Task' interface.
    # ------------------------------------------------------------------------

    def _default_layout_default(self):
        return TaskLayout(left=VSplitter(
            HSplitter(PaneItem("steps.pane1"), PaneItem("steps.pane2"))))
Esempio n. 6
0
 def _tool_bars_default(self):
     bars = []
     desc = self.ui_layout_description["toolbar"]
     for menu_title in desc["order"]:
         menu_desc = desc[menu_title]
         bars.append(self.get_groups("Tool", menu_title, *menu_desc))
     return [
         SToolBar(*bars, show_tool_names=False, id="%s:ToolBar" % self.id)
     ]
Esempio n. 7
0
class ExampleTask(Task):
    """ A simple task for opening a blank editor.
    """

    #### Task interface #######################################################

    id = 'example.example_task'
    name = 'Multi-Tab Editor'

    active_editor = Property(Instance(IEditor),
                             depends_on='editor_area.active_editor')

    editor_area = Instance(IEditorAreaPane)

    menu_bar = SMenuBar(
        SMenu(TaskAction(name='New', method='new', accelerator='Ctrl+N'),
              id='File',
              name='&File'),
        SMenu(DockPaneToggleGroup(), id='View', name='&View'))

    tool_bars = [
        SToolBar(TaskAction(method='new',
                            tooltip='New file',
                            image=ImageResource('document_new')),
                 image_size=(32, 32)),
    ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        self.editor_area = EditorAreaPane()
        return self.editor_area

    ###########################################################################
    # 'ExampleTask' interface.
    ###########################################################################

    def new(self):
        """ Opens a new empty window
        """
        editor = Editor()
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    #### Trait property getter/setters ########################################

    def _get_active_editor(self):
        if self.editor_area is not None:
            return self.editor_area.active_editor
        return None
Esempio n. 8
0
 def _tool_bars_default(self):
     toolbars = [
         SToolBar(TaskAction(name="Import",
                             method='on_import',
                             image=ImageResource('import')),
                  TaskAction(name="Open",
                             method='on_open',
                             image=ImageResource('survey')),
                  TaskAction(name="Save",
                             method='on_save',
                             enabled_name='dirty',
                             image=ImageResource('save')),
                  id='File',
                  name="File",
                  show_tool_names=False,
                  image_size=(24, 24)),
         SToolBar(TaskCommandAction(name='New Group',
                                    method='on_new_group',
                                    command_stack_name='command_stack',
                                    image=ImageResource('new-group')),
                  TaskCommandAction(name='Delete Group',
                                    method='on_delete_group',
                                    enabled_name='have_current_group',
                                    command_stack_name='command_stack',
                                    image=ImageResource('delete-group')),
                  TaskAction(name='Previous Line',
                             method='on_previous_line',
                             enabled_name='survey.survey_lines',
                             image=ImageResource("arrow-left")),
                  TaskAction(name='Next Line',
                             method='on_next_line',
                             enabled_name='survey.survey_lines',
                             image=ImageResource("arrow-right")),
                  id='Survey',
                  name="Survey",
                  show_tool_names=False,
                  image_size=(24, 24)),
     ]
     return toolbars
Esempio n. 9
0
def get_toolbar_group(toolbar_name, mouse_handlers):
    """Create the toolbar groups with buttons in the order specified in the
    valid_mouse_modes dict.
    """
    actions = [
        MouseHandlerBaseAction(handler=mode,
                               enabled_name=mode.editor_trait_for_enabled)
        for mode in mouse_handlers
    ]
    return SToolBar(
        Group(*actions),
        show_tool_names=False,
        # image_size=(22,22),
        id=toolbar_name)
Esempio n. 10
0
class SecondTask(ExampleTask):
    """ A simple task for opening a blank editor.
    """

    # Task interface -------------------------------------------------------

    id = "example.second_task"
    name = "Second Multi-Tab Editor"

    menu_bar = SMenuBar(
        SMenu(
            TaskAction(name="New", method="new", accelerator="Ctrl+N"),
            id="File",
            name="&File",
        ),
        SMenu(DockPaneToggleGroup(),
              TaskToggleGroup(),
              id="View",
              name="&View"),
    )

    tool_bars = [
        SToolBar(
            TaskAction(
                method="new",
                tooltip="New file",
                image=ImageResource("document_new"),
            ),
            image_size=(32, 32),
        )
    ]

    # ------------------------------------------------------------------------
    # 'Task' interface.
    # ------------------------------------------------------------------------

    def _default_layout_default(self):
        return TaskLayout(left=VSplitter(
            HSplitter(
                PaneItem("steps.pane1"),
                PaneItem("steps.pane2"),
                PaneItem("steps.pane3"),
            ),
            HSplitter(
                PaneItem("steps.pane4"),
                PaneItem("steps.pane5"),
                PaneItem("steps.pane6"),
            ),
        ))
 def _tool_bars_default(self):
     return [
         SToolBar(
             TaskAction(
                 name="Setup Workflow",
                 tooltip="Setup Workflow",
                 image=ImageResource("outline_build_black_48dp"),
                 method="switch_task",
                 image_size=(64, 64),
             ), ),
         SToolBar(
             TaskAction(
                 name="Open Project",
                 tooltip="Open a project containing a workflow and results",
                 image=ImageResource("baseline_folder_open_black_48dp"),
                 method="open_project",
                 image_size=(64, 64),
             ),
             TaskAction(
                 name="Save Project As",
                 tooltip="Save results and workflow together as JSON",
                 image=ImageResource("outline_save_black_48dp"),
                 method="save_project_as",
                 enabled_name="export_results_enabled",
                 image_size=(64, 64),
             ),
             TaskAction(
                 name="Export Results",
                 tooltip="Export results table to a JSON or CSV file",
                 image=ImageResource("baseline_save_black_48dp"),
                 method="export_analysis_model_as",
                 enabled_name="export_results_enabled",
                 image_size=(64, 64),
             ),
         ),
     ]
Esempio n. 12
0
class SecondTask(ExampleTask):
    """ A simple task for opening a blank editor.
    """

    # Task interface -------------------------------------------------------

    id = "example.second_task"
    name = "Second Multi-Tab Editor"

    tool_bars = [
        SToolBar(
            TaskAction(
                method="new",
                tooltip="New file",
                image=ImageResource("document_new"),
            ),
            image_size=(32, 32),
        )
    ]

    # ------------------------------------------------------------------------
    # 'Task' interface.
    # ------------------------------------------------------------------------

    def _menu_bar_default(self):
        return SMenuBar(
            SMenu(
                TaskAction(name="New", method="new", accelerator="Ctrl+N"),
                id="File",
                name="&File",
            ),
            SMenu(
                DockPaneToggleGroup(),
                TaskToggleGroup(),
                id="View",
                name="&View",
            ),
            SMenu(
                TaskAction(name="Item 1", method="item1"),
                TaskAction(name="Item 2", method="item2"),
                id="Task2",
                name="&Task2",
            ),
        )
 def run_tools(self):
     """ Run/pause/stop workflow tools schema.
     """
     return SToolBar(
         TaskAction(
             name="Run",
             tooltip="Run Workflow",
             image=ImageResource("baseline_play_arrow_black_48dp"),
             method="setup_task.run_bdss",
             enabled_name="setup_task.run_enabled",
             image_size=(64, 64),
         ),
         TaskAction(
             name="Stop",
             tooltip="Stop Workflow",
             method="setup_task.stop_bdss",
             enabled_name='setup_task.computation_running',
             image=ImageResource("baseline_stop_black_18dp"),
             image_size=(64, 64),
         ),
         TaskAction(
             name="Pause",
             tooltip="Pause Workflow",
             method="setup_task.pause_bdss",
             enabled_name='setup_task.computation_running',
             visible_name='setup_task._not_paused',
             image=ImageResource("baseline_pause_black_18dp"),
             image_size=(64, 64),
         ),
         TaskAction(
             name="Resume",
             tooltip="Resume Workflow",
             method="setup_task.pause_bdss",
             enabled_name='setup_task.computation_running',
             visible_name='setup_task._paused',
             image=ImageResource("baseline_skip_next_black_18dp"),
             image_size=(64, 64),
         ),
     )
Esempio n. 14
0
 def _tool_bars_default(self):
     tool_bars = [
         SToolBar(
             TaskAction(
                 name="Run",
                 tooltip="Run PyFibre",
                 image=ImageResource("baseline_play_arrow_black_48dp"),
                 method="_run_pyfibre",
                 image_size=(64, 64),
                 enabled_name='run_enabled'),
             TaskAction(name="Stop",
                        tooltip="Stop PyFibre run",
                        image=ImageResource("baseline_stop_black_18dp"),
                        method="stop_run",
                        image_size=(64, 64),
                        enabled_name='stop_enabled'),
             TaskAction(name="Save Database",
                        tooltip="Save database containing "
                        "image metrics",
                        image=ImageResource("baseline_save_black_48dp"),
                        method="save_database_as"))
     ]
     return tool_bars
class ExampleTask(Task):
    """ A simple task for editing Python code.
    """

    #### Task interface #######################################################

    id = 'example.example_task'
    name = 'Multi-Tab Editor'

    active_editor = Property(Instance(IEditor),
                             depends_on='editor_area.active_editor')

    editor_area = Instance(IEditorAreaPane)

    menu_bar = SMenuBar(
        SMenu(TaskAction(name='New', method='new', accelerator='Ctrl+N'),
              TaskAction(name='Open...', method='open', accelerator='Ctrl+O'),
              TaskAction(name='Save', method='save', accelerator='Ctrl+S'),
              id='File',
              name='&File'),
        SMenu(DockPaneToggleGroup(), id='View', name='&View'))

    tool_bars = [
        SToolBar(TaskAction(method='new',
                            tooltip='New file',
                            image=ImageResource('document_new')),
                 TaskAction(method='open',
                            tooltip='Open a file',
                            image=ImageResource('document_open')),
                 TaskAction(method='save',
                            tooltip='Save the current file',
                            image=ImageResource('document_save')),
                 image_size=(32, 32),
                 show_tool_names=False),
    ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################

    def _default_layout_default(self):
        return TaskLayout(left=PaneItem('example.python_script_browser_pane'))

    def activated(self):
        """ Overriden to set the window's title.
        """
        return
        filename = self.active_editor.path if self.active_editor else ''
        self.window.title = filename if filename else 'Untitled'

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        self.editor_area = EditorAreaPane()
        return self.editor_area

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        browser = PythonScriptBrowserPane()
        handler = lambda: self._open_file(browser.selected_file)
        browser.on_trait_change(handler, 'activated')
        return [browser]

    ###########################################################################
    # 'ExampleTask' interface.
    ###########################################################################

    def new(self):
        """ Opens a new empty window
        """
        editor = PythonEditor()
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    def open(self):
        """ Shows a dialog to open a file.
        """
        dialog = FileDialog(parent=self.window.control, wildcard='*.py')
        if dialog.open() == OK:
            self._open_file(dialog.path)

    def save(self):
        """ Attempts to save the current file, prompting for a path if
            necessary. Returns whether the file was saved.
        """
        editor = self.active_editor
        try:
            editor.save()
        except IOError:
            # If you are trying to save to a file that doesn't exist, open up a
            # FileDialog with a 'save as' action.
            dialog = FileDialog(parent=self.window.control,
                                action='save as',
                                wildcard='*.py')
            if dialog.open() == OK:
                editor.save(dialog.path)
            else:
                return False
        return True

    ###########################################################################
    # Protected interface.
    ###########################################################################

    def _open_file(self, filename):
        """ Opens the file at the specified path in the editor.
        """
        editor = PythonEditor(path=filename)
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    def _prompt_for_save(self):
        """ Prompts the user to save if necessary. Returns whether the dialog
            was cancelled.
        """
        dirty_editors = dict([(editor.name, editor)
                              for editor in self.editor_area.editors
                              if editor.dirty])
        if not list(dirty_editors.keys()):
            return True
        message = 'You have unsaved files. Would you like to save them?'
        dialog = ConfirmationDialog(parent=self.window.control,
                                    message=message,
                                    cancel=True,
                                    default=CANCEL,
                                    title='Save Changes?')
        result = dialog.open()
        if result == CANCEL:
            return False
        elif result == YES:
            for name, editor in list(dirty_editors.items()):
                editor.save(editor.path)
        return True

    #### Trait change handlers ################################################

    @on_trait_change('window:closing')
    def _prompt_on_close(self, event):
        """ Prompt the user to save when exiting.
        """
        close = self._prompt_for_save()
        event.veto = not close

    #### Trait property getter/setters ########################################

    def _get_active_editor(self):
        if self.editor_area is not None:
            return self.editor_area.active_editor
        return None
Esempio n. 16
0
class ExampleTask(Task):
    """ A simple task for opening a blank editor.
    """

    # Task interface -------------------------------------------------------

    id = "example.example_task"
    name = "Multi-Tab Editor"

    active_editor = Property(Instance(IEditor),
                             observe="editor_area.active_editor")

    editor_area = Instance(IEditorAreaPane)

    tool_bars = [
        SToolBar(
            TaskAction(
                method="new",
                tooltip="New file",
                image=ImageResource("document_new"),
            ),
            image_size=(32, 32),
        )
    ]

    # ------------------------------------------------------------------------
    # 'Task' interface.
    # ------------------------------------------------------------------------

    def _menu_bar_default(self):
        return SMenuBar(
            SMenu(
                TaskAction(name="New", method="new", accelerator="Ctrl+N"),
                id="File",
                name="&File",
            ),
            SMenu(
                DockPaneToggleGroup(),
                TaskToggleGroup(),
                id="View",
                name="&View",
            ),
        )

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        self.editor_area = EditorAreaPane()
        return self.editor_area

    # ------------------------------------------------------------------------
    # 'ExampleTask' interface.
    # ------------------------------------------------------------------------

    def new(self):
        """ Opens a new empty window
        """
        editor = Editor()
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    # Trait property getter/setters ----------------------------------------

    def _get_active_editor(self):
        if self.editor_area is not None:
            return self.editor_area.active_editor
        return None
class ExampleTask(Task):
    """ A simple task for opening a blank editor.
    """

    #### Task interface #######################################################

    id = 'example.example_task'
    name = 'Multi-Tab Editor'

    active_editor = Property(Instance(IEditor),
                             depends_on='editor_area.active_editor')

    editor_area = Instance(IEditorAreaPane)

    menu_bar = SMenuBar(
        SMenu(TaskAction(name='New', method='new', accelerator='Ctrl+N'),
              id='File',
              name='&File'),
        SMenu(DockPaneToggleGroup(),
              TaskToggleGroup(),
              id='View',
              name='&View'))

    tool_bars = [
        SToolBar(TaskAction(method='new',
                            tooltip='New file',
                            image=ImageResource('document_new')),
                 image_size=(32, 32)),
    ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################

    def _default_layout_default(self):
        return TaskLayout(top=Tabbed(PaneItem('steps.first_pane'),
                                     PaneItem('steps.second_pane'),
                                     PaneItem('steps.third_pane')))

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        self.editor_area = EditorAreaPane()
        return self.editor_area

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        return [FirstPane(), SecondPane(), ThirdPane()]

    ###########################################################################
    # 'ExampleTask' interface.
    ###########################################################################

    def new(self):
        """ Opens a new empty window
        """
        editor = Editor()
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    #### Trait property getter/setters ########################################

    def _get_active_editor(self):
        if self.editor_area is not None:
            return self.editor_area.active_editor
        return None
class ImageViewerTask(Task):
    """ A simple task for viewing images.
    """
    #### Task interface #######################################################

    id = 'example.image_viewer_task'
    name = 'Image Viewer'

    #default_layout = TaskLayout(
    #    left=PaneItem('example.python_script_browser_pane'))

    menu_bar = SMenuBar(
        SMenu(TaskAction(name='Open...', method='open', accelerator='Ctrl+O'),
              id='File',
              name='&File'),
        SMenu(DockPaneToggleGroup(), id='View', name='&View'))

    tool_bars = [
        SToolBar(
            TaskAction(method='open',
                       tooltip='Open a file',
                       image=ImageResource('document_open')))
    ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################

    def _default_layout_default(self):
        return TaskLayout(left=PaneItem('image_viewer.file_browser_pane'))

    def activated(self):
        """ Overriden to set the window's title.
        """
        filename = self.window.central_pane.model.path
        self.window.title = filename if filename else 'Untitled'

    def create_central_pane(self):
        """ Create the central pane: the image viewer.
        """
        return ImageViewerPane()

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        browser = FileBrowserPane(filters=["*.jpg"])
        handler = lambda: self._open_file(browser.selected_file)
        browser.on_trait_change(handler, 'activated')
        return [browser]

    ###########################################################################
    # 'ExampleTask' interface.
    ###########################################################################

    def open(self):
        """ Shows a dialog to open a file.
        """
        dialog = FileDialog(parent=self.window.control, wildcard='*.jpg')
        if dialog.open() == OK:
            self._open_file(dialog.path)

    ###########################################################################
    # Protected interface.
    ###########################################################################

    def _open_file(self, filename):
        """ Opens the file at the specified path in the editor.
        """
        self.window.central_pane.model.path = filename
        self.activated()
class PythonEditorTask(Task):
    """ A simple task for editing Python code.
    """

    # 'Task' traits -----------------------------------------------------------

    #: The unique id of the task.
    id = 'example.python_editor_task'

    #: The human-readable name of the task.
    name = u"Python Editor"

    #: The currently active editor in the editor area, if any.
    active_editor = Property(Instance(IEditor),
                             depends_on='editor_area.active_editor')

    #: The editor area for this task.
    editor_area = Instance(IEditorAreaPane)

    #: The menu bar for the task.
    menu_bar = SMenuBar(
        SMenu(
            SGroup(
                TaskAction(name='New', method='new', accelerator='Ctrl+N'),
                id='new_group',
            ),
            SGroup(
                TaskAction(name='Open...', method='open',
                           accelerator='Ctrl+O'),
                id='open_group',
            ),
            SGroup(
                TaskAction(name='Save',
                           method='save',
                           accelerator='Ctrl+S',
                           enabled_name='active_editor.dirty'),
                TaskAction(name='Save As...',
                           method='save_as',
                           accelerator='Ctrl+Shift+S'),
                id='save_group',
            ),
            SGroup(
                TaskAction(
                    name='Close Editor',
                    method='close_editor',
                    accelerator='Ctrl+W',
                ),
                id='close_group',
            ),
            id='File',
            name='&File',
        ),
        SMenu(
            SGroup(
                EditorAction(
                    name='Undo',
                    method='undo',
                    enabled_name='can_undo',
                    accelerator='Ctrl+Z',
                ),
                EditorAction(
                    name='Redo',
                    method='redo',
                    enabled_name='can_redo',
                    accelerator='Ctrl+Shift+Z',
                ),
                id='undo_group',
            ),
            SGroup(
                EditorAction(
                    name='Go to Line...',
                    method='go_to_line',
                    accelerator='Ctrl+G',
                ),
                id='search_group',
            ),
            id='Edit',
            name='&Edit',
        ), SMenu(
            DockPaneToggleGroup(),
            id='View',
            name='&View',
        ),
        SMenu(
            SGroup(
                OpenURLAction(
                    name='Python Documentation',
                    id='python_docs',
                    url=PYTHON_DOCS,
                ),
                id="documentation_group",
            ),
            id='Help',
            name='&Help',
        ))

    #: The tool bars for the task.
    tool_bars = [
        SToolBar(TaskAction(
            method='new',
            tooltip='New file',
            image=ImageResource('document_new'),
        ),
                 TaskAction(method='open',
                            tooltip='Open a file',
                            image=ImageResource('document_open')),
                 TaskAction(method='save',
                            tooltip='Save the current file',
                            image=ImageResource('document_save'),
                            enabled_name='active_editor.dirty'),
                 image_size=(16, 16),
                 show_tool_names=False),
    ]

    #: The status bar for the window when this task is active.
    status_bar = Instance(StatusBarManager, ())

    # -------------------------------------------------------------------------
    # 'PythonEditorTask' interface.
    # -------------------------------------------------------------------------

    def create_editor(self, path=''):
        """ Create a new editor in the editor pane.

        Parameters
        ----------
        path : path or ''
            The path to the file to edit, or '' for an empty editor.
        """
        if path:
            path = os.path.abspath(path)
        use_existing = (path != '')
        self.editor_area.edit(
            path,
            factory=PythonEditor,
            use_existing=use_existing,
        )
        if path:
            self.active_editor.load()

    def close_editor(self):
        """ Close the active editor, or if no editors, close the Task window.
        """
        if self.editor_area.active_editor is not None:
            self.editor_area.remove_editor(self.editor_area.active_editor)
        else:
            self.window.close()

    def new(self):
        """ Open a new empty window
        """
        self.create_editor()

    def open(self):
        """ Shows a dialog to open a Python file.
        """
        dialog = FileDialog(parent=self.window.control, wildcard='*.py')
        if dialog.open() == OK:
            self.create_editor(dialog.path)

    def save(self):
        """ Save the current file.
        
        If needed, this code prompts for a path.
        
        Returns
        -------
        saved : bool
            Whether or not the file was saved.
        """
        editor = self.active_editor
        try:
            editor.save()
        except IOError:
            # If you are trying to save to a file that doesn't exist, open up a
            # FileDialog with a 'save as' action.
            dialog = FileDialog(
                parent=self.window.control,
                action='save as',
                wildcard='*.py',
            )
            if dialog.open() == OK:
                editor.save(dialog.path)
            else:
                return False
        return True

    # -------------------------------------------------------------------------
    # 'Task' interface.
    # -------------------------------------------------------------------------

    def _default_layout_default(self):
        """ The default layout with the browser pane on the left.
        """
        return TaskLayout(
            left=PaneItem('example.python_browser_pane', width=200))

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        self.editor_area = EditorAreaPane()
        return self.editor_area

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        browser = PythonBrowserPane()

        def handler():
            return self.create_editor(browser.selected_file)

        browser.on_trait_change(handler, 'activated')
        return [browser]

    # -------------------------------------------------------------------------
    # Protected interface.
    # -------------------------------------------------------------------------

    def _prompt_for_save(self):
        """ Prompts the user to save if necessary. Returns whether the dialog
            was cancelled.
        """
        dirty_editors = {
            editor.name: editor
            for editor in self.editor_area.editors
            if editor.dirty and (editor.obj or editor.code)
        }
        if not dirty_editors:
            return True

        message = 'You have unsaved files. Would you like to save them?'
        dialog = ConfirmationDialog(parent=self.window.control,
                                    message=message,
                                    cancel=True,
                                    default=CANCEL,
                                    title='Save Changes?')
        result = dialog.open()
        if result == CANCEL:
            return False
        elif result == YES:
            for name, editor in dirty_editors.items():
                editor.save(editor.path)
        return True

    # Trait change handlers --------------------------------------------------

    @on_trait_change('window:closing')
    def _prompt_on_close(self, event):
        """ Prompt the user to save when exiting.
        """
        close = self._prompt_for_save()
        event.veto = not close

    @on_trait_change('active_editor.name')
    def _change_title(self):
        """ Update the window title when the active editor changes.
        """
        if self.window.active_task == self:
            if self.active_editor is not None:
                self.window.title = self.active_editor.name
            else:
                self.window.title = self.name

    @on_trait_change('active_editor.[line,column,selection_length]')
    def _update_status(self):
        if self.active_editor is not None:
            editor = self.active_editor
            if editor.selection_length:
                self.status_bar.messages = [
                    "Ln {}, Col {} ({} selected)".format(
                        editor.line, editor.column, editor.selection_length)
                ]
            else:
                self.status_bar.messages = [
                    "Ln {}, Col {}".format(editor.line, editor.column)
                ]
        else:
            self.status_bar.messages = []

    # Trait property getter/setters ------------------------------------------

    @cached_property
    def _get_active_editor(self):
        if self.editor_area is not None:
            return self.editor_area.active_editor
        return None
Esempio n. 20
0
class FlowTask(Task):
    """
    classdocs
    """
    
    id = "edu.mit.synbio.cytoflowgui.flow_task"
    name = "Cytometry analysis"
    
    # the main workflow instance.
    model = Instance(Workflow)
        
    # the center pane
    workflow_pane = Instance(WorkflowDockPane)
    view_pane = Instance(ViewDockPane)
    help_pane = Instance(HelpDockPane)
    plot_params_pane = Instance(PlotParamsPane)
    
    # plugin lists, to setup the interface
    op_plugins = List(IOperationPlugin)
    view_plugins = List(IViewPlugin)
    
    menu_bar = SMenuBar(SMenu(TaskAction(name='Open...',
                                         method='on_open',
                                         accelerator='Ctrl+O'),
                              TaskAction(name='Save',
                                         #image='save', 
                                         method='on_save',
                                         accelerator='Ctrl+S'),
                              TaskAction(name='Save As...',
                                         method='on_save_as',
                                         accelerator='Ctrl+e'),
                              TaskAction(name='Save Plot...',
                                         method='on_export',
                                         accelerator='Ctrl+x'),
                              TaskAction(name='Export Jupyter notebook...',
                                         method='on_notebook',
                                         accelerator='Ctrl+I'),                              
#                               TaskAction(name='Preferences...',
#                                          method='on_prefs',
#                                          accelerator='Ctrl+P'),
                              id='File', name='&File'),
                        SMenu(TaskToggleGroup(),
                              id = 'View', name = '&View'),
                        SMenu(TaskAction(name = 'Online documentation...',
                                         method = 'on_docs'),
                                         TaskAction(name = 'Report a problem....',
                                         method = 'on_problem'),
                              TaskAction(name='About...',
                                         method='on_about'),
                              id="Help", name ="&Help"))
    
    tool_bars = [ SToolBar(TaskAction(method='on_new',
                                      name = "New",
                                      tooltip='New workflow',
                                      image=ImageResource('new')),
                           TaskAction(method='on_open',
                                      name = "Open",
                                      tooltip='Open a file',
                                      image=ImageResource('open')),
                           TaskAction(method='on_save',
                                      name = "Save",
                                      tooltip='Save the current file',
                                      image=ImageResource('save')),
                           TaskAction(method='on_export',
                                      name = "Save Plot",
                                      tooltip='Save the current plot',
                                      image=ImageResource('export')),
                           TaskAction(method='on_notebook',
                                       name='Notebook',
                                       tooltip="Export to an Jupyter notebook...",
                                       image=ImageResource('jupyter')),
                           TaskAction(method = "on_calibrate",
                                      name = "Calibrate FCS...",
                                      tooltip = "Calibrate FCS files",
                                      image = ImageResource('tasbe')),
                           TaskAction(method = 'on_problem',
                                      name = "Report a bug...",
                                      tooltib = "Report a bug",
                                      image = ImageResource('bug')))]
#                            TaskAction(method='on_prefs',
#                                       name = "Prefs",
#                                       tooltip='Preferences',
#                                       image=ImageResource('prefs')),
    
    # the file to save to if the user clicks "save" and has already clicked
    # "open" or "save as".
    filename = Str
        
    def initialized(self):
        if self.filename:
            self.open_file(self.filename)

        
    def activated(self):
        
        # if we're coming back from the TASBE task, re-load the saved
        # workflow
        if self.model.backup_workflow:
            self.model.workflow = self.model.backup_workflow
            self.model.backup_workflow = []
            return
        
        # else, set up a new workflow
        # add the import op
        if not self.model.workflow:
            self.add_operation(ImportPlugin().id) 
            self.model.selected = self.model.workflow[0]
                    
        self.model.modified = False
    
    def _default_layout_default(self):
        return TaskLayout(left = VSplitter(PaneItem("edu.mit.synbio.cytoflowgui.workflow_pane", width = 350),
                                           PaneItem("edu.mit.synbio.cytoflowgui.help_pane", width = 350, height = 350)),
                          right = VSplitter(PaneItem("edu.mit.synbio.cytoflowgui.view_traits_pane", width = 350),
                                            PaneItem("edu.mit.synbio.cytoflowgui.params_pane", width = 350, height = 350)),
                          top_left_corner = 'left',
                          bottom_left_corner = 'left',
                          top_right_corner = 'right',
                          bottom_right_corner = 'right')
     
    def create_central_pane(self):   
        # set the toolbar image size
        # this isn't really the right place for this, but it's the only
        # place control passes back to user code before the toolbar
        # is created.
        
        dpi = self.window.control.physicalDpiX()
        self.tool_bars[0].image_size = (int(0.4 * dpi), int(0.4 * dpi))
        return self.application.plot_pane
     
    def create_dock_panes(self):
        self.workflow_pane = WorkflowDockPane(model = self.model, 
                                              plugins = self.op_plugins,
                                              task = self)
        
        self.view_pane = ViewDockPane(model = self.model,
                                      plugins = self.view_plugins,
                                      task = self)
        
        self.help_pane = HelpDockPane(view_plugins = self.view_plugins,
                                      op_plugins = self.op_plugins,
                                      task = self)
        
        self.plot_params_pane = PlotParamsPane(model = self.model,
                                               task = self)
        
        return [self.workflow_pane, self.view_pane, self.help_pane, self.plot_params_pane]
        
    def on_new(self):
        if self.model.modified:
            ret = confirm(parent = None,
                          message = "Are you sure you want to discard the current workflow?",
                          title = "Clear workflow?")
            
            if ret != YES:
                return
            
        self.filename = ""
        self.window.title = "Cytoflow"
        
        # clear the workflow
        self.model.workflow = []
        
        # add the import op
        self.add_operation(ImportPlugin().id) 
        
        # and select the operation
        self.model.selected = self.model.workflow[0]
        
        self.model.modified = False
     
        
    def on_open(self):
        """ 
        Shows a dialog to open a file.
        """
        
        if self.model.modified:
            ret = confirm(parent = None,
                          message = "Are you sure you want to discard the current workflow?",
                          title = "Clear workflow?")
            
            if ret != YES:
                return
        
        dialog = FileDialog(parent = self.window.control, 
                            action = 'open',
                            wildcard = (FileDialog.create_wildcard("Cytoflow workflow", "*.flow") + ';' +  #@UndefinedVariable  
                                        FileDialog.create_wildcard("All files", "*"))) #@UndefinedVariable  
        if dialog.open() == OK:
            self.open_file(dialog.path)
            self.filename = dialog.path
            self.window.title = "Cytoflow - " + self.filename
            

    def open_file(self, path):
        
        try:
            new_workflow = load_yaml(path)

            # a few things to take care of when reloading.
            # we do this in the try block to catch people who
            # load valid YAML files that aren't from cytoflow.
            
            for wi_idx, wi in enumerate(new_workflow):
                
                # get wi lock
                wi.lock.acquire()
                
                # clear the wi status
                wi.status = "loading"
    
                # re-link the linked list.
                if wi_idx > 0:
                    wi.previous_wi = new_workflow[wi_idx - 1]
                
                if wi_idx < len(new_workflow) - 1:
                    wi.next_wi = new_workflow[wi_idx + 1]

        except yaml.parser.ParserError as e:
            error(None,
                  "Parser error loading {} -- is it a Cytoflow file?\n\n{}"
                  .format(path, str(e)))
            return
        except Exception as e:
            error(None,
                  "{} loading {} -- is it a Cytoflow file?\n\n{}"
                  .format(e.__class__.__name__, path, str(e)))
            return
        
        # are we just running a smoke test?
        if 'startup_test' in new_workflow[0].metadata:
            def quit_app(app):
                app.exit(force = True)
                
            from pyface.timer.api import do_after
            do_after(5*1000, quit_app, self.application)
            return
            
        # check that the FCS files are all there
        
        wi = new_workflow[0]
        assert(wi.operation.id == "edu.mit.synbio.cytoflow.operations.import")
        missing_tubes = 0
        for tube in wi.operation.tubes:
            file = pathlib.Path(tube.file)
            if not file.exists():
                missing_tubes += 1
                
        if missing_tubes == len(wi.operation.tubes):
            warning(self.window.control,
                    "Cytoflow couldn't find any of the FCS files from that "
                    "workflow.  If they've been moved, please open one FCS "
                    "file to show Cytoflow where they've been moved to.")
            
            dialog = FileDialog(parent = self.window.control, 
                                action = 'open',
                                wildcard = (FileDialog.create_wildcard("FCS files", "*.fcs *.lmd")))  # @UndefinedVariable
            
            if dialog.open() == OK:
                # find the "best" file match -- ie, the one with the longest
                # tail match
                fcs_path = pathlib.Path(dialog.path).parts
                best_path_len = -1
                                
                for tube in wi.operation.tubes:
                    tube_path = pathlib.Path(tube.file).parts
                    
                    for i in range(len(fcs_path)):
                        if list(reversed(fcs_path))[:i] == list(reversed(tube_path))[:i] and i > best_path_len:
                            best_path_len = i
                            
                if best_path_len >= 0:
                    for tube in wi.operation.tubes:
                        tube_path = pathlib.Path(tube.file).parts
                        new_path = fcs_path[:-1 * best_path_len] + tube_path[-1 * best_path_len :]
                        tube.file = str(pathlib.Path(*new_path))
                        
        elif missing_tubes > 0:
            warning(self.window.control,
                    "Cytoflow couldn't find some of the FCS files from that "
                    "workflow.  You'll need to re-load them from the Import "
                    "operation.")

        # replace the current workflow with the one we just loaded
        
        if False:  # for debugging the loading of things
            from .event_tracer import record_events 
            
            with record_events() as container:
                self.model.workflow = new_workflow
                                
            container.save_to_directory(os.getcwd()) 
        else:
            self.model.workflow = new_workflow
            self.model.modified = False
            
        for wi in self.model.workflow:
            wi.lock.release()
            
        if self.model.debug:
            self.model.run_all()
        else:
            ret = confirm(parent = None,
                          message = "Do you want to execute the workflow now?",
                          title = "Run workflow?")
            
            if ret == YES:
                self.model.run_all()

        
    def on_save(self):
        """ Save the file to the previous filename  """
        if self.filename:
            save_yaml(self.model.workflow, self.filename)
            self.model.modified = False
        else:
            self.on_save_as()
            
    def on_save_as(self):
        dialog = DefaultFileDialog(parent = self.window.control,
                                   action = 'save as', 
                                   default_suffix = "flow",
                                   wildcard = (FileDialog.create_wildcard("Cytoflow workflow", "*.flow") + ';' + #@UndefinedVariable  
                                               FileDialog.create_wildcard("All files", "*")))                    #@UndefinedVariable  
        
        if dialog.open() == OK:
            save_yaml(self.model.workflow, dialog.path)
            self.filename = dialog.path
            self.model.modified = False
            self.window.title = "Cytoflow - " + self.filename
            
    @on_trait_change('model.modified', post_init = True)
    def _on_model_modified(self, val):
        if val:
            if not self.window.title.endswith("*"):
                self.window.title += "*"
        else:
            if self.window.title.endswith("*"):
                self.window.title = self.window.title[:-1]
        

    def on_export(self):
        task = next(x for x in self.window.tasks if x.id == 'edu.mit.synbio.cytoflowgui.export_task')
        self.window.activate_task(task)        


    def on_calibrate(self):
        task = next(x for x in self.window.tasks if x.id == 'edu.mit.synbio.cytoflowgui.tasbe_task')
        self.window.activate_task(task)
        
            
    def on_notebook(self):
        """
        Shows a dialog to export the workflow to an Jupyter notebook
        """

        dialog = DefaultFileDialog(parent = self.window.control,
                                   action = 'save as',
                                   default_suffix = "ipynb",
                                   wildcard = (FileDialog.create_wildcard("Jupyter notebook", "*.ipynb") + ';' + #@UndefinedVariable  
                                               FileDialog.create_wildcard("All files", "*")))  # @UndefinedVariable
        if dialog.open() == OK:
            save_notebook(self.model.workflow, dialog.path)

    
    def on_prefs(self):
        pass
    
    def on_docs(self):
        webbrowser.open_new_tab("https://cytoflow.readthedocs.io/en/stable/manual.html")

    
    def on_problem(self):

        log = str(self._get_package_versions()) + "\n" + self.application.application_log.getvalue()
        
        msg = "The best way to report a problem is send an application log to " \
              "the developers.  If you click 'Yes' below, you will be given then " \
              "opportunity to save the log to a file and then file a " \
              "new issue on GitHub at " \
              "https://github.com/cytoflow/cytoflow/issues/new" 
        
        dialog = ConfirmationDialog(message = msg,
                                    informative = "Would you like to report an issue to the developers?")
                
        if dialog.open() == YES:
            dialog = DefaultFileDialog(parent = self.window.control,
                                       action = 'save as', 
                                       default_suffix = "log",
                                       wildcard = (FileDialog.create_wildcard("Log files", "*.log") + ';' + #@UndefinedVariable  
                                                   FileDialog.create_wildcard("All files", "*")))                    #@UndefinedVariable  
            
            if dialog.open() == OK:
                with open(dialog.path, 'w') as f:
                    f.write(log)
                  
                webbrowser.open_new_tab("https://github.com/cytoflow/cytoflow/issues/new")
                  
            return
    
    def _get_package_versions(self):    
        from cytoflow import __version__ as cf_version
        from fcsparser import __version__ as fcs_version
        from pandas import __version__ as pd_version
        from numpy import __version__ as np_version
        from numexpr import __version__ as nxp_version
        from bottleneck import __version__ as btl_version
        from seaborn import __version__ as sns_version
        from matplotlib import __version__ as mpl_version
        from scipy import __version__ as scipy_version
        from sklearn import __version__ as skl_version
        from statsmodels import __version__ as stats_version
        from pyface import __version__ as pyf_version
        from envisage import __version__ as env_version
        from traits import __version__ as trt_version
        from traitsui import __version__ as trt_ui_version
        from yapf import __version__ as yapf_version
        from nbformat import __version__ as nb_version
        from yaml import __version__ as yaml_version
        
        return {"python" : sys.version,
                "cytoflow" : cf_version,
                "fcsparser" : fcs_version,
                "pandas" : pd_version,
                "numpy" : np_version,
                "numexpr" : nxp_version,
                "bottleneck" : btl_version,
                "seaborn" : sns_version,
                "matplotlib" : mpl_version,
                "scipy" : scipy_version,
                "scikit-learn" : skl_version,
                "statsmodels" : stats_version,
                "pyface" : pyf_version,
                "envisage" : env_version,
                "traits" : trt_version,
                "traitsui" : trt_ui_version,
                "nbformat" : nb_version,
                "yapf" : yapf_version,
                "yaml" : yaml_version}
        
        
    def on_about(self):
        versions = self._get_package_versions()
        text = ["<b>Cytoflow {0}</b>".format(versions['cytoflow']),
                "<p>"]
        
        ver_text = ["{0} {1}".format(key, value) for key, value in versions.items()]
        
        text.extend(ver_text)
        
        text.extend(["Icons from the <a href=http://tango.freedesktop.org>Tango Desktop Project</a>",
                "<a href=https://thenounproject.com/search/?q=setup&i=14287>Settings icon</a> by Paulo Sa Ferreira from <a href=https://thenounproject.com>The Noun Project</a>",
                "<a href=https://thenounproject.com/search/?q=processing&i=849831>Processing icon</a> by Gregor Cresnar from <a href=https://thenounproject.com>The Noun Project</a>",
                "<a href=http://www.freepik.com/free-photos-vectors/background>App icon from Starline - Freepik.com</a>",
                "Cuvette image from Wikimedia Commons user <a href=http://commons.wikimedia.org/wiki/File:Hellma_Large_cone_cytometry_cell.JPG>HellmaUSA</a>"])
        
        dialog = AboutDialog(text = text,
                             parent = self.window.control,
                             title = "About",
                             image = ImageResource('cuvette'),
                             additions = text)
        dialog.open()
        
    @on_trait_change('model.selected', post_init = True)
    def _on_select_op(self, selected):
        if selected:
            self.view_pane.enabled = (selected is not None)
            self.view_pane.default_view = selected.default_view.id if selected.default_view else ""
            self.view_pane.selected_view = selected.current_view.id if selected.current_view else ""
            self.help_pane.help_id = selected.operation.id
        else:
            self.view_pane.enabled = False
            
    @on_trait_change('view_pane.selected_view', post_init = True)
    def _on_select_view(self, view_id):
        
        if not view_id:
            return
        
        # if we already have an instantiated view object, find it
        try:
            self.model.selected.current_view = next((x for x in self.model.selected.views if x.id == view_id))
        except StopIteration:
            # else make the new view
            plugin = next((x for x in self.view_plugins if x.view_id == view_id))
            view = plugin.get_view()
            self.model.selected.views.append(view)
            self.model.selected.current_view = view
            
        self.help_pane.help_id = view_id
    
    def add_operation(self, op_id):
        # first, find the matching plugin
        plugin = next((x for x in self.op_plugins if x.id == op_id))
        
        # next, get an operation
        op = plugin.get_operation()
        
        # make a new workflow item
        wi = WorkflowItem(operation = op,
                          deletable = (op_id != 'edu.mit.synbio.cytoflowgui.op_plugins.import'))
        
        # if the op has a default view, add it to the wi
        try:
            wi.default_view = op.default_view()
            wi.views.append(wi.default_view)
            wi.current_view = wi.default_view
        except AttributeError:
            pass
        
        # figure out where to add it
        if self.model.selected:
            idx = self.model.workflow.index(self.model.selected) + 1
        else:
            idx = len(self.model.workflow)
             
        # the add_remove_items handler takes care of updating the linked list
        self.model.workflow.insert(idx, wi)
        
        # and make sure to actually select the new wi
        self.model.selected = wi
class ExampleTask(Task):
    """ A simple task for editing Python code.
    """

    #### Task interface #######################################################

    id = 'example.example_task'
    name = 'Python Script Editor'

    #default_layout = TaskLayout(
    #    left=PaneItem('example.python_script_browser_pane'))

    menu_bar = SMenuBar(
        SMenu(
            TaskAction(
                name='Open...', method='open', accelerator='Ctrl+O'),
            TaskAction(
                name='Save', method='save', accelerator='Ctrl+S'),
            id='File',
            name='&File'),
        SMenu(
            DockPaneToggleGroup(), id='View', name='&View'))

    tool_bars = [
        SToolBar(
            TaskAction(
                method='open',
                tooltip='Open a file',
                image=ImageResource('document_open')),
            TaskAction(
                method='save',
                tooltip='Save the current file',
                image=ImageResource('document_save')))
    ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################

    def _default_layout_default(self):
        return TaskLayout(left=PaneItem('example.python_script_browser_pane'))

    def activated(self):
        """ Overriden to set the window's title.
        """
        filename = self.window.central_pane.editor.path
        self.window.title = filename if filename else 'Untitled'

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        return PythonEditorPane()

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        browser = PythonScriptBrowserPane()
        handler = lambda: self._open_file(browser.selected_file)
        browser.on_trait_change(handler, 'activated')
        return [browser]

    ###########################################################################
    # 'ExampleTask' interface.
    ###########################################################################

    def open(self):
        """ Shows a dialog to open a file.
        """
        dialog = FileDialog(parent=self.window.control, wildcard='*.py')
        if dialog.open() == OK:
            self._open_file(dialog.path)

    def save(self):
        """ Attempts to save the current file, prompting for a path if
            necessary. Returns whether the file was saved.
        """
        editor = self.window.central_pane.editor
        try:
            editor.save()
        except IOError:
            # If you are trying to save to a file that doesn't exist, open up a
            # FileDialog with a 'save as' action.
            dialog = FileDialog(
                parent=self.window.control, action='save as', wildcard='*.py')
            if dialog.open() == OK:
                editor.save(dialog.path)
            else:
                return False
        return True

    ###########################################################################
    # Protected interface.
    ###########################################################################

    def _open_file(self, filename):
        """ Opens the file at the specified path in the editor.
        """
        if self._prompt_for_save():
            self.window.central_pane.editor.path = filename
            self.activated()

    def _prompt_for_save(self):
        """ Prompts the user to save if necessary. Returns whether the dialog
            was cancelled.
        """
        if self.window.central_pane.editor.dirty:
            message = 'The current file has unsaved changes. ' \
                      'Do you want to save your changes?'
            dialog = ConfirmationDialog(
                parent=self.window.control,
                message=message,
                cancel=True,
                default=CANCEL,
                title='Save Changes?')
            result = dialog.open()
            if result == CANCEL:
                return False
            elif result == YES:
                if not self.save():
                    return self._prompt_for_save()
        return True

    @on_trait_change('window:closing')
    def _prompt_on_close(self, event):
        """ Prompt the user to save when exiting.
        """
        if not self._prompt_for_save():
            event.veto = True
Esempio n. 22
0
class ExampleTask(Task):
    """ A simple task for editing Python code.
    """

    # Task interface -------------------------------------------------------

    id = "example.example_task"
    name = "Python Script Editor"

    # default_layout = TaskLayout(
    #    left=PaneItem('example.python_script_browser_pane'))

    menu_bar = SMenuBar(
        SMenu(
            TaskAction(name="Open...", method="open", accelerator="Ctrl+O"),
            TaskAction(name="Save", method="save", accelerator="Ctrl+S"),
            id="File",
            name="&File",
        ),
        SMenu(DockPaneToggleGroup(), id="View", name="&View"),
    )

    tool_bars = [
        SToolBar(
            TaskAction(
                method="open",
                tooltip="Open a file",
                image=ImageResource("document_open"),
            ),
            TaskAction(
                method="save",
                tooltip="Save the current file",
                image=ImageResource("document_save"),
            ),
        )
    ]

    # ------------------------------------------------------------------------
    # 'Task' interface.
    # ------------------------------------------------------------------------

    def _default_layout_default(self):
        return TaskLayout(left=PaneItem("example.python_script_browser_pane"))

    def activated(self):
        """ Overriden to set the window's title.
        """
        filename = self.window.central_pane.editor.path
        self.window.title = filename if filename else "Untitled"

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        return PythonEditorPane()

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        browser = PythonScriptBrowserPane()
        handler = lambda _: self._open_file(browser.selected_file)
        browser.observe(handler, "activated")
        return [browser]

    # ------------------------------------------------------------------------
    # 'ExampleTask' interface.
    # ------------------------------------------------------------------------

    def open(self):
        """ Shows a dialog to open a file.
        """
        dialog = FileDialog(parent=self.window.control, wildcard="*.py")
        if dialog.open() == OK:
            self._open_file(dialog.path)

    def save(self):
        """ Attempts to save the current file, prompting for a path if
            necessary. Returns whether the file was saved.
        """
        editor = self.window.central_pane.editor
        try:
            editor.save()
        except IOError:
            # If you are trying to save to a file that doesn't exist, open up a
            # FileDialog with a 'save as' action.
            dialog = FileDialog(parent=self.window.control,
                                action="save as",
                                wildcard="*.py")
            if dialog.open() == OK:
                editor.save(dialog.path)
            else:
                return False
        return True

    # ------------------------------------------------------------------------
    # Protected interface.
    # ------------------------------------------------------------------------

    def _open_file(self, filename):
        """ Opens the file at the specified path in the editor.
        """
        if self._prompt_for_save():
            self.window.central_pane.editor.path = filename
            self.activated()

    def _prompt_for_save(self):
        """ Prompts the user to save if necessary. Returns whether the dialog
            was cancelled.
        """
        if self.window.central_pane.editor.dirty:
            message = ("The current file has unsaved changes. "
                       "Do you want to save your changes?")
            dialog = ConfirmationDialog(
                parent=self.window.control,
                message=message,
                cancel=True,
                default=CANCEL,
                title="Save Changes?",
            )
            result = dialog.open()
            if result == CANCEL:
                return False
            elif result == YES:
                if not self.save():
                    return self._prompt_for_save()
        return True

    @observe("window:closing")
    def _prompt_on_close(self, event):
        """ Prompt the user to save when exiting.
        """
        window = event.new
        if not self._prompt_for_save():
            window.veto = True
Esempio n. 23
0
class FlowTask(Task):
    """
    classdocs
    """

    id = "edu.mit.synbio.cytoflow.flow_task"
    name = "Cytometry analysis"

    # the main workflow instance.
    model = Instance(Workflow)

    # the center pane
    plot_pane = Instance(FlowTaskPane)
    workflow_pane = Instance(WorkflowDockPane)
    view_pane = Instance(ViewDockPane)

    # plugin lists, to setup the interface
    op_plugins = List(IOperationPlugin)
    view_plugins = List(IViewPlugin)

    menu_bar = SMenuBar(
        SMenu(
            TaskAction(name='Open...', method='on_open', accelerator='Ctrl+O'),
            TaskAction(
                name='Save',
                #image='save',
                method='on_save',
                accelerator='Ctrl+S'),
            TaskAction(name='Save As...',
                       method='on_save_as',
                       accelerator='Ctrl+e'),
            TaskAction(name='Save Plot...',
                       method='on_export',
                       accelerator='Ctrl+x'),
            #                               TaskAction(name='Export Jupyter notebook...',
            #                                          method='on_notebook',
            #                                          accelerator='Ctrl+I'),
            #                               TaskAction(name='Preferences...',
            #                                          method='on_prefs',
            #                                          accelerator='Ctrl+P'),
            id='File',
            name='&File'),
        SMenu(id='View', name='&View'),
        SMenu(TaskAction(name='Report a problem....', method='on_problem'),
              TaskAction(name='About...', method='on_about'),
              id="Help",
              name="&Help"))

    tool_bars = [
        SToolBar(
            TaskAction(method='on_new',
                       name="New",
                       tooltip='New workflow',
                       image=ImageResource('new')),
            TaskAction(method='on_open',
                       name="Open",
                       tooltip='Open a file',
                       image=ImageResource('open')),
            TaskAction(method='on_save',
                       name="Save",
                       tooltip='Save the current file',
                       image=ImageResource('save')),
            TaskAction(method='on_export',
                       name="Save Plot",
                       tooltip='Save the current plot',
                       image=ImageResource('export')),
            #                            TaskAction(method='on_notebook',
            #                                       name='Notebook',
            #                                       tooltip="Export to an Jupyter notebook...",
            #                                       image=ImageResource('ipython')),
            #                            TaskAction(method='on_prefs',
            #                                       name = "Prefs",
            #                                       tooltip='Preferences',
            #                                       image=ImageResource('prefs')),
            image_size=(32, 32))
    ]

    # the file to save to if the user clicks "save" and has already clicked
    # "open" or "save as".
    filename = Unicode

    def prepare_destroy(self):
        self.model.shutdown_remote_process()

    def activated(self):
        # add the import op
        self.add_operation(ImportPlugin().id)
        self.model.selected = self.model.workflow[0]

        # if we're debugging, add a few data bits
        if self.model.debug:
            from cytoflow import Tube

            import_op = self.model.workflow[0].operation
            import_op.conditions = {"Dox": "float", "Well": "category"}
            #             import_op.conditions["Dox"] = "float"
            #             import_op.conditions["Well"] = "category"

            tube1 = Tube(file="../cytoflow/tests/data/Plate01/CFP_Well_A4.fcs",
                         conditions={
                             "Dox": 0.0,
                             "Well": 'A'
                         })

            tube2 = Tube(file="../cytoflow/tests/data/Plate01/RFP_Well_A3.fcs",
                         conditions={
                             "Dox": 10.0,
                             "Well": 'A'
                         })

            tube3 = Tube(file="../cytoflow/tests/data/Plate01/CFP_Well_B4.fcs",
                         conditions={
                             "Dox": 0.0,
                             "Well": 'B'
                         })

            tube4 = Tube(file="../cytoflow/tests/data/Plate01/RFP_Well_A6.fcs",
                         conditions={
                             "Dox": 10.0,
                             "Well": 'B'
                         })

            import_op.tubes = [tube1, tube2, tube3, tube4]

#             self.add_operation(ChannelStatisticPlugin().id)
#             stat_op = self.model.workflow[1].operation
#             stat_op.name = "Test"
#             stat_op.channel = "Y2-A"
#             stat_op.statistic_name = "Geom.Mean"
#             stat_op.by = ["Dox", "Well"]
#             self.model.selected = self.model.workflow[1]

        self.model.modified = False

    def _default_layout_default(self):
        return TaskLayout(left=PaneItem("edu.mit.synbio.workflow_pane"),
                          right=PaneItem("edu.mit.synbio.view_traits_pane"))

    def create_central_pane(self):
        self.plot_pane = FlowTaskPane(model=self.model)
        return self.plot_pane

    def create_dock_panes(self):
        self.workflow_pane = WorkflowDockPane(model=self.model,
                                              plugins=self.op_plugins,
                                              task=self)

        self.view_pane = ViewDockPane(model=self.model,
                                      plugins=self.view_plugins,
                                      task=self)

        return [self.workflow_pane, self.view_pane]

    def on_new(self):
        if self.model.modified:
            ret = confirm(
                parent=None,
                message=
                "Are you sure you want to discard the current workflow?",
                title="Clear workflow?")

            if ret != YES:
                return

        self.filename = ""
        self.window.title = "Cytoflow"

        # clear the workflow
        self.model.workflow = []

        # add the import op
        self.add_operation(ImportPlugin().id)

        # and select the operation
        self.model.selected = self.model.workflow[0]

        self.model.modified = False

    def on_open(self):
        """ 
        Shows a dialog to open a file.
        """

        if self.model.modified:
            ret = confirm(
                parent=None,
                message=
                "Are you sure you want to discard the current workflow?",
                title="Clear workflow?")

            if ret != YES:
                return

        dialog = FileDialog(
            parent=self.window.control,
            action='open',
            wildcard=(
                FileDialog.create_wildcard("Cytoflow workflow", "*.flow") +
                ';' +  #@UndefinedVariable  
                FileDialog.create_wildcard("All files",
                                           "*")))  #@UndefinedVariable
        if dialog.open() == OK:
            self.open_file(dialog.path)
            self.filename = dialog.path
            self.window.title = "Cytoflow - " + self.filename

    def open_file(self, path):
        f = open(path, 'r')
        unpickler = pickle.Unpickler(f)

        try:
            version = unpickler.load()
        except TraitError:
            error(parent=None,
                  message="This doesn't look like a Cytoflow file. Or maybe "
                  "you tried to load a workflow older than version "
                  "0.5?")
            return

        if version != self.model.version:
            ret = confirm(
                parent=None,
                message="This is Cytoflow {}, but you're trying "
                "to load a workflow from version {}. This may or "
                "may not work!  Are you sure you want to proceed?".format(
                    self.model.version, version),
                title="Load workflow?")
            if ret != YES:
                return

        try:
            new_workflow = unpickler.load()
        except TraitError as e:
            error(parent=None, message="Error trying to load the workflow.")
            return

        # a few things to take care of when reloading
        for wi_idx, wi in enumerate(new_workflow):

            # get wi lock
            wi.lock.acquire()

            # clear the wi status
            wi.status = "loading"

            # re-link the linked list.  i thought this would get taken care
            # of in deserialization, but i guess not...
            if wi_idx > 0:
                wi.previous_wi = new_workflow[wi_idx - 1]

        # replace the current workflow with the one we just loaded

        if False:  # for debugging the loading of things
            from .event_tracer import record_events

            with record_events() as container:
                self.model.workflow = new_workflow

            container.save_to_directory(os.getcwd())
        else:
            self.model.workflow = new_workflow
            self.model.modified = False

        for wi in self.model.workflow:
            wi.lock.release()

    def on_save(self):
        """ Save the file to the previous filename  """
        if self.filename:
            self.save_file(self.filename)
        else:
            self.on_save_as()

    def on_save_as(self):
        dialog = DefaultFileDialog(
            parent=self.window.control,
            action='save as',
            default_suffix="flow",
            wildcard=(
                FileDialog.create_wildcard("Cytoflow workflow", "*.flow") +
                ';' +  #@UndefinedVariable  
                FileDialog.create_wildcard("All files",
                                           "*")))  #@UndefinedVariable

        if dialog.open() == OK:
            self.save_file(dialog.path)
            self.filename = dialog.path
            self.window.title = "Cytoflow - " + self.filename
        pass

    def save_file(self, path):
        # TODO - error handling
        f = open(path, 'w')
        pickler = pickle.Pickler(f, 0)  # text protocol for now
        pickler.dump(self.model.version)
        pickler.dump(self.model.workflow)
        self.model.modified = False

    @on_trait_change('model.modified', post_init=True)
    def _on_model_modified(self, val):
        if val:
            if not self.window.title.endswith("*"):
                self.window.title += "*"
        else:
            if self.window.title.endswith("*"):
                self.window.title = self.window.title[:-1]

    def on_export(self):
        """
        Shows a dialog to export a file
        """

        information(
            None, "This will save exactly what you see on the screen "
            "to a file.", "Export")

        f = ""
        filetypes_groups = self.plot_pane.canvas.get_supported_filetypes_grouped(
        )
        filename_exts = []
        for name, ext in filetypes_groups.items():
            if f:
                f += ";"
            f += FileDialog.create_wildcard(name,
                                            " ".join(["*." + e for e in ext
                                                      ]))  #@UndefinedVariable
            filename_exts.append(ext)

        dialog = FileDialog(parent=self.window.control,
                            action='save as',
                            wildcard=f)

        if dialog.open() == OK:
            filetypes = list(
                self.plot_pane.canvas.get_supported_filetypes().keys())
            if not [
                    ext for ext in ["." + ext for ext in filetypes]
                    if dialog.path.endswith(ext)
            ]:
                selected_exts = filename_exts[dialog.wildcard_index]
                ext = sorted(selected_exts, key=len)[0]
                dialog.path += "."
                dialog.path += ext

            self.plot_pane.export(dialog.path)

    def on_notebook(self):
        """
        Shows a dialog to export the workflow to an Jupyter notebook
        """

        return

        dialog = FileDialog(parent=self.window.control,
                            action='save as',
                            wildcard='*.ipynb')
        if dialog.open() == OK:
            writer = JupyterNotebookWriter(file=dialog.path)
            writer.export(self.model.workflow)

    def on_prefs(self):
        pass

    def on_problem(self):

        information(
            None, "Your email client will now create a new message to the "
            "developer.  Debugging logs are attached.  Please fill "
            "out the template bug report and send -- thank you for "
            "reporting a bug!")

        log = self.application.application_log.getvalue()

        versions = [
            "{0} {1}".format(key, value)
            for key, value in self._get_package_versions().items()
        ]

        body = """
Thank you for your bug report!  Please fill out the following template.

PLATFORM (Mac, PC, Linux, other):

OPERATING SYSTEM (eg OSX 10.7, Windows 8.1):

SEVERITY (Critical? Major? Minor? Enhancement?):

DESCRIPTION:
  - What were you trying to do?
  - What happened?
  - What did you expect to happen?
  

PACKAGE VERSIONS: {0}

DEBUG LOG: {1}
""".format(versions, log)


#         mailto.mailto("*****@*****.**",
#                       subject = "Cytoflow bug report",
#                       body = body)

    def _get_package_versions(self):

        import sys
        from cytoflow import __version__ as cf_version
        from fcsparser import __version__ as fcs_version
        from pandas import __version__ as pd_version
        from numpy import __version__ as np_version
        from numexpr import __version__ as nxp_version
        from bottleneck import __version__ as btl_version
        from seaborn import __version__ as sns_version
        from matplotlib import __version__ as mpl_version
        from scipy import __version__ as scipy_version
        from sklearn import __version__ as skl_version
        from pyface import __version__ as pyf_version
        from envisage import __version__ as env_version
        from traits import __version__ as trt_version
        from traitsui import __version__ as trt_ui_version

        return {
            "python": sys.version,
            "cytoflow": cf_version,
            "fcsparser": fcs_version,
            "pandas": pd_version,
            "numpy": np_version,
            "numexpr": nxp_version,
            "bottleneck": btl_version,
            "seaborn": sns_version,
            "matplotlib": mpl_version,
            "scipy": scipy_version,
            "scikit-learn": skl_version,
            "pyface": pyf_version,
            "envisage": env_version,
            "traits": trt_version,
            "traitsui": trt_ui_version
        }

    def on_about(self):
        versions = self._get_package_versions()
        text = ["<b>Cytoflow {0}</b>".format(versions['cytoflow']), "<p>"]

        ver_text = [
            "{0} {1}".format(key, value) for key, value in versions.items()
        ]

        text.extend(ver_text)

        text.extend([
            "Icons from the <a href=http://tango.freedesktop.org>Tango Desktop Project</a>",
            "<a href=https://thenounproject.com/search/?q=setup&i=14287>Settings icon</a> by Paulo Sa Ferreira from <a href=https://thenounproject.com>The Noun Project</a>",
            "<a href=http://www.freepik.com/free-photos-vectors/background>App icon from Starline - Freepik.com</a>",
            "Cuvette image from Wikimedia Commons user <a href=http://commons.wikimedia.org/wiki/File:Hellma_Large_cone_cytometry_cell.JPG>HellmaUSA</a>"
        ])

        dialog = AboutDialog(text=text,
                             parent=self.window.control,
                             title="About",
                             image=ImageResource('cuvette'),
                             additions=text)
        dialog.open()

    @on_trait_change('model.selected', post_init=True)
    def _on_select_op(self, selected):
        if selected:
            self.view_pane.enabled = (selected is not None)
            self.view_pane.default_view = selected.default_view.id if selected.default_view else ""
            self.view_pane.selected_view = selected.current_view.id if selected.current_view else ""
        else:
            self.view_pane.enabled = False

    @on_trait_change('view_pane.selected_view', post_init=True)
    def _on_select_view(self, view_id):

        if not view_id:
            return

        # if we already have an instantiated view object, find it
        try:
            self.model.selected.current_view = next(
                (x for x in self.model.selected.views if x.id == view_id))
        except StopIteration:
            # else make the new view
            plugin = next(
                (x for x in self.view_plugins if x.view_id == view_id))
            view = plugin.get_view()
            self.model.selected.views.append(view)
            self.model.selected.current_view = view

    def add_operation(self, op_id):
        # first, find the matching plugin
        plugin = next((x for x in self.op_plugins if x.id == op_id))

        # next, get an operation
        op = plugin.get_operation()

        # make a new workflow item
        wi = WorkflowItem(
            operation=op,
            deletable=(op_id !=
                       'edu.mit.synbio.cytoflowgui.op_plugins.import'))

        # if the op has a default view, add it to the wi
        try:
            wi.default_view = op.default_view()
            wi.views.append(wi.default_view)
            wi.current_view = wi.default_view
        except AttributeError:
            pass

        # figure out where to add it
        if self.model.selected:
            idx = self.model.workflow.index(self.model.selected) + 1
        else:
            idx = len(self.model.workflow)

        # the add_remove_items handler takes care of updating the linked list
        self.model.workflow.insert(idx, wi)

        # and make sure to actually select the new wi
        self.model.selected = wi
Esempio n. 24
0
class ExampleTask(Task):
    """ A simple task for editing Python code.
    """

    # Task interface -------------------------------------------------------

    id = "example.example_task"
    name = "Multi-Tab Editor"

    active_editor = Property(Instance(IEditor),
                             observe="editor_area.active_editor")

    editor_area = Instance(IEditorAreaPane)

    menu_bar = SMenuBar(
        SMenu(
            TaskAction(name="New", method="new", accelerator="Ctrl+N"),
            TaskAction(name="Open...", method="open", accelerator="Ctrl+O"),
            TaskAction(name="Save", method="save", accelerator="Ctrl+S"),
            id="File",
            name="&File",
        ),
        SMenu(DockPaneToggleGroup(), id="View", name="&View"),
    )

    tool_bars = [
        SToolBar(
            TaskAction(
                method="new",
                tooltip="New file",
                image=ImageResource("document_new"),
            ),
            TaskAction(
                method="open",
                tooltip="Open a file",
                image=ImageResource("document_open"),
            ),
            TaskAction(
                method="save",
                tooltip="Save the current file",
                image=ImageResource("document_save"),
            ),
            image_size=(32, 32),
            show_tool_names=False,
        )
    ]

    # ------------------------------------------------------------------------
    # 'Task' interface.
    # ------------------------------------------------------------------------

    def _default_layout_default(self):
        return TaskLayout(left=PaneItem("example.python_script_browser_pane"))

    def activated(self):
        """ Overriden to set the window's title.
        """
        return
        filename = self.active_editor.path if self.active_editor else ""
        self.window.title = filename if filename else "Untitled"

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        self.editor_area = EditorAreaPane()
        return self.editor_area

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        browser = PythonScriptBrowserPane()
        handler = lambda _: self._open_file(browser.selected_file)
        browser.observe(handler, "activated")
        return [browser]

    # ------------------------------------------------------------------------
    # 'ExampleTask' interface.
    # ------------------------------------------------------------------------

    def new(self):
        """ Opens a new empty window
        """
        editor = PythonEditor()
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    def open(self):
        """ Shows a dialog to open a file.
        """
        dialog = FileDialog(parent=self.window.control, wildcard="*.py")
        if dialog.open() == OK:
            self._open_file(dialog.path)

    def save(self):
        """ Attempts to save the current file, prompting for a path if
            necessary. Returns whether the file was saved.
        """
        editor = self.active_editor
        try:
            editor.save()
        except IOError:
            # If you are trying to save to a file that doesn't exist, open up a
            # FileDialog with a 'save as' action.
            dialog = FileDialog(parent=self.window.control,
                                action="save as",
                                wildcard="*.py")
            if dialog.open() == OK:
                editor.save(dialog.path)
            else:
                return False
        return True

    # ------------------------------------------------------------------------
    # Protected interface.
    # ------------------------------------------------------------------------

    def _open_file(self, filename):
        """ Opens the file at the specified path in the editor.
        """
        editor = PythonEditor(path=filename)
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    def _prompt_for_save(self):
        """ Prompts the user to save if necessary. Returns whether the dialog
            was cancelled.
        """
        dirty_editors = dict([(editor.name, editor)
                              for editor in self.editor_area.editors
                              if editor.dirty])
        if not dirty_editors.keys():
            return True
        message = "You have unsaved files. Would you like to save them?"
        dialog = ConfirmationDialog(
            parent=self.window.control,
            message=message,
            cancel=True,
            default=CANCEL,
            title="Save Changes?",
        )
        result = dialog.open()
        if result == CANCEL:
            return False
        elif result == YES:
            for name, editor in dirty_editors.items():
                editor.save(editor.path)
        return True

    # Trait change handlers ------------------------------------------------

    @observe("window:closing")
    def _prompt_on_close(self, event):
        """ Prompt the user to save when exiting.
        """
        close = self._prompt_for_save()
        window = event.new
        window.veto = not close

    # Trait property getter/setters ----------------------------------------

    def _get_active_editor(self):
        if self.editor_area is not None:
            return self.editor_area.active_editor
        return None
Esempio n. 25
0
class FlowTask(Task):
    """
    classdocs
    """

    id = "edu.mit.synbio.cytoflow.flow_task"
    name = "Cytometry analysis"

    # the main workflow instance.
    # THIS IS WHERE IT'S INITIALLY INSTANTIATED (note the args=())
    model = Instance(Workflow, args=())

    # the center pane
    view = Instance(FlowTaskPane)

    # plugin lists, to setup the interface
    op_plugins = List(IOperationPlugin)
    view_plugins = List(IViewPlugin)

    menu_bar = SMenuBar(
        SMenu(
            TaskAction(name='Open...', method='on_open', accelerator='Ctrl+O'),
            TaskAction(
                name='Save',
                #image='save',
                method='on_save',
                accelerator='Ctrl+S'),
            TaskAction(name='Save As...',
                       method='on_save_as',
                       accelerator='Ctrl+e'),
            TaskAction(name='Export image...',
                       method='on_export',
                       accelerator='Ctrl+x'),
            TaskAction(name='Export IPython notebook...',
                       method='on_ipython',
                       accelerator='Ctrl+I'),
            TaskAction(name='Preferences...',
                       method='on_prefs',
                       accelerator='Ctrl+P'),
            id='File',
            name='&File'),
        SMenu(TaskAction(name='About...',
                         method='on_about',
                         accelerator="Ctrl+A"),
              id="Help",
              name="&Help"))

    tool_bars = [
        SToolBar(TaskAction(method='on_new',
                            name="New",
                            tooltip='New workflow',
                            image=ImageResource('new')),
                 TaskAction(method='on_open',
                            name="Open",
                            tooltip='Open a file',
                            image=ImageResource('open')),
                 TaskAction(method='on_save',
                            name="Save",
                            tooltip='Save the current file',
                            image=ImageResource('save')),
                 TaskAction(method='on_export',
                            name="Export",
                            tooltip='Export the current plot',
                            image=ImageResource('export')),
                 TaskAction(method='on_ipython',
                            name='IPython',
                            tooltip="Export to an IPython notebook...",
                            image=ImageResource('ipython')),
                 TaskAction(method='on_prefs',
                            name="Prefs",
                            tooltip='Preferences',
                            image=ImageResource('prefs')),
                 image_size=(32, 32))
    ]

    # are we debugging?  ie, do we need a default setup?
    debug = Bool

    worker = Instance(threading.Thread)
    to_update = Instance(UniquePriorityQueue, ())
    worker_flag = Instance(threading.Event, args=())
    worker_lock = Instance(threading.Lock, args=())

    def initialized(self):

        # make sure that when the result changes we get notified
        # can't use a static notifier because selected.result gets updated
        # on the worker thread, but we need to dispatch on the UI thread
        self.model.on_trait_change(self._result_updated,
                                   "selected:result",
                                   dispatch='ui')

    def activated(self):
        # add an import plugin
        plugin = ImportPlugin()
        wi = WorkflowItem(task=self)
        wi.operation = plugin.get_operation()

        self.model.workflow.append(wi)
        self.model.selected = wi

        # if we're debugging, add a few data bits
        if self.debug:
            from cytoflow import Tube

            wi.operation.conditions["Dox"] = "log"

            tube1 = Tube(file="../cytoflow/tests/data/Plate01/CFP_Well_A4.fcs",
                         conditions={"Dox": 0.1})

            tube2 = Tube(file="../cytoflow/tests/data/Plate01/RFP_Well_A3.fcs",
                         conditions={"Dox": 1.0})

            wi.operation.tubes.append(tube1)
            wi.operation.tubes.append(tube2)

            self.add_operation(
                'edu.mit.synbio.cytoflowgui.op_plugins.threshold')
            self.model.selected.operation.channel = "Y2-A"
            self.model.selected.operation.threshold = 2000
            self.model.selected.operation.name = "T"

    def prepare_destroy(self):
        self.model = None

    def _default_layout_default(self):
        return TaskLayout(left=PaneItem("edu.mit.synbio.workflow_pane"),
                          right=PaneItem("edu.mit.synbio.view_traits_pane"))

    def create_central_pane(self):
        self.view = FlowTaskPane(model=self.model)
        return self.view

    def create_dock_panes(self):
        return [
            WorkflowDockPane(model=self.model,
                             plugins=self.op_plugins,
                             task=self),
            ViewDockPane(model=self.model,
                         plugins=self.view_plugins,
                         task=self)
        ]

    def on_new(self):
        self.model.workflow = []

        # add an import plugin
        plugin = ImportPlugin()
        wi = WorkflowItem(task=self)
        wi.operation = plugin.get_operation()

        self.model.workflow.append(wi)
        self.model.selected = wi

    def on_open(self):
        """ Shows a dialog to open a file.
        """
        dialog = FileDialog(parent=self.window.control,
                            action='open',
                            wildcard='*.flow')
        if dialog.open() == OK:
            self.open_file(dialog.path)

    def open_file(self, path):
        f = open(path, 'r')
        unpickler = pickle.Unpickler(f)
        new_model = unpickler.load()

        # update the link back to the controller (ie, self)
        for wi in new_model.workflow:
            wi.task = self

            # and set up the view handlers
            for view in wi.views:
                view.handler = view.handler_factory(model=view, wi=wi)

        # replace the current workflow with the one we just loaded

        if False:
            from event_tracer import record_events

            with record_events() as container:
                self.model.workflow[:] = new_model.workflow
                self.model.selected = new_model.selected

            container.save_to_directory(os.getcwd())
        else:
            self.model.workflow[:] = new_model.workflow
            self.model.selected = new_model.selected

        wi = self.model.workflow[0]
        while True:
            wi.status = "invalid"
            with self.worker_lock:
                self.to_update.put_nowait((self.model.workflow.index(wi), wi))
            if wi.next:
                wi = wi.next
            else:
                break

        # check to see if we have a worker thread around
        if not self.worker or not self.worker.is_alive():
            self.worker = threading.Thread(target=update_model,
                                           args=(self.worker_flag,
                                                 self.worker_lock,
                                                 self.to_update))
            self.worker.daemon = True
            self.worker.start()

        # start the worker thread processing
        with self.worker_lock:
            if not self.to_update.empty():
                self.worker_flag.set()

    def on_save(self):
        """ Shows a dialog to open a file.
        """
        dialog = FileDialog(parent=self.window.control,
                            action='save as',
                            wildcard='*.flow')
        if dialog.open() == OK:
            self.save_file(dialog.path)

    def on_save_as(self):
        pass

    def save_file(self, path):
        # TODO - error handling
        f = open(path, 'w')
        pickler = pickle.Pickler(f, 0)  # text protocol for now
        pickler.dump(self.model)

    def on_export(self):
        """
        Shows a dialog to export a file
        """
        dialog = FileDialog(parent=self.window.control, action='save as')
        if dialog.open() == OK:
            self.view.export(dialog.path)

    def on_ipython(self):
        """
        Shows a dialog to export the workflow to an IPython notebook
        """

        dialog = FileDialog(parent=self.window.control,
                            action='save as',
                            wildcard='*.ipynb')
        if dialog.open() == OK:
            writer = IPythonNotebookWriter(file=dialog.path)
            writer.export(self.workflow)

    def on_prefs(self):
        pass

    def on_about(self):
        from cytoflow import __version__ as cf_version
        from fcsparser import __version__ as fcs_version
        from pandas.version import __version__ as pd_version
        from numpy.version import version as np_version
        from numexpr import __version__ as numexp_version
        from seaborn import __version__ as sns_version
        from matplotlib import __version__ as mpl_version
        from pyface import __version__ as py_version
        from envisage import __version__ as env_version
        from traits import __version__ as trt_version
        from traitsui import __version__ as trt_ui_version

        text = [
            "<b>Cytoflow {0}</b>".format(cf_version), "<p>",
            "fcsversion {0}".format(fcs_version),
            "pandas {0}".format(pd_version), "numpy {0}".format(np_version),
            "numexpr {0}".format(numexp_version),
            "seaborn {0}".format(sns_version),
            "matplotlib {0}".format(mpl_version),
            "pyface {0}".format(py_version),
            "envisage {0}".format(env_version),
            "traits {0}".format(trt_version),
            "traitsui {0}".format(trt_ui_version),
            "Icons from the <a href=http://tango.freedesktop.org>Tango Desktop Project</a>",
            "<a href=https://thenounproject.com/search/?q=setup&i=14287>Settings icon</a> by Paulo Sa Ferreira from <a href=https://thenounproject.com>The Noun Project</a>",
            "Cuvette image from Wikimedia Commons user <a href=http://commons.wikimedia.org/wiki/File:Hellma_Large_cone_cytometry_cell.JPG>HellmaUSA</a>"
        ]
        dialog = AboutDialog(parent=self.window.control,
                             title="About",
                             image=ImageResource('cuvette'),
                             additions=text)
        dialog.open()

    def add_operation(self, op_id):
        # first, find the matching plugin
        plugin = next((x for x in self.op_plugins if x.id == op_id))

        # default to inserting at the end of the list if none selected
        after = self.model.selected
        if after is None:
            after = self.model.workflow[-1]

        idx = self.model.workflow.index(after)

        wi = WorkflowItem(task=self)
        wi.operation = plugin.get_operation()

        wi.next = after.next
        after.next = wi
        wi.previous = after
        if wi.next:
            wi.next.previous = wi
        self.model.workflow.insert(idx + 1, wi)

        # set up the default view
        wi.default_view = plugin.get_default_view()
        if wi.default_view is not None:
            wi.default_view.op = wi.operation
            wi.default_view.handler = \
                wi.default_view.handler_factory(model = wi.default_view, wi = wi.previous)
            wi.views.append(wi.default_view)

        # select (open) the new workflow item
        self.model.selected = wi
        if wi.default_view:
            wi.current_view = wi.default_view

        # invalidate everything following
        self.operation_parameters_updated()

    @on_trait_change("model:workflow[]")
    def _on_remove_operation(self, obj, name, old, new):
        if name == "workflow_items" and len(new) == 0 and len(old) > 0:
            assert len(old) == 1
            wi = old[0]

            if self.model.selected == wi:
                self.model.selected = wi.previous

            wi.previous.next = wi.next
            if wi.next:
                wi.next.previous = wi.previous

            del wi.default_view
            del wi.views
            del wi

            self.operation_parameters_updated()

    @on_trait_change("model:selected:operation:+")
    def operation_parameters_updated(self):

        # invalidate this workflow item and all the ones following it
        wi = self.model.selected
        while True:
            wi.status = "invalid"
            with self.worker_lock:
                self.to_update.put_nowait((self.model.workflow.index(wi), wi))
            if wi.next:
                wi = wi.next
            else:
                break

        # check to see if we have a worker thread around
        if not self.worker or not self.worker.is_alive():
            self.worker = threading.Thread(target=update_model,
                                           args=(self.worker_flag,
                                                 self.worker_lock,
                                                 self.to_update))
            self.worker.daemon = True
            self.worker.start()

        # start the worker thread processing
        with self.worker_lock:
            if not self.to_update.empty():
                self.worker_flag.set()

    def set_current_view(self, view_id):
        """
        called by the view pane 
        """
        wi = self.model.selected

        if view_id == "default":
            view_id = self.model.selected.default_view.id

        view = next((x for x in wi.views if x.id == view_id), None)

        if not view:
            plugin = next(
                (x for x in self.view_plugins if x.view_id == view_id))
            view = plugin.get_view()
            view.handler = view.handler_factory(model=view, wi=wi)
            wi.views.append(view)

        wi.current_view = view

    @on_trait_change("model:selected.current_view")
    def _current_view_changed(self, obj, name, old, new):

        # we get notified if *either* the currently selected workflowitem
        # *or* the current view changes.

        if name == 'selected':
            new = new.current_view if new else None
            old = old.current_view if old else None

        # remove the notifications from the old view
        if old:
            old.on_trait_change(self.view_parameters_updated, remove=True)

            # and if the old view was interactive, turn off its interactivity
            # to remove the matplotlib event handlers
            if "interactive" in old.traits():
                old.interactive = False

        # whenever the view parameters change, we need to know so we can
        # update the plot(s)
        if new:
            new.on_trait_change(self.view_parameters_updated)

            if self.model.selected:
                self.view.plot(self.model.selected)
            else:
                self.view.clear_plot()
        else:
            self.view.clear_plot()

    def _result_updated(self, obj, name, old, new):
        print "result updated"
        if self.model.selected:
            self.view.plot(self.model.selected)
        else:
            self.view.clear_plot()

    def view_parameters_updated(self, obj, name, new):

        # i should be able to specify the metadata i want in the listener,
        # but there's an odd interaction (bug) between metadata, dynamic
        # trait listeners and instance traits.  so, check for 'transient'
        # here instead,

        if obj.trait(name).transient:
            return

        print "view parameters updated: {0}".format(name)
        wi = self.model.selected
        if wi is None:
            wi = self.model.workflow[-1]

        self.view.plot(wi)
Esempio n. 26
0
class SkeletonTask(Task):
    """ A simple task for opening a blank editor.
    """

    #### Task interface #######################################################

    id = 'omnivore.framework.text_edit_task'
    name = 'Skeleton'

    active_editor = Property(Instance(IEditor),
                             depends_on='editor_area.active_editor')

    editor_area = Instance(IEditorAreaPane)

    menu_bar = SMenuBar(
        SMenu(TaskAction(name='New', method='new', accelerator='Ctrl+N'),
              id='File',
              name='&File'),
        SMenu(id='Edit', name='&Edit'),
        SMenu(  #DockPaneToggleGroup(),
            TaskToggleGroup(),
            id='View',
            name='&View'))

    tool_bars = [
        SToolBar(TaskAction(method='new',
                            tooltip='New file',
                            image=ImageResource('document_new')),
                 image_size=(32, 32)),
    ]

    ###########################################################################
    # 'Task' interface.
    ###########################################################################

    def _default_layout_default(self):
        return TaskLayout(left=VSplitter(
            PaneItem('text_edit.pane1'),
            HSplitter(
                PaneItem('text_edit.pane2'),
                PaneItem('text_edit.pane3'),
            ),
        ))

    def create_central_pane(self):
        """ Create the central pane: the text editor.
        """
        self.editor_area = EditorAreaPane()
        return self.editor_area

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        return [SkeletonPane1(), SkeletonPane2(), SkeletonPane3()]

    ###########################################################################
    # 'ExampleTask' interface.
    ###########################################################################

    def new(self):
        """ Opens a new empty window
        """
        editor = Editor()
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    #### Trait property getter/setters ########################################

    def _get_active_editor(self):
        if self.editor_area is not None:
            return self.editor_area.active_editor
        return None
Esempio n. 27
0
class FlowTask(Task):
    """
    classdocs
    """
    
    id = "edu.mit.synbio.cytoflowgui.flow_task"
    name = "Cytometry analysis"
    
    # the main workflow instance.
    model = Instance(Workflow)
        
    # the center pane
    workflow_pane = Instance(WorkflowDockPane)
    view_pane = Instance(ViewDockPane)
    help_pane = Instance(HelpDockPane)
    plot_params_pane = Instance(PlotParamsPane)
    
    # plugin lists, to setup the interface
    op_plugins = List(IOperationPlugin)
    view_plugins = List(IViewPlugin)
    
    menu_bar = SMenuBar(SMenu(TaskAction(name='Open...',
                                         method='on_open',
                                         accelerator='Ctrl+O'),
                              TaskAction(name='Save',
                                         #image='save', 
                                         method='on_save',
                                         accelerator='Ctrl+S'),
                              TaskAction(name='Save As...',
                                         method='on_save_as',
                                         accelerator='Ctrl+e'),
                              TaskAction(name='Save Plot...',
                                         method='on_export',
                                         accelerator='Ctrl+x'),
                              TaskAction(name='Export Jupyter notebook...',
                                         method='on_notebook',
                                         accelerator='Ctrl+I'),                              
#                               TaskAction(name='Preferences...',
#                                          method='on_prefs',
#                                          accelerator='Ctrl+P'),
                              id='File', name='&File'),
                        SMenu(TaskToggleGroup(),
#                               TaskWindowToggleGroup(),
                              id = 'View', name = '&View'),
                        SMenu(TaskAction(name = 'Report a problem....',
                                         method = 'on_problem'),
                              TaskAction(name='About...',
                                         method='on_about'),
                              id="Help", name ="&Help"))
    
    tool_bars = [ SToolBar(TaskAction(method='on_new',
                                      name = "New",
                                      tooltip='New workflow',
                                      image=ImageResource('new')),
                           TaskAction(method='on_open',
                                      name = "Open",
                                      tooltip='Open a file',
                                      image=ImageResource('open')),
                           TaskAction(method='on_save',
                                      name = "Save",
                                      tooltip='Save the current file',
                                      image=ImageResource('save')),
                           TaskAction(method='on_export',
                                      name = "Save Plot",
                                      tooltip='Save the current plot',
                                      image=ImageResource('export')),
                           TaskAction(method='on_notebook',
                                       name='Notebook',
                                       tooltip="Export to an Jupyter notebook...",
                                       image=ImageResource('ipython')),
                           TaskAction(method = "on_calibrate",
                                      name = "Calibrate FCS...",
                                      tooltip = "Calibrate FCS files",
                                      image = ImageResource('tasbe')),
                           TaskAction(method = 'on_problem',
                                      name = "Report a bug...",
                                      tooltib = "Report a bug",
                                      image = ImageResource('bug')),
#                            TaskAction(method='on_prefs',
#                                       name = "Prefs",
#                                       tooltip='Preferences',
#                                       image=ImageResource('prefs')),
                           image_size = (32, 32))]
    
    # the file to save to if the user clicks "save" and has already clicked
    # "open" or "save as".
    filename = Unicode
        
    def activated(self):
        
        # if we're coming back from the TASBE task, re-load the saved
        # workflow
        if self.model.backup_workflow:
            self.model.workflow = self.model.backup_workflow
            self.model.backup_workflow = []
            return
        
        # else, set up a new workflow
        
        # add the import op
        if not self.model.workflow:
            self.add_operation(ImportPlugin().id) 
            self.model.selected = self.model.workflow[0]
        
        # if we're debugging, add a few data bits
        if self.model.debug:
            from cytoflow import Tube
                        
            import_op = self.model.workflow[0].operation
            import_op.conditions = {"Dox" : "float", "Well" : "category"}
         
            tube1 = Tube(file = "../cytoflow/tests/data/Plate01/CFP_Well_A4.fcs",
                         conditions = {"Dox" : 0.0, "Well" : 'A'})
         
            tube2 = Tube(file = "../cytoflow/tests/data/Plate01/RFP_Well_A3.fcs",
                         conditions = {"Dox" : 10.0, "Well" : 'A'})
             
            tube3 = Tube(file = "../cytoflow/tests/data/Plate01/CFP_Well_B4.fcs",
                         conditions = {"Dox" : 0.0, "Well" : 'B'})
         
            tube4 = Tube(file = "../cytoflow/tests/data/Plate01/RFP_Well_A6.fcs",
                         conditions = {"Dox" : 10.0, "Well" : 'B'})
         
            import_op.tubes = [tube1, tube2, tube3, tube4]
            
#             from cytoflowgui.op_plugins import ChannelStatisticPlugin

#             self.add_operation(ChannelStatisticPlugin().id)
#             stat_op = self.model.workflow[1].operation
#             stat_op.name = "Test"
#             stat_op.channel = "Y2-A"
#             stat_op.statistic_name = "Geom.Mean"
#             stat_op.by = ["Dox", "Well"]
#             self.model.selected = self.model.workflow[1]
                    
        self.model.modified = False
    
    def _default_layout_default(self):
        return TaskLayout(left = VSplitter(PaneItem("edu.mit.synbio.cytoflowgui.workflow_pane"),
                                           PaneItem("edu.mit.synbio.cytoflowgui.help_pane")),
                          right = VSplitter(PaneItem("edu.mit.synbio.cytoflowgui.view_traits_pane"),
                                            PaneItem("edu.mit.synbio.cytoflowgui.params_pane")),
                          top_left_corner = 'left',
                          bottom_left_corner = 'left',
                          top_right_corner = 'right',
                          bottom_right_corner = 'right')
     
    def create_central_pane(self):       
        return self.application.plot_pane
     
    def create_dock_panes(self):
        self.workflow_pane = WorkflowDockPane(model = self.model, 
                                              plugins = self.op_plugins,
                                              task = self)
        
        self.view_pane = ViewDockPane(model = self.model,
                                      plugins = self.view_plugins,
                                      task = self)
        
        self.help_pane = HelpDockPane(view_plugins = self.view_plugins,
                                      op_plugins = self.op_plugins,
                                      task = self)
        
        self.plot_params_pane = PlotParamsPane(model = self.model,
                                               task = self)
        
        return [self.workflow_pane, self.view_pane, self.help_pane, self.plot_params_pane]
        
    def on_new(self):
        if self.model.modified:
            ret = confirm(parent = None,
                          message = "Are you sure you want to discard the current workflow?",
                          title = "Clear workflow?")
            
            if ret != YES:
                return
            
        self.filename = ""
        self.window.title = "Cytoflow"
        
        # clear the workflow
        self.model.workflow = []
        
        # add the import op
        self.add_operation(ImportPlugin().id) 
        
        # and select the operation
        self.model.selected = self.model.workflow[0]
        
        self.model.modified = False
     
        
    def on_open(self):
        """ 
        Shows a dialog to open a file.
        """
        
        if self.model.modified:
            ret = confirm(parent = None,
                          message = "Are you sure you want to discard the current workflow?",
                          title = "Clear workflow?")
            
            if ret != YES:
                return
        
        dialog = FileDialog(parent = self.window.control, 
                            action = 'open',
                            wildcard = (FileDialog.create_wildcard("Cytoflow workflow", "*.flow") + ';' +  #@UndefinedVariable  
                                        FileDialog.create_wildcard("All files", "*"))) #@UndefinedVariable  
        if dialog.open() == OK:
            self.open_file(dialog.path)
            self.filename = dialog.path
            self.window.title = "Cytoflow - " + self.filename
            

    def open_file(self, path):
        
        new_workflow = load_yaml(path)
        
        # a few things to take care of when reloading
        for wi_idx, wi in enumerate(new_workflow):
            
            # get wi lock
            wi.lock.acquire()
            
            # clear the wi status
            wi.status = "loading"

            # re-link the linked list.
            if wi_idx > 0:
                wi.previous_wi = new_workflow[wi_idx - 1]
            
            if wi_idx < len(new_workflow) - 1:
                wi.next_wi = new_workflow[wi_idx + 1]


        # replace the current workflow with the one we just loaded
        
        if False:  # for debugging the loading of things
            from .event_tracer import record_events 
            
            with record_events() as container:
                self.model.workflow = new_workflow
                                
            container.save_to_directory(os.getcwd()) 
        else:
            self.model.workflow = new_workflow
            self.model.modified = False
            
        for wi in self.model.workflow:
            wi.lock.release()

        
    def on_save(self):
        """ Save the file to the previous filename  """
        if self.filename:
            save_yaml(self.model.workflow, self.filename)
            self.model.modified = False
        else:
            self.on_save_as()
            
    def on_save_as(self):
        dialog = DefaultFileDialog(parent = self.window.control,
                                   action = 'save as', 
                                   default_suffix = "flow",
                                   wildcard = (FileDialog.create_wildcard("Cytoflow workflow", "*.flow") + ';' + #@UndefinedVariable  
                                               FileDialog.create_wildcard("All files", "*")))                    #@UndefinedVariable  
        
        if dialog.open() == OK:
            save_yaml(self.model.workflow, dialog.path)
            self.filename = dialog.path
            self.model.modified = False
            self.window.title = "Cytoflow - " + self.filename
            
    @on_trait_change('model.modified', post_init = True)
    def _on_model_modified(self, val):
        if val:
            if not self.window.title.endswith("*"):
                self.window.title += "*"
        else:
            if self.window.title.endswith("*"):
                self.window.title = self.window.title[:-1]
        

    def on_export(self):
        task = next(x for x in self.window.tasks if x.id == 'edu.mit.synbio.cytoflowgui.export_task')
        self.window.activate_task(task)        


    def on_calibrate(self):
        task = next(x for x in self.window.tasks if x.id == 'edu.mit.synbio.cytoflowgui.tasbe_task')
        self.window.activate_task(task)
        
            
    def on_notebook(self):
        """
        Shows a dialog to export the workflow to an Jupyter notebook
        """

        dialog = FileDialog(parent = self.window.control,
                            action = 'save as',
                            default_suffix = "ipynb",
                            wildcard = (FileDialog.create_wildcard("Jupyter notebook", "*.ipynb") + ';' + #@UndefinedVariable  
                                        FileDialog.create_wildcard("All files", "*")))  # @UndefinedVariable
        if dialog.open() == OK:
            save_notebook(self.model.workflow, dialog.path)

    
    def on_prefs(self):
        pass
    
    def on_problem(self):

        log = str(self._get_package_versions()) + "\n" + self.application.application_log.getvalue()
        
        msg = "The best way to report a problem is send an application log to " \
              "the developers.  You can do so by either sending us an email " \
              "with the log in it, or saving the log to a file and filing a " \
              "new issue on GitHub at " \
              "https://github.com/bpteague/cytoflow/issues/new" 
        
        dialog = ConfirmationDialog(message = msg,
                                    informative = "Which would you like to do?",
                                    yes_label = "Send an email...",
                                    no_label = "Save to a file...")
                
        if dialog.open() == NO:
            dialog = DefaultFileDialog(parent = self.window.control,
                                       action = 'save as', 
                                       default_suffix = "log",
                                       wildcard = (FileDialog.create_wildcard("Log files", "*.log") + ';' + #@UndefinedVariable  
                                                   FileDialog.create_wildcard("All files", "*")))                    #@UndefinedVariable  
            
            if dialog.open() == OK:
                with open(dialog.path, 'w') as f:
                    f.write(log)
                  
                webbrowser.open_new_tab("https://github.com/bpteague/cytoflow/issues/new")
                  
            return
        
        information(None, "I'll now try to open your email client and create a "
                    "new message to the developer.  Debugging logs are "
                    "attached.  Please fill out the template bug report and " 
                    "send -- thank you for reporting a bug!")

        log = self.application.application_log.getvalue()
        
        versions = ["{0} {1}".format(key, value) for key, value in self._get_package_versions().items()]

        body = """
Thank you for your bug report!  Please fill out the following template.

PLATFORM (Mac, PC, Linux, other):

OPERATING SYSTEM (eg OSX 10.7, Windows 8.1):

SEVERITY (Critical? Major? Minor? Enhancement?):

DESCRIPTION:
  - What were you trying to do?
  - What happened?
  - What did you expect to happen?
  
PACKAGE VERSIONS: {0}

DEBUG LOG: {1}
""".format(versions, log)

        mailto("*****@*****.**", 
               subject = "Cytoflow bug report",
               body = body)
    
    def _get_package_versions(self):
    
        import sys
        from cytoflow import __version__ as cf_version
        from fcsparser import __version__ as fcs_version
        from pandas import __version__ as pd_version
        from numpy import __version__ as np_version
        from numexpr import __version__ as nxp_version
        from bottleneck import __version__ as btl_version
        from seaborn import __version__ as sns_version
        from matplotlib import __version__ as mpl_version
        from scipy import __version__ as scipy_version
        from sklearn import __version__ as skl_version
        from statsmodels import __version__ as stats_version
        from pyface import __version__ as pyf_version
        from envisage import __version__ as env_version
        from traits import __version__ as trt_version
        from traitsui import __version__ as trt_ui_version
        from yapf import __version__ as yapf_version
        from nbformat import __version__ as nb_version
        from yaml import __version__ as yaml_version
        
        return {"python" : sys.version,
                "cytoflow" : cf_version,
                "fcsparser" : fcs_version,
                "pandas" : pd_version,
                "numpy" : np_version,
                "numexpr" : nxp_version,
                "bottleneck" : btl_version,
                "seaborn" : sns_version,
                "matplotlib" : mpl_version,
                "scipy" : scipy_version,
                "scikit-learn" : skl_version,
                "statsmodels" : stats_version,
                "pyface" : pyf_version,
                "envisage" : env_version,
                "traits" : trt_version,
                "traitsui" : trt_ui_version,
                "nbformat" : nb_version,
                "yapf" : yapf_version,
                "yaml" : yaml_version}
        
        
    def on_about(self):
        versions = self._get_package_versions()
        text = ["<b>Cytoflow {0}</b>".format(versions['cytoflow']),
                "<p>"]
        
        ver_text = ["{0} {1}".format(key, value) for key, value in versions.items()]
        
        text.extend(ver_text)
        
        text.extend(["Icons from the <a href=http://tango.freedesktop.org>Tango Desktop Project</a>",
                "<a href=https://thenounproject.com/search/?q=setup&i=14287>Settings icon</a> by Paulo Sa Ferreira from <a href=https://thenounproject.com>The Noun Project</a>",
                "<a href=http://www.freepik.com/free-photos-vectors/background>App icon from Starline - Freepik.com</a>",
                "Cuvette image from Wikimedia Commons user <a href=http://commons.wikimedia.org/wiki/File:Hellma_Large_cone_cytometry_cell.JPG>HellmaUSA</a>"])
        
        dialog = AboutDialog(text = text,
                             parent = self.window.control,
                             title = "About",
                             image = ImageResource('cuvette'),
                             additions = text)
        dialog.open()
        
    @on_trait_change('model.selected', post_init = True)
    def _on_select_op(self, selected):
        if selected:
            self.view_pane.enabled = (selected is not None)
            self.view_pane.default_view = selected.default_view.id if selected.default_view else ""
            self.view_pane.selected_view = selected.current_view.id if selected.current_view else ""
            self.help_pane.help_id = selected.operation.id
        else:
            self.view_pane.enabled = False
            
    @on_trait_change('view_pane.selected_view', post_init = True)
    def _on_select_view(self, view_id):
        
        if not view_id:
            return
        
        # if we already have an instantiated view object, find it
        try:
            self.model.selected.current_view = next((x for x in self.model.selected.views if x.id == view_id))
        except StopIteration:
            # else make the new view
            plugin = next((x for x in self.view_plugins if x.view_id == view_id))
            view = plugin.get_view()
            self.model.selected.views.append(view)
            self.model.selected.current_view = view
            
        self.help_pane.help_id = view_id
    
    def add_operation(self, op_id):
        # first, find the matching plugin
        plugin = next((x for x in self.op_plugins if x.id == op_id))
        
        # next, get an operation
        op = plugin.get_operation()
        
        # make a new workflow item
        wi = WorkflowItem(operation = op,
                          deletable = (op_id != 'edu.mit.synbio.cytoflowgui.op_plugins.import'))
        
        # if the op has a default view, add it to the wi
        try:
            wi.default_view = op.default_view()
            wi.views.append(wi.default_view)
            wi.current_view = wi.default_view
        except AttributeError:
            pass
        
        # figure out where to add it
        if self.model.selected:
            idx = self.model.workflow.index(self.model.selected) + 1
        else:
            idx = len(self.model.workflow)
             
        # the add_remove_items handler takes care of updating the linked list
        self.model.workflow.insert(idx, wi)
        
        # and make sure to actually select the new wi
        self.model.selected = wi
Esempio n. 28
0
class ExampleTask(Task):
    """ A simple task for opening a blank editor.
    """

    # Task interface -------------------------------------------------------

    id = "example.example_task"
    name = "Multi-Tab Editor"

    active_editor = Property(Instance(IEditor),
                             depends_on="editor_area.active_editor")

    editor_area = Instance(IEditorAreaPane)

    menu_bar = SMenuBar(
        SMenu(
            TaskAction(name="New", method="new", accelerator="Ctrl+N"),
            TaskAction(name="Add Task",
                       method="add_task",
                       accelerator="Ctrl+A"),
            TaskAction(name="Remove Task",
                       method="remove_task",
                       accelerator="Ctrl+R"),
            id="File",
            name="&File",
        ),
        SMenu(DockPaneToggleGroup(),
              TaskToggleGroup(),
              id="View",
              name="&View"),
    )

    tool_bars = [
        SToolBar(
            TaskAction(
                method="new",
                tooltip="New file",
                image=ImageResource("document_new"),
            ),
            image_size=(32, 32),
        )
    ]

    # ------------------------------------------------------------------------
    # 'Task' interface.
    # ------------------------------------------------------------------------

    def _default_layout_default(self):
        return TaskLayout(top=VSplitter(
            HSplitter(PaneItem("steps.pane1"), PaneItem("steps.pane2"))))

    def create_central_pane(self):
        """ Create the central pane: the script editor.
        """
        self.editor_area = EditorAreaPane()
        return self.editor_area

    def create_dock_panes(self):
        """ Create the file browser and connect to its double click event.
        """
        return [Pane1(), Pane2()]

    # ------------------------------------------------------------------------
    # 'ExampleTask' interface.
    # ------------------------------------------------------------------------

    def new(self):
        """ Opens a new empty window
        """
        editor = Editor()
        self.editor_area.add_editor(editor)
        self.editor_area.activate_editor(editor)
        self.activated()

    def add_task(self):
        """ Opens a new empty window
        """
        task3 = ThirdTask()
        self.window.add_task(task3)
        self.window.activate_task(task3)

    def remove_task(self):
        """ Opens a new empty window
        """
        task = self.window.tasks[0]
        window = self.window
        window.remove_task(self)
        window.activate_task(task)

    # Trait property getter/setters ----------------------------------------

    def _get_active_editor(self):
        if self.editor_area is not None:
            return self.editor_area.active_editor
        return None