예제 #1
0
    def __init__(self, session, parent=None):

        super(SpecvizViewer, self).__init__(session, parent=parent)

        # We set up the specviz viewer and controller as done for the standalone
        # specviz application
        self.viewer = Viewer()
        self.controller = Controller(self.viewer)
        self.setCentralWidget(self.viewer)

        # We now set up the options widget. This controls for example which
        # attribute should be used to indicate the filenames of the spectra.
        self._options_widget = OptionsWidget(data_viewer=self)

        # The layer widget is used to select which data or subset to show.
        # We don't use the default layer list, because in this case we want to
        # make sure that only one dataset or subset can be selected at any one
        # time.
        self._layer_widget = LayerWidget()

        # We keep a cache of the specviz data objects that correspond to a given
        # filename - although this could take up a lot of memory if there are
        # many spectra, so maybe this isn't needed
        self._specviz_data_cache = {}

        # Make sure we update the viewer if either the selected layer or the
        # column specifying the filename is changed.
        self._layer_widget.ui.combo_active_layer.currentIndexChanged.connect(nonpartial(self._update_options))
        self._layer_widget.ui.combo_active_layer.currentIndexChanged.connect(nonpartial(self._refresh_specviz_data))
        self._options_widget.ui.combo_file_attribute.currentIndexChanged.connect(nonpartial(self._refresh_specviz_data))
예제 #2
0
    def __init__(self, layer, axes, viewer_state):

        # Keep a reference to the layer (data or subset) and axes
        self.layer = layer
        self.axes = axes
        self.viewer_state = viewer_state

        # Watch for changes in the viewer state which would require the
        # layers to be redrawn
        # TODO: don't connect to ALL signals here
        self.viewer_state.connect_all(nonpartial(self.update))

        # Set up a state object for the layer artists
        self.layer_state = ScatterLayerState()
        self.layer_state.layer = layer
        self.layer_state.connect_all(self.update)

        # TODO: need to connect to visual properties of layer in one go
        add_callback(self.layer.style, 'color', nonpartial(self.update))
        add_callback(self.layer.style, 'markersize', nonpartial(self.update))

        # Set up the layer style editor
        self.style_editor = ScatterLayerStyleEditor(self.layer_state)

        # Set up an initially empty artist
        self.artist1 = self.axes.plot([], [], 'o')[0]
        self.artist2 = self.axes.plot([], [], '-')[0]

        self.zorder = 0
        self.update()
예제 #3
0
파일: application.py 프로젝트: pllim/glue
    def __init__(self, parent=None):
        super(GlueLogger, self).__init__(parent)
        self._text = QtWidgets.QTextEdit()
        self._text.setTextInteractionFlags(Qt.TextSelectableByMouse)

        clear = QtWidgets.QPushButton("Clear")
        clear.clicked.connect(nonpartial(self._clear))

        report = QtWidgets.QPushButton("Send Bug Report")
        report.clicked.connect(nonpartial(self._send_report))

        self.stderr = sys.stderr
        sys.stderr = self

        self._status = ClickableLabel()
        self._status.setToolTip("View Errors and Warnings")
        self._status.clicked.connect(self._show)
        self._status.setPixmap(status_pixmap())
        self._status.setContentsMargins(0, 0, 0, 0)

        l = QtWidgets.QVBoxLayout()
        h = QtWidgets.QHBoxLayout()
        l.setContentsMargins(2, 2, 2, 2)
        l.setSpacing(2)
        h.setContentsMargins(0, 0, 0, 0)

        l.addWidget(self._text)
        h.insertStretch(0)
        h.addWidget(report)
        h.addWidget(clear)
        l.addLayout(h)

        self.setLayout(l)
예제 #4
0
    def __init__(self, vispy_viewer, layer=None, layer_state=None):

        super(ScatterLayerArtist, self).__init__(layer)

        self._clip_limits = None

        self._marker_keep = Ellipsis

        # Set data caches
        self._marker_data = None
        self._color_data = None
        self._size_data = None

        self.layer = layer or layer_state.layer
        self.vispy_viewer = vispy_viewer
        self.vispy_widget = vispy_viewer._vispy_widget

        # TODO: need to remove layers when layer artist is removed
        self._viewer_state = vispy_viewer.state
        self.state = layer_state or ScatterLayerState(layer=self.layer)
        if self.state not in self._viewer_state.layers:
            self._viewer_state.layers.append(self.state)

        # We create a unique ID for this layer artist, that will be used to
        # refer to the layer artist in the MultiColorScatter. We have to do this
        # rather than use self.id because we can't guarantee the latter is
        # unique.
        self.id = str(uuid.uuid4())

        # We need to use MultiColorScatter instance to store scatter plots, but
        # we should only have one per canvas. Therefore, we store the
        # MultiColorScatter instance in the vispy viewer instance.
        if not hasattr(self.vispy_widget, '_multiscat'):
            multiscat = MultiColorScatter()
            multiscat.set_gl_state(depth_test=False,
                                   blend=True,
                                   blend_func=('src_alpha', 'one_minus_src_alpha'))

            self.vispy_widget.add_data_visual(multiscat)
            self.vispy_widget._multiscat = multiscat

        self._multiscat = self.vispy_widget._multiscat
        self._multiscat.allocate(self.id)
        self._multiscat.set_zorder(self.id, self.get_zorder)

        try:
            self.state.add_callback('*', self._update_from_state, as_kwargs=True)
        except TypeError:  # glue-core >= 0.11
            self.state.add_global_callback(self._update_from_state)

        self._update_from_state(**self.state.as_dict())

        self._viewer_state.add_callback('x_att', nonpartial(self._update_data))
        self._viewer_state.add_callback('y_att', nonpartial(self._update_data))
        self._viewer_state.add_callback('z_att', nonpartial(self._update_data))

        self._update_data()

        self.visible = True
예제 #5
0
파일: viewer_widget.py 프로젝트: pllim/glue
 def register_to_hub(self, hub):
     super(ScatterWidget, self).register_to_hub(hub)
     self.client.register_to_hub(hub)
     hub.subscribe(self, core.message.DataUpdateMessage,
                   nonpartial(self._sync_labels))
     hub.subscribe(self, core.message.ComponentsChangedMessage,
                   nonpartial(self._update_combos))
     hub.subscribe(self, core.message.ComponentReplacedMessage,
                   self._on_component_replace)
