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

Commitbb3d7fc

Browse files
committed
Build lognorm/symlognorm from corresponding scales.
This fails test_colors.py::test_SymLogNorm because the old symlog normand scale were not consistent.test_contour::test_contourf_log_extension looks better with the patch?
1 parentd311b9b commitbb3d7fc

File tree

1 file changed

+82
-143
lines changed

1 file changed

+82
-143
lines changed

‎lib/matplotlib/colors.py

Lines changed: 82 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@
6767

6868
fromcollections.abcimportSized
6969
importfunctools
70+
importinspect
7071
importitertools
7172
fromnumbersimportNumber
7273
importre
7374

7475
importnumpyasnp
75-
importmatplotlib.cbookascbook
76-
frommatplotlibimportdocstring
76+
frommatplotlibimportcbook,docstring,scale
7777
from ._color_dataimportBASE_COLORS,TABLEAU_COLORS,CSS4_COLORS,XKCD_COLORS
7878

7979

@@ -1139,61 +1139,67 @@ class DivergingNorm(TwoSlopeNorm):
11391139
...
11401140

11411141

1142+
def_make_norm_from_scale(scale_cls,base_cls=None,*,init=None):
1143+
ifbase_clsisNone:
1144+
returnfunctools.partial(_make_norm_from_scale,scale_cls,init=init)
1145+
1146+
ifinitisNone:
1147+
init=lambdavmin=None,vmax=None,clip=False:None
1148+
init_signature=inspect.signature(init)
1149+
1150+
classNorm(base_cls):
1151+
1152+
def__init__(self,*args,**kwargs):
1153+
ba=init_signature.bind(*args,**kwargs)
1154+
ba.apply_defaults()
1155+
super().__init__(
1156+
**{k:ba.arguments.pop(k)forkin ["vmin","vmax","clip"]})
1157+
self._scale=scale_cls(axis=None,**ba.arguments)
1158+
self._trf=self._scale.get_transform()
1159+
self._inv_trf=self._trf.inverted()
1160+
1161+
def__call__(self,value,clip=None):
1162+
value,is_scalar=self.process_value(value)
1163+
self.autoscale_None(value)
1164+
ifself.vmin>self.vmax:
1165+
raiseValueError("vmin must be less or equal to vmax")
1166+
ifself.vmin==self.vmax:
1167+
returnnp.full_like(value,0)
1168+
ifclipisNone:
1169+
clip=self.clip
1170+
ifclip:
1171+
value=np.clip(value,self.vmin,self.vmax)
1172+
t_value=self._trf.transform(value).reshape(np.shape(value))
1173+
t_vmin,t_vmax=self._trf.transform([self.vmin,self.vmax])
1174+
ifnotnp.isfinite([t_vmin,t_vmax]).all():
1175+
raiseValueError("Invalid vmin or vmax")
1176+
t_value-=t_vmin
1177+
t_value/= (t_vmax-t_vmin)
1178+
t_value=np.ma.masked_invalid(t_value,copy=False)
1179+
returnt_value[0]ifis_scalarelset_value
1180+
1181+
definverse(self,value):
1182+
ifnotself.scaled():
1183+
raiseValueError("Not invertible until scaled")
1184+
ifself.vmin>self.vmax:
1185+
raiseValueError("vmin must be less or equal to vmax")
1186+
t_vmin,t_vmax=self._trf.transform([self.vmin,self.vmax])
1187+
ifnotnp.isfinite([t_vmin,t_vmax]).all():
1188+
raiseValueError("Invalid vmin or vmax")
1189+
rescaled=value* (t_vmax-t_vmin)
1190+
rescaled+=t_vmin
1191+
returnself._inv_trf.transform(rescaled).reshape(np.shape(value))
1192+
1193+
Norm.__name__=base_cls.__name__
1194+
Norm.__qualname__=base_cls.__qualname__
1195+
Norm.__module__=base_cls.__module__
1196+
returnNorm
1197+
1198+
1199+
@_make_norm_from_scale(functools.partial(scale.LogScale,nonpositive="mask"))
11421200
classLogNorm(Normalize):
11431201
"""Normalize a given value to the 0-1 range on a log scale."""
11441202

1145-
def_check_vmin_vmax(self):
1146-
ifself.vmin>self.vmax:
1147-
raiseValueError("minvalue must be less than or equal to maxvalue")
1148-
elifself.vmin<=0:
1149-
raiseValueError("minvalue must be positive")
1150-
1151-
def__call__(self,value,clip=None):
1152-
ifclipisNone:
1153-
clip=self.clip
1154-
1155-
result,is_scalar=self.process_value(value)
1156-
1157-
result=np.ma.masked_less_equal(result,0,copy=False)
1158-
1159-
self.autoscale_None(result)
1160-
self._check_vmin_vmax()
1161-
vmin,vmax=self.vmin,self.vmax
1162-
ifvmin==vmax:
1163-
result.fill(0)
1164-
else:
1165-
ifclip:
1166-
mask=np.ma.getmask(result)
1167-
result=np.ma.array(np.clip(result.filled(vmax),vmin,vmax),
1168-
mask=mask)
1169-
# in-place equivalent of above can be much faster
1170-
resdat=result.data
1171-
mask=result.mask
1172-
ifmaskisnp.ma.nomask:
1173-
mask= (resdat<=0)
1174-
else:
1175-
mask|=resdat<=0
1176-
np.copyto(resdat,1,where=mask)
1177-
np.log(resdat,resdat)
1178-
resdat-=np.log(vmin)
1179-
resdat/= (np.log(vmax)-np.log(vmin))
1180-
result=np.ma.array(resdat,mask=mask,copy=False)
1181-
ifis_scalar:
1182-
result=result[0]
1183-
returnresult
1184-
1185-
definverse(self,value):
1186-
ifnotself.scaled():
1187-
raiseValueError("Not invertible until scaled")
1188-
self._check_vmin_vmax()
1189-
vmin,vmax=self.vmin,self.vmax
1190-
1191-
ifnp.iterable(value):
1192-
val=np.ma.asarray(value)
1193-
returnvmin*np.ma.power((vmax/vmin),val)
1194-
else:
1195-
returnvmin*pow((vmax/vmin),value)
1196-
11971203
defautoscale(self,A):
11981204
# docstring inherited.
11991205
super().autoscale(np.ma.masked_less_equal(A,0,copy=False))
@@ -1203,6 +1209,9 @@ def autoscale_None(self, A):
12031209
super().autoscale_None(np.ma.masked_less_equal(A,0,copy=False))
12041210

12051211

