From 291046a97c3ea89d6e8955caafa03f364f862976 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 15 Oct 2020 16:40:36 -0700 Subject: [PATCH 1/4] DOC: discuss colormapping and anti alaising --- .../image_antialiasing.py | 63 ++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/examples/images_contours_and_fields/image_antialiasing.py b/examples/images_contours_and_fields/image_antialiasing.py index 9fd2e3954e31..a3c0381b068e 100644 --- a/examples/images_contours_and_fields/image_antialiasing.py +++ b/examples/images_contours_and_fields/image_antialiasing.py @@ -18,6 +18,8 @@ import numpy as np import matplotlib.pyplot as plt +import matplotlib.colors as mcolors +import matplotlib.cm as cm ############################################################################### # First we generate a 500x500 px image with varying frequency content: @@ -72,6 +74,65 @@ ax.set_title(f"interpolation='{interp}'") plt.show() +############################################################################### +# Data antialiasing and RGBA antialiasing +# ---------------------------------------- +# +# The examples above all used grayscale. When colormapping is added there +# is the complication that downsampling and the antialiasing filters are +# applied to the data in Matplotlib, before the data is mapped to +# colors. So in the following note how the corners fade to white, the middle +# of the colormap, because the data is being smoothed and the high and low +# values are averaging out to the middle of the colormap. + +f0 = 10 +k = 150 +a = np.sin(np.pi * 2 * (f0 * R + k * R**2 / 2)) + +fig, axs = plt.subplots(1, 2, figsize=(7, 4), sharex=True, sharey=True, + constrained_layout=True) +for ax, interp in zip(axs, ['nearest', 'antialiased']): + ax.imshow(a, interpolation=interp, cmap='RdBu_r', vmin=-1, vmax=1) + ax.set_title(f"'{interp}'", fontsize='small') +plt.show() + +############################################################################### +# Sometimes, however, we want the antialiasing to occur in RGBA space. In +# this case purple is actually the perceptual mixture of red and blue. +# Matplotlib doesn't allow this to be directly achieved, but we can pass +# RGBA data to `~.Axes.imshow`, and then the antialiasing filter will be +# applied to the RGBA data: + +fig, axs = plt.subplots(1, 2, figsize=(7, 4), sharex=True, sharey=True, + constrained_layout=True) +norm = mcolors.Normalize(vmin=-1, vmax=1) +cmap = cm.RdBu_r +a_rgba = cmap(norm(a)) +for ax, interp in zip(axs, ['nearest', 'antialiased']): + ax.imshow(a_rgba, interpolation=interp) + ax.set_title(f"'{interp}'", fontsize='small') +plt.show() + +############################################################################### +# A concrete example of where antialiasing in data space may not be desirable +# is given here, where the anti-aliasing returns white pixels in data space, +# and (imperceptible) purple pixels in RGBA space: + +fig, axs = plt.subplots(1, 2, figsize=(3.5, 2), sharex=True, sharey=True, + constrained_layout=True) +aa = np.ones_like(a) +aa[np.sqrt(R)<0.5] = -1 + +norm = mcolors.Normalize(vmin=-1, vmax=1) +cmap = cm.RdBu_r +a_rgba = cmap(norm(aa)) + +axs[0].imshow(aa, interpolation=interp, cmap='RdBu_r') +axs[0].set_title('Data antialiasing') +axs[1].imshow(a_rgba, interpolation=interp) +axs[1].set_title('RGBA antialiasing') +plt.show() + ############################################################################# # @@ -84,4 +145,4 @@ # in this example: import matplotlib -matplotlib.axes.Axes.imshow +matplotlib.axes.Axes.imshow; From c6159930ea8d57ee7632009ee502bac8f08ec396 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 15 Oct 2020 16:46:39 -0700 Subject: [PATCH 2/4] Add colorbar --- .../images_contours_and_fields/image_antialiasing.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/examples/images_contours_and_fields/image_antialiasing.py b/examples/images_contours_and_fields/image_antialiasing.py index a3c0381b068e..e40c835b189c 100644 --- a/examples/images_contours_and_fields/image_antialiasing.py +++ b/examples/images_contours_and_fields/image_antialiasing.py @@ -92,8 +92,9 @@ fig, axs = plt.subplots(1, 2, figsize=(7, 4), sharex=True, sharey=True, constrained_layout=True) for ax, interp in zip(axs, ['nearest', 'antialiased']): - ax.imshow(a, interpolation=interp, cmap='RdBu_r', vmin=-1, vmax=1) + pc = ax.imshow(a, interpolation=interp, cmap='RdBu_r', vmin=-1, vmax=1) ax.set_title(f"'{interp}'", fontsize='small') +fig.colorbar(pc, ax=axs) plt.show() ############################################################################### @@ -109,7 +110,7 @@ cmap = cm.RdBu_r a_rgba = cmap(norm(a)) for ax, interp in zip(axs, ['nearest', 'antialiased']): - ax.imshow(a_rgba, interpolation=interp) + pc = ax.imshow(a_rgba, interpolation=interp) ax.set_title(f"'{interp}'", fontsize='small') plt.show() @@ -121,7 +122,7 @@ fig, axs = plt.subplots(1, 2, figsize=(3.5, 2), sharex=True, sharey=True, constrained_layout=True) aa = np.ones_like(a) -aa[np.sqrt(R)<0.5] = -1 +aa[np.sqrt(R) < 0.5] = -1 norm = mcolors.Normalize(vmin=-1, vmax=1) cmap = cm.RdBu_r @@ -129,7 +130,7 @@ axs[0].imshow(aa, interpolation=interp, cmap='RdBu_r') axs[0].set_title('Data antialiasing') -axs[1].imshow(a_rgba, interpolation=interp) +pc = axs[1].imshow(a_rgba, interpolation=interp) axs[1].set_title('RGBA antialiasing') plt.show() @@ -145,4 +146,4 @@ # in this example: import matplotlib -matplotlib.axes.Axes.imshow; +matplotlib.axes.Axes.imshow From da69dfdc7af718e7a795273652efeec86d60fa95 Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Thu, 15 Oct 2020 19:56:13 -0700 Subject: [PATCH 3/4] Better example --- .../image_antialiasing.py | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/examples/images_contours_and_fields/image_antialiasing.py b/examples/images_contours_and_fields/image_antialiasing.py index e40c835b189c..9760723fa128 100644 --- a/examples/images_contours_and_fields/image_antialiasing.py +++ b/examples/images_contours_and_fields/image_antialiasing.py @@ -119,19 +119,26 @@ # is given here, where the anti-aliasing returns white pixels in data space, # and (imperceptible) purple pixels in RGBA space: -fig, axs = plt.subplots(1, 2, figsize=(3.5, 2), sharex=True, sharey=True, +fig, axs = plt.subplots(1, 3, figsize=(5.5, 2), sharex=True, sharey=True, constrained_layout=True) -aa = np.ones_like(a) +f0 = 10 +k = 100 +a = np.sin(np.pi * 2 * (f0 * R + k * R**2 / 2)) + +aa = a +aa[np.sqrt(R) < 0.6] = 1 aa[np.sqrt(R) < 0.5] = -1 norm = mcolors.Normalize(vmin=-1, vmax=1) cmap = cm.RdBu_r a_rgba = cmap(norm(aa)) -axs[0].imshow(aa, interpolation=interp, cmap='RdBu_r') -axs[0].set_title('Data antialiasing') -pc = axs[1].imshow(a_rgba, interpolation=interp) -axs[1].set_title('RGBA antialiasing') +axs[0].imshow(aa, interpolation='nearest', cmap='RdBu_r') +axs[0].set_title('No antialiasing') +axs[1].imshow(aa, interpolation=interp, cmap='RdBu_r') +axs[1].set_title('Data antialiasing') +pc = axs[2].imshow(a_rgba, interpolation=interp) +axs[2].set_title('RGBA antialiasing') plt.show() From 44bfb9b7a307c557e837c5667e0b88e4fef4997b Mon Sep 17 00:00:00 2001 From: Jody Klymak Date: Mon, 1 Feb 2021 16:32:42 -0800 Subject: [PATCH 4/4] DOC: improvements from thoffman --- .../image_antialiasing.py | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/examples/images_contours_and_fields/image_antialiasing.py b/examples/images_contours_and_fields/image_antialiasing.py index 9760723fa128..32f153e2174a 100644 --- a/examples/images_contours_and_fields/image_antialiasing.py +++ b/examples/images_contours_and_fields/image_antialiasing.py @@ -93,7 +93,7 @@ constrained_layout=True) for ax, interp in zip(axs, ['nearest', 'antialiased']): pc = ax.imshow(a, interpolation=interp, cmap='RdBu_r', vmin=-1, vmax=1) - ax.set_title(f"'{interp}'", fontsize='small') + ax.set_title(f"'{interp}'") fig.colorbar(pc, ax=axs) plt.show() @@ -111,15 +111,23 @@ a_rgba = cmap(norm(a)) for ax, interp in zip(axs, ['nearest', 'antialiased']): pc = ax.imshow(a_rgba, interpolation=interp) - ax.set_title(f"'{interp}'", fontsize='small') + ax.set_title(f"'{interp}'") plt.show() ############################################################################### # A concrete example of where antialiasing in data space may not be desirable -# is given here, where the anti-aliasing returns white pixels in data space, -# and (imperceptible) purple pixels in RGBA space: - -fig, axs = plt.subplots(1, 3, figsize=(5.5, 2), sharex=True, sharey=True, +# is given here. The middle circle is all -1 (maps to blue), and the outer +# large circle is all +1 (maps to red). Data anti-aliasing smooths the +# large jumps from -1 to +1 and makes some zeros in between that map to white. +# While this is an accurate smoothing of the data, it is not a perceptually +# correct antialiasing of the border between red and blue. The RGBA +# anti-aliasing smooths in colorspace instead, and creates some purple pixels +# on the border between the two circles. While purple is not in the colormap, +# it indeed makes the transition between the two circles look correct. +# The same can be argued for the striped region, where the background fades to +# purple rather than fading to white. + +fig, axs = plt.subplots(1, 3, figsize=(5.5, 2.3), sharex=True, sharey=True, constrained_layout=True) f0 = 10 k = 100