示例#1
0
class TextConfigEditor(QPlainTextEdit):

    new_config = pyqtSignal(str)

    def __init__(self, *args):
        super(TextConfigEditor, self).__init__(*args)
        self._timer = TimedUpdate(self._timer_event)
        self.textChanged.connect(lambda: self._timer.add_delayed_callback(400))

    @pyqtSlot()
    def _timer_event(self):
        self.new_config.emit(self.toPlainText())
示例#2
0
class ScientificNumberScroller(Ui_ScientificScroller, QWidget):

    valueChanged = pyqtSignal([float], ['QString'])

    def __init__(self, parent):
        super(ScientificNumberScroller, self).__init__(parent)
        self.setupUi(self)
        self.mantissa.valueChanged.connect(self._value_changed_cb)
        self.exponent.valueChanged.connect(self._value_changed_cb)
        self._timer = TimedUpdate(self._signal_new_value)
        self._update_delay = 0

    @pyqtSlot()
    def _value_changed_cb(self):
        return self._timer.add_delayed_callback(self._update_delay)

    def set_update_delay(self, update_delay):
        self._update_delay = update_delay

    @pyqtSlot()
    def _signal_new_value(self):
        self.valueChanged.emit(self.mantissa.value() *
                               10**self.exponent.value())

    @pyqtSlot(float)
    def setValue(self, value):
        if value == 0:
            self.exponent.setValue(0)
            self.mantissa.setValue(0)
        elif 1e-3 < np.abs(value) < 1e3:
            self.exponent.setValue(0)
            self.mantissa.setValue(value)
        else:
            exponent = int(np.floor(np.log10(np.abs(value))))
            self.exponent.setValue(exponent)
            self.mantissa.setValue(value / 10**exponent)

    def blockSignals(self, block):
        self.mantissa.blockSignals(block)
        return self.exponent.blockSignals(block)