1212+
@_make_norm_from_scale(
1213+
scale.SymmetricalLogScale,
1214+
init=lambdalinthresh,linscale=1.,vmin=None,vmax=None,clip=False:None)
12061215
classSymLogNorm(Normalize):
12071216
"""
12081217
The symmetrical logarithmic scale is logarithmic in both the
@@ -1212,98 +1221,28 @@ class SymLogNorm(Normalize):
12121221
need to have a range around zero that is linear. The parameter
12131222
*linthresh* allows the user to specify the size of this range
12141223
(-*linthresh*, *linthresh*).
1215-
"""
1216-
def__init__(self,linthresh,linscale=1.0,
1217-
vmin=None,vmax=None,clip=False):
1218-
"""
1219-
Parameters
1220-
----------
1221-
linthresh : float
1222-
The range within which the plot is linear (to avoid having the plot
1223-
go to infinity around zero).
1224-
linscale : float, default: 1
1225-
This allows the linear range (-*linthresh* to *linthresh*) to be
1226-
stretched relative to the logarithmic range. Its value is the
1227-
number of decades to use for each half of the linear range. For
1228-
example, when *linscale* == 1.0 (the default), the space used for
1229-
the positive and negative halves of the linear range will be equal
1230-
to one decade in the logarithmic range.
1231-
"""
1232-
Normalize.__init__(self,vmin,vmax,clip)
1233-
self.linthresh=float(linthresh)
1234-
self._linscale_adj= (linscale/ (1.0-np.e**-1))
1235-
ifvminisnotNoneandvmaxisnotNone:
1236-
self._transform_vmin_vmax()
1237-
1238-
def__call__(self,value,clip=None):
1239-
ifclipisNone:
1240-
clip=self.clip
1241-
1242-
result,is_scalar=self.process_value(value)
1243-
self.autoscale_None(result)
1244-
vmin,vmax=self.vmin,self.vmax
1245-
1246-
ifvmin>vmax:
1247-
raiseValueError("minvalue must be less than or equal to maxvalue")
1248-
elifvmin==vmax:
1249-
result.fill(0)
1250-
else:
1251-
ifclip:
1252-
mask=np.ma.getmask(result)
1253-
result=np.ma.array(np.clip(result.filled(vmax),vmin,vmax),
1254-
mask=mask)
1255-
# in-place equivalent of above can be much faster
1256-
resdat=self._transform(result.data)
1257-
resdat-=self._lower
1258-
resdat/= (self._upper-self._lower)
1259-
1260-
ifis_scalar:
1261-
result=result[0]
1262-
returnresult
12631224
1264-
def_transform(self,a):
1265-
"""Inplace transformation."""
1266-
withnp.errstate(invalid="ignore"):
1267-
masked=np.abs(a)>self.linthresh
1268-
sign=np.sign(a[masked])
1269-
log= (self._linscale_adj+np.log(np.abs(a[masked])/self.linthresh))
1270-
log*=sign*self.linthresh
1271-
a[masked]=log
1272-
a[~masked]*=self._linscale_adj
1273-
returna
1274-
1275-
def_inv_transform(self,a):
1276-
"""Inverse inplace Transformation."""
1277-
masked=np.abs(a)> (self.linthresh*self._linscale_adj)
1278-
sign=np.sign(a[masked])
1279-
exp=np.exp(sign*a[masked]/self.linthresh-self._linscale_adj)
1280-
exp*=sign*self.linthresh
1281-
a[masked]=exp
1282-
a[~masked]/=self._linscale_adj
1283-
returna
1284-
1285-
def_transform_vmin_vmax(self):
1286-
"""Calculates vmin and vmax in the transformed system."""
1287-
vmin,vmax=self.vmin,self.vmax
1288-
arr=np.array([vmax,vmin]).astype(float)
1289-
self._upper,self._lower=self._transform(arr)
1290-
1291-
definverse(self,value):
1292-
ifnotself.scaled():
1293-
raiseValueError("Not invertible until scaled")
1294-
val=np.ma.asarray(value)
1295-
val=val* (self._upper-self._lower)+self._lower
1296-
returnself._inv_transform(val)
1225+
Parameters
1226+
----------
1227+
linthresh : float
1228+
The range within which the plot is linear (to avoid having the plot
1229+
go to infinity around zero).
1230+
linscale : float, default: 1
1231+
This allows the linear range (-*linthresh* to *linthresh*) to be
1232+
stretched relative to the logarithmic range. Its value is the
1233+
number of decades to use for each half of the linear range. For
1234+
example, when *linscale* == 1.0 (the default), the space used for
1235+
the positive and negative halves of the linear range will be equal
1236+
to one decade in the logarithmic range.
1237+
"""
12971238

1298-
defautoscale(self,A):
1299-
# docstring inherited.
1300-
super().autoscale(A)
1301-
self._transform_vmin_vmax()
1239+
@property
1240+
deflinthresh(self):
1241+
returnself._scale.linthresh
13021242

1303-
defautoscale_None(self,A):
1304-
# docstring inherited.
1305-
super().autoscale_None(A)
1306-
self._transform_vmin_vmax()
1243+
@linthresh.setter
1244+
deflinthresh(self,value):
1245+
self._scale.linthresh=value
13071246

13081247

13091248
classPowerNorm(Normalize):

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp