Skip to content

Commit e2ce142

Browse files
committed
Compress comments in make_image.
make_image is a huge function; shorten it (in physical screen space) a bit by rewriting/rewrapping some comments, and a few small stylistic changes.
1 parent a6e01b5 commit e2ce142

File tree

1 file changed

+39
-62
lines changed

1 file changed

+39
-62
lines changed

lib/matplotlib/image.py

+39-62
Original file line numberDiff line numberDiff line change
@@ -402,43 +402,34 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
402402
# have to resample to the correct number of pixels
403403

404404
# TODO slice input array first
405-
inp_dtype = A.dtype
406405
a_min = A.min()
407406
a_max = A.max()
408-
# figure out the type we should scale to. For floats,
409-
# leave as is. For integers cast to an appropriate-sized
410-
# float. Small integers get smaller floats in an attempt
411-
# to keep the memory footprint reasonable.
412-
if a_min is np.ma.masked:
413-
# all masked, so values don't matter
407+
if a_min is np.ma.masked: # All masked; values don't matter.
414408
a_min, a_max = np.int32(0), np.int32(1)
415-
if inp_dtype.kind == 'f':
409+
if A.dtype.kind == 'f': # Float dtype: scale to same dtype.
416410
scaled_dtype = np.dtype(
417411
np.float64 if A.dtype.itemsize > 4 else np.float32)
418412
if scaled_dtype.itemsize < A.dtype.itemsize:
419-
_api.warn_external(
420-
f"Casting input data from {A.dtype} to "
421-
f"{scaled_dtype} for imshow")
422-
else:
423-
# probably an integer of some type.
413+
_api.warn_external(f"Casting input data from {A.dtype}"
414+
f" to {scaled_dtype} for imshow.")
415+
else: # Int dtype, likely.
416+
# Scale to appropriately sized float: use float32 if the
417+
# dynamic range is small, to limit the memory footprint.
424418
da = a_max.astype(np.float64) - a_min.astype(np.float64)
425-
# give more breathing room if a big dynamic range
426419
scaled_dtype = np.float64 if da > 1e8 else np.float32
427420

428-
# scale the input data to [.1, .9]. The Agg
429-
# interpolators clip to [0, 1] internally, use a
430-
# smaller input scale to identify which of the
431-
# interpolated points need to be should be flagged as
432-
# over / under.
433-
# This may introduce numeric instabilities in very broadly
434-
# scaled data
421+
# Scale the input data to [.1, .9]. The Agg interpolators clip
422+
# to [0, 1] internally, and we use a smaller input scale to
423+
# identify the interpolated points that need to be flagged as
424+
# over/under. This may introduce numeric instabilities in very
425+
# broadly scaled data.
426+
435427
# Always copy, and don't allow array subtypes.
436428
A_scaled = np.array(A, dtype=scaled_dtype)
437-
# clip scaled data around norm if necessary.
438-
# This is necessary for big numbers at the edge of
439-
# float64's ability to represent changes. Applying
440-
# a norm first would be good, but ruins the interpolation
441-
# of over numbers.
429+
# Clip scaled data around norm if necessary. This is necessary
430+
# for big numbers at the edge of float64's ability to represent
431+
# changes. Applying a norm first would be good, but ruins the
432+
# interpolation of over numbers.
442433
self.norm.autoscale_None(A)
443434
dv = np.float64(self.norm.vmax) - np.float64(self.norm.vmin)
444435
vmid = np.float64(self.norm.vmin) + dv / 2
@@ -456,30 +447,25 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
456447
if newmax is not None or newmin is not None:
457448
np.clip(A_scaled, newmin, newmax, out=A_scaled)
458449

459-
# used to rescale the raw data to [offset, 1-offset]
460-
# so that the resampling code will run cleanly. Using
461-
# dyadic numbers here could reduce the error, but
462-
# would not full eliminate it and breaks a number of
463-
# tests (due to the slightly different error bouncing
464-
# some pixels across a boundary in the (very
450+
# Rescale the raw data to [offset, 1-offset] so that the
451+
# resampling code will run cleanly. Using dyadic numbers here
452+
# could reduce the error, but would not full eliminate it and
453+
# breaks a number of tests (due to the slightly different
454+
# error bouncing some pixels across a boundary in the (very
465455
# quantized) colormapping step).
466456
offset = .1
467457
frac = .8
468-
# we need to run the vmin/vmax through the same rescaling
469-
# that we run the raw data through because there are small
470-
# errors in the round-trip due to float precision. If we
471-
# do not run the vmin/vmax through the same pipeline we can
472-
# have values close or equal to the boundaries end up on the
473-
# wrong side.
458+
# Run vmin/vmax through the same rescaling as the raw data;
459+
# otherwise, data values close or equal to the boundaries can
460+
# end up on the wrong side due to floating point error.
474461
vmin, vmax = self.norm.vmin, self.norm.vmax
475462
if vmin is np.ma.masked:
476463
vmin, vmax = a_min, a_max
477464
vrange = np.array([vmin, vmax], dtype=scaled_dtype)
478465