示例#3
0
class TabGeneral(QWidget, Ui_TabGeneral):

    def __init__(self, controller, parent=None):
        super(TabGeneral, self).__init__(parent)
        self.setupUi(self)

        self._controller = controller
        self._controller.new_data.connect(self.set_new_data)
        self._controller.new_config.connect(self.set_new_config)

        self.general_display_order.setDragDropMode(QAbstractItemView.InternalMove)
        self.general_display_order.setSelectionMode(QAbstractItemView.SingleSelection)

        self.general_colormap.addItems(self._controller.get_config().get_available_colormaps())
        self.general_rotate.addItems(['0', '90', '180', '270'])
        self.general_rotate.setCurrentText(str(self._controller.get_config().rotate))

        self.general_DisplayOrder.set_collapse(True)
        self.general_Miscellaneous.set_collapse(True)
        self.general_Zoom.set_collapse(True)
        self.general_Font.set_collapse(True)

        self.general_dimension.valueChanged.connect(lambda v: self._controller.apply_action(SetDimension(v)))
        self.general_slice_index.valueChanged.connect(lambda v: self._controller.apply_action(SetSliceIndex(v)))
        self.general_volume_index.valueChanged.connect(lambda v: self._controller.apply_action(SetVolumeIndex(v)))
        self.general_colormap.currentIndexChanged.connect(
            lambda i: self._controller.apply_action(SetColormap(self.general_colormap.itemText(i))))
        self.general_rotate.currentIndexChanged.connect(
            lambda i: self._controller.apply_action(SetRotate(int(self.general_rotate.itemText(i)))))

        self._map_selection_timer = TimedUpdate(self._update_maps_to_show)
        self.general_map_selection.itemSelectionChanged.connect(
            lambda: self._map_selection_timer.add_delayed_callback(500))

        self.general_deselect_all_maps.clicked.connect(self._deleselect_all_maps)
        self.general_invert_map_selection.clicked.connect(self._invert_map_selection)

        self.general_zoom_x_0.valueChanged.connect(self._update_zoom)
        self.general_zoom_x_1.valueChanged.connect(self._update_zoom)
        self.general_zoom_y_0.valueChanged.connect(self._update_zoom)
        self.general_zoom_y_1.valueChanged.connect(self._update_zoom)

        self.plot_title.textEdited.connect(lambda txt: self._controller.apply_action(SetPlotTitle(txt)))

        self.general_zoom_reset.clicked.connect(lambda: self._controller.apply_action(SetZoom(Zoom.no_zoom())))
        self.general_zoom_fit.clicked.connect(self._zoom_fit)

        self.general_display_order.items_reordered.connect(self._reorder_maps)
        self.general_show_axis.clicked.connect(lambda: self._controller.apply_action(
            SetShowAxis(self.general_show_axis.isChecked())))
        self.general_colorbar_nmr_ticks.valueChanged.connect(
            lambda v: self._controller.apply_action(SetColorBarNmrTicks(v)))

        self.general_font_family.addItems(Font.font_names())
        self.general_font_family.currentTextChanged.connect(
            lambda v: self._controller.apply_action(SetFont(self._controller.get_config().font.get_updated(family=v))))

        self.general_font_size.valueChanged.connect(
            lambda: self._controller.apply_action(
                SetFont(self._controller.get_config().font.get_updated(size=self.general_font_size.value()))))

        self.general_interpolation.addItems(self._controller.get_config().get_available_interpolations())
        self.general_interpolation.currentTextChanged.connect(
            lambda v: self._controller.apply_action(SetInterpolation(v)))

        self.general_flipud.clicked.connect(lambda: self._controller.apply_action(
            SetFlipud(self.general_flipud.isChecked())))

        self.mask_name.currentIndexChanged.connect(self._update_mask_name)

    @pyqtSlot(DataInfo)
    def set_new_data(self, data_info):
        if data_info.directory:
            self.general_info_directory.setText(self._split_long_path_elements(data_info.directory))
        else:
            self.general_info_directory.setText('-')

        if len(data_info.maps):
            self.general_info_nmr_maps.setText(str(len(data_info.maps)))
        else:
            self.general_info_nmr_maps.setText('0')

        with blocked_signals(self.general_map_selection):
            self.general_map_selection.clear()
            self.general_map_selection.addItems(data_info.sorted_keys)
            for index, map_name in enumerate(data_info.sorted_keys):
                item = self.general_map_selection.item(index)
                item.setData(Qt.UserRole, map_name)

        with blocked_signals(self.mask_name):
            self.mask_name.clear()
            self.mask_name.insertItem(0, '-- None --')
            self.mask_name.insertItems(1, data_info.sorted_keys)

    @pyqtSlot(MapPlotConfig)
    def set_new_config(self, config):
        data_info = self._controller.get_data()
        map_names = config.maps_to_show

        with blocked_signals(self.general_dimension):
            try:
                max_dimension = data_info.get_max_dimension(map_names)
                self.general_dimension.setMaximum(max_dimension)
                self.maximumDimension.setText(str(max_dimension))
            except ValueError:
                self.general_dimension.setMaximum(0)
                self.maximumDimension.setText(str(0))
            self.general_dimension.setValue(config.dimension)

        with blocked_signals(self.general_slice_index):
            try:
                max_slice = data_info.get_max_slice_index(config.dimension, map_names)
                self.general_slice_index.setMaximum(max_slice)
                self.maximumIndex.setText(str(max_slice))
            except ValueError:
                self.general_slice_index.setMaximum(0)
                self.maximumIndex.setText(str(0))
            self.general_slice_index.setValue(config.slice_index)

        with blocked_signals(self.general_volume_index):
            try:
                max_volume = data_info.get_max_volume_index(map_names)
                self.general_volume_index.setMaximum(max_volume)
                self.maximumVolume.setText(str(max_volume))
            except ValueError:
                self.general_volume_index.setMaximum(0)
                self.maximumVolume.setText(str(0))
            self.general_volume_index.setValue(config.volume_index)

        with blocked_signals(self.general_colormap):
            self.general_colormap.setCurrentText(config.colormap)

        with blocked_signals(self.general_rotate):
            self.general_rotate.setCurrentText(str(config.rotate))

        if self.general_map_selection.count():
            for map_name, map_config in config.map_plot_options.items():
                if map_config.title:
                    index = data_info.sorted_keys.index(map_name)
                    item = self.general_map_selection.item(index)
                    item.setData(Qt.DisplayRole, map_name + ' (' + map_config.title + ')')

            self.general_map_selection.blockSignals(True)
            for index, map_name in enumerate(data_info.sorted_keys):
                item = self.general_map_selection.item(index)
                if item:
                    item.setSelected(map_name in map_names)
            self.general_map_selection.blockSignals(False)

        try:
            max_x = data_info.get_max_x_index(config.dimension, config.rotate, map_names)
            max_y = data_info.get_max_y_index(config.dimension, config.rotate, map_names)

            with blocked_signals(self.general_zoom_x_0, self.general_zoom_x_1,
                                 self.general_zoom_y_0, self.general_zoom_y_1):
                self.general_zoom_x_0.setMaximum(max_x)
                self.general_zoom_x_0.setValue(config.zoom.p0.x)

                self.general_zoom_x_1.setMaximum(max_x)
                self.general_zoom_x_1.setMinimum(config.zoom.p0.x)
                self.general_zoom_x_1.setValue(config.zoom.p1.x)

                self.general_zoom_y_0.setMaximum(max_y)
                self.general_zoom_y_0.setValue(config.zoom.p0.y)

                self.general_zoom_y_1.setMaximum(max_y)
                self.general_zoom_y_1.setMinimum(config.zoom.p0.y)
                self.general_zoom_y_1.setValue(config.zoom.p1.y)

                if config.zoom.p0.x == 0 and config.zoom.p1.x == 0:
                    self.general_zoom_x_1.setValue(max_x)

                if config.zoom.p0.y == 0 and config.zoom.p1.y == 0:
                    self.general_zoom_y_1.setValue(max_y)
        except ValueError:
            pass

        with blocked_signals(self.plot_title):
            self.plot_title.setText(config.title)

        with blocked_signals(self.general_display_order):
            self.general_display_order.clear()
            self.general_display_order.addItems(map_names)

            for index, map_name in enumerate(map_names):
                item = self.general_display_order.item(index)
                item.setData(Qt.UserRole, map_name)

                if map_name in config.map_plot_options and config.map_plot_options[map_name].title:
                    title = config.map_plot_options[map_name].title
                    item.setData(Qt.DisplayRole, map_name + ' (' + title + ')')

        with blocked_signals(self.general_show_axis):
            self.general_show_axis.setChecked(config.show_axis)

        with blocked_signals(self.general_colorbar_nmr_ticks):
            self.general_colorbar_nmr_ticks.setValue(config.colorbar_nmr_ticks)

        with blocked_signals(self.general_font_family):
            self.general_font_family.setCurrentText(config.font.family)

        with blocked_signals(self.general_font_size):
            self.general_font_size.setValue(config.font.size)

        with blocked_signals(self.general_interpolation):
            self.general_interpolation.setCurrentText(config.interpolation)

        with blocked_signals(self.general_flipud):
            self.general_flipud.setChecked(config.flipud)

        with blocked_signals(self.mask_name):
            if config.mask_name and config.mask_name in data_info.maps:
                for ind in range(self.mask_name.count()):
                    if self.mask_name.itemText(ind) == config.mask_name:
                        self.mask_name.setCurrentIndex(ind)
                        break
            else:
                self.mask_name.setCurrentIndex(0)

    @pyqtSlot()
    def _reorder_maps(self):
        items = [self.general_display_order.item(ind) for ind in range(self.general_display_order.count())]
        map_names = [item.data(Qt.UserRole) for item in items]
        self._controller.apply_action(SetMapsToShow(map_names))

    @pyqtSlot()
    def _update_maps_to_show(self):
        map_names = copy.copy(self._controller.get_config().maps_to_show)

        for item in [self.general_map_selection.item(ind) for ind in range(self.general_map_selection.count())]:
            map_name = item.data(Qt.UserRole)

            if item.isSelected():
                if map_name not in map_names:
                    self._insert_alphabetically(map_name, map_names)
            else:
                if map_name in map_names:
                    map_names.remove(map_name)

        self._controller.apply_action(SetMapsToShow(map_names))

    @pyqtSlot()
    def _deleselect_all_maps(self):
        self._controller.apply_action(SetMapsToShow([]))

    @pyqtSlot()
    def _invert_map_selection(self):
        self._controller.apply_action(SetMapsToShow(
            set(self._controller.get_data().maps.keys()).difference(set(self._controller.get_config().maps_to_show))))

    @pyqtSlot()
    def _zoom_fit(self):
        data_info = self._controller.get_data()
        config = self._controller.get_config()

        def add_padding(bounding_box, max_x, max_y):
            bounding_box[0].x = max(bounding_box[0].x - 1, 0)
            bounding_box[0].y = max(bounding_box[0].y - 1, 0)

            bounding_box[1].y = min(bounding_box[1].y + 2, max_y)
            bounding_box[1].x = min(bounding_box[1].x + 2, max_x)

            return bounding_box

        if config.maps_to_show or len(data_info.maps):
            bounding_box = data_info.get_bounding_box(config.dimension, config.slice_index,
                                                      config.volume_index, config.rotate, config.maps_to_show)

            max_y = data_info.get_max_y_index(config.dimension, rotate=config.rotate, map_names=config.maps_to_show)
            max_x = data_info.get_max_x_index(config.dimension, rotate=config.rotate, map_names=config.maps_to_show)

            if not config.flipud:
                # Since the renderer plots with a left top coordinate system,
                # we need to flip the y coordinates upside down by default.
                tmp = max_y - bounding_box[0].y
                bounding_box[0].y = max_y - bounding_box[1].y
                bounding_box[1].y = tmp

            bounding_box = add_padding(bounding_box, max_x, max_y)

            self._controller.apply_action(SetZoom(Zoom(*bounding_box)))

    @pyqtSlot()
    def _update_zoom(self):
        np0x, np0y = self.general_zoom_x_0.value(), self.general_zoom_y_0.value()
        np1x, np1y = self.general_zoom_x_1.value(), self.general_zoom_y_1.value()

        if np0x > np1x:
            np1x = np0x
        if np0y > np1y:
            np1y = np0y

        self._controller.apply_action(SetZoom(Zoom.from_coords(np0x, np0y, np1x, np1y)))

    @staticmethod
    def _insert_alphabetically(new_item, item_list):
        for ind, item in enumerate(item_list):
            if item > new_item:
                item_list.insert(ind, new_item)
                return
        item_list.append(new_item)

    @pyqtSlot(int)
    def _update_mask_name(self, index):
        if index == 0:
            self._controller.apply_action(SetGeneralMask(None))
        else:
            self._controller.apply_action(SetGeneralMask(self.mask_name.itemText(index)))

    def _split_long_path_elements(self, original_path, max_single_element_length=25):
        """Split long path elements into smaller ones using spaces

        Args:
            original_path (str): the path you want to split
            max_single_element_length (int): the maximum length allowed per path component (folders and filename).

        Returns:
            str: the same path but with spaces in long path elements. The result will no longer be a valid path.
        """

        def split(p):
            listing = []

            def _split(el):
                if el:
                    head, tail = os.path.split(el)
                    if not tail:
                        listing.append(head)
                    else:
                        _split(head)
                        listing.append(tail)

            _split(p)
            return listing

        elements = list(split(original_path))
        new_elements = []

        for el in elements:
            if len(el) > max_single_element_length:
                item = ''
                for i in range(0, len(el), max_single_element_length):
                    item += el[i:i + max_single_element_length] + ' '
                item = item[:-1]
                new_elements.append(item)
            else:
                new_elements.append(el)

        return os.path.join(*new_elements)
