1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
|
from types import MethodType
import numpy as np
from .axes_divider import make_axes_locatable, Size
from .mpl_axes import Axes, SimpleAxisArtist
def make_rgb_axes(ax, pad=0.01, axes_class=None, **kwargs):
"""
Parameters
----------
ax : `~matplotlib.axes.Axes`
Axes instance to create the RGB Axes in.
pad : float, optional
Fraction of the Axes height to pad.
axes_class : `matplotlib.axes.Axes` or None, optional
Axes class to use for the R, G, and B Axes. If None, use
the same class as *ax*.
**kwargs
Forwarded to *axes_class* init for the R, G, and B Axes.
"""
divider = make_axes_locatable(ax)
pad_size = pad * Size.AxesY(ax)
xsize = ((1-2*pad)/3) * Size.AxesX(ax)
ysize = ((1-2*pad)/3) * Size.AxesY(ax)
divider.set_horizontal([Size.AxesX(ax), pad_size, xsize])
divider.set_vertical([ysize, pad_size, ysize, pad_size, ysize])
ax.set_axes_locator(divider.new_locator(0, 0, ny1=-1))
ax_rgb = []
if axes_class is None:
axes_class = type(ax)
for ny in [4, 2, 0]:
ax1 = axes_class(ax.get_figure(), ax.get_position(original=True),
sharex=ax, sharey=ax, **kwargs)
locator = divider.new_locator(nx=2, ny=ny)
ax1.set_axes_locator(locator)
for t in ax1.yaxis.get_ticklabels() + ax1.xaxis.get_ticklabels():
t.set_visible(False)
try:
for axis in ax1.axis.values():
axis.major_ticklabels.set_visible(False)
except AttributeError:
pass
ax_rgb.append(ax1)
fig = ax.get_figure()
for ax1 in ax_rgb:
fig.add_axes(ax1)
return ax_rgb
class RGBAxes:
"""
4-panel `~.Axes.imshow` (RGB, R, G, B).
Layout::
┌───────────────┬─────┐
│ │ R │
│ ├─────┤
│ RGB │ G │
│ ├─────┤
│ │ B │
└───────────────┴─────┘
Subclasses can override the ``_defaultAxesClass`` attribute.
By default RGBAxes uses `.mpl_axes.Axes`.
Attributes
----------
RGB : ``_defaultAxesClass``
The Axes object for the three-channel `~.Axes.imshow`.
R : ``_defaultAxesClass``
The Axes object for the red channel `~.Axes.imshow`.
G : ``_defaultAxesClass``
The Axes object for the green channel `~.Axes.imshow`.
B : ``_defaultAxesClass``
The Axes object for the blue channel `~.Axes.imshow`.
"""
_defaultAxesClass = Axes
def __init__(self, *args, pad=0, **kwargs):
"""
Parameters
----------
pad : float, default: 0
Fraction of the Axes height to put as padding.
axes_class : `~matplotlib.axes.Axes`
Axes class to use. If not provided, ``_defaultAxesClass`` is used.
*args
Forwarded to *axes_class* init for the RGB Axes
**kwargs
Forwarded to *axes_class* init for the RGB, R, G, and B Axes
"""
axes_class = kwargs.pop("axes_class", self._defaultAxesClass)
self.RGB = ax = axes_class(*args, **kwargs)
ax.get_figure().add_axes(ax)
self.R, self.G, self.B = make_rgb_axes(
ax, pad=pad, axes_class=axes_class, **kwargs)
# Set the line color and ticks for the axes.
for ax1 in [self.RGB, self.R, self.G, self.B]:
if isinstance(ax1.axis, MethodType):
ad = Axes.AxisDict(self)
ad.update(
bottom=SimpleAxisArtist(ax1.xaxis, 1, ax1.spines["bottom"]),
top=SimpleAxisArtist(ax1.xaxis, 2, ax1.spines["top"]),
left=SimpleAxisArtist(ax1.yaxis, 1, ax1.spines["left"]),
right=SimpleAxisArtist(ax1.yaxis, 2, ax1.spines["right"]))
else:
ad = ax1.axis
ad[:].line.set_color("w")
ad[:].major_ticks.set_markeredgecolor("w")
def imshow_rgb(self, r, g, b, **kwargs):
"""
Create the four images {rgb, r, g, b}.
Parameters
----------
r, g, b : array-like
The red, green, and blue arrays.
**kwargs
Forwarded to `~.Axes.imshow` calls for the four images.
Returns
-------
rgb : `~matplotlib.image.AxesImage`
r : `~matplotlib.image.AxesImage`
g : `~matplotlib.image.AxesImage`
b : `~matplotlib.image.AxesImage`
"""
if not (r.shape == g.shape == b.shape):
raise ValueError(
f'Input shapes ({r.shape}, {g.shape}, {b.shape}) do not match')
RGB = np.dstack([r, g, b])
R = np.zeros_like(RGB)
R[:, :, 0] = r
G = np.zeros_like(RGB)
G[:, :, 1] = g
B = np.zeros_like(RGB)
B[:, :, 2] = b
im_rgb = self.RGB.imshow(RGB, **kwargs)
im_r = self.R.imshow(R, **kwargs)
im_g = self.G.imshow(G, **kwargs)
im_b = self.B.imshow(B, **kwargs)
return im_rgb, im_r, im_g, im_b
|