예제 #6
0
    def __init__(self, vispy_widget=None, parent=None):

        super(VispyDataViewerToolbar, self).__init__(parent=parent)

        # Keep a reference to the Vispy Widget and the Vispy Data Viewer
        self._vispy_widget = vispy_widget
        self._vispy_data_viewer = parent
        self._data_collection = parent._data

        # Set visual preferences
        self.setIconSize(QtCore.QSize(25, 25))

        # Initialize drawing visual
        self.line_pos = []
        self.line = scene.visuals.Line(color='white', method='gl', parent=self._vispy_widget.canvas.scene)

        # Selection defaults
        self._scatter = None
        self.mode = None
        self.selection_origin = (0, 0)
        self.selected = []

        # Set up selection actions
        a = QtGui.QAction(get_icon('glue_lasso'), 'Lasso Selection', parent)
        a.triggered.connect(nonpartial(self.toggle_lasso))
        a.setCheckable(True)
        parent.addAction(a)
        self.addAction(a)
        self.lasso_action = a

        a = QtGui.QAction(get_icon('glue_square'), 'Rectangle Selection', parent)
        a.triggered.connect(nonpartial(self.toggle_rectangle))
        a.setCheckable(True)
        parent.addAction(a)
        self.addAction(a)
        self.rectangle_action = a

        a = QtGui.QAction(get_icon('glue_circle'), 'Ellipse Selection', parent)
        a.triggered.connect(nonpartial(self.toggle_ellipse))
        a.setCheckable(True)
        parent.addAction(a)
        self.addAction(a)
        self.ellipse_action = a

        # TODO: change path to icon once it's in a released version of glue
        a = QtGui.QAction(QtGui.QIcon(POINT_ICON), 'Point Selection', parent)
        a.triggered.connect(nonpartial(self.toggle_point))
        a.setCheckable(True)
        parent.addAction(a)
        self.addAction(a)
        self.point_action = a

        # Connect callback functions to VisPy Canvas
        self._vispy_widget.canvas.events.mouse_press.connect(self.on_mouse_press)
        self._vispy_widget.canvas.events.mouse_release.connect(self.on_mouse_release)
        self._vispy_widget.canvas.events.mouse_move.connect(self.on_mouse_move)
예제 #7
0
파일: viewer_widget.py 프로젝트: pllim/glue
    def initialize_toolbar(self):

        super(ImageWidget, self).initialize_toolbar()

        # connect viewport update buttons to client commands to
        # allow resampling
        cl = self.client
        self.toolbar.actions['mpl:home'].triggered.connect(nonpartial(cl.check_update))
        self.toolbar.actions['mpl:forward'].triggered.connect(nonpartial(cl.check_update))
        self.toolbar.actions['mpl:back'].triggered.connect(nonpartial(cl.check_update))
예제 #8
0
 def register_to_hub(self, hub):
     super(DataCollectionComboHelper, self).register_to_hub(hub)
     hub.subscribe(self, DataUpdateMessage,
                   handler=nonpartial(self.refresh),
                   filter=lambda msg: msg.sender in self._datasets)
     hub.subscribe(self,DataCollectionAddMessage,
                   handler=nonpartial(self.refresh),
                   filter=lambda msg: msg.sender is self._datasets)
     hub.subscribe(self, DataCollectionDeleteMessage,
                   handler=nonpartial(self.refresh),
                   filter=lambda msg: msg.sender is self._datasets)
예제 #9
0
    def __init__(self, label="", pix2world=None, lo=0, hi=10, parent=None, aggregation=None):
        super(SliceWidget, self).__init__(parent)
        if aggregation is not None:
            raise NotImplemented("Aggregation option not implemented")
        if pix2world is not None:
            raise NotImplemented("Pix2world option not implemented")

        layout = QtGui.QVBoxLayout()
        layout.setContentsMargins(3, 1, 3, 1)
        layout.setSpacing(0)

        top = QtGui.QHBoxLayout()
        top.setContentsMargins(3, 3, 3, 3)
        label = QtGui.QLabel(label)
        top.addWidget(label)

        mode = QtGui.QComboBox()
        mode.addItem("x", "x")
        mode.addItem("y", "y")
        mode.addItem("slice", "slice")
        mode.currentIndexChanged.connect(lambda x: self.mode_changed.emit(self.mode))
        mode.currentIndexChanged.connect(self._update_mode)
        top.addWidget(mode)

        layout.addLayout(top)

        slider = load_ui("data_slice_widget.ui", None, directory=os.path.dirname(__file__))
        slider.slider

        slider.slider.setMinimum(lo)
        slider.slider.setMaximum(hi)
        slider.slider.setValue((lo + hi) / 2)
        slider.slider.valueChanged.connect(lambda x: self.slice_changed.emit(self.mode))
        slider.slider.valueChanged.connect(lambda x: slider.label.setText(str(x)))

        slider.label.setMinimumWidth(50)
        slider.label.setText(str(slider.slider.value()))
        slider.label.textChanged.connect(lambda x: slider.slider.setValue(int(x)))

        slider.first.clicked.connect(nonpartial(self._browse_slice, "first"))
        slider.prev.clicked.connect(nonpartial(self._browse_slice, "prev"))
        slider.next.clicked.connect(nonpartial(self._browse_slice, "next"))
        slider.last.clicked.connect(nonpartial(self._browse_slice, "last"))

        layout.addWidget(slider)

        self.setLayout(layout)

        self._ui_label = label
        self._ui_slider = slider
        self._ui_mode = mode
        self._update_mode()
        self._frozen = False
예제 #10
0
    def __init__(self, parent=None):

        super(VispyWidget, self).__init__(parent=parent)

        # Prepare Vispy canvas. We set the depth_size to 24 to avoid issues
        # with isosurfaces on MacOS X
        self.canvas = scene.SceneCanvas(keys='interactive', show=False,
                                        config={'depth_size': 24}, bgcolor=rgb(settings.BACKGROUND_COLOR))

        # Set up a viewbox
        self.view = self.canvas.central_widget.add_view()
        self.view.parent = self.canvas.scene

        # Set whether we are emulating a 3D texture. This needs to be enabled
        # as a workaround on Windows otherwise VisPy crashes.
        self.emulate_texture = (sys.platform == 'win32' and
                                sys.version_info[0] < 3)

        self.scene_transform = scene.STTransform()
        self.limit_transforms = {}

        # Add a 3D cube to show us the unit cube. The 1.001 factor is to make
        # sure that the grid lines are not 'hidden' by volume renderings on the
        # front side due to numerical precision.
        vertices, filled_indices, outline_indices = create_cube()
        self.axis = scene.visuals.Mesh(vertices['position'],
                                       outline_indices,
                                       color=rgb(settings.FOREGROUND_COLOR), mode='lines')
        self.axis.transform = self.scene_transform
        self.view.add(self.axis)

        # Create a turntable camera. For now, this is the only camerate type
        # we support, but if we support more in future, we should implement
        # that here

        # Orthographic perspective view as default
        self.view.camera = scene.cameras.TurntableCamera(parent=self.view.scene, fov=0., distance=4.0)

        # Add the native canvas widget to this widget
        layout = QtGui.QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.canvas.native)
        self.setLayout(layout)

        # We need to call render here otherwise we'll later encounter an OpenGL
        # program validation error.
        self.canvas.render()

        # Set up callbacks
        add_callback(self, 'visible_axes', nonpartial(self._toggle_axes))
        add_callback(self, 'perspective_view', nonpartial(self._toggle_perspective))
예제 #11
0
    def __init__(self, parent=None):
        super(DataCollectionView, self).__init__(parent)
        self.doubleClicked.connect(self._edit)

        # this keeps the full-row of the selection bar in-sync
        self.pressed.connect(nonpartial(self._update_viewport))

        # only edit label on model.new_item
        self.setItemDelegate(LabeledDelegate())
        self.setEditTriggers(self.NoEditTriggers)

        self._timer = QtCore.QTimer(self)
        self._timer.timeout.connect(nonpartial(self._update_viewport))
        self._timer.start(1000)
