summaryrefslogtreecommitdiff
path: root/silx/gui/plot/backends/glutils
diff options
context:
space:
mode:
authorPicca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>2019-12-23 13:45:09 +0100
committerPicca Frédéric-Emmanuel <picca@synchrotron-soleil.fr>2019-12-23 13:45:09 +0100
commit5d647cf9a6159afd2933da594b9c79ad93d3cd9b (patch)
tree2571025a602f68fc8933b01104dc712d41f84034 /silx/gui/plot/backends/glutils
parent654a6ac93513c3cc1ef97cacd782ff674c6f4559 (diff)
New upstream version 0.12.0~b0+dfsg
Diffstat (limited to 'silx/gui/plot/backends/glutils')
-rw-r--r--silx/gui/plot/backends/glutils/GLPlotCurve.py165
-rw-r--r--silx/gui/plot/backends/glutils/GLPlotImage.py4
-rw-r--r--silx/gui/plot/backends/glutils/GLPlotTriangles.py9
3 files changed, 156 insertions, 22 deletions
diff --git a/silx/gui/plot/backends/glutils/GLPlotCurve.py b/silx/gui/plot/backends/glutils/GLPlotCurve.py
index 5f8d652..3a0ebac 100644
--- a/silx/gui/plot/backends/glutils/GLPlotCurve.py
+++ b/silx/gui/plot/backends/glutils/GLPlotCurve.py
@@ -132,8 +132,7 @@ class _Fill2D(object):
self.xData is not None and self.yData is not None):
# Get slices of not NaN values longer than 1 element
- isnan = numpy.logical_or(numpy.isnan(self.xData),
- numpy.isnan(self.yData))
+ isnan = numpy.logical_or(numpy.isnan(self.xData), numpy.isnan(self.yData))
notnan = numpy.logical_not(isnan)
start = numpy.where(numpy.logical_and(isnan[:-1], notnan[1:]))[0] + 1
if notnan[0]:
@@ -147,22 +146,25 @@ class _Fill2D(object):
# Number of points: slice + 2 * leading and trailing points
# Twice leading and trailing points to produce degenerated triangles
- nbPoints = numpy.sum(numpy.diff(slices, axis=1)) + 4 * len(slices)
+ nbPoints = numpy.sum(numpy.diff(slices, axis=1)) * 2 + 4 * len(slices)
points = numpy.empty((nbPoints, 2), dtype=numpy.float32)
offset = 0
+ # invert baseline for filling
+ new_y_data = numpy.append(self.yData, self.baseline)
for start, end in slices:
# Duplicate first point for connecting degenerated triangle
- points[offset:offset+2] = self.xData[start], self.baseline
+ points[offset:offset+2] = self.xData[start], new_y_data[start]
# 2nd point of the polygon is last point
- points[offset+2] = self.xData[end-1], self.baseline
+ points[offset+2] = self.xData[start], self.baseline[start]
- # Add all points from the data
- indices = start + buildFillMaskIndices(end - start)
+ indices = numpy.append(numpy.arange(start, end),
+ numpy.arange(len(self.xData) + end-1, len(self.xData) + start-1, -1))
+ indices = indices[buildFillMaskIndices(len(indices))]
- points[offset+3:offset+3+len(indices), 0] = self.xData[indices]
- points[offset+3:offset+3+len(indices), 1] = self.yData[indices]
+ points[offset+3:offset+3+len(indices), 0] = self.xData[indices % len(self.xData)]
+ points[offset+3:offset+3+len(indices), 1] = new_y_data[indices]
# Duplicate last point for connecting degenerated triangle
points[offset+3+len(indices)] = points[offset+3+len(indices)-1]
@@ -526,7 +528,16 @@ def distancesFromArrays(xData, yData):
DIAMOND, CIRCLE, SQUARE, PLUS, X_MARKER, POINT, PIXEL, ASTERISK = \
'd', 'o', 's', '+', 'x', '.', ',', '*'
-H_LINE, V_LINE = '_', '|'
+H_LINE, V_LINE, HEART = '_', '|', u'\u2665'
+
+TICK_LEFT = "tickleft"
+TICK_RIGHT = "tickright"
+TICK_UP = "tickup"
+TICK_DOWN = "tickdown"
+CARET_LEFT = "caretleft"
+CARET_RIGHT = "caretright"
+CARET_UP = "caretup"
+CARET_DOWN = "caretdown"
class _Points2D(object):
@@ -542,7 +553,8 @@ class _Points2D(object):
"""
MARKERS = (DIAMOND, CIRCLE, SQUARE, PLUS, X_MARKER, POINT, PIXEL, ASTERISK,
- H_LINE, V_LINE)
+ H_LINE, V_LINE, HEART, TICK_LEFT, TICK_RIGHT, TICK_UP, TICK_DOWN,
+ CARET_LEFT, CARET_RIGHT, CARET_UP, CARET_DOWN)
"""List of supported markers"""
_VERTEX_SHADER = """
@@ -640,7 +652,110 @@ class _Points2D(object):
return 0.0;
}
}
- """
+ """,
+ HEART: """
+ float alphaSymbol(vec2 coord, float size) {
+ coord = (coord - 0.5) * 2.;
+ coord *= 0.75;
+ coord.y += 0.25;
+ float a = atan(coord.x,-coord.y)/3.141593;
+ float r = length(coord);
+ float h = abs(a);
+ float d = (13.0*h - 22.0*h*h + 10.0*h*h*h)/(6.0-5.0*h);
+ float res = clamp(r-d, 0., 1.);
+ // antialiasing
+ res = smoothstep(0.1, 0.001, res);
+ return res;
+ }
+ """,
+ TICK_LEFT: """
+ float alphaSymbol(vec2 coord, float size) {
+ coord = size * (coord - 0.5);
+ float dy = abs(coord.y);
+ if (dy < 0.5 && coord.x < 0.5) {
+ return 1.0;
+ } else {
+ return 0.0;
+ }
+ }
+ """,
+ TICK_RIGHT: """
+ float alphaSymbol(vec2 coord, float size) {
+ coord = size * (coord - 0.5);
+ float dy = abs(coord.y);
+ if (dy < 0.5 && coord.x > -0.5) {
+ return 1.0;
+ } else {
+ return 0.0;
+ }
+ }
+ """,
+ TICK_UP: """
+ float alphaSymbol(vec2 coord, float size) {
+ coord = size * (coord - 0.5);
+ float dx = abs(coord.x);
+ if (dx < 0.5 && coord.y < 0.5) {
+ return 1.0;
+ } else {
+ return 0.0;
+ }
+ }
+ """,
+ TICK_DOWN: """
+ float alphaSymbol(vec2 coord, float size) {
+ coord = size * (coord - 0.5);
+ float dx = abs(coord.x);
+ if (dx < 0.5 && coord.y > -0.5) {
+ return 1.0;
+ } else {
+ return 0.0;
+ }
+ }
+ """,
+ CARET_LEFT: """
+ float alphaSymbol(vec2 coord, float size) {
+ coord = size * (coord - 0.5);
+ float d = abs(coord.x) - abs(coord.y);
+ if (d >= -0.1 && coord.x > 0.5) {
+ return smoothstep(-0.1, 0.1, d);
+ } else {
+ return 0.0;
+ }
+ }
+ """,
+ CARET_RIGHT: """
+ float alphaSymbol(vec2 coord, float size) {
+ coord = size * (coord - 0.5);
+ float d = abs(coord.x) - abs(coord.y);
+ if (d >= -0.1 && coord.x < 0.5) {
+ return smoothstep(-0.1, 0.1, d);
+ } else {
+ return 0.0;
+ }
+ }
+ """,
+ CARET_UP: """
+ float alphaSymbol(vec2 coord, float size) {
+ coord = size * (coord - 0.5);
+ float d = abs(coord.y) - abs(coord.x);
+ if (d >= -0.1 && coord.y > 0.5) {
+ return smoothstep(-0.1, 0.1, d);
+ } else {
+ return 0.0;
+ }
+ }
+ """,
+ CARET_DOWN: """
+ float alphaSymbol(vec2 coord, float size) {
+ coord = size * (coord - 0.5);
+ float d = abs(coord.y) - abs(coord.x);
+ if (d >= -0.1 && coord.y < 0.5) {
+ return smoothstep(-0.1, 0.1, d);
+ } else {
+ return 0.0;
+ }
+ }
+ """,
}
_FRAGMENT_SHADER_TEMPLATE = """
@@ -964,6 +1079,7 @@ class GLPlotCurve2D(object):
markerColor=(0., 0., 0., 1.),
markerSize=7,
fillColor=None,
+ baseline=None,
isYLog=False):
self.colorData = colorData
@@ -1003,11 +1119,28 @@ class GLPlotCurve2D(object):
self.offset = 0., 0.
self.xData = xData
self.yData = yData
-
if fillColor is not None:
+ def deduce_baseline(baseline):
+ if baseline is None:
+ _baseline = 0
+ else:
+ _baseline = baseline
+ if not isinstance(_baseline, numpy.ndarray):
+ _baseline = numpy.repeat(_baseline,
+ len(self.xData))
+ if isYLog is True:
+ with warnings.catch_warnings(): # Ignore NaN comparison warnings
+ warnings.simplefilter('ignore',
+ category=RuntimeWarning)
+ log_val = numpy.log10(_baseline)
+ _baseline = numpy.where(_baseline>0.0, log_val, -38)
+ return _baseline
+
+ _baseline = deduce_baseline(baseline)
+
# Use different baseline depending of Y log scale
self.fill = _Fill2D(self.xData, self.yData,
- baseline=-38 if isYLog else 0,
+ baseline=_baseline,
color=fillColor,
offset=self.offset)
else:
@@ -1129,7 +1262,7 @@ class GLPlotCurve2D(object):
and the segment [i-1, i] is not tested for picking.
:return: The indices of the picked data
- :rtype: list of int
+ :rtype: Union[List[int],None]
"""
if (self.marker is None and self.lineStyle is None) or \
self.xMin > xPickMax or xPickMin > self.xMax or \
@@ -1209,4 +1342,4 @@ class GLPlotCurve2D(object):
(self.yData >= yPickMin) &
(self.yData <= yPickMax))[0].tolist()
- return indices
+ return tuple(indices) if len(indices) > 0 else None
diff --git a/silx/gui/plot/backends/glutils/GLPlotImage.py b/silx/gui/plot/backends/glutils/GLPlotImage.py
index 6f3c487..5d79023 100644
--- a/silx/gui/plot/backends/glutils/GLPlotImage.py
+++ b/silx/gui/plot/backends/glutils/GLPlotImage.py
@@ -1,7 +1,7 @@
# coding: utf-8
# /*##########################################################################
#
-# Copyright (c) 2014-2018 European Synchrotron Radiation Facility
+# Copyright (c) 2014-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
@@ -56,7 +56,7 @@ class _GLPlotData2D(object):
sx, sy = self.scale
col = int((x - ox) / sx)
row = int((y - oy) / sy)
- return col, row
+ return ((row, col),)
else:
return None
diff --git a/silx/gui/plot/backends/glutils/GLPlotTriangles.py b/silx/gui/plot/backends/glutils/GLPlotTriangles.py
index c756749..7aeb5ab 100644
--- a/silx/gui/plot/backends/glutils/GLPlotTriangles.py
+++ b/silx/gui/plot/backends/glutils/GLPlotTriangles.py
@@ -114,11 +114,12 @@ class GLPlotTriangles(object):
:param float x: X coordinates in plot data frame
:param float y: Y coordinates in plot data frame
:return: List of picked data point indices
- :rtype: numpy.ndarray
+ :rtype: Union[List[int],None]
"""
if (x < self.xMin or x > self.xMax or
y < self.yMin or y > self.yMax):
- return ()
+ return None
+
xPts, yPts = self.__x_y_color[:2]
if self.__picking_triangles is None:
self.__picking_triangles = numpy.zeros(
@@ -135,9 +136,9 @@ class GLPlotTriangles(object):
# Sorted from furthest to closest point
dists = (xPts[indices] - x) ** 2 + (yPts[indices] - y) ** 2
- indices = indices[numpy.flip(numpy.argsort(dists))]
+ indices = indices[numpy.flip(numpy.argsort(dists), axis=0)]
- return tuple(indices)
+ return tuple(indices) if len(indices) > 0 else None
def discard(self):
"""Release resources on the GPU"""