479466
A_scaled -= a_min
480467
vrange -= a_min
481-
# a_min and a_max might be ndarray subclasses so use
482-
# item to avoid errors
468+
# .item() handles a_min/a_max being ndarray subclasses.
483469
a_min = a_min.astype(scaled_dtype).item()
484470
a_max = a_max.astype(scaled_dtype).item()
485471

@@ -490,13 +476,11 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
490476
vrange += offset
491477
# resample the input data to the correct resolution and shape
492478
A_resampled = _resample(self, A_scaled, out_shape, t)
493-
# done with A_scaled now, remove from namespace to be sure!
494-
del A_scaled
495-
# un-scale the resampled data to approximately the
496-
# original range things that interpolated to above /
497-
# below the original min/max will still be above /
498-
# below, but possibly clipped in the case of higher order
499-
# interpolation + drastically changing data.
479+
del A_scaled # Make sure we don't use A_scaled anymore!
480+
# Un-scale the resampled data to approximately the original
481+
# range. Things that interpolated to outside the original range
482+
# will still be outside, but possibly clipped in the case of
483+
# higher order interpolation + drastically changing data.
500484
A_resampled -= offset
501485
vrange -= offset
502486
if a_min != a_max:
@@ -514,8 +498,7 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
514498
# we always have to interpolate the mask to account for
515499
# non-affine transformations
516500
out_alpha = _resample(self, mask, out_shape, t, resample=True)
517-
# done with the mask now, delete from namespace to be sure!
518-
del mask
501+
del mask # Make sure we don't use mask anymore!
519502
# Agg updates out_alpha in place. If the pixel has no image
520503
# data it will not be updated (and still be 0 as we initialized
521504
# it), if input data that would go into that output pixel than
@@ -539,12 +522,9 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
539522
s_vmin = np.finfo(scaled_dtype).eps
540523
# Block the norm from sending an update signal during the
541524
# temporary vmin/vmax change
542-
with self.norm.callbacks.blocked():
543-
with cbook._setattr_cm(self.norm,
544-
vmin=s_vmin,
545-
vmax=s_vmax,
546-
):
547-
output = self.norm(resampled_masked)
525+
with self.norm.callbacks.blocked(), \
526+
cbook._setattr_cm(self.norm, vmin=s_vmin, vmax=s_vmax):
527+
output = self.norm(resampled_masked)
548528
else:
549529
if A.ndim == 2: # _interpolation_stage == 'rgba'
550530
self.norm.autoscale_None(A)
@@ -558,8 +538,7 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
558538
self, _rgb_to_rgba(A[..., :3]), out_shape, t, alpha=alpha)
559539
output[..., 3] = output_alpha # recombine rgb and alpha
560540

561-
# at this point output is either a 2D array of normed data
562-
# (of int or float)
541+
# output is now either a 2D array of normed (int or float) data
563542
# or an RGBA array of re-sampled input
564543
output = self.to_rgba(output, bytes=True, norm=False)
565544
# output is now a correctly sized RGBA array of uint8
@@ -568,17 +547,15 @@ def _make_image(self, A, in_bbox, out_bbox, clip_bbox, magnification=1.0,
568547
if A.ndim == 2:
569548
alpha = self._get_scalar_alpha()
570549
alpha_channel = output[:, :, 3]
571-
alpha_channel[:] = np.asarray(
572-
np.asarray(alpha_channel, np.float32) * out_alpha * alpha,
573-
np.uint8)
550+
alpha_channel[:] = (
551+
alpha_channel.astype(np.float32) * out_alpha * alpha)
574552

575553
else:
576554
if self._imcache is None:
577555
self._imcache = self.to_rgba(A, bytes=True, norm=(A.ndim == 2))
578556
output = self._imcache
579557

580-
# Subset the input image to only the part that will be
581-
# displayed
558+
# Subset the input image to only the part that will be displayed.
582559
subset = TransformedBbox(clip_bbox, t0.inverted()).frozen()
583560
output = output[
584561
int(max(subset.ymin, 0)):

0 commit comments

Comments
 (0)