예제 #12
0
    def menu_actions(self):
        result = []

        a = QtWidgets.QAction("minmax", None)
        a.triggered.connect(nonpartial(self.set_clip_percentile, 0, 100))
        result.append(a)

        a = QtWidgets.QAction("99%", None)
        a.triggered.connect(nonpartial(self.set_clip_percentile, 1, 99))
        result.append(a)

        a = QtWidgets.QAction("95%", None)
        a.triggered.connect(nonpartial(self.set_clip_percentile, 5, 95))
        result.append(a)

        a = QtWidgets.QAction("90%", None)
        a.triggered.connect(nonpartial(self.set_clip_percentile, 10, 90))
        result.append(a)

        rng = QtWidgets.QAction("Set range...", None)
        rng.triggered.connect(nonpartial(self.choose_vmin_vmax))
        result.append(rng)

        a = QtWidgets.QAction("", None)
        a.setSeparator(True)
        result.append(a)

        a = QtWidgets.QAction("linear", None)
        a.triggered.connect(nonpartial(setattr, self, 'stretch', 'linear'))
        result.append(a)

        a = QtWidgets.QAction("log", None)
        a.triggered.connect(nonpartial(setattr, self, 'stretch', 'log'))
        result.append(a)

        a = QtWidgets.QAction("sqrt", None)
        a.triggered.connect(nonpartial(setattr, self, 'stretch', 'sqrt'))
        result.append(a)

        a = QtWidgets.QAction("asinh", None)
        a.triggered.connect(nonpartial(setattr, self, 'stretch', 'arcsinh'))
        result.append(a)

        for r in result:
            if r is rng:
                continue
            if self._move_callback is not None:
                r.triggered.connect(nonpartial(self._move_callback, self))

        return result
예제 #13
0
파일: exporter.py 프로젝트: saimn/glue
    def __init__(self, plotly_args=[], plotly_kwargs={}, parent=None):

        super(QtPlotlyExporter, self).__init__(parent=parent)

        self.plotly_args = plotly_args
        self.plotly_kwargs = plotly_kwargs

        self.ui = load_ui('exporter.ui', self,
                          directory=os.path.dirname(__file__))

        self.button_cancel.clicked.connect(self.reject)
        self.button_export.clicked.connect(self.accept)

        # Set up radio button groups

        self._radio_account = QtWidgets.QButtonGroup()
        self._radio_account.addButton(self.ui.radio_account_glue)
        self._radio_account.addButton(self.ui.radio_account_config)
        self._radio_account.addButton(self.ui.radio_account_manual)

        self._radio_sharing = QtWidgets.QButtonGroup()
        self._radio_sharing.addButton(self.ui.radio_sharing_public)
        self._radio_sharing.addButton(self.ui.radio_sharing_secret)
        self._radio_sharing.addButton(self.ui.radio_sharing_private)

        # Find out stored credentials (note that this will create the
        # credentials file if it doesn't already exist)

        from plotly import plotly

        credentials = plotly.get_credentials()
        config_available = credentials['username'] != "" and credentials['api_key'] != ""

        if config_available:
            self.ui.radio_account_config.setChecked(True)
            label = self.ui.radio_account_config.text()
            self.ui.radio_account_config.setText(label + " (username: {0})".format(credentials['username']))
        else:
            self.ui.radio_account_glue.setChecked(True)
            self.ui.radio_account_config.setEnabled(False)

        self.ui.radio_sharing_secret.setChecked(True)

        self.ui.text_username.textChanged.connect(nonpartial(self._set_manual_mode))
        self.ui.text_api_key.textChanged.connect(nonpartial(self._set_manual_mode))
        self.ui.radio_account_glue.toggled.connect(nonpartial(self._set_allowed_sharing_modes))

        self.set_status('', color='black')

        self._set_allowed_sharing_modes()
예제 #14
0
    def _create_actions(self):
        tree = self.ui.layerTree

        sep = QtWidgets.QAction("", tree)
        sep.setSeparator(True)
        tree.addAction(sep)

        # Actions relating to I/O
        self._actions['save_data'] = ExportDataAction(self)
        self._actions['save_subset'] = ExportSubsetAction(self)
        self._actions['import_subset_mask'] = ImportSubsetMaskAction(self)
        self._actions['export_subset_mask'] = ExportSubsetMaskAction(self)

        self._actions['copy'] = CopyAction(self)
        self._actions['paste'] = PasteAction(self)
        self._actions['paste_special'] = PasteSpecialAction(self)
        self._actions['invert'] = Inverter(self)
        self._actions['new'] = NewAction(self)
        self._actions['clear'] = ClearAction(self)
        self._actions['delete'] = DeleteAction(self)
        self._actions['facet'] = FacetAction(self)
        self._actions['metadata'] = MetadataAction(self)
        self._actions['merge'] = MergeAction(self)
        self._actions['maskify'] = MaskifySubsetAction(self)
        self._actions['link'] = LinkAction(self)

        sep = QtWidgets.QAction("", tree)
        sep.setSeparator(True)
        tree.addAction(sep)

        a = action("Add/edit arithmetic attributes", self,
                   tip="Add/edit attributes derived from existing ones")
        tree.addAction(a)
        a.triggered.connect(nonpartial(self._create_component))
        self._actions['new_component'] = a

        a = action("Reorder/rename data attributes", self,
                   tip="Reorder/rename data attributes")
        tree.addAction(a)
        a.triggered.connect(nonpartial(self._manage_components))
        self._actions['manage_components'] = a

        # Add user-defined layer actions. Note that _asdict is actually a public
        # method, but just has an underscore to prevent conflict with
        # namedtuple attributes.
        for item in layer_action:
            self._actions[item.label] = UserAction(self, **item._asdict())

        # right click pulls up menu
        tree.setContextMenuPolicy(Qt.ActionsContextMenu)
예제 #15
0
    def __init__(self, state, attribute, cache=None, **kwargs):

        self._state = state
        self._attribute = attribute
        self._values = dict((key, kwargs[key]) for key in self.values_names if key in kwargs)
        self._modifiers = dict((key, kwargs[key]) for key in self.modifiers_names if key in kwargs)

        self._attribute_lookup = {'attribute': self._attribute}
        self._attribute_lookup.update(self._values)
        self._attribute_lookup.update(self._modifiers)
        self._attribute_lookup_inv = {v: k for k, v in self._attribute_lookup.items()}

        self._state.add_callback(self._attribute, nonpartial(self._update_attribute))

        for prop in self._modifiers.values():
            self._state.add_callback(prop, self._update_values, as_kwargs=True)

        for prop in self._values.values():
            self._state.add_callback(prop, self._update_values, as_kwargs=True)

        # NOTE: don't use self._cache = cache or {} here since if the initial
        #       cache is empty it will evaluate as False!
        if cache is None:
            self._cache = {}
        else:
            self._cache = cache
예제 #16
0
파일: simpleforms.py 프로젝트: PennyQ/glue
    def __init__(self, instance, option):
        super(BoolFormItem, self).__init__(instance, option)

        value = option.__get__(instance)
        self.widget = QtWidgets.QCheckBox()
        self.widget.setChecked(value)
        self.widget.clicked.connect(nonpartial(self.changed.emit))
