|
24 | 24 | classColorizer():
|
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.__call__(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 |
|
@@ -94,7 +94,7 @@ def norm(self, norm):
|
94 | 94 | ifnotin_init:
|
95 | 95 | self.changed()
|
96 | 96 |
|
97 |
| -defto_rgba(self,x,alpha=None,bytes=False,norm=True): |
| 97 | +def__call__(self,x,alpha=None,bytes=False,norm=True): |
98 | 98 | """
|
99 | 99 | Return a normalized RGBA array corresponding to *x*.
|
100 | 100 |
|
@@ -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 |
| -ifx.ndim==3: |
131 |
| -ifx.shape[2]==3: |
132 |
| -ifalphaisNone: |
133 |
| -alpha=1 |
134 |
| -ifx.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 |
| -elifx.shape[2]==4: |
141 |
| -xx=x |
142 |
| -else: |
143 |
| -raiseValueError("Third dimension must be 3 or 4") |
144 |
| -ifxx.dtype.kind=='f': |
145 |
| -# If any of R, G, B, or A is nan, set to 0 |
146 |
| -ifnp.any(nans:=np.isnan(x)): |
147 |
| -ifx.shape[2]==4: |
148 |
| -xx=xx.copy() |
149 |
| -xx[np.any(nans,axis=2), :]=0 |
150 |
| - |
151 |
| -ifnormand (xx.max()>1orxx.min()<0): |
152 |
| -raiseValueError("Floating point image RGB values " |
153 |
| -"must be in the 0..1 range.") |
154 |
| -ifbytes: |
155 |
| -xx= (xx*255).astype(np.uint8) |
156 |
| -elifxx.dtype==np.uint8: |
157 |
| -ifnotbytes: |
158 |
| -xx=xx.astype(np.float32)/255 |
159 |
| -else: |
160 |
| -raiseValueError("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 |
| -ifnp.ma.is_masked(x): |
165 |
| -xx[np.any(np.ma.getmaskarray(x),axis=2),3]=0 |
166 |
| -returnxx |
167 |
| -exceptAttributeError: |
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 | +ifisinstance(x,np.ndarray)andx.ndim==3: |
| 129 | +returnself._pass_image_data(x,alpha,bytes,norm) |
| 130 | + |
| 131 | +# Otherwise run norm -> colormap pipeline |
172 | 132 | x=ma.asarray(x)
|
173 | 133 | ifnorm:
|
174 | 134 | x=self.norm(x)
|
175 | 135 | rgba=self.cmap(x,alpha=alpha,bytes=bytes)
|
176 | 136 | returnrgba
|
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 `__call__()`, see `__call__()` for docstring. |
| 143 | + """ |
| 144 | +ifx.shape[2]==3: |
| 145 | +ifalphaisNone: |
| 146 | +alpha=1 |
| 147 | +ifx.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 | +elifx.shape[2]==4: |
| 154 | +xx=x |
| 155 | +else: |
| 156 | +raiseValueError("Third dimension must be 3 or 4") |
| 157 | +ifxx.dtype.kind=='f': |
| 158 | +# If any of R, G, B, or A is nan, set to 0 |
| 159 | +ifnp.any(nans:=np.isnan(x)): |
| 160 | +ifx.shape[2]==4: |
| 161 | +xx=xx.copy() |
| 162 | +xx[np.any(nans,axis=2), :]=0 |
| 163 | + |
| 164 | +ifnormand (xx.max()>1orxx.min()<0): |
| 165 | +raiseValueError("Floating point image RGB values " |
| 166 | +"must be in the 0..1 range.") |
| 167 | +ifbytes: |
| 168 | +xx= (xx*255).astype(np.uint8) |
| 169 | +elifxx.dtype==np.uint8: |
| 170 | +ifnotbytes: |
| 171 | +xx=xx.astype(np.float32)/255 |
| 172 | +else: |
| 173 | +raiseValueError("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 | +ifnp.ma.is_masked(x): |
| 178 | +xx[np.any(np.ma.getmaskarray(x),axis=2),3]=0 |
| 179 | +returnxx |
| 180 | + |
178 | 181 | defnormalize(self,x):
|
179 | 182 | """
|
180 | 183 | Normalize the data in x.
|
@@ -350,7 +353,7 @@ def to_rgba(self, x, alpha=None, bytes=False, norm=True):
|
350 | 353 | performed, and it is assumed to be in the range (0-1).
|
351 | 354 |
|
352 | 355 | """
|
353 |
| -returnself.colorizer.to_rgba(x,alpha=alpha,bytes=bytes,norm=norm) |
| 356 | +returnself.colorizer(x,alpha=alpha,bytes=bytes,norm=norm) |
354 | 357 |
|
355 | 358 | defget_clim(self):
|
356 | 359 | """
|
|