Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit80dca54

Browse files
committed
ticker.EngFormatter: base upon ScalarFormatter
Allows us to use many order of magnitude and offset related routinesfrom ScalarFormatter, and removes a bit usetex related duplicated code.Solves#28463.
1 parentf7a991e commit80dca54

File tree

3 files changed

+98
-37
lines changed

3 files changed

+98
-37
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
ticker.EngFormatter now computes offset by default
2+
-------------------------------------------
3+
4+
`ticker.EngFormatter` was modified to act very similar to
5+
`ticker.ScalarFormatter`, such that it computes the best offset of the axis
6+
data, and shows the offset with the known SI quantity prefixes. To disable this
7+
new behavior, simply pass `useOffset=False` when you instantiate it. If offsets
8+
are disabled, or if there is no particular offset that fits your axis data, the
9+
formatter will reside to the old behavior.

‎lib/matplotlib/tests/test_ticker.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,6 +1594,18 @@ def test_engformatter_usetex_useMathText():
15941594
assertx_tick_label_text== ['$0$','$500$','$1$ k']
15951595

15961596

1597+
deftest_engformatter_useOffset():
1598+
fig,ax=plt.subplots()
1599+
offset=int(1e7)
1600+
ydata=range(offset,offset+5)
1601+
ax.plot(ydata)
1602+
ax.set_yticks(ydata)
1603+
ax.yaxis.set_major_formatter(mticker.EngFormatter(useOffset=True,unit="Hz"))
1604+
fig.canvas.draw()
1605+
y_tick_label_text= [labl.get_text()forlablinax.get_yticklabels()]
1606+
asserty_tick_label_text== (np.array(ydata)-offset).astype(str).tolist()
1607+
1608+
15971609
classTestPercentFormatter:
15981610
percent_data= [
15991611
# Check explicitly set decimals over different intervals and values

‎lib/matplotlib/ticker.py

Lines changed: 77 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,7 +1338,7 @@ def format_data_short(self, value):
13381338
returnf"1-{1-value:e}"
13391339

13401340

1341-
classEngFormatter(Formatter):
1341+
classEngFormatter(ScalarFormatter):
13421342
"""
13431343
Format axis values using engineering prefixes to represent powers
13441344
of 1000, plus a specified unit, e.g., 10 MHz instead of 1e7.
@@ -1370,7 +1370,7 @@ class EngFormatter(Formatter):
13701370
}
13711371

13721372
def__init__(self,unit="",places=None,sep=" ",*,usetex=None,
1373-
useMathText=None):
1373+
useMathText=None,useOffset=None):
13741374
r"""
13751375
Parameters
13761376
----------
@@ -1404,55 +1404,93 @@ def __init__(self, unit="", places=None, sep=" ", *, usetex=None,
14041404
useMathText : bool, default: :rc:`axes.formatter.use_mathtext`
14051405
To enable/disable the use mathtext for rendering the numbers in
14061406
the formatter.
1407+
useOffset : bool or float, default: :rc:`axes.formatter.useoffset`
1408+
Whether to use offset notation. See `.set_useOffset`.
14071409
"""
14081410
self.unit=unit
14091411
self.places=places
14101412
self.sep=sep
1411-
self.set_usetex(usetex)
1412-
self.set_useMathText(useMathText)
1413-
1414-
defget_usetex(self):
1415-
returnself._usetex
1416-
1417-
defset_usetex(self,val):
1418-
ifvalisNone:
1419-
self._usetex=mpl.rcParams['text.usetex']
1420-
else:
1421-
self._usetex=val
1422-
1423-
usetex=property(fget=get_usetex,fset=set_usetex)
1424-
1425-
defget_useMathText(self):
1426-
returnself._useMathText
1413+
super().__init__(
1414+
useOffset=useOffset,
1415+
useMathText=useMathText,
1416+
useLocale=False,
1417+
usetex=usetex,
1418+
)
14271419

1428-
defset_useMathText(self,val):
1429-
ifvalisNone:
1430-
self._useMathText=mpl.rcParams['axes.formatter.use_mathtext']
1420+
def__call__(self,x,pos=None):
1421+
"""
1422+
Return the format for tick value *x* at position *pos*. If there is no
1423+
currently offset in the data, it returns the best engineering formatting
1424+
that fits the given argument, independently.
1425+
"""
1426+
iflen(self.locs)==0orself.offset==0:
1427+
returnself.fix_minus(self.format_data(x))
14311428
else:
1432-
self._useMathText=val
1429+
xp= (x-self.offset)/ (10.**self.orderOfMagnitude)
1430+
ifabs(xp)<1e-8:
1431+
xp=0
1432+
returnself._format_maybe_minus_and_locale(self.format,xp)
14331433

1434-
useMathText=property(fget=get_useMathText,fset=set_useMathText)
1434+
defset_locs(self,locs):
1435+
# docstring inherited
1436+
self.locs=locs
1437+
iflen(self.locs)>0:
1438+
ifself._useOffset:
1439+
self._compute_offset()
1440+
self._set_order_of_magnitude()
1441+
# This is what's different from ScalarFormatter: We search among
1442+
# the engineers' standard orders of magnitudes (0, -3, 3, -6, 6,
1443+
# -9, 9 etc) the oom closest to our self.orderOfMagnitude. Then we
1444+
# set our self.orderOfMagnitude to it.
1445+
c=abs(self.orderOfMagnitude)
1446+
forsciOominitertools.count(0,3):
1447+
ifc<=sciOom:
1448+
self.orderOfMagnitude=math.copysign(sciOom,self.orderOfMagnitude)
1449+
break
1450+
self._set_format()
14351451

1436-
def__call__(self,x,pos=None):
1437-
s=f"{self.format_eng(x)}{self.unit}"
1438-
# Remove the trailing separator when there is neither prefix nor unit
1439-
ifself.sepands.endswith(self.sep):
1440-
s=s[:-len(self.sep)]
1441-
returnself.fix_minus(s)
1452+
# Simplify a bit ScalarFormatter.get_offset: We always want to use
1453+
# self.format_data. We insert here the surrounding $...$ here, if tex /
1454+
# mathtext is set.
1455+
defget_offset(self):
1456+
# docstring inherited
1457+
iflen(self.locs)==0:
1458+
return''
1459+
ifself.orderOfMagnitudeorself.offset:
1460+
offsetStr=''
1461+
sciNotStr=''
1462+
ifself.offset:
1463+
offsetStr=self.format_data(self.offset)
1464+
ifself.offset>0:
1465+
offsetStr='+'+offsetStr
1466+
ifself.orderOfMagnitude:
1467+
sciNotStr=self.format_data(10**self.orderOfMagnitude)
1468+
ifself._useMathTextorself._usetex:
1469+
ifsciNotStr!='':
1470+
sciNotStr=r'\times%s'%sciNotStr
1471+
s=fr'${sciNotStr}{offsetStr}$'
1472+
else:
1473+
s=''.join((sciNotStr,offsetStr))
1474+
returnself.fix_minus(s)
1475+
return''
14421476

14431477
defformat_eng(self,num):
1478+
"""Alias to EngFormatter.format_data"""
1479+
returnself.format_data(num)
1480+
1481+
defformat_data(self,num):
14441482
"""
14451483
Format a number in engineering notation, appending a letter
14461484
representing the power of 1000 of the original number.
14471485
Some examples:
14481486
1449-
>>>format_eng(0) # for self.places = 0
1487+
>>>format_data(0) # for self.places = 0
14501488
'0'
14511489
1452-
>>>format_eng(1000000) # for self.places = 1
1490+
>>>format_data(1000000) # for self.places = 1
14531491
'1.0 M'
14541492
1455-
>>>format_eng(-1e-6) # for self.places = 2
1493+
>>>format_data(-1e-6) # for self.places = 2
14561494
'-1.00\N{MICRO SIGN}'
14571495
"""
14581496
sign=1
@@ -1482,13 +1520,15 @@ def format_eng(self, num):
14821520
mant/=1000
14831521
pow10+=3
14841522

1485-
prefix=self.ENG_PREFIXES[int(pow10)]
1523+
unitPrefix=self.ENG_PREFIXES[int(pow10)]
1524+
ifself.unitorunitPrefix:
1525+
suffix=f"{self.sep}{unitPrefix}{self.unit}"
1526+
else:
1527+
suffix=""
14861528
ifself._usetexorself._useMathText:
1487-
formatted=f"${mant:{fmt}}${self.sep}{prefix}"
1529+
returnrf"${mant:{fmt}}${suffix}"
14881530
else:
1489-
formatted=f"{mant:{fmt}}{self.sep}{prefix}"
1490-
1491-
returnformatted
1531+
returnrf"{mant:{fmt}}{suffix}"
14921532

14931533

14941534
classPercentFormatter(Formatter):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp