示例#1
0
 def crop_cells(self):
     rows = self.chest.root.cell_description.nrows
     if rows > 0:
         # remove the table
         self.chest.removeNode('/cell_description')
         try:
             # remove the table of peak characteristics - they are not valid.
             self.chest.removeNode('/cell_peaks')
         except:
             pass
         # recreate it
         self.chest.createTable('/', 'cell_description', CellsTable)
         # remove all existing entries in the data group
         for node in self.chest.listNodes('/cells'):
             self.chest.removeNode('/cells/' + node.name)
     # store the template
     template_data = self.template_data.get_data('imagedata')
     self.parent.add_cell_data(template_data, name="template")
     # TODO: set attribute that tells where the template came from
     row = self.chest.root.cell_description.row
     files=[]
     for idx in xrange(self.numfiles):
         # filter the peaks that are outside the selected threshold
         self.set_active_index(idx)
         active_image = self.get_active_image()
         peaks=np.ma.compress_rows(self.mask_peaks(self.get_active_name()))
         files.append(self.get_active_name())
         tmp_sz=self.template_size
         data=np.zeros((peaks.shape[0],tmp_sz,tmp_sz), 
                       dtype=active_image.dtype)
         if data.shape[0] >0:
             for i in xrange(peaks.shape[0]):
                 # store the peak in the table
                 row['file_idx'] = i
                 row['input_data'] = self.data_path
                 row['filename'] = self.get_active_name()
                 row['x_coordinate'] = peaks[i, 1]
                 row['y_coordinate'] = peaks[i, 0]
                 row.append()
                 # crop the cells from the given locations
                 data[i,:,:]=active_image[peaks[i, 1]:peaks[i, 1] + tmp_sz,
                                   peaks[i, 0]:peaks[i, 0] + tmp_sz]
             self.chest.root.cell_description.flush()
             self.parent.add_cell_data(data, name=self.get_active_name())
             # insert the data (one 3d array per file)
             self.chest.setNodeAttr('/cell_description', 'threshold', (self.thresh_lower, self.thresh_upper))
             self.chest.setNodeAttr('/cell_description', 'template_position', (self.template_left, self.template_top))
             self.chest.setNodeAttr('/cell_description', 'template_filename', self.template_filename)
             self.chest.setNodeAttr('/cell_description', 'template_size', (self.template_size))
                                    
             self.chest.root.cell_description.flush()
             self.chest.flush()
     average_data = np.average(data,axis=0).squeeze()
     self.parent.add_cell_data(average_data, name="average")
     self.parent.update_cell_data()
     self.log_action(action="crop cells", files=files, thresh=self.thresh, 
                     template_position=(self.template_left, self.template_top), 
                     template_size=self.template_size, 
                     template_filename=self.template_filename)
     Application.instance().end_session(self._session_id)
示例#2
0
    def activate_proxy(self):
        """ Activate the proxy object tree.

        This method should be called by a node to activate the proxy
        tree by making two initialization passes over the tree, from
        this node downward. This method is automatically at the proper
        times and should not normally need to be invoked by user code.

        """
        self.activate_top_down()
        for child in self.children:
            # Make sure each is initialized upon activation
            if not child.is_initialized:
                child.initialize()
            if isinstance(child, ToolkitObject):
                if not child.proxy_is_active:
                    child.activate_proxy()

        # Generating the model can take a lot of time
        # so process events inbetween to keep the UI from freezing
        Application.instance().process_events()

        self.activate_bottom_up()
        self.proxy_is_active = True
        self.activated()
示例#3
0
    def _create_application(self):
        """ Create the Application object for the ui.

        This will load the highest ranking extension to the application
        factory extension point, and use it to create the instance.

        If an application object already exists, that application will
        be used instead of any defined by a factory, since there can be
        only one application per-process.

        """
        if Application.instance() is not None:
            self._application = Application.instance()
            return

        workbench = self.workbench
        point = workbench.get_extension_point(APPLICATION_FACTORY_POINT)
        extensions = point.extensions
        if not extensions:
            msg = "no contributions to the '%s' extension point"
            raise RuntimeError(msg % APPLICATION_FACTORY_POINT)

        extension = extensions[-1]
        if extension.factory is None:
            msg = "extension '%s' does not declare an application factory"
            raise ValueError(msg % extension.qualified_id)

        application = extension.factory()
        if not isinstance(application, Application):
            msg = "extension '%s' created non-Application type '%s'"
            args = (extension.qualified_id, type(application).__name__)
            raise TypeError(msg % args)

        self._application = application
    def _create_application(self):
        """ Create the Application object for the ui.

        This will load the highest ranking extension to the application
        factory extension point, and use it to create the instance.

        If an application object already exists, that application will
        be used instead of any defined by a factory, since there can be
        only one application per-process.

        """
        if Application.instance() is not None:
            self._application = Application.instance()
            return

        workbench = self.workbench
        point = workbench.get_extension_point(APPLICATION_FACTORY_POINT)
        extensions = point.extensions
        if not extensions:
            msg = "no contributions to the '%s' extension point"
            raise RuntimeError(msg % APPLICATION_FACTORY_POINT)

        extension = extensions[-1]
        if extension.factory is None:
            msg = "extension '%s' does not declare an application factory"
            raise ValueError(msg % extension.qualified_id)

        application = extension.factory()
        if not isinstance(application, Application):
            msg = "extension '%s' created non-Application type '%s'"
            args = (extension.qualified_id, type(application).__name__)
            raise TypeError(msg % args)

        self._application = application
示例#5
0
 def open_save_UI(self, plot_id='plot'):
     save_controller = SaveFileController(plot=self.get_plot(plot_id), parent=self)
     save_dialog = simple_session('save', 'Save dialog', SavePlotDialog, 
                                   controller=save_controller)
     Application.instance().add_factories([save_dialog])
     session_id = Application.instance().start_session('save')
     save_controller._session_id = session_id
示例#6
0
 def open_crop_UI(self):
     crop_controller = CellCropController(parent=self,
                                               treasure_chest=self.chest)
     cell_cropper = simple_session('cropper', 'Cell cropper', CellCropperInterface, 
                                   controller=crop_controller)
     Application.instance().add_factories([cell_cropper])
     session_id = Application.instance().start_session('cropper')
     crop_controller._session_id = session_id
示例#7
0
 def open_MDA_UI(self):
     mda_controller = MDAExecutionController(parent=self, 
                                          treasure_chest=self.chest)
     mda_dialog = simple_session('mda', 'MDA dialog', MDAInterface, 
                                   controller=mda_controller)
     Application.instance().add_factories([mda_dialog])
     session_id = Application.instance().start_session('mda')
     mda_controller._session_id = session_id
示例#8
0
 def open_crop_UI(self):
     crop_controller = CellCropController(parent=self,
                                          treasure_chest=self.chest)
     cell_cropper = simple_session('cropper',
                                   'Cell cropper',
                                   CellCropperInterface,
                                   controller=crop_controller)
     Application.instance().add_factories([cell_cropper])
     session_id = Application.instance().start_session('cropper')
     crop_controller._session_id = session_id
示例#9
0
 def save_plot(self, filename):
     self._save_plot(self.plot, filename, self.plot_width, self.plot_height,
                     self.dpi)
     self.parent.log_action("save plot", 
                            controller=self.parent.__class__.__name__,
                            dpi=self.dpi,
                            width=self.plot_width,
                            height=self.plot_height,
                            filename=filename)
     Application.instance().end_session(self._session_id)
示例#10
0
 def open_MDA_UI(self):
     mda_controller = MDAExecutionController(parent=self,
                                             treasure_chest=self.chest)
     mda_dialog = simple_session('mda',
                                 'MDA dialog',
                                 MDAInterface,
                                 controller=mda_controller)
     Application.instance().add_factories([mda_dialog])
     session_id = Application.instance().start_session('mda')
     mda_controller._session_id = session_id
示例#11
0
 def save_plot(self, filename):
     self._save_plot(self.plot, filename, self.plot_width, self.plot_height,
                     self.dpi)
     self.parent.log_action("save plot",
                            controller=self.parent.__class__.__name__,
                            dpi=self.dpi,
                            width=self.plot_width,
                            height=self.plot_height,
                            filename=filename)
     Application.instance().end_session(self._session_id)
示例#12
0
def test_cache_1():
    from enaml.application import Application
    from enaml.styling import StyleCache
    source = dedent("""\
    from enaml.widgets.api import Window, Container, PushButton
    from enaml.styling import StyleSheet, Style, Setter

    enamldef Sheet(StyleSheet):
        Style:
            element = 'PushButton'
            Setter:
                field = 'background'
                value = 'blue'

    enamldef Main(Window):
        alias button
        Sheet:
            pass
        Container:
            PushButton: button:
                pass

    """)
    _clear_cache()
    app = Application.instance()
    if app is not None:
        app.style_sheet = None
    main = compile_source(source, 'Main')()
    styles = StyleCache.styles(main.button)
    assert len(styles) == 1
    assert not _cache_items_empty()
    assert not _cache_styles_empty()
    main.destroy()
    assert _cache_items_empty()
    assert _cache_styles_empty()
示例#13
0
    def custom_color(index):
        """ Get the custom color for the given index.

        The custom colors are shared among all color dialogs.

        Parameters
        ----------
        index : int
            The integer index of the custom color.

        Returns
        -------
        result : Color
            The custom color for the index.

        Notes
        -----
        The Application object must exist before calling this method.

        """
        app = Application.instance()
        assert app is not None, 'the application object does not exist'
        proxy_cls = app.resolve_proxy_class(ColorDialog)
        if proxy_cls is not None:
            return proxy_cls.custom_color(index)
        return Color(255, 255, 255)
示例#14
0
    def _send_relayout(self):
        """ Send the 'relayout' action to the client widget.

        If an Enaml Application instance exists, then multiple `relayout`
        actions will be collapsed into a single action that will be sent
        on the next cycle of the event loop. If no application exists,
        then the action is sent immediately.

        """
        # The relayout action is deferred until the next cycle of the
        # event loop for two reasons: 1) So that multiple relayout
        # requests can be collapsed into a single action. 2) So that
        # all child events (which are fired synchronously) can finish
        # processing and send their actions to the client before the
        # relayout request is sent. The action itself is batched so
        # that it can be sent along with any object tree changes.
        app = Application.instance()
        if app is not None:
            task = self._layout_task
            if task is None:
                def notifier(ignored):
                    self._layout_task = None
                def layout_task():
                    self.batch_action('relayout', self._layout_info())
                task = app.schedule(layout_task)
                task.notify(notifier)
                self._layout_task = task
示例#15
0
    def _send_relayout(self):
        """ Send the 'relayout' action to the client widget.

        If an Enaml Application instance exists, then multiple `relayout`
        actions will be collapsed into a single action that will be sent
        on the next cycle of the event loop. If no application exists,
        then the action is sent immediately.

        """
        # The relayout action is deferred until the next cycle of the
        # event loop for two reasons: 1) So that multiple relayout
        # requests can be collapsed into a single action. 2) So that
        # all child events (which are fired synchronously) can finish
        # processing and send their actions to the client before the
        # relayout request is sent. The action itself is batched so
        # that it can be sent along with any object tree changes.
        app = Application.instance()
        if app is not None:
            task = self._layout_task
            if task is None:

                def notifier(ignored):
                    self._layout_task = None

                def layout_task():
                    self.batch_action('relayout', self._layout_info())

                task = app.schedule(layout_task)
                task.notify(notifier)
                self._layout_task = task
示例#16
0
def _app_style_sheet():
    app = Application.instance()
    if app is not None:
        sheet = app.style_sheet
        if sheet is not None and not sheet.is_initialized:
            sheet.initialize()
        return sheet
示例#17
0
文件: styling.py 项目: rutsky/enaml
def _app_style_sheet():
    app = Application.instance()
    if app is not None:
        sheet = app.style_sheet
        if sheet is not None and not sheet.is_initialized:
            sheet.initialize()
        return sheet
示例#18
0
def test_cache_1():
    from enaml.application import Application
    from enaml.styling import StyleCache
    source = dedent("""\
    from enaml.widgets.api import Window, Container, PushButton
    from enaml.styling import StyleSheet, Style, Setter

    enamldef Sheet(StyleSheet):
        Style:
            element = 'PushButton'
            Setter:
                field = 'background'
                value = 'blue'

    enamldef Main(Window):
        alias button
        Sheet:
            pass
        Container:
            PushButton: button:
                pass

    """)
    _clear_cache()
    app = Application.instance()
    if app is not None:
        app.style_sheet = None
    main = compile_source(source, 'Main')()
    styles = StyleCache.styles(main.button)
    assert len(styles) == 1
    assert not _cache_items_empty()
    assert not _cache_styles_empty()
    main.destroy()
    assert _cache_items_empty()
    assert _cache_styles_empty()
示例#19
0
 def execute(self):
     method = self.methods[self.selected_method_idx]
     try:
         if method == 'PCA':
             self.PCA(n_components=self.number_to_derive)
         elif method == 'ICA':
             self.ICA(n_components=self.number_to_derive)
         self.chest.set_node_attr('/mda_results/'+self.context, 
                            'dimensionality', self.number_to_derive)
         # close the dialog window
         Application.instance().end_session(self._session_id)
         # add to the log file
         self.parent.log_action(action=method, 
                                n_components = self.number_to_derive,
                                on_peaks = self.on_peaks,
                                backend=mda.name)
         # show the results windows
         self.parent.update_mda_data()
     except RuntimeError:
         print sys.exc_info()[0]
         print "MDA not executed."