示例#4
0
class MapSpecificOptions(QWidget, Ui_MapSpecificOptions):
    def __init__(self, controller, parent=None):
        super().__init__(parent)
        self.setupUi(self)
        self._controller = controller

        current_model = self._controller.get_model()

        self._current_map = None
        self.colormap.addItems(
            ['-- Use global --'] +
            current_model.get_config().get_available_colormaps())
        self.colormap.currentIndexChanged.connect(self._update_colormap)
        self.data_clipping_min.valueChanged.connect(self._update_clipping_min)
        self.data_clipping_max.valueChanged.connect(self._update_clipping_max)
        self.data_scale_min.valueChanged.connect(self._update_scale_min)
        self.data_scale_max.valueChanged.connect(self._update_scale_max)

        self.data_set_use_scale.stateChanged.connect(self._set_use_scale)
        self.use_data_scale_min.stateChanged.connect(
            self._set_use_data_scale_min)
        self.use_data_scale_max.stateChanged.connect(
            self._set_use_data_scale_max)

        self.data_set_use_clipping.stateChanged.connect(self._set_use_clipping)
        self.use_data_clipping_min.stateChanged.connect(
            self._set_use_data_clipping_min)
        self.use_data_clipping_max.stateChanged.connect(
            self._set_use_data_clipping_max)

        self._title_timer = TimedUpdate(self._update_map_title)
        self.map_title.textChanged.connect(
            lambda: self._title_timer.add_delayed_callback(500))
        self.map_title.setFixedHeight(
            QFontMetrics(self.map_title.font()).lineSpacing() * 3)

        self._colorbar_label_timer = TimedUpdate(self._update_colorbar_label)
        self.data_colorbar_label.textChanged.connect(
            lambda: self._colorbar_label_timer.add_delayed_callback(500))
        self.data_colorbar_label.setFixedHeight(
            QFontMetrics(self.data_colorbar_label.font()).lineSpacing() * 3)

        self.info_Clipping.set_collapse(True)

        self._auto_enable_scale_min = False
        self._auto_enable_scale_max = False
        self._auto_enable_clipping_min = False
        self._auto_enable_clipping_max = False

        self.reset()
        self._update_scaling_delays()

    def _update_scaling_delays(self):
        if self.use_data_scale_max.isChecked():
            self.data_scale_max.set_update_delay(500)
        else:
            self.data_scale_max.set_update_delay(0)

        if self.use_data_scale_min.isChecked():
            self.data_scale_min.set_update_delay(500)
        else:
            self.data_scale_min.set_update_delay(0)

        if self.use_data_clipping_max.isChecked():
            self.data_clipping_max.set_update_delay(500)
        else:
            self.data_clipping_max.set_update_delay(0)

        if self.use_data_clipping_min.isChecked():
            self.data_clipping_min.set_update_delay(500)
        else:
            self.data_clipping_min.set_update_delay(0)

    def reset(self):
        """Set all the values to their defaults"""
        self._current_map = None
        self.colormap.setCurrentText('hot')

        with blocked_signals(self.map_title):
            self.map_title.document().setPlainText('')

        with blocked_signals(self.data_colorbar_label):
            self.data_colorbar_label.document().setPlainText('')

        with blocked_signals(self.data_clipping_min):
            self.data_clipping_min.setValue(0)

        with blocked_signals(self.data_clipping_max):
            self.data_clipping_max.setValue(0)

        with blocked_signals(self.data_scale_min):
            self.data_scale_min.setValue(0)

        with blocked_signals(self.data_scale_max):
            self.data_scale_max.setValue(0)

        with blocked_signals(self.use_data_clipping_min):
            self.use_data_clipping_min.setChecked(False)

        with blocked_signals(self.use_data_clipping_max):
            self.use_data_clipping_max.setChecked(False)

        with blocked_signals(self.use_data_scale_min):
            self.use_data_scale_min.setChecked(False)

        with blocked_signals(self.use_data_scale_max):
            self.use_data_scale_max.setChecked(False)

        self.info_file_location.setText('-')
        self.info_maximum.setText('-')
        self.info_minimum.setText('-')
        self.info_shape.setText('-')

    def _get_mask(self, data_info, map_name):
        current_model = self._controller.get_model()
        plot_config = current_model.get_config()

        def get_map_attr():
            if map_name in plot_config.map_plot_options:
                value = getattr(plot_config.map_plot_options[map_name],
                                'mask_name')
                if value is not None:
                    return value
            return plot_config.mask_name

        mask_name = get_map_attr()

        if mask_name is not None:
            return data_info.get_map_data(mask_name)
        return None

    def use(self, map_name):
        """Load the settings of the given map"""
        self._current_map = map_name

        current_model = self._controller.get_model()

        try:
            map_info = current_model.get_config().map_plot_options[map_name]
        except KeyError:
            map_info = SingleMapConfig()

        data_info = current_model.get_data()
        vmin, vmax = data_info.get_single_map_info(map_name).min_max(
            mask=self._get_mask(data_info, map_name))

        with blocked_signals(self.map_title):
            self.map_title.document().setPlainText(
                map_info.title if map_info.title else '')

        with blocked_signals(self.data_colorbar_label):
            self.data_colorbar_label.document().setPlainText(
                map_info.colorbar_label if map_info.colorbar_label else '')

        with blocked_signals(self.colormap):
            if map_info.colormap is None:
                self.colormap.setCurrentIndex(0)
            else:
                self.colormap.setCurrentText(map_info.colormap)

        with blocked_signals(self.data_clipping_min):
            self.data_clipping_min.setValue(map_info.clipping.vmin)

        with blocked_signals(self.data_clipping_max):
            self.data_clipping_max.setValue(map_info.clipping.vmax)

        with blocked_signals(self.data_scale_min):
            self.data_scale_min.setValue(map_info.scale.vmin)

        with blocked_signals(self.data_scale_max):
            self.data_scale_max.setValue(map_info.scale.vmax)

        with blocked_signals(self.data_set_use_scale):
            self.data_set_use_scale.setChecked(map_info.scale.use_min
                                               or map_info.scale.use_max)

        with blocked_signals(self.data_set_use_clipping):
            self.data_set_use_clipping.setChecked(map_info.clipping.use_min
                                                  or map_info.clipping.use_max)

        with blocked_signals(self.use_data_clipping_min):
            self.use_data_clipping_min.setChecked(map_info.clipping.use_min)

        with blocked_signals(self.use_data_clipping_max):
            self.use_data_clipping_max.setChecked(map_info.clipping.use_max)

        with blocked_signals(self.use_data_scale_min):
            self.use_data_scale_min.setChecked(map_info.scale.use_min)

        with blocked_signals(self.use_data_scale_max):
            self.use_data_scale_max.setChecked(map_info.scale.use_max)

        map_filename = data_info.get_file_path(map_name)
        if map_filename:
            self.info_file_location.setText(
                split_long_path_elements(map_filename, 25))

        self.info_minimum.setText(str(vmin))
        self.info_maximum.setText(str(vmax))
        self.info_has_nan.setText('Yes' if data_info.get_single_map_info(
            map_name).has_nan() else 'No')

        self.info_shape.setText(
            str(data_info.get_single_map_info(map_name).shape))

    def _get_current_map_config(self):
        current_model = self._controller.get_model()
        current_config = current_model.get_config()
        current_map_config = current_config.map_plot_options.get(
            self._current_map, SingleMapConfig())
        return current_map_config

    @pyqtSlot()
    def _update_map_title(self):
        string = self.map_title.toPlainText()
        if self._current_map:
            if string == '':
                string = None
            self._controller.apply_action(
                SetMapTitle(self._current_map, string))

    @pyqtSlot()
    def _update_colorbar_label(self):
        string = self.data_colorbar_label.toPlainText()
        if self._current_map:
            if string == '':
                string = None
            self._controller.apply_action(
                SetMapColorbarLabel(self._current_map, string))

    @pyqtSlot(int)
    def _update_colormap(self, index):
        if self._current_map:
            if index == 0:
                self._controller.apply_action(
                    SetMapColormap(self._current_map, None))
            else:
                self._controller.apply_action(
                    SetMapColormap(self._current_map,
                                   self.colormap.itemText(index)))

    @pyqtSlot(float)
    def _update_scale_min(self, value):
        if self._current_map:
            current_scale = self._get_current_map_config().scale
            kwargs = dict(vmin=value)

            if current_scale.use_max and current_scale.use_min and value > current_scale.vmax:
                kwargs.update(dict(use_min=False))
                self._auto_enable_scale_min = True
            elif self._auto_enable_scale_min and value < current_scale.vmax:
                kwargs.update(dict(use_min=True))
                self._auto_enable_scale_min = False

            new_scale = current_scale.get_updated(**kwargs)
            self._controller.apply_action(
                SetMapScale(self._current_map, new_scale))

    @pyqtSlot(float)
    def _update_scale_max(self, value):
        if self._current_map:
            current_scale = self._get_current_map_config().scale
            kwargs = dict(vmax=value)

            if current_scale.use_max and current_scale.use_min and value < current_scale.vmin:
                kwargs.update(dict(use_max=False))
                self._auto_enable_scale_max = True
            elif self._auto_enable_scale_max and value > current_scale.vmin:
                kwargs.update(dict(use_max=True))
                self._auto_enable_scale_max = False

            new_scale = current_scale.get_updated(**kwargs)
            self._controller.apply_action(
                SetMapScale(self._current_map, new_scale))

    @pyqtSlot(int)
    def _set_use_scale(self, check_state):
        use_scale = check_state == 2
        if self._current_map:
            current_scale = self._get_current_map_config().scale
            if use_scale and current_scale.vmax < current_scale.vmin:
                new_scale = current_scale.get_updated(use_min=use_scale,
                                                      use_max=use_scale,
                                                      vmax=current_scale.vmin)
            else:
                new_scale = current_scale.get_updated(use_min=use_scale,
                                                      use_max=use_scale)
            self._controller.apply_action(
                SetMapScale(self._current_map, new_scale))
        self._update_scaling_delays()

    @pyqtSlot(int)
    def _set_use_data_scale_min(self, check_state):
        use_scale = check_state == 2
        if self._current_map:
            if use_scale and self._get_current_map_config().scale.use_max:
                self._set_use_scale(2)
            else:
                new_scale = self._get_current_map_config().scale.get_updated(
                    use_min=use_scale)
                self._controller.apply_action(
                    SetMapScale(self._current_map, new_scale))

    @pyqtSlot(int)
    def _set_use_data_scale_max(self, check_state):
        use_scale = check_state == 2
        if self._current_map:
            if use_scale and self._get_current_map_config().scale.use_min:
                self._set_use_scale(2)
            else:
                new_scale = self._get_current_map_config().scale.get_updated(
                    use_max=use_scale)
                self._controller.apply_action(
                    SetMapScale(self._current_map, new_scale))

    @pyqtSlot(float)
    def _update_clipping_min(self, value):
        if self._current_map:
            current_clipping = self._get_current_map_config().clipping
            kwargs = dict(vmin=value)

            if current_clipping.use_max and current_clipping.use_min and value > current_clipping.vmax:
                kwargs.update(dict(use_min=False))
                self._auto_enable_scale_min = True
            elif self._auto_enable_scale_min and value < current_clipping.vmax:
                kwargs.update(dict(use_min=True))
                self._auto_enable_scale_min = False

            new_clipping = current_clipping.get_updated(**kwargs)
            self._controller.apply_action(
                SetMapClipping(self._current_map, new_clipping))

    @pyqtSlot(float)
    def _update_clipping_max(self, value):
        if self._current_map:
            current_clipping = self._get_current_map_config().clipping
            kwargs = dict(vmax=value)

            if current_clipping.use_max and current_clipping.use_min and value < current_clipping.vmin:
                kwargs.update(dict(use_max=False))
                self._auto_enable_scale_max = True
            elif self._auto_enable_scale_max and value > current_clipping.vmin:
                kwargs.update(dict(use_max=True))
                self._auto_enable_scale_max = False

            new_clipping = current_clipping.get_updated(**kwargs)
            self._controller.apply_action(
                SetMapClipping(self._current_map, new_clipping))

    @pyqtSlot(int)
    def _set_use_clipping(self, check_state):
        use_clipping = check_state == 2
        if self._current_map:
            current_clipping = self._get_current_map_config().clipping
            if use_clipping and current_clipping.vmax < current_clipping.vmin:
                new_clipping = current_clipping.get_updated(
                    use_min=use_clipping,
                    use_max=use_clipping,
                    vmax=current_clipping.vmin)
            else:
                new_clipping = current_clipping.get_updated(
                    use_min=use_clipping, use_max=use_clipping)
            self._controller.apply_action(
                SetMapClipping(self._current_map, new_clipping))
        self._update_scaling_delays()

    @pyqtSlot(int)
    def _set_use_data_clipping_min(self, check_state):
        use_clipping = check_state == 2
        if self._current_map:
            if use_clipping and self._get_current_map_config(
            ).clipping.use_max:
                self._set_use_clipping(2)
            else:
                new_clipping = self._get_current_map_config(
                ).clipping.get_updated(use_min=use_clipping)
                self._controller.apply_action(
                    SetMapClipping(self._current_map, new_clipping))

    @pyqtSlot(int)
    def _set_use_data_clipping_max(self, check_state):
        use_clipping = check_state == 2
        if self._current_map:
            if use_clipping and self._get_current_map_config(
            ).clipping.use_min:
                self._set_use_clipping(2)
            else:
                new_clipping = self._get_current_map_config(
                ).clipping.get_updated(use_max=use_clipping)
                self._controller.apply_action(
                    SetMapClipping(self._current_map, new_clipping))
