|
24 | 24 | class Colorizer():
|
25 | 25 | """
|
26 | 26 | Class that holds the data to color pipeline
|
27 |
| - accessible via `.to_rgba(A)` and executed via |
28 |
| - the `.norm` and `.cmap` attributes. |
| 27 | + accessible via `Colorizer.to_rgba(A)` and executed via |
| 28 | + the `Colorizer.norm` and `Colorizer.cmap` attributes. |
29 | 29 | """
|
30 | 30 | def __init__(self, cmap=None, norm=None):
|
31 | 31 |
|
@@ -125,56 +125,59 @@ def to_rgba(self, x, alpha=None, bytes=False, norm=True):
|
125 | 125 |
|
126 | 126 | """
|
127 | 127 | # First check for special case, image input:
|
128 |
| - # First check for special case, image input: |
129 |
| - try: |
130 |
| - if x.ndim == 3: |
131 |
| - if x.shape[2] == 3: |
132 |
| - if alpha is None: |
133 |
| - alpha = 1 |
134 |
| - if x.dtype == np.uint8: |
135 |
| - alpha = np.uint8(alpha * 255) |
136 |
| - m, n = x.shape[:2] |
137 |
| - xx = np.empty(shape=(m, n, 4), dtype=x.dtype) |
138 |
| - xx[:, :, :3] = x |
139 |
| - xx[:, :, 3] = alpha |
140 |
| - elif x.shape[2] == 4: |
141 |
| - xx = x |
142 |
| - else: |
143 |
| - raise ValueError("Third dimension must be 3 or 4") |
144 |
| - if xx.dtype.kind == 'f': |
145 |
| - # If any of R, G, B, or A is nan, set to 0 |
146 |
| - if np.any(nans := np.isnan(x)): |
147 |
| - if x.shape[2] == 4: |
148 |
| - xx = xx.copy() |
149 |
| - xx[np.any(nans, axis=2), :] = 0 |
150 |
| - |
151 |
| - if norm and (xx.max() > 1 or xx.min() < 0): |
152 |
| - raise ValueError("Floating point image RGB values " |
153 |
| - "must be in the 0..1 range.") |
154 |
| - if bytes: |
155 |
| - xx = (xx * 255).astype(np.uint8) |
156 |
| - elif xx.dtype == np.uint8: |
157 |
| - if not bytes: |
158 |
| - xx = xx.astype(np.float32) / 255 |
159 |
| - else: |
160 |
| - raise ValueError("Image RGB array must be uint8 or " |
161 |
| - "floating point; found %s" % xx.dtype) |
162 |
| - # Account for any masked entries in the original array |
163 |
| - # If any of R, G, B, or A are masked for an entry, we set alpha to 0 |
164 |
| - if np.ma.is_masked(x): |
165 |
| - xx[np.any(np.ma.getmaskarray(x), axis=2), 3] = 0 |
166 |
| - return xx |
167 |
| - except AttributeError: |
168 |
| - # e.g., x is not an ndarray; so try mapping it |
169 |
| - pass |
170 |
| - |
171 |
| - # This is the normal case, mapping a scalar array: |
| 128 | + if isinstance(x, np.ndarray) and x.ndim == 3: |
| 129 | + return self._pass_image_data(x, alpha, bytes, norm) |
| 130 | + |
| 131 | + # Otherwise run norm -> colormap pipeline |
172 | 132 | x = ma.asarray(x)
|
173 | 133 | if norm:
|
174 | 134 | x = self.norm(x)
|
175 | 135 | rgba = self.cmap(x, alpha=alpha, bytes=bytes)
|
176 | 136 | return rgba
|
177 | 137 |
|
| 138 | + @staticmethod |
| 139 | + def _pass_image_data(x, alpha=None, bytes=False, norm=True): |
| 140 | + """ |
| 141 | + Helper function to pass ndarray of shape (...,3) or (..., 4) |
| 142 | + through `to_rgba()`, see `to_rgba()` for docstring. |
| 143 | + """ |
| 144 | + if x.shape[2] == 3: |
| 145 | + if alpha is None: |
| 146 | + alpha = 1 |
| 147 | + if x.dtype == np.uint8: |
| 148 | + alpha = np.uint8(alpha * 255) |
| 149 | + m, n = x.shape[:2] |
| 150 | + xx = np.empty(shape=(m, n, 4), dtype=x.dtype) |
| 151 | + xx[:, :, :3] = x |
| 152 | + xx[:, :, 3] = alpha |
| 153 | + elif x.shape[2] == 4: |
| 154 | + xx = x |
| 155 | + else: |
| 156 | + raise ValueError("Third dimension must be 3 or 4") |
| 157 | + if xx.dtype.kind == 'f': |
| 158 | + # If any of R, G, B, or A is nan, set to 0 |
| 159 | + if np.any(nans := np.isnan(x)): |
| 160 | + if x.shape[2] == 4: |
| 161 | + xx = xx.copy() |
| 162 | + xx[np.any(nans, axis=2), :] = 0 |
| 163 | + |
| 164 | + if norm and (xx.max() > 1 or xx.min() < 0): |
| 165 | + raise ValueError("Floating point image RGB values " |
| 166 | + "must be in the 0..1 range.") |
| 167 | + if bytes: |
| 168 | + xx = (xx * 255).astype(np.uint8) |
| 169 | + elif xx.dtype == np.uint8: |
| 170 | + if not bytes: |
| 171 | + xx = xx.astype(np.float32) / 255 |
| 172 | + else: |
| 173 | + raise ValueError("Image RGB array must be uint8 or " |
| 174 | + "floating point; found %s" % xx.dtype) |
| 175 | + # Account for any masked entries in the original array |
| 176 | + # If any of R, G, B, or A are masked for an entry, we set alpha to 0 |
| 177 | + if np.ma.is_masked(x): |
| 178 | + xx[np.any(np.ma.getmaskarray(x), axis=2), 3] = 0 |
| 179 | + return xx |
| 180 | + |
178 | 181 | def normalize(self, x):
|
179 | 182 | """
|
180 | 183 | Normalize the data in x.
|
|
0 commit comments