示例#20
0
 def execute(self):
     method = self.methods[self.selected_method_idx]
     try:
         if method == 'PCA':
             self.PCA(n_components=self.number_to_derive)
         elif method == 'ICA':
             self.ICA(n_components=self.number_to_derive)
         self.chest.set_node_attr('/mda_results/' + self.context,
                                  'dimensionality', self.number_to_derive)
         # close the dialog window
         Application.instance().end_session(self._session_id)
         # add to the log file
         self.parent.log_action(action=method,
                                n_components=self.number_to_derive,
                                on_peaks=self.on_peaks,
                                backend=mda.name)
         # show the results windows
         self.parent.update_mda_data()
     except RuntimeError:
         print sys.exc_info()[0]
         print "MDA not executed."
示例#21
0
    def initialize(self):
        """ A reimplemented initializer.

        This initializer will invoke the application to create the
        proxy if one has not already been provided.

        """
        if not self.proxy:
            app = Application.instance()
            if app is None:
                msg = 'cannot create a proxy without an active Application'
                raise RuntimeError(msg)
            self.proxy = app.create_proxy(self)
        super(ToolkitObject, self).initialize()
示例#22
0
    def initialize(self):
        """ A reimplemented initializer.

        This initializer will invoke the application to create the
        proxy if one has not already been provided.

        """
        if not self.proxy:
            app = Application.instance()
            if app is None:
                msg = 'cannot create a proxy without an active Application'
                raise RuntimeError(msg)
            self.proxy = app.create_proxy(self)
        super(ToolkitObject, self).initialize()
示例#23
0
def enaml_run(enaml_qtbot, monkeypatch):
    """ Patches the QtApplication to allow using the qtbot when the
    enaml application is started. It also patches QApplication.exit as
    recommended in the pytest-qt docs.

    Yields
    -------
    handler: object
        an object with a `run` attribute that can be set to a callback that
        will be invoked with the application and first window shown.

    References
    ----------
    1. https://pytest-qt.readthedocs.io/en/latest/app_exit.html

    """
    from enaml.qt.qt_application import QtApplication, QApplication

    app = Application.instance()
    if app:
        Application._instance = None

    class Runner:
        # Set this to a callback
        run = None

    runner = Runner()

    def start(self):
        for window in Window.windows:
            wait_for_window_displayed(enaml_qtbot, window)
            if callable(runner.run):
                runner.run(self, window)
            else:
                close_window_or_popup(enaml_qtbot, window)
            break

    try:
        with monkeypatch.context() as m:
            m.setattr(QtApplication, 'start', start)
            m.setattr(QApplication, 'exit', lambda self: None)
            yield runner
    finally:
        Application._instance = app
示例#24
0
def enaml_run(qtbot):
    """ Patch the start method to use the qtbot """
    app = Application.instance()
    if app:
        Application._instance = None
    _start = QtApplication.start

    def start(self):
        for window in Window.windows:
            qtbot.wait_for_window_shown(window.proxy.widget)
            qtbot.wait(1000)
            window.close()
            break

    QtApplication.start = start
    try:
        yield
    finally:
        QtApplication.start = _start
        Application._instance = app
示例#25
0
    def custom_count():
        """ Get the number of available custom colors.

        The custom colors are shared among all color dialogs.

        Returns
        -------
        result : int
            The number of available custom colors.

        Notes
        -----
        The Application object must exist before calling this method.

        """
        app = Application.instance()
        assert app is not None, 'the application object does not exist'
        proxy_cls = app.resolve_proxy_class(ColorDialog)
        if proxy_cls is not None:
            return proxy_cls.custom_count()
        return 0
示例#26
0
    def set_custom_color(index, color):
        """ Set the custom color for the given index.

        The custom colors are shared among all color dialogs.

        Parameters
        ----------
        index : int
            The integer index of the custom color.

        color : Color
            The custom color to set for the index

        Notes
        -----
        The Application object must exist before calling this method.

        """
        app = Application.instance()
        assert app is not None, 'the application object does not exist'
        proxy_cls = app.resolve_proxy_class(ColorDialog)
        if proxy_cls is not None:
            proxy_cls.set_custom_color(index, color)
示例#27
0
 def _default_app(self):
     return Application.instance()
示例#28
0
def test_cascade():
    source = dedent("""\
    from enaml.widgets.api import Window, Container, PushButton
    from enaml.styling import StyleSheet, Style, Setter

    enamldef Sheet1(StyleSheet):
        Style:
            style_class = 'yellow'
            Setter:
                field = 'background'
                value = 'yellow'
        Style:
            element = 'PushButton'
            Setter:
                field = 'background'
                value = 'red'

    enamldef Sheet2(StyleSheet):
        Style:
            style_class = 'cyan'
            Setter:
                field = 'background'
                value = 'cyan'
        Style:
            element = 'PushButton'
            Setter:
                field = 'background'
                value = 'green'

    enamldef Sheet3(StyleSheet):
        Style:
            style_class = 'magenta'
            Setter:
                field = 'background'
                value = 'magenta'
        Style:
            element = 'PushButton'
            Setter:
                field = 'background'
                value = 'blue'

    enamldef Main(Window):
        alias one
        alias two
        alias three
        alias four
        alias five
        alias six
        alias seven
        alias eight
        alias nine
        alias ten
        alias eleven
        Sheet2:
            pass
        Container:
            PushButton: one:
                pass
            PushButton: two:
                style_class = 'yellow'
            PushButton: three:
                style_class = 'cyan'
            PushButton: four:
                Sheet3:
                    pass
            PushButton: five:
                style_class = 'yellow'
                Sheet3:
                    pass
            PushButton: six:
                style_class = 'cyan'
                Sheet3:
                    pass
            PushButton: seven:
                style_class = 'magenta'
                Sheet3:
                    pass
            Container:
                Sheet3:
                    pass
                PushButton: eight:
                    pass
                PushButton: nine:
                    style_class = 'yellow'
                PushButton: ten:
                    style_class = 'cyan'
                PushButton: eleven:
                    style_class = 'magenta'

    def init():
        from enaml.application import Application
        app = Application()
        app.style_sheet = Sheet1()
        return Main()

    """)
    old_instance = None
    if Application.instance():
        old_instance = Application._instance
        Application._instance = None
    try:
        main = compile_source(source, 'init')()
        _assert_setters(main.one, (
            ('background', 'red'),
            ('background', 'green'),
        ))
        _assert_setters(main.two, (
            ('background', 'red'),
            ('background', 'yellow'),
            ('background', 'green'),
        ))
        _assert_setters(main.three, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'cyan'),
        ))
        _assert_setters(main.four, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'blue'),
        ))
        _assert_setters(main.five, (
            ('background', 'red'),
            ('background', 'yellow'),
            ('background', 'green'),
            ('background', 'blue'),
        ))
        _assert_setters(main.six, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'cyan'),
            ('background', 'blue'),
        ))
        _assert_setters(main.seven, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'blue'),
            ('background', 'magenta'),
        ))
        _assert_setters(main.eight, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'blue'),
        ))
        _assert_setters(main.nine, (
            ('background', 'red'),
            ('background', 'yellow'),
            ('background', 'green'),
            ('background', 'blue'),
        ))
        _assert_setters(main.ten, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'cyan'),
            ('background', 'blue'),
        ))
        _assert_setters(main.eleven, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'blue'),
            ('background', 'magenta'),
        ))
    finally:
        Application._instance = old_instance
示例#29
0
def test_cascade():
    source = dedent("""\
    from enaml.widgets.api import Window, Container, PushButton
    from enaml.styling import StyleSheet, Style, Setter

    enamldef Sheet1(StyleSheet):
        Style:
            style_class = 'yellow'
            Setter:
                field = 'background'
                value = 'yellow'
        Style:
            element = 'PushButton'
            Setter:
                field = 'background'
                value = 'red'

    enamldef Sheet2(StyleSheet):
        Style:
            style_class = 'cyan'
            Setter:
                field = 'background'
                value = 'cyan'
        Style:
            element = 'PushButton'
            Setter:
                field = 'background'
                value = 'green'

    enamldef Sheet3(StyleSheet):
        Style:
            style_class = 'magenta'
            Setter:
                field = 'background'
                value = 'magenta'
        Style:
            element = 'PushButton'
            Setter:
                field = 'background'
                value = 'blue'

    enamldef Main(Window):
        alias one
        alias two
        alias three
        alias four
        alias five
        alias six
        alias seven
        alias eight
        alias nine
        alias ten
        alias eleven
        Sheet2:
            pass
        Container:
            PushButton: one:
                pass
            PushButton: two:
                style_class = 'yellow'
            PushButton: three:
                style_class = 'cyan'
            PushButton: four:
                Sheet3:
                    pass
            PushButton: five:
                style_class = 'yellow'
                Sheet3:
                    pass
            PushButton: six:
                style_class = 'cyan'
                Sheet3:
                    pass
            PushButton: seven:
                style_class = 'magenta'
                Sheet3:
                    pass
            Container:
                Sheet3:
                    pass
                PushButton: eight:
                    pass
                PushButton: nine:
                    style_class = 'yellow'
                PushButton: ten:
                    style_class = 'cyan'
                PushButton: eleven:
                    style_class = 'magenta'

    def init():
        from enaml.application import Application
        app = Application()
        app.style_sheet = Sheet1()
        return Main()

    """)
    old_instance = None
    if Application.instance():
        old_instance = Application._instance
        Application._instance = None
    try:
        main = compile_source(source, 'init')()
        _assert_setters(main.one, (
            ('background', 'red'),
            ('background', 'green'),
        ))
        _assert_setters(main.two, (
            ('background', 'red'),
            ('background', 'yellow'),
            ('background', 'green'),
        ))
        _assert_setters(main.three, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'cyan'),
        ))
        _assert_setters(main.four, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'blue'),
        ))
        _assert_setters(main.five, (
            ('background', 'red'),
            ('background', 'yellow'),
            ('background', 'green'),
            ('background', 'blue'),
        ))
        _assert_setters(main.six, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'cyan'),
            ('background', 'blue'),
        ))
        _assert_setters(main.seven, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'blue'),
            ('background', 'magenta'),
        ))
        _assert_setters(main.eight, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'blue'),
        ))
        _assert_setters(main.nine, (
            ('background', 'red'),
            ('background', 'yellow'),
            ('background', 'green'),
            ('background', 'blue'),
        ))
        _assert_setters(main.ten, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'cyan'),
            ('background', 'blue'),
        ))
        _assert_setters(main.eleven, (
            ('background', 'red'),
            ('background', 'green'),
            ('background', 'blue'),
            ('background', 'magenta'),
        ))
    finally:
        Application._instance = old_instance
示例#30
0
    def crop_cells(self):
        rows = self.chest.root.cell_description.nrows
        if rows > 0:
            # remove the table
            self.chest.remove_node('/cell_description')
            try:
                # remove the table of peak characteristics - they are not valid.
                self.chest.remove_node('/cell_peaks')
            except:
                pass
            # recreate it
            self.chest.create_table('/', 'cell_description', CellsTable)
            # remove all existing entries in the data group
            for node in self.chest.list_nodes('/cells'):
                self.chest.remove_node('/cells/' + node.name)
        # store the template
        template_data = self.template_data.get_data('imagedata')
        self.parent.add_cell_data(template_data, name="template")
        # TODO: set attribute that tells where the template came from
        row = self.chest.root.cell_description.row
        files = []
        for idx in xrange(self.numfiles):
            # filter the peaks that are outside the selected threshold
            self.set_active_index(idx)
            active_image = self.get_active_image()
            peaks = np.ma.compress_rows(self.mask_peaks(
                self.get_active_name()))
            files.append(self.get_active_name())
            tmp_sz = self.template_size
            data = np.zeros((peaks.shape[0], tmp_sz, tmp_sz),
                            dtype=active_image.dtype)
            if data.shape[0] > 0:
                for i in xrange(peaks.shape[0]):
                    # store the peak in the table
                    row['file_idx'] = i
                    row['input_data'] = self.data_path
                    row['filename'] = self.get_active_name()
                    row['x_coordinate'] = peaks[i, 0]
                    row['y_coordinate'] = peaks[i, 1]
                    row.append()
                    # crop the cells from the given locations
                    data[i, :, :] = active_image[
                        int(peaks[i, 0]):int(peaks[i, 0] + tmp_sz),
                        int(peaks[i, 1]):int(peaks[i, 1] + tmp_sz)]
                self.chest.root.cell_description.flush()
                self.parent.add_cell_data(data, name=self.get_active_name())
                # insert the data (one 3d array per file)
                self.chest.set_node_attr(
                    '/cell_description', 'threshold',
                    (self.thresh_lower, self.thresh_upper))
                self.chest.set_node_attr(
                    '/cell_description', 'template_position',
                    (self.template_left, self.template_top))
                self.chest.set_node_attr('/cell_description',
                                         'template_filename',
                                         self.template_filename)
                self.chest.set_node_attr('/cell_description', 'template_size',
                                         (self.template_size))

                self.chest.root.cell_description.flush()
                self.chest.flush()
        average_data = np.average(data, axis=0).squeeze()
        self.parent.add_cell_data(average_data, name="average")
        row = self.chest.root.cell_description.row
        row['file_idx'] = 0
        row['input_data'] = self.data_path
        row['filename'] = "average"
        row['x_coordinate'] = 0
        row['y_coordinate'] = 0
        row.append()
        self.chest.root.cell_description.flush()
        self.parent.update_cell_data()
        self.parent.add_image_data(average_data, "average")
        self.log_action(action="crop cells",
                        files=files,
                        thresh=self.thresh,
                        template_position=(self.template_left,
                                           self.template_top),
                        template_size=self.template_size,
                        template_filename=self.template_filename)
        Application.instance().end_session(self._session_id)