예제 #17
0
    def __init__(self, layer, vispy_viewer):

        super(IsosurfaceLayerArtist, self).__init__(layer)

        self.layer = layer
        self.vispy_viewer = vispy_viewer

        self._iso_visual = scene.Isosurface(np.ones((3, 3, 3)), level=0.5, shading='smooth')
        self.vispy_viewer.add_data_visual(self._iso_visual)

        # Set up connections so that when any of the properties are
        # modified, we update the appropriate part of the visualization
        add_callback(self, 'attribute', nonpartial(self._update_data))
        add_callback(self, 'level', nonpartial(self._update_level))
        add_callback(self, 'color', nonpartial(self._update_color))
        add_callback(self, 'alpha', nonpartial(self._update_color))
예제 #18
0
    def __init__(self, application, parent=None):

        super(PreferencesDialog, self).__init__(parent=parent)

        self.app = application

        self.ui = load_ui('preferences.ui', self,
                          directory=os.path.dirname(__file__))

        self.ui.cancel.clicked.connect(self.reject)
        self.ui.ok.clicked.connect(self.accept)

        self.ui.combo_theme.currentIndexChanged.connect(nonpartial(self._update_colors_from_theme))

        from glue.config import settings
        self.background = settings.BACKGROUND_COLOR
        self.foreground = settings.FOREGROUND_COLOR
        self.data_color = settings.DATA_COLOR
        self.data_alpha = settings.DATA_ALPHA
        self.show_large_data_warning = settings.SHOW_LARGE_DATA_WARNING

        self._update_theme_from_colors()

        self.panes = []

        from glue.config import preference_panes
        for label, widget_cls in sorted(preference_panes):
            pane = widget_cls()
            self.ui.tab_widget.addTab(pane, label)
            self.panes.append(pane)
예제 #19
0
 def register_to_hub(self, hub):
     hub.subscribe(self, ComponentsChangedMessage,
                   handler=nonpartial(self.refresh),
                   filter=lambda msg: msg.data in self._data)
     hub.subscribe(self, DataCollectionDeleteMessage,
                   handler=lambda msg: self.remove_data(msg.data),
                   filter=lambda msg: msg.sender is self._data_collection)
예제 #20
0
    def __init__(self, session, parent=None):
        super(PyspeckitViewer, self).__init__(session, parent=parent)

        class Client(object):
            pass

        self.central_widget = MplWidget()
        self.client = Client()
        self.client.axes = self.central_widget.canvas.fig.add_subplot(1, 1, 1)

        self.central_widget = self.central_widget

        self._control_panel = ControlPanel()
        self._control_panel.modeChanged.connect(lambda mode: self.set_mode(init=True))
        self._control_panel.fitEvent.connect(nonpartial(self.run_fitter))
        # TODO: implement subtraction
        # self._control_panel.subtractEvent.connect(nonpartial(self.subtract))

        self._options_widget = OptionsWidget(data_viewer=self)

        self._splitter = QtWidgets.QSplitter()
        self._splitter.setOrientation(Qt.Horizontal)
        self._splitter.addWidget(self.central_widget)
        self._splitter.addWidget(self._control_panel)

        self.setCentralWidget(self._splitter)

        self.spectra = {}
        self.spectrum = None
예제 #21
0
    def __init__(self, **kwargs):

        super(Vispy3DViewerState, self).__init__(**kwargs)

        if self.limits_cache is None:
            self.limits_cache = {}

        self.x_lim_helper = StateAttributeLimitsHelper(self, attribute='x_att',
                                                       lower='x_min', upper='x_max',
                                                       cache=self.limits_cache)

        self.y_lim_helper = StateAttributeLimitsHelper(self, attribute='y_att',
                                                       lower='y_min', upper='y_max',
                                                       cache=self.limits_cache)

        self.z_lim_helper = StateAttributeLimitsHelper(self, attribute='z_att',
                                                       lower='z_min', upper='z_max',
                                                       cache=self.limits_cache)

        # TODO: if limits_cache is re-assigned to a different object, we need to
        # update the attribute helpers. However if in future we make limits_cache
        # into a smart dictionary that can call callbacks when elements are
        # changed then we shouldn't always call this. It'd also be nice to
        # avoid this altogether and make it more clean.
        self.add_callback('limits_cache', nonpartial(self._update_limits_cache))
예제 #22
0
파일: link_equation.py 프로젝트: saimn/glue
 def _add_argument_widget(self, argument):
     """ Create and add a single argument widget to the input canvas
     :param arguement: The argument name (string)
     """
     widget = ArgumentWidget(argument)
     widget.editor.textChanged.connect(nonpartial(self._update_add_enabled))
     self._ui.input_canvas.layout().addWidget(widget)
     self._argument_widgets.append(widget)
예제 #23
0
파일: mouse_modes.py 프로젝트: saimn/glue
 def menu_actions(self):
     acts = []
     for label in ginga_cmap.get_names():
         cmap = ginga_cmap.get_cmap(label)
         a = ColormapAction(label, cmap, self.viewer)
         a.triggered.connect(nonpartial(self.viewer.client.set_cmap, cmap))
         acts.append(a)
     return acts
예제 #24
0
 def _connect(self):
     # attach Qt signals
     ds = self._ui.data_selector
     ds.currentIndexChanged.connect(nonpartial(self._set_components))
     self._ui.component_selector.currentItemChanged.connect(
         lambda *args: self.component_changed.emit())
     self._ui.data_selector.currentIndexChanged.connect(
         lambda *args: self.data_changed.emit())
예제 #25
0
    def make_toolbar(self):
        result = GlueToolbar(self.central_widget.canvas, self, name='Image')
        for mode in self._mouse_modes():
            result.add_mode(mode)

        cmap = _colormap_mode(self, self.client.set_cmap)
        result.addWidget(cmap)

        # connect viewport update buttons to client commands to
        # allow resampling
        cl = self.client
        result.buttons['HOME'].triggered.connect(nonpartial(cl.check_update))
        result.buttons['FORWARD'].triggered.connect(nonpartial(
            cl.check_update))
        result.buttons['BACK'].triggered.connect(nonpartial(cl.check_update))

        return result
예제 #26
0
 def menu_actions(self):
     from glue import config
     acts = []
     for label, cmap in config.colormaps:
         a = ColormapAction(label, cmap, self.viewer)
         a.triggered.connect(nonpartial(self.viewer.set_cmap, cmap))
         acts.append(a)
     return acts
예제 #27
0
    def __init__(self, parent=None):

        # Prepare Vispy canvas. We set the depth_size to 24 to avoid issues
        # with isosurfaces on MacOS X
        self.canvas = scene.SceneCanvas(keys=None, show=False,
                                        config={'depth_size': 24},
                                        bgcolor=rgb(settings.BACKGROUND_COLOR))

        # Set up a viewbox
        self.view = self.canvas.central_widget.add_view()
        self.view.parent = self.canvas.scene

        # Set whether we are emulating a 3D texture. This needs to be enabled
        # as a workaround on Windows otherwise VisPy crashes.
        self.emulate_texture = (sys.platform == 'win32' and
                                sys.version_info[0] < 3)

        self.scene_transform = scene.STTransform()
        self.limit_transforms = {}

        fc = rgb(settings.FOREGROUND_COLOR)

        self.axis = AxesVisual3D(axis_color=fc, tick_color=fc, text_color=fc,
                                 tick_width=1, minor_tick_length=2,
                                 major_tick_length=4, axis_width=0,
                                 tick_label_margin=10, axis_label_margin=25,
                                 tick_font_size=6, axis_font_size=8,
                                 view=self.view,
                                 transform=self.scene_transform)

        # Create a turntable camera. For now, this is the only camerate type
        # we support, but if we support more in future, we should implement
        # that here

        # Orthographic perspective view as default
        self.view.camera = scene.cameras.TurntableCamera(parent=self.view.scene,
                                                         fov=0., distance=4.0)

        # We need to call render here otherwise we'll later encounter an OpenGL
        # program validation error.
        # self.canvas.render()

        # Set up callbacks
        add_callback(self, 'visible_axes', nonpartial(self._toggle_axes))
        add_callback(self, 'perspective_view', nonpartial(self._toggle_perspective))
