Skip to content

Commit

Permalink
Merge branch 'master' of https://github.com/vasole/pymca
Browse files Browse the repository at this point in the history
  • Loading branch information
vasole committed Nov 19, 2014
2 parents 798904a + 092fcb5 commit 97d2be8
Show file tree
Hide file tree
Showing 4 changed files with 357 additions and 66 deletions.
22 changes: 18 additions & 4 deletions PyMca5/PyMcaGraph/Plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,12 +448,18 @@ def addCurve(self, x, y, legend=None, info=None, replace=False,
info.get('plot_yaxis', 'left')

if self.isXAxisLogarithmic() or self.isYAxisLogarithmic():
xplot, yplot = self.logFilterData(x, y)
if hasattr(color, "size"):
xplot, yplot, colorplot = self.logFilterData(x, y, color=color)
else:
xplot, yplot, colorplot = self.logFilterData(x, y, color=None)
colorplot = color
else:
xplot, yplot = x, y
colorplot = color
if len(xplot):
curveHandle = self._plot.addCurve(xplot, yplot, key, info,
replot=False, replace=replace)
replot=False, replace=replace,
color=colorplot)
info['plot_handle'] = curveHandle
else:
info['plot_handle'] = key
Expand Down Expand Up @@ -847,7 +853,7 @@ def setXAxisLogarithmic(self, flag):
print("x axis was already linear mode")
return

def logFilterData(self, x, y, xLog=None, yLog=None):
def logFilterData(self, x, y, xLog=None, yLog=None, color=None):
if xLog is None:
xLog = self._logX
if yLog is None:
Expand All @@ -865,7 +871,15 @@ def logFilterData(self, x, y, xLog=None, yLog=None):
idx = numpy.nonzero(x > 0)[0]
x = numpy.take(x, idx)
y = numpy.take(y, idx)
return x, y
if isinstance(color, numpy.ndarray):
colors = numpy.zeros((x.size, 4), color.dtype)
colors[:, 0] = color[idx, 0]
colors[:, 1] = color[idx, 1]
colors[:, 2] = color[idx, 2]
colors[:, 3] = color[idx, 3]
else:
colors = color
return x, y, colors

def _update(self):
if DEBUG:
Expand Down
134 changes: 76 additions & 58 deletions PyMca5/PyMcaGraph/backends/MatplotlibBackend.py
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,12 @@ def onMouseMoved(self, event):
if 'draggable' in marker._plot_options:
ddict['draggable'] = True
if QT:
self.setCursor(QtGui.QCursor(QtCore.Qt.SizeHorCursor))
if 'ymarker' in artist._plot_options:
self.setCursor(QtGui.QCursor(QtCore.Qt.SizeVerCursor))
if 'xmarker' in artist._plot_options:
self.setCursor(QtGui.QCursor(QtCore.Qt.SizeHorCursor))
else:
self.setCursor(QtGui.QCursor(QtCore.Qt.SizeAllCursor))
else:
ddict['draggable'] = False
if 'selectable' in marker._plot_options:
Expand Down Expand Up @@ -1092,9 +1097,16 @@ def setLimits(self, xmin, xmax, ymin, ymax):

def resetZoom(self):
xmin, xmax, ymin, ymax = self.getDataLimits('left')
xmin2, xmax2, ymin2, ymax2 = self.getDataLimits('right')
if hasattr(self.ax2, "get_visible"):
if self.ax2.get_visible():
xmin2, xmax2, ymin2, ymax2 = self.getDataLimits('right')
else:
xmin2 = None
xmax2 = None
else:
xmin2, xmax2, ymin2, ymax2 = self.getDataLimits('right')
#self.ax2.set_ylim(ymin2, ymax2)
if (xmin2 != 0) or (xmax2 != 1):
if (xmin2 is not None) and ((xmin2 != 0) or (xmax2 != 1)):
xmin = min(xmin, xmin2)
xmax = max(xmax, xmax2)
self.setLimits(xmin, xmax, ymin, ymax)
Expand Down Expand Up @@ -1202,6 +1214,8 @@ def getDataLimits(self, axesLabel='left'):
xmax = 1
ymin = 0
ymax = 1
if axesLabel == 'right':
return None, None, None, None

xSize = float(xmax - xmin)
ySize = float(ymax - ymin)
Expand Down Expand Up @@ -1302,58 +1316,58 @@ def addCurve(self, x, y, legend, info=None, replace=False, replot=True, **kw):
else:
axes = self.ax

