@@ -1174,22 +1174,45 @@ def _autolev(self, N):
11741174 """
11751175 Select contour levels to span the data.
11761176
1177+ The target number of levels, *N*, is used only when the
1178+ scale is not log and default locator is used.
1179+
11771180 We need two more levels for filled contours than for
11781181 line contours, because for the latter we need to specify
11791182 the lower and upper boundary of each range. For example,
11801183 a single contour boundary, say at z = 0, requires only
11811184 one contour line, but two filled regions, and therefore
11821185 three levels to provide boundaries for both regions.
11831186 """
1187+ self ._auto = True
11841188 if self .locator is None :
11851189 if self .logscale :
11861190 self .locator = ticker .LogLocator ()
11871191 else :
11881192 self .locator = ticker .MaxNLocator (N + 1 , min_n_ticks = 1 )
11891193
11901194 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 ]
11931216
11941217 def _contour_level_args (self , z , args ):
11951218 """
@@ -1220,8 +1243,8 @@ def _contour_level_args(self, z, args):
12201243
12211244 if not self .filled :
12221245 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 :
12251248 self .levels = [self .zmin ]
12261249 warnings .warn ("No contour levels were found"
12271250 " within the data range." )
@@ -1246,27 +1269,28 @@ def _process_levels(self):
12461269 # (Colorbar needs this even for line contours.)
12471270 self ._levels = list (self .levels )
12481271
1272+ if self .logscale :
1273+ lower , upper = 1e-250 , 1e250
1274+ else :
1275+ lower , upper = - 1e250 , 1e250
1276+
12491277 if self .extend in ('both' , 'min' ):
1250- self ._levels .insert (0 , min ( self . levels [ 0 ], self . zmin ) - 1 )
1278+ self ._levels .insert (0 , lower )
12511279 if self .extend in ('both' , 'max' ):
1252- self ._levels .append (max ( self . levels [ - 1 ], self . zmax ) + 1 )
1280+ self ._levels .append (upper )
12531281 self ._levels = np .asarray (self ._levels )
12541282
12551283 if not self .filled :
12561284 self .layers = self .levels
12571285 return
12581286
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 :])
12701294
12711295 def _process_colors (self ):
12721296 """
0 commit comments