DigitalGlobe / gbdxtools

(Deprecated) Python SDK for using GBDX
MIT License
74 stars 57 forks source link

Can't plot an image with different bands #349

Closed leatkinson closed 6 years ago

leatkinson commented 6 years ago

When trying plot an image with a different band combination using the bands parameter I get an Index out of bounds error. An example of this error can be found in this notebook. https://notebooks.geobigdata.io/hub/notebooks/5b2ac7332c7831647a307034?tab=code

This is the stack trace I receive: ` IndexErrorTraceback (most recent call last)

in () ----> 1 vnir.plot(bands=[5,4,3]) /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/meta.pyc in plot(self, spec, **kwargs) 180 else: 181 if spec == "rgb" and self._has_token(**kwargs): --> 182 self._plot(tfm=self.base_layer_match, **kwargs) 183 else: 184 self._plot(tfm=getattr(self, spec), **kwargs) /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/meta.pyc in _plot(self, tfm, **kwargs) 196 f, ax1 = plt.subplots(1, figsize=(kwargs.get("w", 10), kwargs.get("h", 10))) 197 ax1.axis('off') --> 198 plt.imshow(tfm(**kwargs), interpolation='nearest', cmap=kwargs.get("cmap", None)) 199 plt.show(block=False) 200 /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/meta.pyc in base_layer_match(self, blm, **kwargs) 145 146 def base_layer_match(self, blm=False, **kwargs): --> 147 rgb = self.rgb(**kwargs) 148 if not blm: 149 return rgb /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/meta.pyc in rgb(self, **kwargs) 157 158 def rgb(self, **kwargs): --> 159 data = self._read(self[kwargs.get("bands", self._rgb_bands),...], **kwargs) 160 data = np.rollaxis(data.astype(np.float32), 0, 3) 161 lims = np.percentile(data, kwargs.get("stretch", [2, 98]), axis=(0, 1)) /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/meta.pyc in _read(self, data, **kwargs) 201 def _read(self, data, **kwargs): 202 if hasattr(data, 'read'): --> 203 return data.read(**kwargs) 204 else: 205 return data.compute(get=threaded_get) /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/ipe_image.pyc in read(self, bands, quiet, **kwargs) 156 if not quiet: 157 print('Fetching Image... {} {}'.format(self.ntiles, 'tiles' if self.ntiles > 1 else 'tile')) --> 158 return super(IpeImage, self).read(bands=bands) /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/meta.pyc in read(self, bands, **kwargs) 97 arr = self 98 if bands is not None: ---> 99 arr = self[bands, ...] 100 return arr.compute(get=threaded_get) 101 /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/ipe_image.pyc in __getitem__(self, geometry) 128 129 def __getitem__(self, geometry): --> 130 im = super(IpeImage, self).__getitem__(geometry) 131 im._ipe_op = self._ipe_op 132 return im /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/meta.pyc in __getitem__(self, geometry) 534 return self[:, :, arg1.start:arg1.stop] 535 elif arg1 == Ellipsis: --> 536 return self[arg0, :, :] 537 538 elif len(geometry) == 3: /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/ipe_image.pyc in __getitem__(self, geometry) 128 129 def __getitem__(self, geometry): --> 130 im = super(IpeImage, self).__getitem__(geometry) 131 im._ipe_op = self._ipe_op 132 return im /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/gbdxtools/images/meta.pyc in __getitem__(self, geometry) 555 556 g = ops.transform(self.__geo_transform__.fwd, box(xmin, ymin, xmax, ymax)) --> 557 result = super(GeoDaskImage, self).__getitem__(geometry) 558 559 else: /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/dask/array/core.pyc in __getitem__(self, index) 1322 1323 from .slicing import normalize_index, slice_with_dask_array -> 1324 index2 = normalize_index(index, self.shape) 1325 1326 if any(isinstance(i, Array) for i in index2): /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/dask/array/slicing.pyc in normalize_index(idx, shape) 796 for i, d in zip(idx, none_shape): 797 if d is not None: --> 798 check_index(i, d) 799 idx = tuple(map(sanitize_index, idx)) 800 idx = tuple(map(normalize_slice, idx, none_shape)) /anaconda/envs/gbdx_py2/lib/python2.7/site-packages/dask/array/slicing.pyc in check_index(ind, dimension) 839 x = np.asanyarray(ind) 840 if (x >= dimension).any() or (x < -dimension).any(): --> 841 raise IndexError("Index out of bounds %s" % dimension) 842 elif isinstance(ind, slice): 843 return IndexError: Index out of bounds 3 `
rjpolackwich commented 6 years ago

the problem is that plot doesn’t care when there’s more than one band:

        if self.shape[0] == 1 or ("bands" in kwargs and len(kwargs["bands"]) == 1):
            if "cmap" in kwargs:
                cmap = kwargs["cmap"]
                del kwargs["cmap"]
            else:
                cmap = "Greys_r"
            self._plot(tfm=self._single_band, cmap=cmap, **kwargs)
            return
        else:
            if spec == "rgb" and self._has_token(**kwargs) and False:
                self._plot(tfm=self.base_layer_match, **kwargs)
            else:
                self._plot(tfm=getattr(self, spec), **kwargs)

so it gets to if spec=="rgb", which it does by default… tries to match baselayers, etc all the while passing the bands argument.

To fix this we have to figure out what this means: img.plot(bands=[1,2,3,4,5,6,7,8])

perhaps we introduce something like def show(self, as_image=False, ...) where it takes bands and makes a subplot array when as_image is False, but when true, it operates on all the bands together in the generic euclidean fashion to produce one image in the same way the imshow does. Suggestions welcome.

chelm commented 6 years ago

im not sure i dig having too many more methods for dealing with plotting, i'd prefer to keep just a single plot method and hope that users become more competent in plotting the raw data etc on their own.

In the case of img.plot(bands=[1,2,3,4,5,6,7,8]) we plot rgb.

the origin intent of image.plot(bands=[6,2,1]) and/or image.plot(bands=[3]) needs to absolutely work. After that we could discuss support specific specs like false_color etc.

chelm commented 6 years ago

fixed via #351