示例#5
0
class TabGeneral(QWidget, Ui_TabGeneral):
    def __init__(self, controller, parent=None):
        super().__init__(parent)
        self.setupUi(self)

        self._controller = controller
        self._controller.model_updated.connect(self.update_model)

        self._previous_model = None
        current_model = self._controller.get_model()

        self.general_display_order.setDragDropMode(
            QAbstractItemView.InternalMove)
        self.general_display_order.setSelectionMode(
            QAbstractItemView.SingleSelection)

        self.general_colormap.addItems(
            current_model.get_config().get_available_colormaps())
        self.general_rotate.addItems(['0', '90', '180', '270'])
        self.general_rotate.setCurrentText(
            str(current_model.get_config().rotate))

        self.general_DisplayOrder.set_collapse(True)
        self.general_Miscellaneous.set_collapse(True)
        self.general_Zoom.set_collapse(True)
        self.general_Font.set_collapse(True)
        self.general_Colorbar.set_collapse(True)

        self.general_dimension.valueChanged.connect(
            lambda v: self._controller.apply_action(SetDimension(v)))
        self.general_slice_index.valueChanged.connect(
            lambda v: self._controller.apply_action(SetSliceIndex(v)))
        self.general_volume_index.valueChanged.connect(
            lambda v: self._controller.apply_action(SetVolumeIndex(v)))
        self.general_colormap.currentIndexChanged.connect(
            lambda i: self._controller.apply_action(
                SetColormap(self.general_colormap.itemText(i))))
        self.general_rotate.currentIndexChanged.connect(
            lambda i: self._controller.apply_action(
                SetRotate(int(self.general_rotate.itemText(i)))))

        self._map_selection_timer = TimedUpdate(self._update_maps_to_show)
        self.general_map_selection.itemSelectionChanged.connect(
            lambda: self._map_selection_timer.add_delayed_callback(500))
        self.general_map_selection.setContextMenuPolicy(Qt.CustomContextMenu)
        self.general_map_selection.customContextMenuRequested.connect(
            self.select_maps_context_menu)

        self.general_deselect_all_maps.clicked.connect(
            self._deleselect_all_maps)
        self.general_invert_map_selection.clicked.connect(
            self._invert_map_selection)

        self.general_zoom_x_0.valueChanged.connect(self._update_zoom)
        self.general_zoom_x_1.valueChanged.connect(self._update_zoom)
        self.general_zoom_y_0.valueChanged.connect(self._update_zoom)
        self.general_zoom_y_1.valueChanged.connect(self._update_zoom)

        self.plot_title.textEdited.connect(
            lambda txt: self._controller.apply_action(SetPlotTitle(txt)))

        self.general_zoom_reset.clicked.connect(
            lambda: self._controller.apply_action(SetZoom(Zoom.no_zoom())))
        self.general_zoom_fit.clicked.connect(self._zoom_fit)

        self.general_display_order.items_reordered.connect(self._reorder_maps)
        self.general_show_axis.clicked.connect(
            lambda: self._controller.apply_action(
                SetShowAxis(self.general_show_axis.isChecked())))

        self.general_font_family.addItems(Font.font_names())
        self.general_font_family.currentTextChanged.connect(
            lambda v: self._controller.apply_action(
                SetFont(self._controller.get_model().get_config().font.
                        get_updated(family=v))))

        self.general_font_size.valueChanged.connect(
            lambda: self._controller.apply_action(
                SetFont(self._controller.get_model().get_config().font.
                        get_updated(size=self.general_font_size.value()))))

        self.general_interpolation.addItems(
            current_model.get_config().get_available_interpolations())
        self.general_interpolation.currentTextChanged.connect(
            lambda v: self._controller.apply_action(SetInterpolation(v)))

        self.general_flipud.clicked.connect(
            lambda: self._controller.apply_action(
                SetFlipud(self.general_flipud.isChecked())))

        self.general_show_plot_titles.clicked.connect(
            lambda: self._controller.apply_action(
                SetShowPlotTitles(self.general_show_plot_titles.isChecked())))

        self.mask_name.currentIndexChanged.connect(self._update_mask_name)

        self.general_colorbar_nmr_ticks.valueChanged.connect(
            lambda v: self._controller.apply_action(SetColorBarNmrTicks(v)))
        self.general_show_colorbar.clicked.connect(
            lambda: self._controller.apply_action(
                SetShowPlotColorbars(self.general_show_colorbar.isChecked())))
        self.general_colorbar_location.currentTextChanged.connect(
            lambda v: self._controller.apply_action(
                SetColorbarLocation(v.lower())))

    @pyqtSlot(DataConfigModel)
    def update_model(self, model):
        data = model.get_data()
        config = model.get_config()

        if not self._previous_model or model.get_data(
        ) != self._previous_model.get_data():
            self._previous_model = model
            self._update_data(data)

        self._update_config(data, config)

    def select_maps_context_menu(self, position):
        global_position = self.general_map_selection.mapToGlobal(position)

        def get_header_action(parent, map_name):
            label = QLabel(map_name)

            font = label.font()
            font.setBold(True)
            label.setFont(font)
            label.setStyleSheet('color: black; margin:5px; margin-left: 15px;')

            action = QWidgetAction(parent)
            action.setDisabled(True)
            action.setDefaultWidget(label)

            return action

        if self.general_map_selection.count():
            row = self.general_map_selection.indexAt(position)
            if row:
                element = self.general_map_selection.item(row.row())
                if element:
                    map_name = element.data(Qt.UserRole)
                    file_path = self._controller.get_model().get_data(
                    ).get_file_path(map_name)

                    menu = QMenu()
                    menu.addAction(get_header_action(menu, map_name))
                    menu.addSeparator()

                    show_in_folder = menu.addAction(
                        '&Show in folder', lambda: QDesktopServices.openUrl(
                            QUrl.fromLocalFile(os.path.dirname(file_path))))
                    if file_path is None:
                        show_in_folder.setEnabled(False)

                    menu.addAction(
                        'Use as &mask', lambda: self._controller.apply_action(
                            SetGeneralMask(map_name)))
                    menu.addAction(
                        'R&emove', lambda: self._controller.apply_action(
                            NewDataAction(self._controller.get_model(
                            ).get_data().get_updated(removals=[map_name]))))
                    menu.exec(global_position)

    @pyqtSlot()
    def _reorder_maps(self):
        items = [
            self.general_display_order.item(ind)
            for ind in range(self.general_display_order.count())
        ]
        map_names = [item.data(Qt.UserRole) for item in items]
        self._controller.apply_action(SetMapsToShow(map_names))

    @pyqtSlot()
    def _update_maps_to_show(self):
        current_model = self._controller.get_model()
        map_names = copy.copy(current_model.get_config().maps_to_show)

        for item in [
                self.general_map_selection.item(ind)
                for ind in range(self.general_map_selection.count())
        ]:
            map_name = item.data(Qt.UserRole)

            if item.isSelected():
                if map_name not in map_names:
                    self._insert_alphabetically(map_name, map_names)
            else:
                if map_name in map_names:
                    map_names.remove(map_name)

        self._controller.apply_action(SetMapsToShow(map_names))

    @pyqtSlot()
    def _deleselect_all_maps(self):
        self._controller.apply_action(SetMapsToShow([]))

    @pyqtSlot()
    def _invert_map_selection(self):
        current_model = self._controller.get_model()
        self._controller.apply_action(
            SetMapsToShow(
                list(
                    set(current_model.get_data().get_map_names()).difference(
                        set(current_model.get_config().maps_to_show)))))

    @pyqtSlot()
    def _zoom_fit(self):
        current_model = self._controller.get_model()
        data_info = current_model.get_data()
        config = current_model.get_config()

        def add_padding(bounding_box, max_x, max_y):
            bounding_box[0].x = max(bounding_box[0].x - 1, 0)
            bounding_box[0].y = max(bounding_box[0].y - 1, 0)

            bounding_box[1].y = min(bounding_box[1].y + 2, max_y)
            bounding_box[1].x = min(bounding_box[1].x + 2, max_x)

            return bounding_box

        if config.maps_to_show or len(data_info.get_map_names()):
            bounding_box = data_info.get_bounding_box(config.dimension,
                                                      config.slice_index,
                                                      config.volume_index,
                                                      config.rotate,
                                                      config.maps_to_show)

            max_y = data_info.get_max_y_index(config.dimension,
                                              rotate=config.rotate,
                                              map_names=config.maps_to_show)
            max_x = data_info.get_max_x_index(config.dimension,
                                              rotate=config.rotate,
                                              map_names=config.maps_to_show)

            if not config.flipud:
                # Since the renderer plots with a left top coordinate system,
                # we need to flip the y coordinates upside down by default.
                tmp = max_y - bounding_box[0].y
                bounding_box[0].y = max_y - bounding_box[1].y
                bounding_box[1].y = tmp

            bounding_box = add_padding(bounding_box, max_x, max_y)

            self._controller.apply_action(SetZoom(Zoom(*bounding_box)))

    @pyqtSlot()
    def _update_zoom(self):
        np0x, np0y = self.general_zoom_x_0.value(
        ), self.general_zoom_y_0.value()
        np1x, np1y = self.general_zoom_x_1.value(
        ), self.general_zoom_y_1.value()

        if np0x > np1x:
            np1x = np0x
        if np0y > np1y:
            np1y = np0y

        self._controller.apply_action(
            SetZoom(Zoom.from_coords(np0x, np0y, np1x, np1y)))

    @staticmethod
    def _insert_alphabetically(new_item, item_list):
        for ind, item in enumerate(item_list):
            if item > new_item:
                item_list.insert(ind, new_item)
                return
        item_list.append(new_item)

    @pyqtSlot(int)
    def _update_mask_name(self, index):
        if index == 0:
            self._controller.apply_action(SetGeneralMask(None))
        else:
            self._controller.apply_action(
                SetGeneralMask(self.mask_name.itemText(index)))

    def _update_data(self, data_info):
        sorted_keys = list(sorted(data_info.get_map_names()))

        if len(data_info.get_map_names()):
            self.general_info_nmr_maps.setText(
                str(len(data_info.get_map_names())))
        else:
            self.general_info_nmr_maps.setText('0')

        with blocked_signals(self.general_map_selection):
            self.general_map_selection.clear()
            self.general_map_selection.addItems(sorted_keys)
            for index, map_name in enumerate(sorted_keys):
                item = self.general_map_selection.item(index)
                item.setData(Qt.UserRole, map_name)

        with blocked_signals(self.mask_name):
            self.mask_name.clear()
            self.mask_name.insertItem(0, '-- None --')
            self.mask_name.insertItems(1, sorted_keys)

    def _update_config(self, data, config):
        map_names = config.maps_to_show

        with blocked_signals(self.general_dimension):
            try:
                max_dimension = data.get_max_dimension(map_names)
                self.general_dimension.setMaximum(max_dimension)
                self.maximumDimension.setText(str(max_dimension))
            except ValueError:
                self.general_dimension.setMaximum(0)
                self.maximumDimension.setText(str(0))
            self.general_dimension.setValue(config.dimension)

        with blocked_signals(self.general_slice_index):
            try:
                max_slice = data.get_max_slice_index(config.dimension,
                                                     map_names)
                self.general_slice_index.setMaximum(max_slice)
                self.maximumIndex.setText(str(max_slice))
            except ValueError:
                self.general_slice_index.setMaximum(0)
                self.maximumIndex.setText(str(0))
            self.general_slice_index.setValue(config.slice_index)

        with blocked_signals(self.general_volume_index):
            try:
                max_volume = data.get_max_volume_index(map_names)
                self.general_volume_index.setMaximum(max_volume)
                self.maximumVolume.setText(str(max_volume))
            except ValueError:
                self.general_volume_index.setMaximum(0)
                self.maximumVolume.setText(str(0))
            self.general_volume_index.setValue(config.volume_index)

        with blocked_signals(self.general_colormap):
            self.general_colormap.setCurrentText(config.colormap)

        with blocked_signals(self.general_rotate):
            self.general_rotate.setCurrentText(str(config.rotate))

        if self.general_map_selection.count():
            for map_name, map_config in config.map_plot_options.items():
                if map_config.title:
                    index = list(sorted(data.get_map_names())).index(map_name)
                    item = self.general_map_selection.item(index)
                    item.setData(Qt.DisplayRole,
                                 map_name + ' (' + map_config.title + ')')

            self.general_map_selection.blockSignals(True)
            for index, map_name in enumerate(list(sorted(
                    data.get_map_names()))):
                item = self.general_map_selection.item(index)
                if item:
                    item.setSelected(map_name in map_names)
            self.general_map_selection.blockSignals(False)

        try:
            max_x = data.get_max_x_index(config.dimension, config.rotate,
                                         map_names)
            max_y = data.get_max_y_index(config.dimension, config.rotate,
                                         map_names)

            with blocked_signals(self.general_zoom_x_0, self.general_zoom_x_1,
                                 self.general_zoom_y_0, self.general_zoom_y_1):
                self.general_zoom_x_0.setMaximum(max_x)
                self.general_zoom_x_0.setValue(config.zoom.p0.x)

                self.general_zoom_x_1.setMaximum(max_x)
                self.general_zoom_x_1.setMinimum(config.zoom.p0.x)
                self.general_zoom_x_1.setValue(config.zoom.p1.x)

                self.general_zoom_y_0.setMaximum(max_y)
                self.general_zoom_y_0.setValue(config.zoom.p0.y)

                self.general_zoom_y_1.setMaximum(max_y)
                self.general_zoom_y_1.setMinimum(config.zoom.p0.y)
                self.general_zoom_y_1.setValue(config.zoom.p1.y)

                if config.zoom.p0.x == 0 and config.zoom.p1.x == 0:
                    self.general_zoom_x_1.setValue(max_x)

                if config.zoom.p0.y == 0 and config.zoom.p1.y == 0:
                    self.general_zoom_y_1.setValue(max_y)
        except ValueError:
            pass

        with blocked_signals(self.plot_title):
            self.plot_title.setText(config.title)

        with blocked_signals(self.general_display_order):
            self.general_display_order.clear()
            self.general_display_order.addItems(map_names)

            for index, map_name in enumerate(map_names):
                item = self.general_display_order.item(index)
                item.setData(Qt.UserRole, map_name)

                if map_name in config.map_plot_options and config.map_plot_options[
                        map_name].title:
                    title = config.map_plot_options[map_name].title
                    item.setData(Qt.DisplayRole, map_name + ' (' + title + ')')

        with blocked_signals(self.general_show_axis):
            self.general_show_axis.setChecked(config.show_axis)

        with blocked_signals(self.general_colorbar_nmr_ticks):
            self.general_colorbar_nmr_ticks.setValue(
                config.colorbar_settings.get_preferred('nmr_ticks'))

        with blocked_signals(self.general_show_colorbar):
            self.general_show_colorbar.setChecked(
                config.colorbar_settings.get_preferred('visible'))

        with blocked_signals(self.general_colorbar_location):
            self.general_colorbar_location.setCurrentText(
                config.colorbar_settings.get_preferred('location').title())

        with blocked_signals(self.general_show_plot_titles):
            self.general_show_plot_titles.setChecked(config.show_titles)

        with blocked_signals(self.general_font_family):
            self.general_font_family.setCurrentText(config.font.family)

        with blocked_signals(self.general_font_size):
            self.general_font_size.setValue(config.font.size)

        with blocked_signals(self.general_interpolation):
            self.general_interpolation.setCurrentText(config.interpolation)

        with blocked_signals(self.general_flipud):
            self.general_flipud.setChecked(config.flipud)

        with blocked_signals(self.mask_name):
            if config.mask_name and config.mask_name in data.get_map_names():
                for ind in range(self.mask_name.count()):
                    if self.mask_name.itemText(ind) == config.mask_name:
                        self.mask_name.setCurrentIndex(ind)
                        break
            else:
                self.mask_name.setCurrentIndex(0)
