summaryrefslogtreecommitdiff
path: root/silx/gui/plot/ScatterMaskToolsWidget.py
diff options
context:
space:
mode:
Diffstat (limited to 'silx/gui/plot/ScatterMaskToolsWidget.py')
-rw-r--r--silx/gui/plot/ScatterMaskToolsWidget.py68
1 files changed, 56 insertions, 12 deletions
diff --git a/silx/gui/plot/ScatterMaskToolsWidget.py b/silx/gui/plot/ScatterMaskToolsWidget.py
index a9c1073..2a10f6d 100644
--- a/silx/gui/plot/ScatterMaskToolsWidget.py
+++ b/silx/gui/plot/ScatterMaskToolsWidget.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2017 European Synchrotron Radiation Facility
+# Copyright (c) 2018 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
@@ -35,7 +35,7 @@ from __future__ import division
__authors__ = ["P. Knobel"]
__license__ = "MIT"
-__date__ = "07/04/2017"
+__date__ = "24/04/2018"
import math
@@ -45,10 +45,11 @@ import numpy
import sys
from .. import qt
+from ...math.combo import min_max
from ...image import shapes
from ._BaseMaskToolsWidget import BaseMask, BaseMaskToolsWidget, BaseMaskToolsDockWidget
-from .Colors import cursorColorForColormap, rgba
+from ..colors import cursorColorForColormap, rgba
_logger = logging.getLogger(__name__)
@@ -186,13 +187,18 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
self._z = 2 # Mask layer in plot
self._data_scatter = None
"""plot Scatter item for data"""
+
+ self._data_extent = None
+ """Maximum extent of the data i.e., max(xMax-xMin, yMax-yMin)"""
+
self._mask_scatter = None
"""plot Scatter item for representing the mask"""
def setSelectionMask(self, mask, copy=True):
"""Set the mask to a new array.
- :param numpy.ndarray mask: The array to use for the mask.
+ :param numpy.ndarray mask:
+ The array to use for the mask or None to reset the mask.
:type mask: numpy.ndarray of uint8, C-contiguous.
Array of other types are converted.
:param bool copy: True (the default) to copy the array,
@@ -201,6 +207,10 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
The mask can be cropped or padded to fit active scatter,
the returned shape is that of the scatter data.
"""
+ if mask is None:
+ self.resetSelectionMask()
+ return self._data_scatter.getXData(copy=False).shape
+
mask = numpy.array(mask, copy=False, dtype=numpy.uint8)
if self._data_scatter.getXData(copy=False).shape == (0,) \
@@ -216,7 +226,7 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
def _updatePlotMask(self):
"""Update mask image in plot"""
mask = self.getSelectionMask(copy=False)
- if len(mask):
+ if mask is not None:
self.plot.addScatter(self._data_scatter.getXData(),
self._data_scatter.getYData(),
mask,
@@ -226,8 +236,7 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
self._mask_scatter = self.plot._getItem(kind="scatter",
legend=self._maskName)
self._mask_scatter.setSymbolSize(
- self._data_scatter.getSymbolSize() * 4.0
- )
+ self._data_scatter.getSymbolSize() + 2.0)
elif self.plot._getItem(kind="scatter",
legend=self._maskName) is not None:
self.plot.remove(self._maskName, kind='scatter')
@@ -248,7 +257,7 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
if not self.browseAction.isChecked():
self.browseAction.trigger() # Disable drawing tool
- if len(self.getSelectionMask(copy=False)):
+ if self.getSelectionMask(copy=False) is not None:
self.plot.sigActiveScatterChanged.connect(
self._activeScatterChangedAfterCare)
@@ -265,6 +274,9 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
# No active scatter or active scatter is the mask...
self.plot.sigActiveScatterChanged.disconnect(
self._activeScatterChangedAfterCare)
+ self._data_extent = None
+ self._data_scatter = None
+
else:
colormap = activeScatter.getColormap()
self._defaultOverlayColor = rgba(cursorColorForColormap(colormap['name']))
@@ -274,13 +286,22 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
self._z = activeScatter.getZValue() + 1
self._data_scatter = activeScatter
- if self._data_scatter.getXData(copy=False).shape != self.getSelectionMask(copy=False).shape:
+
+ # Adjust brush size to data range
+ xMin, xMax = min_max(self._data_scatter.getXData(copy=False))
+ yMin, yMax = min_max(self._data_scatter.getYData(copy=False))
+ self._data_extent = max(xMax - xMin, yMax - yMin)
+
+ if self._data_scatter.getXData(copy=False).shape != self._mask.getMask(copy=False).shape:
# scatter has not the same size, remove mask and stop listening
if self.plot._getItem(kind="scatter", legend=self._maskName):
self.plot.remove(self._maskName, kind='scatter')
self.plot.sigActiveScatterChanged.disconnect(
self._activeScatterChangedAfterCare)
+ self._data_extent = None
+ self._data_scatter = None
+
else:
# Refresh in case z changed
self._mask.setDataItem(self._data_scatter)
@@ -295,6 +316,7 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
self.setEnabled(False)
self._data_scatter = None
+ self._data_extent = None
self._mask.reset()
self._mask.commit()
@@ -309,8 +331,19 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
self._z = activeScatter.getZValue() + 1
self._data_scatter = activeScatter
+
+ # Adjust brush size to data range
+ xData = self._data_scatter.getXData(copy=False)
+ yData = self._data_scatter.getYData(copy=False)
+ if xData.size > 0 and yData.size > 0:
+ xMin, xMax = min_max(xData)
+ yMin, yMax = min_max(yData)
+ self._data_extent = max(xMax - xMin, yMax - yMin)
+ else:
+ self._data_extent = None
+
self._mask.setDataItem(self._data_scatter)
- if self._data_scatter.getXData(copy=False).shape != self.getSelectionMask(copy=False).shape:
+ if self._data_scatter.getXData(copy=False).shape != self._mask.getMask(copy=False).shape:
self._mask.reset(self._data_scatter.getXData(copy=False).shape)
self._mask.commit()
else:
@@ -439,6 +472,16 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
shape=self._data_scatter.getXData(copy=False).shape)
self._mask.commit()
+ def _getPencilWidth(self):
+ """Returns the width of the pencil to use in data coordinates`
+
+ :rtype: float
+ """
+ width = super(ScatterMaskToolsWidget, self)._getPencilWidth()
+ if self._data_extent is not None:
+ width *= 0.01 * self._data_extent
+ return width
+
def _plotDrawEvent(self, event):
"""Handle draw events from the plot"""
if (self._drawingMode is None or
@@ -467,7 +510,7 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
event['event'] == 'drawingFinished'):
doMask = self._isMasking()
vertices = event['points']
- vertices = vertices.astype(numpy.int)[:, (1, 0)] # (y, x)
+ vertices = vertices[:, (1, 0)] # (y, x)
self._mask.updatePolygon(level, vertices, doMask)
self._mask.commit()
@@ -475,7 +518,8 @@ class ScatterMaskToolsWidget(BaseMaskToolsWidget):
doMask = self._isMasking()
# convert from plot to array coords
x, y = event['points'][-1]
- brushSize = self.pencilSpinBox.value()
+
+ brushSize = self._getPencilWidth()
if self._lastPencilPos != (y, x):
if self._lastPencilPos is not None: