@@ -1174,22 +1174,45 @@ def _autolev(self, N):
1174
1174
"""
1175
1175
Select contour levels to span the data.
1176
1176
1177
+ The target number of levels, *N*, is used only when the
1178
+ scale is not log and default locator is used.
1179
+
1177
1180
We need two more levels for filled contours than for
1178
1181
line contours, because for the latter we need to specify
1179
1182
the lower and upper boundary of each range. For example,
1180
1183
a single contour boundary, say at z = 0, requires only
1181
1184
one contour line, but two filled regions, and therefore
1182
1185
three levels to provide boundaries for both regions.
1183
1186
"""
1187
+ self ._auto = True
1184
1188
if self .locator is None :
1185
1189
if self .logscale :
1186
1190
self .locator = ticker .LogLocator ()
1187
1191
else :
1188
1192
self .locator = ticker .MaxNLocator (N + 1 , min_n_ticks = 1 )
1189
1193
1190
1194
lev = self .locator .tick_values (self .zmin , self .zmax )
1191
- self ._auto = True
1192
- return lev
1195
+
1196
+ try :
1197
+ if self .locator ._symmetric :
1198
+ return lev
1199
+ except AttributeError :
1200
+ pass
1201
+
1202
+ # Trim excess levels the locator may have supplied.
1203
+ under = np .nonzero (lev < self .zmin )[0 ]
1204
+ i0 = under [- 1 ] if len (under ) else 0
1205
+ over = np .nonzero (lev > self .zmax )[0 ]
1206
+ i1 = over [0 ] + 1 if len (over ) else len (lev )
1207
+ if self .extend in ('min' , 'both' ):
1208
+ i0 += 1
1209
+ if self .extend in ('max' , 'both' ):
1210
+ i1 -= 1
1211
+
1212
+ if i1 - i0 < 3 :
1213
+ i0 , i1 = 0 , len (lev )
1214
+
1215
+ return lev [i0 :i1 ]
1193
1216
1194
1217
def _contour_level_args (self , z , args ):
1195
1218
"""
@@ -1220,8 +1243,8 @@ def _contour_level_args(self, z, args):
1220
1243
1221
1244
if not self .filled :
1222
1245
inside = (self .levels > self .zmin ) & (self .levels < self .zmax )
1223
- self . levels = self .levels [inside ]
1224
- if len (self . levels ) == 0 :
1246
+ levels_in = self .levels [inside ]
1247
+ if len (levels_in ) == 0 :
1225
1248
self .levels = [self .zmin ]
1226
1249
warnings .warn ("No contour levels were found"
1227
1250
" within the data range." )
@@ -1246,27 +1269,28 @@ def _process_levels(self):
1246
1269
# (Colorbar needs this even for line contours.)
1247
1270
self ._levels = list (self .levels )
1248
1271
1272
+ if self .logscale :
1273
+ lower , upper = 1e-250 , 1e250
1274
+ else :
1275
+ lower , upper = - 1e250 , 1e250
1276
+
1249
1277
if self .extend in ('both' , 'min' ):
1250
- self ._levels .insert (0 , min ( self . levels [ 0 ], self . zmin ) - 1 )
1278
+ self ._levels .insert (0 , lower )
1251
1279
if self .extend in ('both' , 'max' ):
1252
- self ._levels .append (max ( self . levels [ - 1 ], self . zmax ) + 1 )
1280
+ self ._levels .append (upper )
1253
1281
self ._levels = np .asarray (self ._levels )
1254
1282
1255
1283
if not self .filled :
1256
1284
self .layers = self .levels
1257
1285
return
1258
1286
1259
- # layer values are mid-way between levels
1260
- self .layers = 0.5 * (self ._levels [:- 1 ] + self ._levels [1 :])
1261
- # ...except that extended layers must be outside the
1262
- # normed range:
1263
- if self .extend in ('both' , 'min' ):
1264
- if self .logscale :
1265
- self .layers [0 ] = 1e-150
1266
- else :
1267
- self .layers [0 ] = - 1e150
1268
- if self .extend in ('both' , 'max' ):
1269
- self .layers [- 1 ] = 1e150
1287
+ # Layer values are mid-way between levels in screen space.
1288
+ if self .logscale :
1289
+ # Avoid overflow by taking sqrt before multiplying.
1290
+ self .layers = (np .sqrt (self ._levels [:- 1 ])
1291
+ * np .sqrt (self ._levels [1 :]))
1292
+ else :
1293
+ self .layers = 0.5 * (self ._levels [:- 1 ] + self ._levels [1 :])
1270
1294
1271
1295
def _process_colors (self ):
1272
1296
"""
0 commit comments