diff options
author | Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr> | 2019-12-23 13:45:09 +0100 |
---|---|---|
committer | Picca Frédéric-Emmanuel <picca@synchrotron-soleil.fr> | 2019-12-23 13:45:09 +0100 |
commit | 5d647cf9a6159afd2933da594b9c79ad93d3cd9b (patch) | |
tree | 2571025a602f68fc8933b01104dc712d41f84034 /silx/gui/plot/backends/glutils | |
parent | 654a6ac93513c3cc1ef97cacd782ff674c6f4559 (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.py | 165 | ||||
-rw-r--r-- | silx/gui/plot/backends/glutils/GLPlotImage.py | 4 | ||||
-rw-r--r-- | silx/gui/plot/backends/glutils/GLPlotTriangles.py | 9 |
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""" |