示例#6
0
class MapSpecificOptions(QWidget, Ui_MapSpecificOptions):
    def __init__(self, controller, parent=None):
        super(MapSpecificOptions, self).__init__(parent)
        self.setupUi(self)
        self._controller = controller
        self._current_map = None
        self.colormap.addItems(
            ['-- Use global --'] +
            self._controller.get_config().get_available_colormaps())
        self.colormap.currentIndexChanged.connect(self._update_colormap)
        self.data_clipping_min.valueChanged.connect(self._update_clipping_min)
        self.data_clipping_max.valueChanged.connect(self._update_clipping_max)
        self.data_scale_min.valueChanged.connect(self._update_scale_min)
        self.data_scale_max.valueChanged.connect(self._update_scale_max)

        self.data_set_use_scale.stateChanged.connect(self._set_use_scale)
        self.use_data_scale_min.stateChanged.connect(
            self._set_use_data_scale_min)
        self.use_data_scale_max.stateChanged.connect(
            self._set_use_data_scale_max)

        self.data_set_use_clipping.stateChanged.connect(self._set_use_clipping)
        self.use_data_clipping_min.stateChanged.connect(
            self._set_use_data_clipping_min)
        self.use_data_clipping_max.stateChanged.connect(
            self._set_use_data_clipping_max)

        self._title_timer = TimedUpdate(self._update_map_title)
        self.map_title.textChanged.connect(
            lambda v: self._title_timer.add_delayed_callback(500, v))

        self._colorbar_label_timer = TimedUpdate(self._update_colorbar_label)
        self.data_colorbar_label.textChanged.connect(
            lambda v: self._colorbar_label_timer.add_delayed_callback(500, v))

        self.info_Clipping.set_collapse(True)

    def reset(self):
        """Set all the values to their defaults"""
        self._current_map = None
        self.colormap.setCurrentText('hot')

        with blocked_signals(self.map_title):
            self.map_title.setText('')

        with blocked_signals(self.data_colorbar_label):
            self.data_colorbar_label.setText('')

        with blocked_signals(self.data_clipping_min):
            self.data_clipping_min.setValue(0)

        with blocked_signals(self.data_clipping_max):
            self.data_clipping_max.setValue(0)

        with blocked_signals(self.data_scale_min):
            self.data_scale_min.setValue(0)

        with blocked_signals(self.data_scale_max):
            self.data_scale_max.setValue(0)

        with blocked_signals(self.use_data_clipping_min):
            self.use_data_clipping_min.setChecked(False)

        with blocked_signals(self.use_data_clipping_max):
            self.use_data_clipping_max.setChecked(False)

        with blocked_signals(self.use_data_scale_min):
            self.use_data_scale_min.setChecked(False)

        with blocked_signals(self.use_data_scale_max):
            self.use_data_scale_max.setChecked(False)

        self.info_file_location.setText('-')
        self.info_maximum.setText('-')
        self.info_minimum.setText('-')
        self.info_shape.setText('-')

    def use(self, map_name):
        """Load the settings of the given map"""
        self._current_map = map_name

        try:
            map_info = self._controller.get_config().map_plot_options[map_name]
        except KeyError:
            map_info = SingleMapConfig()

        data_info = self._controller.get_data()
        vmin = data_info.maps[map_name].min()
        vmax = data_info.maps[map_name].max()

        with blocked_signals(self.map_title):
            self.map_title.setText(map_info.title if map_info.title else '')

        with blocked_signals(self.data_colorbar_label):
            self.data_colorbar_label.setText(
                map_info.colorbar_label if map_info.colorbar_label else '')

        with blocked_signals(self.colormap):
            if map_info.colormap is None:
                self.colormap.setCurrentIndex(0)
            else:
                self.colormap.setCurrentText(map_info.colormap)

        with blocked_signals(self.data_clipping_min):
            self.data_clipping_min.setValue(map_info.clipping.vmin)

        with blocked_signals(self.data_clipping_max):
            self.data_clipping_max.setValue(map_info.clipping.vmax)

        with blocked_signals(self.data_scale_min):
            self.data_scale_min.setValue(map_info.scale.vmin)

        with blocked_signals(self.data_scale_max):
            self.data_scale_max.setValue(map_info.scale.vmax)

        with blocked_signals(self.data_set_use_scale):
            self.data_set_use_scale.setChecked(map_info.scale.use_min
                                               or map_info.scale.use_max)

        with blocked_signals(self.data_set_use_clipping):
            self.data_set_use_clipping.setChecked(map_info.clipping.use_min
                                                  or map_info.clipping.use_max)

        with blocked_signals(self.use_data_clipping_min):
            self.use_data_clipping_min.setChecked(map_info.clipping.use_min)

        with blocked_signals(self.use_data_clipping_max):
            self.use_data_clipping_max.setChecked(map_info.clipping.use_max)

        with blocked_signals(self.use_data_scale_min):
            self.use_data_scale_min.setChecked(map_info.scale.use_min)

        with blocked_signals(self.use_data_scale_max):
            self.use_data_scale_max.setChecked(map_info.scale.use_max)

        map_filename = data_info.get_file_name(map_name)
        if map_filename:
            self.info_file_location.setText(map_filename)

        self.info_maximum.setText(str(vmax))
        self.info_minimum.setText(str(vmin))
        self.info_shape.setText(str(data_info.maps[map_name].shape))

    def _get_current_map_config(self):
        current_config = self._controller.get_config()
        current_map_config = current_config.map_plot_options.get(
            self._current_map, SingleMapConfig())
        return current_map_config

    @pyqtSlot(str)
    def _update_map_title(self, string):
        if self._current_map:
            if string == '':
                string = None
            self._controller.apply_action(
                SetMapTitle(self._current_map, string))

    @pyqtSlot(str)
    def _update_colorbar_label(self, string):
        if self._current_map:
            if string == '':
                string = None
            self._controller.apply_action(
                SetMapColorbarLabel(self._current_map, string))

    @pyqtSlot(int)
    def _update_colormap(self, index):
        if self._current_map:
            if index == 0:
                self._controller.apply_action(
                    SetMapColormap(self._current_map, None))
            else:
                self._controller.apply_action(
                    SetMapColormap(self._current_map,
                                   self.colormap.itemText(index)))

    @pyqtSlot(float)
    def _update_scale_min(self, value):
        if self._current_map:
            current_scale = self._get_current_map_config().scale
            if current_scale.use_min and current_scale.use_max and value > current_scale.vmax:
                new_scale = current_scale.get_updated(vmin=value, vmax=value)
            else:
                new_scale = current_scale.get_updated(vmin=value)
            self._controller.apply_action(
                SetMapScale(self._current_map, new_scale))

    @pyqtSlot(float)
    def _update_scale_max(self, value):
        if self._current_map:
            current_scale = self._get_current_map_config().scale
            if current_scale.use_min and current_scale.use_max and value < current_scale.vmin:
                new_scale = current_scale.get_updated(vmin=value, vmax=value)
            else:
                new_scale = current_scale.get_updated(vmax=value)
            self._controller.apply_action(
                SetMapScale(self._current_map, new_scale))

    @pyqtSlot(int)
    def _set_use_scale(self, use_scale):
        if self._current_map:
            current_scale = self._get_current_map_config().scale
            if use_scale and current_scale.vmax < current_scale.vmin:
                new_scale = current_scale.get_updated(use_min=use_scale,
                                                      use_max=use_scale,
                                                      vmax=current_scale.vmin)
            else:
                new_scale = current_scale.get_updated(use_min=use_scale,
                                                      use_max=use_scale)
            self._controller.apply_action(
                SetMapScale(self._current_map, new_scale))

    @pyqtSlot(int)
    def _set_use_data_scale_min(self, use_scale):
        if self._current_map:
            if use_scale and self._get_current_map_config().scale.use_max:
                self._set_use_scale(True)
            else:
                new_scale = self._get_current_map_config().scale.get_updated(
                    use_min=use_scale)
                self._controller.apply_action(
                    SetMapScale(self._current_map, new_scale))

    @pyqtSlot(int)
    def _set_use_data_scale_max(self, use_scale):
        if self._current_map:
            if use_scale and self._get_current_map_config().scale.use_min:
                self._set_use_scale(True)
            else:
                new_scale = self._get_current_map_config().scale.get_updated(
                    use_max=use_scale)
                self._controller.apply_action(
                    SetMapScale(self._current_map, new_scale))

    @pyqtSlot(float)
    def _update_clipping_min(self, value):
        if self._current_map:
            current_clipping = self._get_current_map_config().clipping
            if current_clipping.use_min and current_clipping.use_max and value > current_clipping.vmax:
                new_clipping = current_clipping.get_updated(vmin=value,
                                                            vmax=value)
            else:
                new_clipping = current_clipping.get_updated(vmin=value)
            self._controller.apply_action(
                SetMapClipping(self._current_map, new_clipping))

    @pyqtSlot(float)
    def _update_clipping_max(self, value):
        if self._current_map:
            current_clipping = self._get_current_map_config().clipping
            if current_clipping.use_min and current_clipping.use_max and value < current_clipping.vmin:
                new_clipping = current_clipping.get_updated(vmin=value,
                                                            vmax=value)
            else:
                new_clipping = current_clipping.get_updated(vmax=value)
            self._controller.apply_action(
                SetMapClipping(self._current_map, new_clipping))

    @pyqtSlot(int)
    def _set_use_clipping(self, use_clipping):
        if self._current_map:
            current_clipping = self._get_current_map_config().clipping
            if use_clipping and current_clipping.vmax < current_clipping.vmin:
                new_clipping = current_clipping.get_updated(
                    use_min=use_clipping,
                    use_max=use_clipping,
                    vmax=current_clipping.vmin)
            else:
                new_clipping = current_clipping.get_updated(
                    use_min=use_clipping, use_max=use_clipping)
            self._controller.apply_action(
                SetMapClipping(self._current_map, new_clipping))

    @pyqtSlot(int)
    def _set_use_data_clipping_min(self, use_clipping):
        if self._current_map:
            if use_clipping and self._get_current_map_config(
            ).clipping.use_max:
                self._set_use_clipping(True)
            else:
                new_clipping = self._get_current_map_config(
                ).clipping.get_updated(use_min=use_clipping)
                self._controller.apply_action(
                    SetMapClipping(self._current_map, new_clipping))

    @pyqtSlot(int)
    def _set_use_data_clipping_max(self, use_clipping):
        if self._current_map:
            if use_clipping and self._get_current_map_config(
            ).clipping.use_min:
                self._set_use_clipping(True)
            else:
                new_clipping = self._get_current_map_config(
                ).clipping.get_updated(use_max=use_clipping)
                self._controller.apply_action(
                    SetMapClipping(self._current_map, new_clipping))