@@ -807,6 +807,26 @@ def __call__(self, x, pos=None):
807
807
nearest_long (fx ))
808
808
809
809
810
+ class LogitFormatter (Formatter ):
811
+ '''Probability formatter (using Math text)'''
812
+ def __call__ (self , x , pos = None ):
813
+ s = ''
814
+ if 0.01 <= x <= 0.99 :
815
+ if x in [.01 , 0.1 , 0.5 , 0.9 , 0.99 ]:
816
+ s = '{:.2f}' .format (x )
817
+ elif x < 0.01 :
818
+ if is_decade (x ):
819
+ s = '$10^{%.0f}$' % np .log10 (x )
820
+ elif x > 0.99 :
821
+ if is_decade (1 - x ):
822
+ s = '$1-10^{%.0f}$' % np .log10 (1 - x )
823
+ return s
824
+
825
+ def format_data_short (self , value ):
826
+ 'return a short formatted string representation of a number'
827
+ return '%-12g' % value
828
+
829
+
810
830
class EngFormatter (Formatter ):
811
831
"""
812
832
Formats axis values using engineering prefixes to represent powers of 1000,
@@ -1694,6 +1714,88 @@ def view_limits(self, vmin, vmax):
1694
1714
return result
1695
1715
1696
1716
1717
+ class LogitLocator (Locator ):
1718
+ """
1719
+ Determine the tick locations for logit axes
1720
+ """
1721
+
1722
+ def __init__ (self , minor = False ):
1723
+ """
1724
+ place ticks on the logit locations
1725
+ """
1726
+ self .minor = minor
1727
+
1728
+ def __call__ (self ):
1729
+ 'Return the locations of the ticks'
1730
+ vmin , vmax = self .axis .get_view_interval ()
1731
+ return self .tick_values (vmin , vmax )
1732
+
1733
+ def tick_values (self , vmin , vmax ):
1734
+ # dummy axis has no axes attribute
1735
+ if hasattr (self .axis , 'axes' ) and self .axis .axes .name == 'polar' :
1736
+ raise NotImplementedError ('Polar axis cannot be logit scaled yet' )
1737
+
1738
+ # what to do if a window beyond ]0, 1[ is chosen
1739
+ if vmin <= 0.0 :
1740
+ if self .axis is not None :
1741
+ vmin = self .axis .get_minpos ()
1742
+
1743
+ if (vmin <= 0.0 ) or (not np .isfinite (vmin )):
1744
+ raise ValueError (
1745
+ "Data has no values in ]0, 1[ and therefore can not be "
1746
+ "logit-scaled." )
1747
+
1748
+ # NOTE: for vmax, we should query a property similar to get_minpos, but
1749
+ # related to the maximal, less-than-one data point. Unfortunately,
1750
+ # get_minpos is defined very deep in the BBox and updated with data,
1751
+ # so for now we use the trick below.
1752
+ if vmax >= 1.0 :
1753
+ if self .axis is not None :
1754
+ vmax = 1 - self .axis .get_minpos ()
1755
+
1756
+ if (vmax >= 1.0 ) or (not np .isfinite (vmax )):
1757
+ raise ValueError (
1758
+ "Data has no values in ]0, 1[ and therefore can not be "
1759
+ "logit-scaled." )
1760
+
1761
+ if vmax < vmin :
1762
+ vmin , vmax = vmax , vmin
1763
+
1764
+ vmin = np .log10 (vmin / (1 - vmin ))
1765
+ vmax = np .log10 (vmax / (1 - vmax ))
1766
+
1767
+ decade_min = np .floor (vmin )
1768
+ decade_max = np .ceil (vmax )
1769
+
1770
+ # major ticks
1771
+ if not self .minor :
1772
+ ticklocs = []
1773
+ if (decade_min <= - 1 ):
1774
+ expo = np .arange (decade_min , min (0 , decade_max + 1 ))
1775
+ ticklocs .extend (list (10 ** expo ))
1776
+ if (decade_min <= 0 ) and (decade_max >= 0 ):
1777
+ ticklocs .append (0.5 )
1778
+ if (decade_max >= 1 ):
1779
+ expo = - np .arange (max (1 , decade_min ), decade_max + 1 )
1780
+ ticklocs .extend (list (1 - 10 ** expo ))
1781
+
1782
+ # minor ticks
1783
+ else :
1784
+ ticklocs = []
1785
+ if (decade_min <= - 2 ):
1786
+ expo = np .arange (decade_min , min (- 1 , decade_max ))
1787
+ newticks = np .outer (np .arange (2 , 10 ), 10 ** expo ).ravel ()
1788
+ ticklocs .extend (list (newticks ))
1789
+ if (decade_min <= 0 ) and (decade_max >= 0 ):
1790
+ ticklocs .extend ([0.2 , 0.3 , 0.4 , 0.6 , 0.7 , 0.8 ])
1791
+ if (decade_max >= 2 ):
1792
+ expo = - np .arange (max (2 , decade_min ), decade_max + 1 )
1793
+ newticks = 1 - np .outer (np .arange (2 , 10 ), 10 ** expo ).ravel ()
1794
+ ticklocs .extend (list (newticks ))
1795
+
1796
+ return self .raise_if_exceeds (np .array (ticklocs ))
1797
+
1798
+
1697
1799
class AutoLocator (MaxNLocator ):
1698
1800
def __init__ (self ):
1699
1801
MaxNLocator .__init__ (self , nbins = 9 , steps = [1 , 2 , 5 , 10 ])
0 commit comments