diff --git a/eomaps/_data_manager.py b/eomaps/_data_manager.py index 1a3f0cde5..61b32fd29 100644 --- a/eomaps/_data_manager.py +++ b/eomaps/_data_manager.py @@ -652,7 +652,12 @@ def _select_vals(self, val, qs, slices=None): else: val = np.asanyarray(val) - if len(val.shape) == 2 and qx is not None and qy is not None: + if ( + len(val.shape) == 2 + and qx is not None + and qy is not None + and slices is not None + ): (x0, x1, y0, y1) = slices ret = val[y0:y1, x0:x1] else: @@ -895,6 +900,11 @@ def get_props(self, *args, **kwargs): else: slices, blocksize = None, None + # remember last selection and slices (required in case explicit + # colors are provided since they must be selected accordingly) + self._last_qs = qs + self._last_slices = slices + self._current_data = dict( xorig=self._select_vals(self.xorig, qs, slices), yorig=self._select_vals(self.yorig, qs, slices), diff --git a/eomaps/_webmap.py b/eomaps/_webmap.py index 8934b50da..3d7dccebe 100644 --- a/eomaps/_webmap.py +++ b/eomaps/_webmap.py @@ -584,12 +584,15 @@ def _do_add_layer(self, m, layer, **kwargs): class _WebServiceCollection: - def __init__(self, m, service_type="wmts", url=None): + def __init__(self, m, service_type="wmts", url=None, **kwargs): self._m = m self._service_type = service_type if url is not None: self._url = url + # additional kwargs that will be passed to owslib.WebMapService() + self._service_kwargs = kwargs.copy() + def __getitem__(self, key): return self.add_layer.__dict__[key] @@ -626,28 +629,28 @@ def findlayer(self, name): return [i for i in self.layers if name.lower() in i.lower()] @staticmethod - def _get_wmts(url): + def _get_wmts(url, **kwargs): # TODO expose useragent # lazy import used to avoid long import times from owslib.wmts import WebMapTileService - return WebMapTileService(url) + return WebMapTileService(url, **kwargs) @staticmethod - def _get_wms(url): + def _get_wms(url, **kwargs): # TODO expose useragent # lazy import used to avoid long import times from owslib.wms import WebMapService - return WebMapService(url) + return WebMapService(url, **kwargs) @property @lru_cache() def add_layer(self): if self._service_type == "wmts": - wmts = self._get_wmts(self._url) + wmts = self._get_wmts(self._url, **self._service_kwargs) layers = dict() for key in wmts.contents.keys(): layername = _sanitize(key) @@ -665,7 +668,7 @@ def add_layer(self): layers[layername] = wmtslayer elif self._service_type == "wms": - wms = self._get_wms(self._url) + wms = self._get_wms(self._url, **self._service_kwargs) layers = dict() for key in wms.contents.keys(): layername = _sanitize(key) @@ -821,14 +824,14 @@ def _fetch_layers(self): url = self._url if url is not None: if self._service_type == "wms": - wms = self._get_wms(url) + wms = self._get_wms(url, **self._service_kwargs) layer_names = list(wms.contents.keys()) for lname in layer_names: self._layers["layer_" + _sanitize(lname)] = _WMSLayer( self._m, wms, lname ) elif self._service_type == "wmts": - wmts = self._get_wmts(url) + wmts = self._get_wmts(url, **self._service_kwargs) layer_names = list(wmts.contents.keys()) for lname in layer_names: self._layers["layer_" + _sanitize(lname)] = _WMTSLayer( diff --git a/eomaps/eomaps.py b/eomaps/eomaps.py index f8642b6a4..6d43f01ab 100644 --- a/eomaps/eomaps.py +++ b/eomaps/eomaps.py @@ -3462,21 +3462,13 @@ def snapshot(self, *layer, transparent=False, clear=False): else: sn = self._get_snapshot() try: - from IPython.display import display, Image as IpyImage - from io import BytesIO - - # fix issues with PILLOW 10.0 and transparent snapshots - # in jupyter notebooks (TODO should be fixed in PILLOW 10.1.0) - # ...bug causes unwanted errors in _repr__jpeg_ for RGBA images - # the fix enforces png as format - temp = BytesIO() - Image.fromarray(sn, "RGBA").save(temp, format="png") - - display( - IpyImage(temp.getvalue()), - display_id=True, - clear=clear, - ) + from IPython.display import display_png, clear_output + + if clear: + clear_output(wait=True) + # use display_png to avoid issues with transparent snapshots + display_png(Image.fromarray(sn, "RGBA"), raw=False) + except Exception: _log.exception( "Unable to display the snapshot... is the script " @@ -4827,7 +4819,9 @@ def _plot_map( def _sel_c_transp(self, c): return self._data_manager._select_vals( - c.T if self._data_manager._z_transposed else c + c.T if self._data_manager._z_transposed else c, + qs=self._data_manager._last_qs, + slices=self._data_manager._last_slices, ) def _handle_explicit_colors(self, color): diff --git a/eomaps/helpers.py b/eomaps/helpers.py index a3b39c4c1..04bea7dfa 100644 --- a/eomaps/helpers.py +++ b/eomaps/helpers.py @@ -1587,11 +1587,12 @@ def apply_layout(self, layout): valid_keys = set(self.get_layout()) active_keys = set(layout) - missing_keys = [ - i for i in (valid_keys - active_keys) if not i.endswith("extent") - ] - if len(missing_keys) > 0: - warnings.warn( + if valid_keys != set(layout): + missing_keys = [ + i for i in (valid_keys - active_keys) if not i.endswith("extent") + ] + + _log.warning( "EOmaps: The the layout does not match the expected structure! " "Layout might not be properly restored. " "Invalid or missing keys:\n" diff --git a/eomaps/shapes.py b/eomaps/shapes.py index 044d53c7f..bfe5640df 100644 --- a/eomaps/shapes.py +++ b/eomaps/shapes.py @@ -326,7 +326,6 @@ def _get_colors_and_array(kwargs, mask): # identify colors and the array # special treatment of array input to properly mask values array = kwargs.pop("array", None) - if array is not None: if mask is not None: array = array[mask] @@ -336,17 +335,18 @@ def _get_colors_and_array(kwargs, mask): color_vals = dict() for c_key in ["fc", "facecolor", "color"]: color = kwargs.pop(c_key, None) + if color is not None: # explicit treatment for recarrays (to avoid performance issues) # with matplotlib.colors.to_rgba_array() # (recarrays are used to convert 3/4 arrays into an rgb(a) array # in m._handle_explicit_colors() ) if isinstance(color, np.recarray): - color_vals[c_key] = color[mask].view( + color_vals[c_key] = color[mask.reshape(color.shape)].view( (float, len(color.dtype.names)) ) # .ravel() elif isinstance(color, np.ndarray): - color_vals[c_key] = color[mask] + color_vals[c_key] = color[mask.reshape(color.shape)] else: color_vals[c_key] = color diff --git a/eomaps/webmap_containers.py b/eomaps/webmap_containers.py index 8162b2a5c..112970c4d 100644 --- a/eomaps/webmap_containers.py +++ b/eomaps/webmap_containers.py @@ -2422,7 +2422,9 @@ def Austria(self): WMS.__doc__ = type(self).Austria.__doc__ return WMS - def get_service(self, url, service_type="wms", rest_API=False, maxzoom=19): + def get_service( + self, url, service_type="wms", rest_API=False, maxzoom=19, **kwargs + ): """ Get a object that can be used to add WMS, WMTS or XYZ services based on a GetCapabilities-link or a link to a ArcGIS REST API @@ -2470,6 +2472,11 @@ def get_service(self, url, service_type="wms", rest_API=False, maxzoom=19): The maximum zoom-level available (to avoid http-request errors) for too high zoom levels. The default is 19. + kwargs : + Additional keyword arguments passed to `owslib.WebMapService()`. + (only relevant if type is "wms" or "wmts") + + For example: `version=1.3.0` Returns ------- @@ -2541,6 +2548,8 @@ def get_service(self, url, service_type="wms", rest_API=False, maxzoom=19): service_type=service_type, ) else: - service = _WebServiceCollection(self._m, service_type="wms", url=url) + service = _WebServiceCollection( + self._m, service_type="wms", url=url, **kwargs + ) return service