if self._logY:
curveList = axes.semilogy( x, y, label=legend,
linestyle=style,
color=color,
linewidth=linewidth,
picker=3,
**kw)
elif hasattr(color, "__len__"):
scatterPlot = False
if hasattr(color, "dtype"):
if len(color) == len(x):
# scatter plot
if color.dtype not in [numpy.float32, numpy.float]:
actualColor = color / 255.
else:
actualColor = color
pathObject = axes.scatter(x, y,
label=legend,
color=actualColor,
marker=symbol,
picker=3)

if style not in [" ", None]:
# scatter plot with an actual line ...
# we need to assign a color ...
curveList = axes.plot(x, y, label=legend,
linestyle=style,
color=actualColor[0],
linewidth=linewidth,
picker=3,
marker=None,
**kw)
curveList[-1]._plot_info = {'color':actualColor,
'linewidth':linewidth,
'brush':brush,
'style':style,
'symbol':symbol,
'label':legend,
'axes':axisId,
'fill':fill}
if hasattr(x, "min") and hasattr(y, "min"):
curveList[-1]._plot_info['xmin'] = x.min()
curveList[-1]._plot_info['xmax'] = x.max()
curveList[-1]._plot_info['ymin'] = y.min()
curveList[-1]._plot_info['ymax'] = y.max()
# scatter plot is a collection
curveList = [pathObject]
scatterPlot = True
if "color" in kw:
del kw["color"]
if scatterPlot:
# scatter plot
if color.dtype not in [numpy.float32, numpy.float]:
actualColor = color / 255.
else:
curveList = axes.plot( x, y, label=legend,
actualColor = color
pathObject = axes.scatter(x, y,
label=legend,
color=actualColor,
marker=symbol,
picker=3)

if style not in [" ", None]:
# scatter plot with an actual line ...
# we need to assign a color ...
curveList = axes.plot(x, y, label=legend,
linestyle=style,
color=color,
color=actualColor[0],
linewidth=linewidth,
picker=3,
marker=None,
**kw)
curveList[-1]._plot_info = {'color':actualColor,
'linewidth':linewidth,
'brush':brush,
'style':style,
'symbol':symbol,
'label':legend,
'axes':axisId,
'fill':fill}
if hasattr(x, "min") and hasattr(y, "min"):
curveList[-1]._plot_info['xmin'] = x.min()
curveList[-1]._plot_info['xmax'] = x.max()
curveList[-1]._plot_info['ymin'] = y.min()
curveList[-1]._plot_info['ymax'] = y.max()
# scatter plot is a collection
curveList = [pathObject]
if self._logY:
axes.set_yscale('log')
elif self._logY:
curveList = axes.semilogy( x, y, label=legend,
linestyle=style,
color=color,
linewidth=linewidth,
picker=3,
**kw)
else:
curveList = axes.plot( x, y, label=legend,
linestyle=style,
Expand Down Expand Up @@ -1715,22 +1729,26 @@ def removeCurve(self, handle, replot=True):
if hasattr(handle, "remove"):
if handle in self.ax.lines:
handle.remove()
if handle in self.ax2.lines:
handle.remove()
if handle in self.ax.collections:
handle.remove()
if handle in self.ax2.collections:
handle.remove()
else:
# we have received a legend!
legend = handle
handle = None
for line2d in self.ax.lines:
label = line2d.get_label()
if label == legend:
handle = line2d
if handle is None:
for line2d in self.ax2.lines:
testLists = [self.ax.lines, self.ax2.lines,
self.ax.collections, self.ax2.collections]
for container in testLists:
for line2d in container:
label = line2d.get_label()
if label == legend:
handle = line2d
if handle is not None:
handle.remove()
del handle
if handle is not None:
handle.remove()
del handle
if replot:
self.replot()

Expand Down
159 changes: 159 additions & 0 deletions PyMca5/PyMcaGui/plotting/MaskScatterWidget.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
#/*##########################################################################
# Copyright (C) 2004-2014 V.A. Sole, European Synchrotron Radiation Facility
#
# This file is part of the PyMca X-ray Fluorescence Toolkit developed at
# the ESRF by the Software group.
#
# 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.
#
#############################################################################*/
__author__ = "V.A. Sole - ESRF Data Analysis"
__contact__ = "[email protected]"
__license__ = "MIT"
__copyright__ = "European Synchrotron Radiation Facility, Grenoble, France"
import sys
import os
import numpy
from PyMca5.PyMcaGraph.ctools import pnpoly

DEBUG = 0

from . import PlotWindow
qt = PlotWindow.qt
IconDict = PlotWindow.IconDict

class MaskScatterWidget(PlotWindow.PlotWindow):
def __init__(self, parent=None, backend=None, plugins=False, newplot=False,
control=False, position=False, maxNRois=1, grid=False,
logx=False, logy=False, togglePoints=False, normal=True,
polygon=True, colormap=False, aspect=True,
imageIcons=True, **kw):
super(MaskScatterWidget, self).__init__(parent=parent,
backend=backend,
plugins=plugins,
newplot=newplot,
control=control,
position=position,
grid=grid,
logx=logx,
logy=logy,
togglePoints=togglePoints,
normal=normal,
aspect=aspect,
colormap=colormap,
imageIcons=imageIcons,
polygon=polygon,
**kw)
self._selectionCurve = None
self._selectionMask = None
self._selectionColors = numpy.zeros((len(self.colorList), 4), numpy.uint8)
for i in range(len(self.colorList)):
self._selectionColors[i, 0] = eval("0x" + self.colorList[i][-2:])
self._selectionColors[i, 1] = eval("0x" + self.colorList[i][3:-2])
self._selectionColors[i, 2] = eval("0x" + self.colorList[i][1:3])
self._selectionColors[i, 3] = 0xff
self._maxNRois = maxNRois
self._nRoi = 1
self._zoomMode = True
self._eraseMode = False
self._brushMode = False
self.setDrawModeEnabled(False)

def setSelectionCurveData(self, x, y, legend="MaskScatterWidget", info=None,
replot=True, replace=True, line_style=" ", color="r", symbol=None, **kw):
self.enableActiveCurveHandling(False)
if symbol is None:
symbol = "o"
self.addCurve(x=x, y=y, legend=legend, info=info,
replace=replace, replot=replot, line_style=line_style, color=color, symbol=symbol, **kw)
self._selectionCurve = legend

def setSelectionMask(self, mask=None):
if self._selectionCurve is not None:
selectionCurve = self.getCurve(self._selectionCurve)
if selectionCurve in [[], None]:
self._selectionCurve = None
self._selectionMask = mask
else:
x, y = selectionCurve[0:2]
x = numpy.array(x, copy=False)
if hasattr(mask, "size"):
if mask.size == x.size:
if self._selectionMask is None:
self._selectionMask = mask
elif self._selectionMask.size == mask.size:
# keep shape because we may refer to images
tmpView = self._selectionMask[:]
tmpView.shape = -1
tmpMask = mask[:]
tmpMask.shape = -1
tmpView[:] = tmpMask[:]
else:
self._selectionMask = mask
else:
raise ValueError("Mask size = %d while data size = %d" % (mask.size(), x.size()))
self._updatePlot()

def getSelectionMask(self):
# TODO: Deal with non-finite data like in MaskImageWidget
return self._selectionMask

def _updatePlot(self, replot=True, replace=True):
if self._selectionCurve is None:
return
x, y, legend, info = self.getCurve(self._selectionCurve)
x.shape = -1
y.shape = -1
mask = numpy.zeros(y.shape, dtype=numpy.uint8)
colors = numpy.zeros((y.size, 4), dtype=numpy.uint8)
if self._selectionMask is not None:
tmpMask = self._selectionMask[:]
tmpMask.shape = -1
for i in range(1, self._maxNRois):
colors[tmpMask == i, :] = self._selectionColors[i]
self.setSelectionCurveData(x, y, legend=legend, info=info, color=colors, line_style=" ",
replot=replot, replace=replace)

def setActiveRoiNumber(self, intValue):
if (intValue < 0) or (intValue > self._maxNRois):
raise ValueError("Value %d outside the interval [0, %d]" % (intValue, self._maxNRois))
self._nRoi = intValue

def setPolygonSelectionMode(self):
"""
Resets zoom mode and enters selection mode with the current active ROI index
"""
self._zoomMode = False
self._brushMode = False
# one should be able to erase with a polygonal mask
self._eraseMode = False
self.setDrawModeEnabled(True, shape="polygon", label="mask")

if __name__ == "__main__":
app = qt.QApplication([])
x = numpy.arange(1000.)
y = x * x
w = MaskScatterWidget(maxNRois=8)
w.setSelectionCurveData(x, y, color="k", symbol="o")
import numpy.random
w.setSelectionMask(numpy.random.permutation(1000) % 10)
w.setPolygonSelectionMode()
w.show()
app.exec_()

Loading

0 comments on commit 97d2be8

Please sign in to comment.