예제 #28
0
 def _make_mode(self, name, tip, icon, mode):
     a = action(name, self, tip, icon)
     a.setCheckable(True)
     a.triggered.connect(nonpartial(set_mode, mode))
     self._group.addAction(a)
     self.addAction(a)
     self._modes[mode] = a
     label = name.split()[0].lower().replace('&', '')
     self._modes[label] = mode
예제 #29
0
def connect_color(client, prop, widget):
    def update_widget(text):
        widget.setColor(text)

    def update_prop():
        setattr(client, prop, widget.color())

    add_callback(client, prop, update_widget)
    widget.colorChanged.connect(nonpartial(update_prop))
예제 #30
0
 def register_to_hub(self, hub):
     hub.subscribe(self,
                   ComponentsChangedMessage,
                   handler=nonpartial(self.refresh),
                   filter=lambda msg: msg.data in self._data)
     hub.subscribe(self,
                   DataCollectionDeleteMessage,
                   handler=lambda msg: self.remove_data(msg.data),
                   filter=lambda msg: msg.sender is self._data_collection)
예제 #31
0
    def __init__(self, layer, vispy_viewer):

        super(IsosurfaceLayerArtist, self).__init__(layer)

        self.layer = layer
        self.vispy_viewer = vispy_viewer

        self._iso_visual = Isosurface(np.ones((3, 3, 3)),
                                      level=0.5,
                                      shading='smooth')
        self.vispy_viewer.add_data_visual(self._iso_visual)

        # Set up connections so that when any of the properties are
        # modified, we update the appropriate part of the visualization
        add_callback(self, 'attribute', nonpartial(self._update_data))
        add_callback(self, 'level', nonpartial(self._update_level))
        add_callback(self, 'color', nonpartial(self._update_color))
        add_callback(self, 'alpha', nonpartial(self._update_color))
예제 #32
0
 def _make_mode(self, name, tip, icon, mode):
     a = action(name, self, tip, icon)
     a.setCheckable(True)
     a.triggered.connect(nonpartial(set_mode, mode))
     self._group.addAction(a)
     self.addAction(a)
     self._modes[mode] = a
     label = name.split()[0].lower().replace('&', '')
     self._modes[label] = mode
예제 #33
0
파일: toolbar.py 프로젝트: omad/glue
    def add_mode(self, mode):
        parent = QtWidgets.QToolBar.parent(self)

        def toggle():
            self._custom_mode(mode)

        def enable():
            # turn on if not
            if self._active != mode.mode_id:
                self._custom_mode(mode)

        action = QtWidgets.QAction(mode.icon, mode.action_text, parent)
        action.triggered.connect(nonpartial(toggle))
        parent.addAction(action)

        self.__signals.extend([toggle, enable])

        if mode.shortcut is not None:
            action.setShortcut(mode.shortcut)
            action.setShortcutContext(Qt.WidgetShortcut)

        action.setToolTip(mode.tool_tip)
        action.setCheckable(True)
        self.buttons[mode.mode_id] = action

        menu_actions = mode.menu_actions()
        if len(menu_actions) > 0:
            menu = QtWidgets.QMenu(self)
            for ma in mode.menu_actions():
                ma.setParent(self)
                menu.addAction(ma)
            action.setMenu(menu)
            menu.triggered.connect(nonpartial(enable))

        self.addAction(action)

        # bind action status to mode.enabled
        def toggle(state):
            action.setVisible(state)
            action.setEnabled(state)

        add_callback(mode, 'enabled', toggle)

        return action
예제 #34
0
    def __init__(self, instance, option):
        super(NumberFormItem, self).__init__(instance, option)

        value = option.__get__(instance)

        w = self.widget_cls()
        w.setRange(option.min, option.max)
        w.setValue(value)
        w.valueChanged.connect(nonpartial(self.changed.emit))
        self.widget = w
예제 #35
0
    def _build_ui(self):
        w = QtGui.QComboBox()
        for p in sorted(self.params):
            w.addItem(p)

        if isinstance(self.params, list):
            self.params = dict((p, p) for p in self.params)

        w.currentIndexChanged.connect(nonpartial(self.changed))
        return w
예제 #36
0
    def _create_actions(self):
        act = QtGui.QAction("Edit style", self)
        act.triggered.connect(nonpartial(self._edit_style))
        self.addAction(act)

        act = QtGui.QAction("Remove", self)
        act.setShortcut(QtGui.QKeySequence(Qt.Key_Backspace))
        act.setShortcutContext(Qt.WidgetShortcut)
        act.triggered.connect(lambda *args: self.model().removeRow(self.current_row()))
        self.addAction(act)
예제 #37
0
    def menu_actions(self):
        from ginga.ColorDist import get_dist_names
        result = []

        for algname in get_dist_names():
            a = QtWidgets.QAction(algname, None)
            a.triggered.connect(nonpartial(self.set_dist, algname))
            result.append(a)

        return result
예제 #38
0
    def register_to_hub(self, hub):

        super(ManualDataComboHelper, self).register_to_hub(hub)

        hub.subscribe(self, DataUpdateMessage,
                      handler=nonpartial(self.refresh),
                      filter=lambda msg: msg.sender in self._datasets)
        hub.subscribe(self, DataCollectionDeleteMessage,
                      handler=lambda msg: self.remove(msg.data),
                      filter=lambda msg: msg.sender is self._data_collection)
예제 #39
0
    def _create_actions(self):
        act = QtGui.QAction('Edit style', self)
        act.triggered.connect(nonpartial(self._edit_style))
        self.addAction(act)

        act = QtGui.QAction('Remove', self)
        act.setShortcut(QtGui.QKeySequence(Qt.Key_Backspace))
        act.setShortcutContext(Qt.WidgetShortcut)
        act.triggered.connect(
            lambda *args: self.model().removeRow(self.current_row()))
        self.addAction(act)
예제 #40
0
파일: mouse_mode.py 프로젝트: omad/glue
    def menu_actions(self):
        result = []

        a = QtWidgets.QAction('Rectangle', None)
        a.triggered.connect(nonpartial(self.set_roi_tool, 'Rectangle'))
        result.append(a)

        a = QtWidgets.QAction('Circle', None)
        a.triggered.connect(nonpartial(self.set_roi_tool, 'Circle'))
        result.append(a)

        a = QtWidgets.QAction('Polygon', None)
        a.triggered.connect(nonpartial(self.set_roi_tool, 'Polygon'))
        result.append(a)

        for r in result:
            if self._move_callback is not None:
                r.triggered.connect(nonpartial(self._move_callback, self))

        return result
