diff options
Diffstat (limited to 'silx/gui/plot/ColorBar.py')
-rw-r--r-- | silx/gui/plot/ColorBar.py | 884 |
1 files changed, 0 insertions, 884 deletions
diff --git a/silx/gui/plot/ColorBar.py b/silx/gui/plot/ColorBar.py deleted file mode 100644 index 9798123..0000000 --- a/silx/gui/plot/ColorBar.py +++ /dev/null @@ -1,884 +0,0 @@ -# coding: utf-8 -# /*########################################################################## -# -# Copyright (c) 2016-2019 European Synchrotron Radiation Facility -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. -# -# ###########################################################################*/ -"""Module containing several widgets associated to a colormap. -""" - -__authors__ = ["H. Payno", "T. Vincent"] -__license__ = "MIT" -__date__ = "24/04/2018" - - -import logging -import weakref -import numpy - -from ._utils import ticklayout -from .. import qt -from silx.gui import colors - -_logger = logging.getLogger(__name__) - - -class ColorBarWidget(qt.QWidget): - """Colorbar widget displaying a colormap - - It uses a description of colormap as dict compatible with :class:`Plot`. - - .. image:: img/linearColorbar.png - :width: 80px - :align: center - - To run the following sample code, a QApplication must be initialized. - - >>> from silx.gui.plot import Plot2D - >>> from silx.gui.plot.ColorBar import ColorBarWidget - - >>> plot = Plot2D() # Create a plot widget - >>> plot.show() - - >>> colorbar = ColorBarWidget(plot=plot, legend='Colormap') # Associate the colorbar with it - >>> colorbar.show() - - Initializer parameters: - - :param parent: See :class:`QWidget` - :param plot: PlotWidget the colorbar is attached to (optional) - :param str legend: the label to set to the colorbar - """ - sigVisibleChanged = qt.Signal(bool) - """Emitted when the property `visible` have changed.""" - - def __init__(self, parent=None, plot=None, legend=None): - self._isConnected = False - self._plotRef = None - self._colormap = None - self._data = None - - super(ColorBarWidget, self).__init__(parent) - - self.__buildGUI() - self.setLegend(legend) - self.setPlot(plot) - - def __buildGUI(self): - self.setLayout(qt.QHBoxLayout()) - - # create color scale widget - self._colorScale = ColorScaleBar(parent=self, - colormap=None) - self.layout().addWidget(self._colorScale) - - # legend (is the right group) - self.legend = _VerticalLegend('', self) - self.layout().addWidget(self.legend) - - self.layout().setSizeConstraint(qt.QLayout.SetMinAndMaxSize) - - def getPlot(self): - """Returns the :class:`Plot` associated to this widget or None""" - return None if self._plotRef is None else self._plotRef() - - def setPlot(self, plot): - """Associate a plot to the ColorBar - - :param plot: the plot to associate with the colorbar. - If None will remove any connection with a previous plot. - """ - self._disconnectPlot() - self._plotRef = None if plot is None else weakref.ref(plot) - self._connectPlot() - - def _disconnectPlot(self): - """Disconnect from Plot signals""" - plot = self.getPlot() - if plot is not None and self._isConnected: - self._isConnected = False - plot.sigActiveImageChanged.disconnect( - self._activeImageChanged) - plot.sigActiveScatterChanged.disconnect( - self._activeScatterChanged) - plot.sigPlotSignal.disconnect(self._defaultColormapChanged) - - def _connectPlot(self): - """Connect to Plot signals""" - plot = self.getPlot() - if plot is not None and not self._isConnected: - activeImageLegend = plot.getActiveImage(just_legend=True) - activeScatterLegend = plot._getActiveItem( - kind='scatter', just_legend=True) - if activeImageLegend is None and activeScatterLegend is None: - # Show plot default colormap - self._syncWithDefaultColormap() - elif activeImageLegend is not None: # Show active image colormap - self._activeImageChanged(None, activeImageLegend) - elif activeScatterLegend is not None: # Show active scatter colormap - self._activeScatterChanged(None, activeScatterLegend) - - plot.sigActiveImageChanged.connect(self._activeImageChanged) - plot.sigActiveScatterChanged.connect(self._activeScatterChanged) - plot.sigPlotSignal.connect(self._defaultColormapChanged) - self._isConnected = True - - def setVisible(self, isVisible): - # isHidden looks to be always synchronized, while isVisible is not - wasHidden = self.isHidden() - qt.QWidget.setVisible(self, isVisible) - if wasHidden != self.isHidden(): - self.sigVisibleChanged.emit(not self.isHidden()) - - def showEvent(self, event): - self._connectPlot() - - def hideEvent(self, event): - self._disconnectPlot() - - def getColormap(self): - """Returns the colormap displayed in the colorbar. - - :rtype: ~silx.gui.colors.Colormap - """ - return self.getColorScaleBar().getColormap() - - def setColormap(self, colormap, data=None): - """Set the colormap to be displayed. - - :param ~silx.gui.colors.Colormap colormap: - The colormap to apply on the ColorBarWidget - :param numpy.ndarray data: the data to display, needed if the colormap - require an autoscale - """ - self._data = data - self.getColorScaleBar().setColormap(colormap=colormap, - data=data) - if self._colormap is not None: - self._colormap.sigChanged.disconnect(self._colormapHasChanged) - self._colormap = colormap - if self._colormap is not None: - self._colormap.sigChanged.connect(self._colormapHasChanged) - - def _colormapHasChanged(self): - """handler of the Colormap.sigChanged signal - """ - assert self._colormap is not None - self.setColormap(colormap=self._colormap, - data=self._data) - - def setLegend(self, legend): - """Set the legend displayed along the colorbar - - :param str legend: The label - """ - if legend is None or legend == "": - self.legend.hide() - self.legend.setText("") - else: - assert type(legend) is str - self.legend.show() - self.legend.setText(legend) - - def getLegend(self): - """ - Returns the legend displayed along the colorbar - - :return: return the legend displayed along the colorbar - :rtype: str - """ - return self.legend.text() - - def _activeScatterChanged(self, previous, legend): - """Handle plot active scatter changed""" - plot = self.getPlot() - - # Do not handle active scatter while there is an image - if plot.getActiveImage() is not None: - return - - if legend is None: # No active scatter, display no colormap - self.setColormap(colormap=None) - return - - # Sync with active scatter - activeScatter = plot._getActiveItem(kind='scatter') - - self.setColormap(colormap=activeScatter.getColormap(), - data=activeScatter.getValueData(copy=False)) - - def _activeImageChanged(self, previous, legend): - """Handle plot active image changed""" - plot = self.getPlot() - - if legend is None: # No active image, try with active scatter - activeScatterLegend = plot._getActiveItem( - kind='scatter', just_legend=True) - # No more active image, use active scatter if any - self._activeScatterChanged(None, activeScatterLegend) - else: - # Sync with active image - image = plot.getActiveImage().getData(copy=False) - - # RGB(A) image, display default colormap - if image.ndim != 2: - self.setColormap(colormap=None) - return - - # data image, sync with image colormap - # do we need the copy here : used in the case we are changing - # vmin and vmax but should have already be done by the plot - self.setColormap(colormap=plot.getActiveImage().getColormap(), - data=image) - - def _defaultColormapChanged(self, event): - """Handle plot default colormap changed""" - if event['event'] == 'defaultColormapChanged': - plot = self.getPlot() - if (plot is not None and - plot.getActiveImage() is None and - plot._getActiveItem(kind='scatter') is None): - # No active item, take default colormap update into account - self._syncWithDefaultColormap() - - def _syncWithDefaultColormap(self, data=None): - """Update colorbar according to plot default colormap""" - self.setColormap(self.getPlot().getDefaultColormap(), data) - - def getColorScaleBar(self): - """ - - :return: return the :class:`ColorScaleBar` used to display ColorScale - and ticks""" - return self._colorScale - - -class _VerticalLegend(qt.QLabel): - """Display vertically the given text - """ - def __init__(self, text, parent=None): - """ - - :param text: the legend - :param parent: the Qt parent if any - """ - qt.QLabel.__init__(self, text, parent) - self.setLayout(qt.QVBoxLayout()) - self.layout().setContentsMargins(0, 0, 0, 0) - - def paintEvent(self, event): - painter = qt.QPainter(self) - painter.setFont(self.font()) - - painter.translate(0, self.rect().height()) - painter.rotate(270) - newRect = qt.QRect(0, 0, self.rect().height(), self.rect().width()) - - painter.drawText(newRect, qt.Qt.AlignHCenter, self.text()) - - fm = qt.QFontMetrics(self.font()) - preferedHeight = fm.width(self.text()) - preferedWidth = fm.height() - self.setFixedWidth(preferedWidth) - self.setMinimumHeight(preferedHeight) - - -class ColorScaleBar(qt.QWidget): - """This class is making the composition of a :class:`_ColorScale` and a - :class:`_TickBar`. - - It is the simplest widget displaying ticks and colormap gradient. - - .. image:: img/colorScaleBar.png - :width: 150px - :align: center - - To run the following sample code, a QApplication must be initialized. - - >>> colormap = Colormap(name='gray', - ... norm='log', - ... vmin=1, - ... vmax=100000, - ... ) - >>> colorscale = ColorScaleBar(parent=None, - ... colormap=colormap ) - >>> colorscale.show() - - Initializer parameters : - - :param colormap: the colormap to be displayed - :param parent: the Qt parent if any - :param displayTicksValues: display the ticks value or only the '-' - """ - - _TEXT_MARGIN = 5 - """The tick bar need a margin to display all labels at the correct place. - So the ColorScale should have the same margin in order for both to fit""" - - def __init__(self, parent=None, colormap=None, data=None, - displayTicksValues=True): - super(ColorScaleBar, self).__init__(parent) - - self.minVal = None - """Value set to the _minLabel""" - self.maxVal = None - """Value set to the _maxLabel""" - - self.setLayout(qt.QGridLayout()) - - # create the left side group (ColorScale) - self.colorScale = _ColorScale(colormap=colormap, - data=data, - parent=self, - margin=ColorScaleBar._TEXT_MARGIN) - if colormap: - vmin, vmax = colormap.getColormapRange(data) - else: - vmin, vmax = colors.DEFAULT_MIN_LIN, colors.DEFAULT_MAX_LIN - - norm = colormap.getNormalization() if colormap else colors.Colormap.LINEAR - self.tickbar = _TickBar(vmin=vmin, - vmax=vmax, - norm=norm, - parent=self, - displayValues=displayTicksValues, - margin=ColorScaleBar._TEXT_MARGIN) - - self.layout().addWidget(self.tickbar, 1, 0, 1, 1, qt.Qt.AlignRight) - self.layout().addWidget(self.colorScale, 1, 1, qt.Qt.AlignLeft) - - self.layout().setContentsMargins(0, 0, 0, 0) - self.layout().setSpacing(0) - - # max label - self._maxLabel = qt.QLabel(str(1.0), parent=self) - self._maxLabel.setToolTip(str(0.0)) - self.layout().addWidget(self._maxLabel, 0, 0, 1, 2, qt.Qt.AlignRight) - - # min label - self._minLabel = qt.QLabel(str(0.0), parent=self) - self._minLabel.setToolTip(str(0.0)) - self.layout().addWidget(self._minLabel, 2, 0, 1, 2, qt.Qt.AlignRight) - - self.layout().setSizeConstraint(qt.QLayout.SetMinAndMaxSize) - self.layout().setColumnStretch(0, 1) - self.layout().setRowStretch(1, 1) - - def getTickBar(self): - """ - - :return: the instanciation of the :class:`_TickBar` - """ - return self.tickbar - - def getColorScale(self): - """ - - :return: the instanciation of the :class:`_ColorScale` - """ - return self.colorScale - - def getColormap(self): - """ - - :returns: the colormap. - :rtype: :class:`.Colormap` - """ - return self.colorScale.getColormap() - - def setColormap(self, colormap, data=None): - """Set the new colormap to be displayed - - :param Colormap colormap: the colormap to set - :param numpy.ndarray data: the data to display, needed if the colormap - require an autoscale - """ - self.colorScale.setColormap(colormap, data) - - if colormap is not None: - vmin, vmax = colormap.getColormapRange(data) - norm = colormap.getNormalization() - else: - vmin, vmax = None, None - norm = None - - self.tickbar.update(vmin=vmin, - vmax=vmax, - norm=norm) - self._setMinMaxLabels(vmin, vmax) - - def setMinMaxVisible(self, val=True): - """Change visibility of the min label and the max label - - :param val: if True, set the labels visible, otherwise set it not visible - """ - self._minLabel.setVisible(val) - self._maxLabel.setVisible(val) - - def _updateMinMax(self): - """Update the min and max label if we are in the case of the - configuration 'minMaxValueOnly'""" - if self.minVal is None: - text, tooltip = '', '' - else: - if self.minVal == 0 or 0 <= numpy.log10(abs(self.minVal)) < 7: - text = '%.7g' % self.minVal - else: - text = '%.2e' % self.minVal - tooltip = repr(self.minVal) - - self._minLabel.setText(text) - self._minLabel.setToolTip(tooltip) - - if self.maxVal is None: - text, tooltip = '', '' - else: - if self.maxVal == 0 or 0 <= numpy.log10(abs(self.maxVal)) < 7: - text = '%.7g' % self.maxVal - else: - text = '%.2e' % self.maxVal - tooltip = repr(self.maxVal) - - self._maxLabel.setText(text) - self._maxLabel.setToolTip(tooltip) - - def _setMinMaxLabels(self, minVal, maxVal): - """Change the value of the min and max labels to be displayed. - - :param minVal: the minimal value of the TickBar (not str) - :param maxVal: the maximal value of the TickBar (not str) - """ - # bad hack to try to display has much information as possible - self.minVal = minVal - self.maxVal = maxVal - self._updateMinMax() - - def resizeEvent(self, event): - qt.QWidget.resizeEvent(self, event) - self._updateMinMax() - - -class _ColorScale(qt.QWidget): - """Widget displaying the colormap colorScale. - - Show matching value between the gradient color (from the colormap) at mouse - position and value. - - .. image:: img/colorScale.png - :width: 20px - :align: center - - - To run the following sample code, a QApplication must be initialized. - - >>> colormap = Colormap(name='viridis', - ... norm='log', - ... vmin=1, - ... vmax=100000, - ... ) - >>> colorscale = ColorScale(parent=None, - ... colormap=colormap) - >>> colorscale.show() - - Initializer parameters : - - :param colormap: the colormap to be displayed - :param parent: the Qt parent if any - :param int margin: the top and left margin to apply. - - .. warning:: Value drawing will be - done at the center of ticks. So if no margin is done your values - drawing might not be fully done for extrems values. - """ - - _NB_CONTROL_POINTS = 256 - - def __init__(self, colormap, parent=None, margin=5, data=None): - qt.QWidget.__init__(self, parent) - self._colormap = None - self.margin = margin - self.setColormap(colormap, data) - - self.setLayout(qt.QVBoxLayout()) - self.setSizePolicy(qt.QSizePolicy.Fixed, qt.QSizePolicy.Expanding) - # needed to get the mouse event without waiting for button click - self.setMouseTracking(True) - self.setMargin(margin) - self.setContentsMargins(0, 0, 0, 0) - - self.setMinimumHeight(self._NB_CONTROL_POINTS // 2 + 2 * self.margin) - self.setFixedWidth(25) - - def setColormap(self, colormap, data=None): - """Set the new colormap to be displayed - - :param dict colormap: the colormap to set - :param data: Optional data for which to compute colormap range. - """ - self._colormap = colormap - self.setEnabled(colormap is not None) - - if colormap is None: - self.vmin, self.vmax = None, None - else: - assert colormap.getNormalization() in colors.Colormap.NORMALIZATIONS - self.vmin, self.vmax = self._colormap.getColormapRange(data=data) - self._updateColorGradient() - self.update() - - def getColormap(self): - """Returns the colormap - - :rtype: :class:`.Colormap` - """ - return None if self._colormap is None else self._colormap - - def _updateColorGradient(self): - """Compute the color gradient""" - colormap = self.getColormap() - if colormap is None: - return - - indices = numpy.linspace(0., 1., self._NB_CONTROL_POINTS) - colors = colormap.getNColors(nbColors=self._NB_CONTROL_POINTS) - self._gradient = qt.QLinearGradient(0, 1, 0, 0) - self._gradient.setCoordinateMode(qt.QGradient.StretchToDeviceMode) - self._gradient.setStops( - [(i, qt.QColor(*color)) for i, color in zip(indices, colors)] - ) - - def paintEvent(self, event): - """""" - painter = qt.QPainter(self) - if self.getColormap() is not None: - painter.setBrush(self._gradient) - penColor = self.palette().color(qt.QPalette.Active, - qt.QPalette.Foreground) - else: - penColor = self.palette().color(qt.QPalette.Disabled, - qt.QPalette.Foreground) - painter.setPen(penColor) - - painter.drawRect(qt.QRect( - 0, - self.margin, - self.width() - 1., - self.height() - 2. * self.margin - 1.)) - - def mouseMoveEvent(self, event): - tooltip = str(self.getValueFromRelativePosition( - self._getRelativePosition(event.y()))) - qt.QToolTip.showText(event.globalPos(), tooltip, self) - super(_ColorScale, self).mouseMoveEvent(event) - - def _getRelativePosition(self, yPixel): - """yPixel : pixel position into _ColorScale widget reference - """ - # widgets are bottom-top referencial but we display in top-bottom referential - return 1. - (yPixel - self.margin) / float(self.height() - 2 * self.margin) - - def getValueFromRelativePosition(self, value): - """Return the value in the colorMap from a relative position in the - ColorScaleBar (y) - - :param value: float value in [0, 1] - :return: the value in [colormap['vmin'], colormap['vmax']] - """ - colormap = self.getColormap() - if colormap is None: - return - - value = max(0.0, value) - value = min(value, 1.0) - - vmin = self.vmin - vmax = self.vmax - if colormap.getNormalization() == colors.Colormap.LINEAR: - return vmin + (vmax - vmin) * value - elif colormap.getNormalization() == colors.Colormap.LOGARITHM: - rpos = (numpy.log10(vmax) - numpy.log10(vmin)) * value + numpy.log10(vmin) - return numpy.power(10., rpos) - else: - err = "normalization type (%s) is not managed by the _ColorScale Widget" % colormap['normalization'] - raise ValueError(err) - - def setMargin(self, margin): - """Define the margin to fit with a TickBar object. - This is needed since we can only paint on the viewport of the widget. - Didn't work with a simple setContentsMargins - - :param int margin: the margin to apply on the top and bottom. - """ - self.margin = margin - self.update() - - -class _TickBar(qt.QWidget): - """Bar grouping the ticks displayed - - To run the following sample code, a QApplication must be initialized. - - >>> bar = _TickBar(1, 1000, norm='log', parent=None, displayValues=True) - >>> bar.show() - - .. image:: img/tickbar.png - :width: 40px - :align: center - - :param int vmin: smaller value of the range of values - :param int vmax: higher value of the range of values - :param str norm: normalization type to be displayed. Valid values are - 'linear' and 'log' - :param parent: the Qt parent if any - :param bool displayValues: if True display the values close to the tick, - Otherwise only signal it by '-' - :param int nticks: the number of tick we want to display. Should be an - unsigned int ot None. If None, let the Tick bar find the optimal - number of ticks from the tick density. - :param int margin: margin to set on the top and bottom - """ - _WIDTH_DISP_VAL = 45 - """widget width when displayed with ticks labels""" - _WIDTH_NO_DISP_VAL = 10 - """widget width when displayed without ticks labels""" - _FONT_SIZE = 10 - """font size for ticks labels""" - _LINE_WIDTH = 10 - """width of the line to mark a tick""" - - DEFAULT_TICK_DENSITY = 0.015 - - def __init__(self, vmin, vmax, norm, parent=None, displayValues=True, - nticks=None, margin=5): - super(_TickBar, self).__init__(parent) - self.margin = margin - self._nticks = None - self.ticks = () - self.subTicks = () - self._forcedDisplayType = None - self.ticksDensity = _TickBar.DEFAULT_TICK_DENSITY - - self._vmin = vmin - self._vmax = vmax - self._norm = norm - self.displayValues = displayValues - self.setTicksNumber(nticks) - - self.setMargin(margin) - self.setContentsMargins(0, 0, 0, 0) - - self._resetWidth() - - def setTicksValuesVisible(self, val): - self.displayValues = val - self._resetWidth() - - def _resetWidth(self): - width = self._WIDTH_DISP_VAL if self.displayValues else self._WIDTH_NO_DISP_VAL - self.setFixedWidth(width) - - def update(self, vmin, vmax, norm): - self._vmin = vmin - self._vmax = vmax - self._norm = norm - self.computeTicks() - qt.QWidget.update(self) - - def setMargin(self, margin): - """Define the margin to fit with a _ColorScale object. - This is needed since we can only paint on the viewport of the widget - - :param int margin: the margin to apply on the top and bottom. - """ - self.margin = margin - - def setTicksNumber(self, nticks): - """Set the number of ticks to display. - - :param nticks: the number of tick to be display. Should be an - unsigned int ot None. If None, let the :class:`_TickBar` find the - optimal number of ticks from the tick density. - """ - self._nticks = nticks - self.computeTicks() - qt.QWidget.update(self) - - def setTicksDensity(self, density): - """If you let :class:`_TickBar` deal with the number of ticks - (nticks=None) then you can specify a ticks density to be displayed. - """ - if density < 0.0: - raise ValueError('Density should be a positive value') - self.ticksDensity = density - - def computeTicks(self): - """This function compute ticks values labels. It is called at each - update and each resize event. - Deal only with linear and log scale. - """ - nticks = self._nticks - if nticks is None: - nticks = self._getOptimalNbTicks() - - if self._vmin == self._vmax: - # No range: no ticks - self.ticks = () - self.subTicks = () - elif self._norm == colors.Colormap.LOGARITHM: - self._computeTicksLog(nticks) - elif self._norm == colors.Colormap.LINEAR: - self._computeTicksLin(nticks) - else: - err = 'TickBar - Wrong normalization %s' % self._norm - raise ValueError(err) - # update the form - font = qt.QFont() - font.setPixelSize(_TickBar._FONT_SIZE) - - self.form = self._getFormat(font) - - def _computeTicksLog(self, nticks): - logMin = numpy.log10(self._vmin) - logMax = numpy.log10(self._vmax) - lowBound, highBound, spacing, self._nfrac = ticklayout.niceNumbersForLog10(logMin, - logMax, - nticks) - self.ticks = numpy.power(10., numpy.arange(lowBound, highBound, spacing)) - if spacing == 1: - self.subTicks = ticklayout.computeLogSubTicks(ticks=self.ticks, - lowBound=numpy.power(10., lowBound), - highBound=numpy.power(10., highBound)) - else: - self.subTicks = [] - - def resizeEvent(self, event): - qt.QWidget.resizeEvent(self, event) - self.computeTicks() - - def _computeTicksLin(self, nticks): - _min, _max, _spacing, self._nfrac = ticklayout.niceNumbers(self._vmin, - self._vmax, - nticks) - - self.ticks = numpy.arange(_min, _max, _spacing) - self.subTicks = [] - - def _getOptimalNbTicks(self): - return max(2, int(round(self.ticksDensity * self.rect().height()))) - - def paintEvent(self, event): - painter = qt.QPainter(self) - font = painter.font() - font.setPixelSize(_TickBar._FONT_SIZE) - painter.setFont(font) - - # paint ticks - for val in self.ticks: - self._paintTick(val, painter, majorTick=True) - - # paint subticks - for val in self.subTicks: - self._paintTick(val, painter, majorTick=False) - - def _getRelativePosition(self, val): - """Return the relative position of val according to min and max value - """ - if self._norm == colors.Colormap.LINEAR: - return 1 - (val - self._vmin) / (self._vmax - self._vmin) - elif self._norm == colors.Colormap.LOGARITHM: - return 1 - (numpy.log10(val) - numpy.log10(self._vmin)) / (numpy.log10(self._vmax) - numpy.log10(self._vmin)) - else: - raise ValueError('Norm is not recognized') - - def _paintTick(self, val, painter, majorTick=True): - """ - - :param bool majorTick: if False will never draw text and will set a line - with a smaller width - """ - fm = qt.QFontMetrics(painter.font()) - viewportHeight = self.rect().height() - self.margin * 2 - 1 - relativePos = self._getRelativePosition(val) - height = viewportHeight * relativePos - height += self.margin - lineWidth = _TickBar._LINE_WIDTH - if majorTick is False: - lineWidth /= 2 - - painter.drawLine(qt.QLine(self.width() - lineWidth, - height, - self.width(), - height)) - - if self.displayValues and majorTick is True: - painter.drawText(qt.QPoint(0.0, height + (fm.height() / 2)), - self.form.format(val)) - - def setDisplayType(self, disType): - """Set the type of display we want to set for ticks labels - - :param str disType: The type of display we want to set. disType values - can be : - - - 'std' for standard, meaning only a formatting on the number of - digits is done - - 'e' for scientific display - - None to let the _TickBar guess the best display for this kind of data. - """ - if disType not in (None, 'std', 'e'): - raise ValueError("display type not recognized, value should be in (None, 'std', 'e'") - self._forcedDisplayType = disType - - def _getStandardFormat(self): - return "{0:.%sf}" % self._nfrac - - def _getFormat(self, font): - if self._forcedDisplayType is None: - return self._guessType(font) - elif self._forcedDisplayType is 'std': - return self._getStandardFormat() - elif self._forcedDisplayType is 'e': - return self._getScientificForm() - else: - err = 'Forced type for display %s is not recognized' % self._forcedDisplayType - raise ValueError(err) - - def _getScientificForm(self): - return "{0:.0e}" - - def _guessType(self, font): - """Try fo find the better format to display the tick's labels - - :param QFont font: the font we want to use during the painting - """ - form = self._getStandardFormat() - - fm = qt.QFontMetrics(font) - width = 0 - for tick in self.ticks: - width = max(fm.width(form.format(tick)), width) - - # if the length of the string are too long we are moving to scientific - # display - if width > _TickBar._WIDTH_DISP_VAL - _TickBar._LINE_WIDTH: - return self._getScientificForm() - else: - return form |