示例#31
0
    def _do_update(self):
        # Only update when all changes are done
        self._update_count -= 1
        if self._update_count != 0:
            return

        qtapp = Application.instance()._qapp
        start_time = datetime.now()

        self.declaration.loading = True
        try:
            view = self.v3d_view

            self.clear_display()
            displayed_shapes = {}
            ais_shapes = []
            log.debug("Rendering...")

            #: Expand all parts otherwise we lose the material information
            self.dimensions = set()
            shapes = self._expand_shapes(self.children(), self.dimensions)
            if not shapes:
                log.debug("No shapes to display")
                return

            self.set_selection_mode(self.declaration.selection_mode)
            n = len(shapes)
            for i, occ_shape in enumerate(shapes):
                qtapp.processEvents()
                if self._update_count != 0:
                    log.debug("Aborted!")
                    return  # Another update coming abort

                d = occ_shape.declaration
                topods_shape = occ_shape.shape
                if not topods_shape or topods_shape.IsNull():
                    log.error("{} has no shape!".format(occ_shape))
                    continue

                # Translate part locations
                parent = occ_shape.parent()
                if parent and isinstance(parent, OccPart) \
                        and not topods_shape.Locked():

                    # Build transform for nested parts
                    l = topods_shape.Location()
                    while isinstance(parent, OccPart):
                        l = parent.location.Multiplied(l)
                        parent = parent.parent()

                    topods_shape.Location(l)

                    # HACK: Prevent doing this multiple times when the view is
                    # force updated and the same part is rendered
                    topods_shape.Locked(True)

                # Save the mapping of topods_shape to declaracad shape
                displayed_shapes[topods_shape] = occ_shape

                progress = self.declaration.progress = min(
                    100, max(0, i * 100 / n))
                #log.debug("Displaying {} ({}%)".format(
                #    topods_shape, round(progress, 2)))
                ais_shape = self.display_shape(
                    topods_shape,
                    d.color,
                    d.transparency,
                    d.material if d.material.name else None,
                    d.texture,
                    update=False)

                occ_shape.ais_shape = ais_shape
                if ais_shape:
                    ais_shapes.append(ais_shape)

            # Display all dimensions
            log.debug("Adding {} dimensions...".format(len(self.dimensions)))
            displayed_dimensions = {}
            for item in self.dimensions:
                dim = item.dimension
                if dim is not None and item.declaration.display:
                    displayed_dimensions[dim] = item
                    self.display_ais(dim, update=False)

            # Update
            self.ais_context.UpdateCurrentViewer()

            self._displayed_shapes = displayed_shapes
            self._displayed_dimensions = displayed_dimensions

            # Update bounding box
            bbox = self.get_bounding_box(displayed_shapes.keys())
            self.declaration.bbox = BBox(*bbox)
            log.debug("Took: {}".format(datetime.now() - start_time))
            self.declaration.progress = 100
        except:
            log.error("Failed to display shapes: {}".format(
                traceback.format_exc()))
        finally:
            self.declaration.loading = False
示例#32
0
def safe_call(func, *args, **kwargs):
    """utility function for safely calling functions that doesn't return anything"""
    if Application.instance() is None:
        return func(*args, **kwargs)
    deferred_call(func, *args, **kwargs)