예제 #41
0
    def __init__(self, parent=None):

        super(VispyWidget, self).__init__(parent=parent)

        # Prepare Vispy canvas. We set the depth_size to 24 to avoid issues
        # with isosurfaces on MacOS X
        self.canvas = scene.SceneCanvas(keys='interactive',
                                        show=False,
                                        config={'depth_size': 24})

        # Set up a viewbox
        self.view = self.canvas.central_widget.add_view()
        self.view.parent = self.canvas.scene

        # Set whether we are emulating a 3D texture. This needs to be enabled
        # as a workaround on Windows otherwise VisPy crashes.
        self.emulate_texture = (sys.platform == 'win32'
                                and sys.version_info[0] < 3)

        self.scene_transform = scene.STTransform()
        self.limit_transforms = {}

        # Add a 3D cube to show us the unit cube. The 1.001 factor is to make
        # sure that the grid lines are not 'hidden' by volume renderings on the
        # front side due to numerical precision.
        vertices, filled_indices, outline_indices = create_cube()
        self.axis = scene.visuals.Mesh(vertices['position'],
                                       outline_indices,
                                       color=(1, 1, 1),
                                       mode='lines')
        self.axis.transform = self.scene_transform
        self.view.add(self.axis)

        # Create a turntable camera. For now, this is the only camerate type
        # we support, but if we support more in future, we should implement
        # that here

        # Remove the fov=60 here to solve the mismatch of selection problem
        # self.view.camera = scene.cameras.TurntableCamera(parent=self.view.scene, distance=2)
        self.view.camera = scene.cameras.TurntableCamera(
            parent=self.view.scene, distance=2.0)

        # Add the native canvas widget to this widget
        layout = QtGui.QVBoxLayout()
        layout.setContentsMargins(0, 0, 0, 0)
        layout.addWidget(self.canvas.native)
        self.setLayout(layout)

        # We need to call render here otherwise we'll later encounter an OpenGL
        # program validation error.
        self.canvas.render()

        # Set up callbacks
        add_callback(self, 'visible_axes', nonpartial(self._toggle_axes))
예제 #42
0
    def __init__(self, viewer_state, session, parent=None):

        super(HistogramOptionsWidget, self).__init__(parent=parent)

        self.ui = load_ui('options_widget.ui', self,
                          directory=os.path.dirname(__file__))

        autoconnect_callbacks_to_qt(viewer_state, self.ui)

        self.viewer_state = viewer_state

        viewer_state.add_callback('x_att', nonpartial(self._update_attribute))
예제 #43
0
    def _connect(self):
        ui = self.ui

        ui.monochrome.toggled.connect(self._update_rgb_console)
        ui.rgb_options.colors_changed.connect(self.update_window_title)

        # sync client and widget slices
        ui.slice.slice_changed.connect(lambda: setattr(self, 'slice', self.ui.slice.slice))
        update_ui_slice = lambda val: setattr(ui.slice, 'slice', val)
        add_callback(self.client, 'slice', update_ui_slice)
        add_callback(self.client, 'display_data', self.ui.slice.set_data)

        # sync window title to data/attribute
        add_callback(self.client, 'display_data', nonpartial(self._display_data_changed))
        add_callback(self.client, 'display_attribute', nonpartial(self._display_attribute_changed))
        add_callback(self.client, 'display_aspect', nonpartial(self.client._update_aspect))

        # sync data/attribute combos with client properties
        connect_current_combo(self.client, 'display_data', self.ui.displayDataCombo)
        connect_current_combo(self.client, 'display_attribute', self.ui.attributeComboBox)
        connect_current_combo(self.client, 'display_aspect', self.ui.aspectCombo)
예제 #44
0
    def menu_actions(self):

        result = []

        a = QtWidgets.QAction('Rectangle', None)
        a.triggered.connect(nonpartial(self.set_roi_tool, 'rectangle'))
        result.append(a)

        a = QtWidgets.QAction('Circle', None)
        a.triggered.connect(nonpartial(self.set_roi_tool, 'circle'))
        result.append(a)

        a = QtWidgets.QAction('Lasso', None)
        a.triggered.connect(nonpartial(self.set_roi_tool, 'freepolygon'))
        result.append(a)

        a = QtWidgets.QAction('Polygon', None)
        a.triggered.connect(nonpartial(self.set_roi_tool, 'polygon'))
        result.append(a)

        return result
예제 #45
0
    def __init__(self, button_console, parent=None):

        super(GlueLogger, self).__init__(parent)

        self.button_console = button_console
        self.button_stylesheet = button_console.styleSheet()

        self.button_console.clicked.connect(self._show)

        self._text = QtWidgets.QTextEdit()
        self._text.setTextInteractionFlags(Qt.TextSelectableByMouse)

        clear = QtWidgets.QPushButton("Clear")
        clear.clicked.connect(nonpartial(self._clear))

        report = QtWidgets.QPushButton("Send Bug Report")
        report.clicked.connect(nonpartial(self._send_report))

        if isinstance(sys.stderr, GlueLogger):
            if isinstance(sys.stderr._stderr_original, GlueLogger):
                raise Exception('Too many nested GlueLoggers')
            self._stderr_original = sys.stderr._stderr_original
        else:
            self._stderr_original = sys.stderr

        sys.stderr = self

        l = QtWidgets.QVBoxLayout()
        h = QtWidgets.QHBoxLayout()
        l.setContentsMargins(2, 2, 2, 2)
        l.setSpacing(2)
        h.setContentsMargins(0, 0, 0, 0)

        l.addWidget(self._text)
        h.insertStretch(0)
        h.addWidget(report)
        h.addWidget(clear)
        l.addLayout(h)

        self.setLayout(l)
예제 #46
0
    def _connect(self):
        """ Connect widget signals to methods """
        self._actions['link'] = LinkAction(self)
        self.layerAddButton.clicked.connect(nonpartial(self._load_data))
        self.layerRemoveButton.clicked.connect(self._actions['delete'].trigger)
        self.linkButton.set_action(self._actions['link'])
        self.newSubsetButton.set_action(self._actions['new'], text=False)

        rbut = self.layerRemoveButton

        def update_enabled():
            return rbut.setEnabled(self._actions['delete'].isEnabled())
        self.layerTree.selection_changed.connect(update_enabled)
예제 #47
0
    def register_to_hub(self, hub):

        super(TableWidget, self).register_to_hub(hub)

        def dfilter(x):
            return x.sender.data is self.data

        hub.subscribe(self, msg.SubsetCreateMessage,
                      handler=nonpartial(self._refresh),
                      filter=dfilter)

        hub.subscribe(self, msg.SubsetUpdateMessage,
                      handler=nonpartial(self._refresh),
                      filter=dfilter)

        hub.subscribe(self, msg.SubsetDeleteMessage,
                      handler=nonpartial(self._refresh),
                      filter=dfilter)

        hub.subscribe(self, msg.DataUpdateMessage,
                      handler=nonpartial(self._refresh),
                      filter=dfilter)
예제 #48
0
    def menu(self):
        m = QtGui.QMenu()

        a = QtGui.QAction("Or", m)
        a.setIcon(get_icon('glue_or'))
        a.triggered.connect(nonpartial(self._paste, OrMode))
        m.addAction(a)

        a = QtGui.QAction("And", m)
        a.setIcon(get_icon('glue_and'))
        a.triggered.connect(nonpartial(self._paste, AndMode))
        m.addAction(a)

        a = QtGui.QAction("XOR", m)
        a.setIcon(get_icon('glue_xor'))
        a.triggered.connect(nonpartial(self._paste, XorMode))
        m.addAction(a)

        a = QtGui.QAction("Not", m)
        a.setIcon(get_icon('glue_andnot'))
        a.triggered.connect(nonpartial(self._paste, AndNotMode))
        m.addAction(a)
        return m
