34
34
from copy import deepcopy
35
35
import logging
36
36
import enum
37
+ import numbers
37
38
from typing import Optional , Tuple , Union
38
39
import weakref
39
40
@@ -1422,7 +1423,7 @@ def getCurrentVisualizationParameter(self, parameter):
1422
1423
class PointsBase (DataItem , SymbolMixIn , AlphaMixIn ):
1423
1424
"""Base class for :class:`Curve` and :class:`Scatter`"""
1424
1425
1425
- # note: _logFilterData must be overloaded if you overload
1426
+ # note: _filterData must be overloaded if you overload
1426
1427
# getData to change its signature
1427
1428
1428
1429
_DEFAULT_Z_LAYER = 1
@@ -1517,8 +1518,22 @@ def _getClippingBoolArray(self, xPositive, yPositive):
1517
1518
)
1518
1519
return self ._clippedCache [(xPositive , yPositive )]
1519
1520
1520
- def _logFilterData (self , xPositive , yPositive ):
1521
- """Filter out values with x or y <= 0 on log axes
1521
+ @staticmethod
1522
+ def _filterNegativeValues (
1523
+ data : numpy .ndarray | numbers .Number | None ,
1524
+ ) -> numpy .ndarray | numbers .Number | None :
1525
+ """Returns data with negative values to 0"""
1526
+ if data is None :
1527
+ return None
1528
+
1529
+ # Convert data to array to avoid specific case for complex scalar
1530
+ if numpy .all (numpy .array (data , copy = False ) >= 0 ):
1531
+ return data
1532
+
1533
+ return numpy .clip (data , 0 , None ) # Also works for scalars
1534
+
1535
+ def _filterData (self , xPositive , yPositive ):
1536
+ """Filter out errors<0 and values with x or y <= 0 on log axes
1522
1537
1523
1538
:param bool xPositive: True to filter arrays according to X coords.
1524
1539
:param bool yPositive: True to filter arrays according to Y coords.
@@ -1527,8 +1542,8 @@ def _logFilterData(self, xPositive, yPositive):
1527
1542
"""
1528
1543
x = self .getXData (copy = False )
1529
1544
y = self .getYData (copy = False )
1530
- xerror = self .getXErrorData (copy = False )
1531
- yerror = self .getYErrorData (copy = False )
1545
+ xerror = self ._filterNegativeValues ( self . getXErrorData (copy = False ) )
1546
+ yerror = self ._filterNegativeValues ( self . getYErrorData (copy = False ) )
1532
1547
1533
1548
if xPositive or yPositive :
1534
1549
clipped = self ._getClippingBoolArray (xPositive , yPositive )
@@ -1592,7 +1607,7 @@ def _getBounds(self):
1592
1607
if len (data ) == 5 :
1593
1608
# hack to avoid duplicating caching mechanism in Scatter
1594
1609
# (happens when cached data is used, caching done using
1595
- # Scatter._logFilterData )
1610
+ # Scatter._filterData )
1596
1611
x , y , xerror , yerror = data [0 ], data [1 ], data [3 ], data [4 ]
1597
1612
else :
1598
1613
x , y , xerror , yerror = data
@@ -1609,31 +1624,30 @@ def _getBounds(self):
1609
1624
return self ._boundsCache [(xPositive , yPositive )]
1610
1625
1611
1626
def _getCachedData (self ):
1612
- """Return cached filtered data if applicable,
1613
- i.e. if any axis is in log scale.
1627
+ """Return cached filtered data if applicable.
1628
+
1614
1629
Return None if caching is not applicable."""
1615
1630
plot = self .getPlot ()
1616
- if plot is not None :
1617
- xPositive = plot .getXAxis ()._isLogarithmic ()
1618
- yPositive = plot .getYAxis ()._isLogarithmic ()
1619
- if xPositive or yPositive :
1620
- # At least one axis has log scale, filter data
1621
- if (xPositive , yPositive ) not in self ._filteredCache :
1622
- self ._filteredCache [(xPositive , yPositive )] = self ._logFilterData (
1623
- xPositive , yPositive
1624
- )
1625
- return self ._filteredCache [(xPositive , yPositive )]
1626
- return None
1631
+ if plot is None :
1632
+ return None
1633
+
1634
+ xPositive = plot .getXAxis ()._isLogarithmic ()
1635
+ yPositive = plot .getYAxis ()._isLogarithmic ()
1636
+ if (xPositive , yPositive ) not in self ._filteredCache :
1637
+ self ._filteredCache [(xPositive , yPositive )] = self ._filterData (
1638
+ xPositive , yPositive
1639
+ )
1640
+ return self ._filteredCache [(xPositive , yPositive )]
1627
1641
1628
1642
def getData (self , copy = True , displayed = False ):
1629
1643
"""Returns the x, y values of the curve points and xerror, yerror
1630
1644
1631
1645
:param bool copy: True (Default) to get a copy,
1632
1646
False to use internal representation (do not modify!)
1633
- :param bool displayed: True to only get curve points that are displayed
1634
- in the plot. Default: False
1635
- Note: If plot has log scale, negative points
1636
- are not displayed .
1647
+ :param bool displayed:
1648
+ True to only get curve points that are displayed in the plot.
1649
+ Note: If plot has log scale, negative points are not displayed.
1650
+ Negative errors are set to 0 .
1637
1651
:returns: (x, y, xerror, yerror)
1638
1652
:rtype: 4-tuple of numpy.ndarray
1639
1653
"""
0 commit comments