示例#33
0
class QtOccViewer(QtControl, ProxyOccViewer):

    #: Viewer widget
    widget = Typed(QtViewer3d)

    #: Update count
    _redraw_blocked = Bool()

    #: Displayed Shapes
    _displayed_shapes = Dict()
    _displayed_dimensions = Dict()
    _displayed_graphics = Dict()
    _selected_shapes = List()

    #: Errors
    errors = Dict()

    #: Tuple of (Quantity_Color, transparency)
    shape_color = Typed(tuple)

    #: Grid colors
    grid_colors = Dict()

    #: Shapes
    shapes = Property(lambda self: self.get_shapes(), cached=True)

    #: Dimensions
    dimensions = Typed(set)
    graphics = Typed(set)

    # -------------------------------------------------------------------------
    # OpenCascade specific members
    # -------------------------------------------------------------------------
    display_connection = Typed(Aspect_DisplayConnection)
    v3d_viewer = Typed(V3d_Viewer)
    v3d_view = Typed(V3d_View)

    ais_context = Typed(AIS_InteractiveContext)
    prs3d_drawer = Typed(Prs3d_Drawer)
    prs_mgr = Typed(PrsMgr_PresentationManager)
    v3d_window = Typed(V3d_Window)
    gfx_structure_manager = Typed(Graphic3d_StructureManager)
    gfx_structure = Typed(Graphic3d_Structure)
    graphics_driver = Typed(OpenGl_GraphicDriver)
    camera = Typed(Graphic3d_Camera)

    #: List of lights
    lights = List()

    #: Fired
    _redisplay_timer = Typed(QTimer, ())

    _qt_app = Property(lambda self: Application.instance()._qapp, cached=True)

    def get_shapes(self):
        return [c for c in self.children() if not isinstance(c, QtControl)]

    def create_widget(self):
        self.widget = QtViewer3d(parent=self.parent_widget())

    def init_widget(self):
        super().init_widget()
        widget = self.widget
        widget.proxy = self

        redisplay_timer = self._redisplay_timer
        redisplay_timer.setSingleShot(True)
        redisplay_timer.setInterval(8)
        redisplay_timer.timeout.connect(self.on_redisplay_requested)

    def init_viewer(self):
        """ Init viewer when the QOpenGLWidget is ready

        """
        d = self.declaration
        widget = self.widget
        if sys.platform == 'win32':
            display = Aspect_DisplayConnection()
        else:
            display_name = TCollection_AsciiString(
                os.environ.get('DISPLAY', '0'))
            display = Aspect_DisplayConnection(display_name)
        self.display_connection = display

        # Create viewer
        graphics_driver = self.graphics_driver = OpenGl_GraphicDriver(display)

        viewer = self.v3d_viewer = V3d_Viewer(graphics_driver)
        view = self.v3d_view = viewer.CreateView()

        # Setup window
        win_id = widget.get_window_id()
        if sys.platform == 'win32':
            window = WNT_Window(win_id)
        elif sys.platform == 'darwin':
            window = Cocoa_Window(win_id)
        else:
            window = Xw_Window(self.display_connection, win_id)
        if not window.IsMapped():
            window.Map()
        self.v3d_window = window
        view.SetWindow(window)
        view.MustBeResized()

        # Setup viewer
        ais_context = self.ais_context = AIS_InteractiveContext(viewer)
        drawer = self.prs3d_drawer = ais_context.DefaultDrawer()

        # Needed for displaying graphics
        prs_mgr = self.prs_mgr = ais_context.MainPrsMgr()
        gfx_mgr = self.gfx_structure_manager = prs_mgr.StructureManager()
        self.gfx_structure = Graphic3d_Structure(gfx_mgr)

        # Lights camera
        self.camera = view.Camera()

        try:
            self.set_lights(d.lights)
        except Exception as e:
            log.exception(e)
            viewer.SetDefaultLights()

        #viewer.DisplayPrivilegedPlane(True, 1)
        #view.SetShadingModel(Graphic3d_TypeOfShadingModel.V3d_PHONG)

        # background gradient
        with self.redraw_blocked():
            self.set_background_gradient(d.background_gradient)
            self.set_draw_boundaries(d.draw_boundaries)
            self.set_trihedron_mode(d.trihedron_mode)
            self.set_display_mode(d.display_mode)
            self.set_hidden_line_removal(d.hidden_line_removal)
            self.set_selection_mode(d.selection_mode)
            self.set_view_mode(d.view_mode)
            self.set_view_projection(d.view_projection)
            self.set_lock_rotation(d.lock_rotation)
            self.set_lock_zoom(d.lock_zoom)
            self.set_shape_color(d.shape_color)
            self.set_chordial_deviation(d.chordial_deviation)
            self._update_rendering_params()
            self.set_grid_mode(d.grid_mode)
            self.set_grid_colors(d.grid_colors)

            self.init_signals()
            self.dump_gl_info()

        self.redraw()

        qt_app = self._qt_app
        for child in self.children():
            self.child_added(child)
            qt_app.processEvents()

    def dump_gl_info(self):
        # Debug info
        try:
            ctx = self.graphics_driver.GetSharedContext()
            if ctx is None or not ctx.IsValid():
                return
            v1 = ctx.VersionMajor()
            v2 = ctx.VersionMinor()
            log.info("OpenGL version: {}.{}".format(v1, v2))
            log.info("GPU memory: {}".format(ctx.AvailableMemory()))
            log.info("GPU memory info: {}".format(
                ctx.MemoryInfo().ToCString()))
            log.info("Max MSAA samples: {}".format(ctx.MaxMsaaSamples()))

            supports_raytracing = ctx.HasRayTracing()
            log.info("Supports ray tracing: {}".format(supports_raytracing))
            if supports_raytracing:
                log.info("Supports textures: {}".format(
                    ctx.HasRayTracingTextures()))
                log.info("Supports adaptive sampling: {}".format(
                    ctx.HasRayTracingAdaptiveSampling()))
                log.info("Supports adaptive sampling atomic: {}".format(
                    ctx.HasRayTracingAdaptiveSamplingAtomic()))
            else:
                ver_too_low = ctx.IsGlGreaterEqual(3, 1)
                if not ver_too_low:
                    log.info("OpenGL version must be >= 3.1")
                else:
                    ext = "GL_ARB_texture_buffer_object_rgb32"
                    if not ctx.CheckExtension(ext):
                        log.info("OpenGL extension {} is missing".format(ext))
                    else:
                        log.info("OpenGL glBlitFramebuffer is missing")
        except Exception as e:
            log.exception(e)

    def init_signals(self):
        d = self.declaration
        callbacks = self.widget._callbacks
        for name in callbacks.keys():
            cb = getattr(d, name, None)
            if cb is not None:
                callbacks[name].append(cb)

    def child_added(self, child):
        if isinstance(child, OccShape):
            self._add_shape_to_display(child)
        elif isinstance(child, OccDimension):
            self._add_dimension_to_display(child)
        else:
            super().child_added(child)

    def child_removed(self, child):
        if isinstance(child, OccShape):
            self._remove_shape_from_display(child)
        elif isinstance(child, OccDimension):
            self._remove_dimension_from_display(child)
        else:
            super().child_removed(child)

    def _add_shape_to_display(self, occ_shape):
        """ Add an OccShape to the display

        """
        d = occ_shape.declaration
        if not d.display:
            return
        displayed_shapes = self._displayed_shapes
        display = self.ais_context.Display
        qt_app = self._qt_app
        occ_shape.displayed = True
        for s in occ_shape.walk_shapes():
            s.observe('ais_shape', self.on_ais_shape_changed)
            ais_shape = s.ais_shape
            if ais_shape is not None:
                try:
                    display(ais_shape, False)
                    s.displayed = True
                    displayed_shapes[s.shape] = s
                except RuntimeError as e:
                    log.exception(e)

                # Displaying can take a lot of time
                qt_app.processEvents()

        if isinstance(occ_shape, OccPart):
            for d in occ_shape.declaration.traverse():
                proxy = getattr(d, 'proxy', None)
                if proxy is None:
                    continue
                if isinstance(proxy, OccDimension):
                    self._add_dimension_to_display(proxy)
                elif isinstance(proxy, OccDisplayItem):
                    self._add_item_to_display(proxy)

        self._redisplay_timer.start()

    def _remove_shape_from_display(self, occ_shape):
        displayed_shapes = self._displayed_shapes
        remove = self.ais_context.Remove
        occ_shape.displayed = False
        for s in occ_shape.walk_shapes():
            s.unobserve('ais_shape', self.on_ais_shape_changed)
            if s.get_member('ais_shape').get_slot(s) is None:
                continue
            ais_shape = s.ais_shape
            if ais_shape is not None:
                s.displayed = False
                displayed_shapes.pop(ais_shape, None)
                remove(ais_shape, False)

        if isinstance(occ_shape, OccPart):
            for d in occ_shape.declaration.traverse():
                proxy = getattr(d, 'proxy', None)
                if proxy is None:
                    continue
                if isinstance(proxy, OccDimension):
                    self._remove_dimension_from_display(proxy)
                elif isinstance(proxy, OccDisplayItem):
                    self._remove_item_from_display(proxy)

        self._redisplay_timer.start()

    def on_ais_shape_changed(self, change):
        ais_context = self.ais_context
        displayed_shapes = self._displayed_shapes
        occ_shape = change['object']
        if change['type'] == 'update':
            old_ais_shape = change['oldvalue']
            if old_ais_shape is not None:
                old_shape = old_ais_shape.Shape()
                displayed_shapes.pop(old_shape, None)
                ais_context.Remove(old_ais_shape, False)
                occ_shape.displayed = False
            new_ais_shape = change['value']
            if new_ais_shape is not None:
                displayed_shapes[occ_shape.shape] = occ_shape
                ais_context.Display(new_ais_shape, False)
                occ_shape.displayed = True
        self._redisplay_timer.start()

    def _add_dimension_to_display(self, occ_dim):
        ais_dimension = occ_dim.dimension
        if ais_dimension is not None:
            self.ais_context.Display(ais_dimension, False)
            self._displayed_dimensions[ais_dimension] = occ_dim
        self._redisplay_timer.start()

    def _remove_dimension_from_display(self, occ_dim):
        ais_dimension = occ_dim.dimension
        if ais_dimension is not None:
            self.ais_context.Remove(ais_dimension, False)
            self._displayed_dimensions.pop(ais_dimension, None)
        self._redisplay_timer.start()

    def _add_item_to_display(self, occ_disp_item):
        ais_object = occ_disp_item.item
        if ais_object is not None:
            self.ais_context.Display(ais_object, False)
            self._displayed_graphics[ais_object] = occ_disp_item
        self._redisplay_timer.start()

    def _remove_item_from_display(self, occ_disp_item):
        ais_object = occ_disp_item.item
        if ais_object is not None:
            self.ais_context.Remove(ais_object, False)
            self._displayed_graphics.pop(ais_object, None)
        self._redisplay_timer.start()

    def on_redisplay_requested(self):
        self.ais_context.UpdateCurrentViewer()

        # Recompute bounding box
        bbox = self.get_bounding_box(self._displayed_shapes.keys())
        self.declaration.bbox = BBox(*bbox)

    # -------------------------------------------------------------------------
    # Viewer API
    # -------------------------------------------------------------------------
    def get_bounding_box(self, shapes):
        """ Compute the bounding box for the given list of shapes.
        Return values are in 3d coordinate space.

        Parameters
        ----------
        shapes: List
            A list of TopoDS_Shape to compute a bbox for

        Returns
        -------
        bbox: Tuple
            A tuple of (xmin, ymin, zmin, xmax, ymax, zmax).

        """
        bbox = Bnd_Box()
        for shape in shapes:
            BRepBndLib.Add_(shape, bbox)
        try:
            pmin = bbox.CornerMin()
            pmax = bbox.CornerMax()
        except RuntimeError:
            return (0, 0, 0, 0, 0, 0)
        return (pmin.X(), pmin.Y(), pmin.Z(), pmax.X(), pmax.Y(), pmax.Z())

    def get_screen_coordinate(self, point):
        """ Convert a 3d coordinate to a 2d screen coordinate

        Parameters
        ----------
        (x, y, z): Tuple
            A 3d coordinate
        """
        return self.v3d_view.Convert(point[0], point[1], point[2], 0, 0)

    # -------------------------------------------------------------------------
    # Rendering parameters
    # -------------------------------------------------------------------------
    def set_chordial_deviation(self, deviation):
        # Turn up tesselation defaults
        self.prs3d_drawer.SetMaximalChordialDeviation(deviation)

    def set_lights(self, lights):
        viewer = self.v3d_viewer
        new_lights = []

        for d in lights:
            color, _ = color_to_quantity_color(d.color)
            if d.type == "directional":
                if '_' in d.orientation:
                    attr = 'V3d_TypeOfOrientation_{}'.format(d.orientation)
                else:
                    attr = 'V3d_{}'.format(d.orientation)
                orientation = getattr(V3d.V3d_TypeOfOrientation, attr,
                                      V3d.V3d_Zneg)
                light = V3d.V3d_DirectionalLight(orientation, color,
                                                 d.headlight)
            elif d.type == "spot":
                light = V3d.V3d_SpotLight(d.position, d.direction, color)
                light.SetAngle(d.angle)
            else:
                light = V3d.V3d_AmbientLight(color)
            light.SetIntensity(d.intensity)

            if d.range:
                light.SetRange(d.range)

            viewer.AddLight(light)
            if d.enabled:
                viewer.SetLightOn(light)
            new_lights.append(light)

        for light in self.lights:
            viewer.DelLight(self.light)

        self.lights = new_lights

    def set_draw_boundaries(self, enabled):
        self.prs3d_drawer.SetFaceBoundaryDraw(enabled)

    def set_hidden_line_removal(self, enabled):
        view = self.v3d_view
        view.SetComputedMode(enabled)
        self.redraw()

    def set_antialiasing(self, enabled):
        self._update_rendering_params()

    def set_shadows(self, enabled):
        self._update_rendering_params()

    def set_reflections(self, enabled):
        self._update_rendering_params()

    def set_raytracing(self, enabled):
        self._update_rendering_params()

    def set_raytracing_depth(self, depth):
        self._update_rendering_params()

    def _update_rendering_params(self, **params):
        """ Set the rendering parameters of the view

        Parameters
        ----------
        **params:
            See Graphic3d_RenderingParams members

        """
        d = self.declaration
        view = self.v3d_view
        rendering_params = view.ChangeRenderingParams()
        if d.raytracing:
            method = Graphic3d_RM_RAYTRACING
        else:
            method = Graphic3d_RM_RASTERIZATION

        defaults = dict(
            Method=method,
            RaytracingDepth=d.raytracing_depth,
            # IsGlobalIlluminationEnabled=d.raytracing,
            IsShadowEnabled=d.shadows,
            IsReflectionEnabled=d.reflections,
            IsAntialiasingEnabled=d.antialiasing,
            IsTransparentShadowEnabled=d.shadows,
            NbMsaaSamples=4,
            StereoMode=Graphic3d_StereoMode_QuadBuffer,
            AnaglyphFilter=Graphic3d_RenderingParams.
            Anaglyph_RedCyan_Optimized,
            ToReverseStereo=False)
        defaults.update(**params)
        for attr, v in defaults.items():
            setattr(rendering_params, attr, v)
        self.redraw()

    def set_background_gradient(self, gradient):
        """ Set the background gradient

        Parameters
        ----------
        gradient: Tuple
            Gradient parameters Color 1, Color 2, and optionally th fill method

        """
        c1, _ = color_to_quantity_color(gradient[0])
        c2, _ = color_to_quantity_color(gradient[1])
        fill_method = Aspect_GFM_VER
        if len(gradient) == 3:
            attr = 'Aspect_GFM_{}'.format(gradient[2].upper())
            fill_method = getattr(Aspect, attr, Aspect_GFM_VER)
        self.v3d_view.SetBgGradientColors(c1, c2, fill_method, True)

    def set_shape_color(self, color):
        self.shape_color = color_to_quantity_color(color)

    def set_trihedron_mode(self, mode):
        attr = 'Aspect_TOTP_{}'.format(mode.upper().replace("-", "_"))
        position = getattr(Aspect, attr)
        self.v3d_view.TriedronDisplay(position, BLACK, 0.1, V3d.V3d_ZBUFFER)
        self.redraw()

    def set_grid_mode(self, mode):
        if not mode:
            self.v3d_viewer.DeactivateGrid()
        else:
            a, b = mode.title().split("-")
            grid_type = getattr(Aspect_GridType, f'Aspect_GT_{a}')
            grid_mode = getattr(Aspect_GridDrawMode, f'Aspect_GDM_{b}')
            self.v3d_viewer.ActivateGrid(grid_type, grid_mode)

    def set_grid_colors(self, colors):
        c1, _ = color_to_quantity_color(colors[0])
        c2, _ = color_to_quantity_color(colors[1])
        grid = self.v3d_viewer.Grid()
        grid.SetColors(c1, c2)

    # -------------------------------------------------------------------------
    # Viewer interaction
    # -------------------------------------------------------------------------
    def set_selection_mode(self, mode):
        """ Set the selection mode.

        Parameters
        ----------
        mode: String
            The mode to use (Face, Edge, Vertex, Shell, or Solid)

        """
        ais_context = self.ais_context
        ais_context.Deactivate()
        if mode == 'any':
            for mode in (TopAbs.TopAbs_SHAPE, TopAbs.TopAbs_SHELL,
                         TopAbs.TopAbs_FACE, TopAbs.TopAbs_EDGE,
                         TopAbs.TopAbs_WIRE, TopAbs.TopAbs_VERTEX):
                ais_context.Activate(AIS_Shape.SelectionMode_(mode))
            return
        attr = 'TopAbs_%s' % mode.upper()
        mode = getattr(TopAbs, attr, TopAbs.TopAbs_SHAPE)
        ais_context.Activate(AIS_Shape.SelectionMode_(mode))

    def set_display_mode(self, mode):
        mode = V3D_DISPLAY_MODES.get(mode)
        if mode is None:
            return
        self.ais_context.SetDisplayMode(mode, True)
        self.redraw()

    def set_view_mode(self, mode):
        """ Set the view mode or (or direction)

        Parameters
        ----------
        mode: String
            The mode to or direction to view.

        """
        mode = V3D_VIEW_MODES.get(mode.lower())
        if mode is None:
            return
        self.v3d_view.SetProj(mode)

    def set_view_projection(self, mode):
        mode = getattr(Graphic3d_Camera, 'Projection_%s' % mode.title())
        self.camera.SetProjectionType(mode)
        self.redraw()

    def set_lock_rotation(self, locked):
        self.widget._lock_rotation = locked

    def set_lock_zoom(self, locked):
        self.widget._lock_zoom = locked

    def zoom_factor(self, factor):
        self.v3d_view.SetZoom(factor)

    def rotate_view(self, x=0, y=0, z=0):
        self.v3d_view.Rotate(x, y, z, True)

    def turn_view(self, x=0, y=0, z=0):
        self.v3d_view.Turn(x, y, z, True)

    def fit_all(self):
        view = self.v3d_view
        view.FitAll()
        view.ZFitAll()
        self.redraw()

    def fit_selection(self):
        if not self._selected_shapes:
            return

        # Compute bounding box of the selection
        view = self.v3d_view
        pad = 20
        bbox = self.get_bounding_box(self._selected_shapes)
        xmin, ymin = self.get_screen_coordinate(bbox[0:3])
        xmax, ymax = self.get_screen_coordinate(bbox[3:6])
        cx, cy = int(xmin + (xmax - xmin) / 2), int(ymin + (ymax - ymin) / 2)
        self.ais_context.MoveTo(cx, cy, view, True)
        view.WindowFit(xmin - pad, ymin - pad, xmax + pad, ymax + pad)

    def take_screenshot(self, filename):
        return self.v3d_view.Dump(filename)

    # -------------------------------------------------------------------------
    # Display Handling
    # -------------------------------------------------------------------------

    def update_selection(self, pos, area, shift):
        """ Update the selection state

        """
        widget = self.widget
        view = self.v3d_view
        ais_context = self.ais_context

        if area:
            xmin, ymin, dx, dy = area
            ais_context.Select(xmin, ymin, xmin + dx, ymin + dy, view, True)
        elif shift:
            # multiple select if shift is pressed
            ais_context.ShiftSelect(True)
        else:
            ais_context.Select(True)
        ais_context.InitSelected()

        # Lookup the shape declrations based on the selection context
        selection = {}
        shapes = []
        displayed_shapes = self._displayed_shapes
        occ_shapes = set(self._displayed_shapes.values())
        while ais_context.MoreSelected():
            if ais_context.HasSelectedShape():
                i = None
                found = False
                topods_shape = Topology.cast_shape(ais_context.SelectedShape())
                shape_type = topods_shape.ShapeType()
                attr = str(shape_type).split("_")[-1].lower() + 's'

                # Try long lookup based on topology
                for occ_shape in occ_shapes:
                    shape_list = getattr(occ_shape.topology, attr, None)
                    if not shape_list:
                        continue
                    for i, s in enumerate(shape_list):
                        if topods_shape.IsPartner(s):
                            found = True
                            break
                    if found:
                        d = occ_shape.declaration
                        shapes.append(topods_shape)
                        # Insert what was selected into the options
                        info = selection.get(d)
                        if info is None:
                            info = selection[d] = {}
                        selection_info = info.get(attr)
                        if selection_info is None:
                            selection_info = info[attr] = {}
                        selection_info[i] = topods_shape
                        break

                # Mark it as found we don't know what shape it's from
                if not found:
                    if None not in selection:
                        selection[None] = {}
                    if attr not in selection[None]:
                        selection[None][attr] = {}
                    info = selection[None][attr]
                    # Just keep incrementing the index
                    info[len(info)] = topods_shape

            ais_context.NextSelected()

        if shift:
            ais_context.UpdateSelected(True)
        # Set selection
        self._selected_shapes = shapes
        self.declaration.selection = ViewerSelection(selection=selection,
                                                     position=pos,
                                                     area=area)

    def update_display(self, change=None):
        """ Queue an update request """
        self._redisplay_timer.start()

    def clear_display(self):
        """ Remove all shapes and dimensions drawn """
        # Erase all just hides them
        remove = self.ais_context.Remove
        for occ_shape in self._displayed_shapes.values():
            remove(occ_shape.ais_shape, False)
        for ais_dim in self._displayed_dimensions.keys():
            remove(ais_dim, False)
        for ais_item in self._displayed_graphics.keys():
            remove(ais_item, False)
        self.gfx_structure.Clear()
        self.ais_context.UpdateCurrentViewer()

    def reset_view(self):
        """ Reset to default zoom and orientation """
        self.v3d_view.Reset()

    @contextmanager
    def redraw_blocked(self):
        """ Temporarily stop redraw during """
        self._redraw_blocked = True
        yield
        self._redraw_blocked = False

    def redraw(self):
        if not self._redraw_blocked:
            self.v3d_view.Redraw()

    def update(self):
        """ Redisplay """
        self.ais_context.UpdateCurrentViewer()
示例#34
0
def safe_setattr(obj, name, value):
    if Application.instance() is None:
        return setattr(obj, name, value)
    deferred_call(setattr, obj, name, value)
示例#35
0
def safe_getattr(obj, name, default=None):
    if Application.instance() is None:
        return getattr(obj, name, default)
    return schedule(getattr, args=(obj, name, default))
示例#36
0
def _app_style_sheet():
    app = Application.instance()
    if app is not None:
        return app.style_sheet