예제 #49
0
    def __init__(self, session, parent=None):
        super(BaseVizViewer, self).__init__(session, parent=parent)

        # Connect the dataview to the specviz messaging system
        DispatchHandle.setup(self)

        # We now set up the options widget. This controls for example which
        # attribute should be used to indicate the filenames of the spectra.
        self._options_widget = OptionsWidget(data_viewer=self)

        # The layer widget is used to select which data or subset to show.
        # We don't use the default layer list, because in this case we want to
        # make sure that only one dataset or subset can be selected at any one
        # time.
        self._layer_widget = LayerWidget()

        # Make sure we update the viewer if either the selected layer or the
        # column specifying the filename is changed.
        self._layer_widget.ui.combo_active_layer.currentIndexChanged.connect(
            nonpartial(self._update_options))
        self._layer_widget.ui.combo_active_layer.currentIndexChanged.connect(
            nonpartial(self._refresh_data))
        self._options_widget.ui.combo_file_attribute.currentIndexChanged.connect(
            nonpartial(self._refresh_data))
    def __init__(self, session, viewer_state=None, parent=None):

        super(BaseVispyViewer, self).__init__(session, parent=parent)

        self.state = viewer_state or self._state_cls()

        if BROKEN_CONDA_PYQT5:
            QtWidgets.QMessageBox.critical(self, "Error", BROKEN_CONDA_PYQT5_MESSAGE)
            raise Exception(BROKEN_CONDA_PYQT5_MESSAGE)

        self._vispy_widget = VispyWidgetHelper(viewer_state=self.state)
        self.setCentralWidget(self._vispy_widget.canvas.native)

        self._options_widget = VispyOptionsWidget(parent=self, viewer_state=self.state)

        self.state.add_callback('clip_data', nonpartial(self._toggle_clip))

        self.status_label = None
        self.client = None

        # When layer artists are removed from the layer artist container, we need
        # to make sure we remove matching layer states in the viewer state
        # layers attribute.
        self._layer_artist_container.on_changed(nonpartial(self._sync_state_layers))
예제 #51
0
    def __init__(self, *args, **kwargs):

        super(QVersionsDialog, self).__init__(*args, **kwargs)

        self.ui = load_ui('versions.ui', self, directory=os.path.dirname(__file__))

        self.resize(400, 500)
        self.setWindowFlags(Qt.Window | Qt.WindowStaysOnTopHint)

        self.center()

        self._update_deps()

        self._clipboard = QtWidgets.QApplication.clipboard()
        self.ui.button_copy.clicked.connect(nonpartial(self._copy))
예제 #52
0
    def _create_actions(self):
        tree = self.ui.layerTree

        sep = QtWidgets.QAction("", tree)
        sep.setSeparator(True)
        tree.addAction(sep)

        # Actions relating to I/O
        self._actions['save_data'] = ExportDataAction(self)
        self._actions['save_subset'] = ExportSubsetAction(self)
        self._actions['import_subset_mask'] = ImportSubsetMaskAction(self)
        self._actions['export_subset_mask'] = ExportSubsetMaskAction(self)

        self._actions['copy'] = CopyAction(self)
        self._actions['paste'] = PasteAction(self)
        self._actions['paste_special'] = PasteSpecialAction(self)
        self._actions['invert'] = Inverter(self)
        self._actions['new'] = NewAction(self)
        self._actions['clear'] = ClearAction(self)
        self._actions['delete'] = DeleteAction(self)
        self._actions['facet'] = FacetAction(self)
        self._actions['merge'] = MergeAction(self)
        self._actions['maskify'] = MaskifySubsetAction(self)
        self._actions['link'] = LinkAction(self)

        # new component definer
        separator = QtWidgets.QAction("sep", tree)
        separator.setSeparator(True)
        tree.addAction(separator)

        a = action("Define new component",
                   self,
                   tip="Define a new component using python expressions")
        tree.addAction(a)
        a.triggered.connect(nonpartial(self._create_component))
        self._actions['new_component'] = a

        # user-defined layer actions
        for name, callback, tooltip, icon in single_subset_action:
            self._actions[name] = SingleSubsetUserAction(self,
                                                         callback,
                                                         name=name,
                                                         tooltip=tooltip,
                                                         icon=icon)

        # right click pulls up menu
        tree.setContextMenuPolicy(Qt.ActionsContextMenu)
예제 #53
0
파일: toolbar.py 프로젝트: omad/glue
    def _init_toolbar(self):
        self.basedir = os.path.join(matplotlib.rcParams['datapath'], 'images')
        parent = QtWidgets.QToolBar.parent(self)

        a = QtWidgets.QAction(get_icon('glue_home'), 'Home', parent)
        a.triggered.connect(nonpartial(self.home))
        a.setToolTip('Reset original zoom')
        a.setShortcut('H')
        a.setShortcutContext(Qt.WidgetShortcut)
        parent.addAction(a)
        self.buttons['HOME'] = a
        self.addAction(a)

        a = QtWidgets.QAction(get_icon('glue_filesave'), 'Save', parent)
        a.triggered.connect(nonpartial(self.save_figure))
        a.setToolTip('Save the figure')
        a.setShortcut('Ctrl+Shift+S')
        parent.addAction(a)
        self.buttons['SAVE'] = a
        self.addAction(a)

        a = QtWidgets.QAction(get_icon('glue_back'), 'Back', parent)
        a.triggered.connect(nonpartial(self.back))
        parent.addAction(a)
        self.addAction(a)
        self.buttons['BACK'] = a
        a.setToolTip('Back to previous view')

        a = QtWidgets.QAction(get_icon('glue_forward'), 'Forward', parent)
        a.triggered.connect(nonpartial(self.forward))
        a.setToolTip('Forward to next view')
        parent.addAction(a)
        self.buttons['FORWARD'] = a
        self.addAction(a)

        a = QtWidgets.QAction(get_icon('glue_move'), 'Pan', parent)
        a.triggered.connect(nonpartial(self.pan))
        a.setToolTip('Pan axes with left mouse, zoom with right')
        a.setCheckable(True)
        a.setShortcut('M')
        a.setShortcutContext(Qt.WidgetShortcut)
        parent.addAction(a)
        self.addAction(a)
        self.buttons['PAN'] = a

        a = QtWidgets.QAction(get_icon('glue_zoom_to_rect'), 'Zoom', parent)
        a.triggered.connect(nonpartial(self.zoom))
        a.setToolTip('Zoom to rectangle')
        a.setShortcut('Z')
        a.setShortcutContext(Qt.WidgetShortcut)
        a.setCheckable(True)
        parent.addAction(a)
        self.addAction(a)
        self.buttons['ZOOM'] = a
예제 #54
0
    def _create_actions(self):
        tree = self.ui.layerTree

        sep = QtWidgets.QAction("", tree)
        sep.setSeparator(True)
        tree.addAction(sep)

        # Actions relating to I/O
        self._actions['save_data'] = ExportDataAction(self)
        self._actions['save_subset'] = ExportSubsetAction(self)
        self._actions['import_subset_mask'] = ImportSubsetMaskAction(self)
        self._actions['export_subset_mask'] = ExportSubsetMaskAction(self)

        self._actions['copy'] = CopyAction(self)
        self._actions['paste'] = PasteAction(self)
        self._actions['paste_special'] = PasteSpecialAction(self)
        self._actions['invert'] = Inverter(self)
        self._actions['new'] = NewAction(self)
        self._actions['clear'] = ClearAction(self)
        self._actions['delete'] = DeleteAction(self)
        self._actions['facet'] = FacetAction(self)
        self._actions['merge'] = MergeAction(self)
        self._actions['maskify'] = MaskifySubsetAction(self)
        self._actions['link'] = LinkAction(self)

        sep = QtWidgets.QAction("", tree)
        sep.setSeparator(True)
        tree.addAction(sep)

        a = action("Add/edit data components",
                   self,
                   tip="Change existing data components and add new "
                   "components derived from existing ones")
        tree.addAction(a)
        a.triggered.connect(nonpartial(self._create_component))
        self._actions['new_component'] = a

        # Add user-defined layer actions. Note that _asdict is actually a public
        # method, but just has an underscore to prevent conflict with
        # namedtuple attributes.
        for item in layer_action:
            self._actions[item.label] = UserAction(self, **item._asdict())

        # right click pulls up menu
        tree.setContextMenuPolicy(Qt.ActionsContextMenu)
예제 #55
0
    def __init__(self, parent=None):
        super(LayerArtistView, self).__init__(parent)
        self.setDragEnabled(True)
        self.setAcceptDrops(True)
        self.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
        self.setIconSize(QtCore.QSize(15, 15))
        self.setSelectionMode(QtGui.QAbstractItemView.SingleSelection)
        self.setSelectionBehavior(QtGui.QAbstractItemView.SelectRows)
        self.setContextMenuPolicy(Qt.ActionsContextMenu)
        self.setEditTriggers(self.NoEditTriggers)

        self._set_palette()
        self._actions = {}
        self._create_actions()

        self._timer = QtCore.QTimer(self)
        self._timer.timeout.connect(nonpartial(self._update_viewport))
        self._timer.start(1000)
예제 #56
0
    def __init__(self, viewer_state, session, parent=None):

        super(HistogramOptionsWidget, self).__init__(parent=parent)

        self.ui = load_ui('options_widget.ui',
                          self,
                          directory=os.path.dirname(__file__))

        autoconnect_callbacks_to_qt(viewer_state, self.ui)

        viewer_state.add_callback('layers', self._update_combo_data)

        self.x_att_helper = ComponentIDComboHelper(self.ui.combodata_x_att,
                                                   session.data_collection)

        self.viewer_state = viewer_state

        viewer_state.add_callback('x_att', nonpartial(self._update_attribute))
예제 #57
0
    def __init__(self, layer, vispy_viewer):

        super(VolumeLayerArtist, self).__init__(layer)

        self.layer = layer
        self.vispy_viewer = vispy_viewer

        # We create a unique ID for this layer artist, that will be used to
        # refer to the layer artist in the MultiVolume. We have to do this
        # rather than use self.id because we can't guarantee the latter is
        # unique.
        self.id = str(uuid.uuid4())

        # We need to use MultiVolume instance to store volumes, but we should
        # only have one per canvas. Therefore, we store the MultiVolume
        # instance in the vispy viewer instance.
        if not hasattr(vispy_viewer, '_multivol'):

            # Set whether we are emulating a 3D texture. This needs to be
            # enabled as a workaround on Windows otherwise VisPy crashes.
            emulate_texture = (sys.platform == 'win32'
                               and sys.version_info[0] < 3)

            try:
                multivol = MultiVolume(threshold=0.1,
                                       emulate_texture=emulate_texture)
            except:
                multivol = MultiVolumeLegacy(threshold=0.1,
                                             emulate_texture=emulate_texture)

            self.vispy_viewer.add_data_visual(multivol)
            vispy_viewer._multivol = multivol

        self._multivol = vispy_viewer._multivol
        self._multivol.allocate(self.id)

        # Set up connections so that when any of the properties are
        # modified, we update the appropriate part of the visualization
        add_callback(self, 'attribute', nonpartial(self._update_data))
        add_callback(self, 'vmin', nonpartial(self._update_limits))
        add_callback(self, 'vmax', nonpartial(self._update_limits))
        add_callback(self, 'color', nonpartial(self._update_cmap_from_color))
        add_callback(self, 'cmap', nonpartial(self._update_cmap))
        add_callback(self, 'alpha', nonpartial(self._update_alpha))
        if isinstance(self.layer, Subset):
            add_callback(self, 'subset_mode', nonpartial(self._update_data))
예제 #58
0
    def _connect(self):
        ui = self.ui
        cl = self.client

        connect_bool_button(cl, 'xlog', ui.xLogCheckBox)
        connect_bool_button(cl, 'ylog', ui.yLogCheckBox)
        connect_bool_button(cl, 'xflip', ui.xFlipCheckBox)
        connect_bool_button(cl, 'yflip', ui.yFlipCheckBox)

        ui.xAxisComboBox.currentIndexChanged.connect(self.update_xatt)
        ui.yAxisComboBox.currentIndexChanged.connect(self.update_yatt)
        ui.hidden_attributes.toggled.connect(lambda x: self._update_combos())
        ui.swapAxes.clicked.connect(nonpartial(self.swap_axes))
        ui.snapLimits.clicked.connect(cl.snap)

        connect_float_edit(cl, 'xmin', ui.xmin)
        connect_float_edit(cl, 'xmax', ui.xmax)
        connect_float_edit(cl, 'ymin', ui.ymin)
        connect_float_edit(cl, 'ymax', ui.ymax)
예제 #59
0
    def __init__(self, session, parent=None, wcs=None, state=None):

        super(MatplotlibDataViewer, self).__init__(session,
                                                   parent,
                                                   state=state)

        # Use MplWidget to set up a Matplotlib canvas inside the Qt window
        self.mpl_widget = MplWidget()
        self.setCentralWidget(self.mpl_widget)

        # TODO: shouldn't have to do this
        self.central_widget = self.mpl_widget

        self.figure, self._axes = init_mpl(self.mpl_widget.canvas.fig, wcs=wcs)

        self.state.add_callback('aspect', self.update_aspect)

        self.update_aspect()

        self.state.add_callback('x_min', nonpartial(self.limits_to_mpl))
        self.state.add_callback('x_max', nonpartial(self.limits_to_mpl))
        self.state.add_callback('y_min', nonpartial(self.limits_to_mpl))
        self.state.add_callback('y_max', nonpartial(self.limits_to_mpl))

        self.limits_to_mpl()

        self.state.add_callback('x_log', nonpartial(self.update_x_log))
        self.state.add_callback('y_log', nonpartial(self.update_y_log))

        self.update_x_log()

        self.axes.callbacks.connect('xlim_changed',
                                    nonpartial(self.limits_from_mpl))
        self.axes.callbacks.connect('ylim_changed',
                                    nonpartial(self.limits_from_mpl))

        self.axes.set_autoscale_on(False)

        self.central_widget.resize(600, 400)
        self.resize(self.central_widget.size())