diff --git a/CHANGELOG.md b/CHANGELOG.md index cdc850cc0..5761bdb38 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ quietly excludes all realizations lacking an `OK` file written by `ERT` on compl - [#428](https://github.com/equinor/webviz-subsurface/pull/428) - Plugin controls, such as dropdown selections, set by the user is kept on page reload. - [#435](https://github.com/equinor/webviz-subsurface/pull/435) - Suppress a warning in SurfaceViewerFMU when calculating statistics from surfaces where one or more surface only has NaN values. [#399](https://github.com/equinor/webviz-subsurface/pull/399) - [#438](https://github.com/equinor/webviz-subsurface/pull/438) - Improved documentation of generation of data input for `RelativePermability` plugin. +- [#434](https://github.com/equinor/webviz-subsurface/pull/434) - Improved hillshading and colors in plugins with map views. ### Fixed - [#432](https://github.com/equinor/webviz-subsurface/pull/432) - Bug fix in ReservoirSimulationTimeSeries. Vectors starting with A, V, G, I, N, T, V and L resulted in crash due to a bug introduced in [#373](https://github.com/equinor/webviz-subsurface/pull/373) (most notably group and aquifer vectors). diff --git a/webviz_subsurface/_datainput/surface.py b/webviz_subsurface/_datainput/surface.py index 84834b7d6..d3d5f5840 100644 --- a/webviz_subsurface/_datainput/surface.py +++ b/webviz_subsurface/_datainput/surface.py @@ -13,9 +13,12 @@ def load_surface(surface_path): return RegularSurface(surface_path) -def get_surface_arr(surface, unrotate=True, flip=True): +def get_surface_arr(surface, unrotate=True, flip=True, clip_min=None, clip_max=None): + if clip_min or clip_max: + np.ma.clip(surface.values, clip_min, clip_max, out=surface.values) if unrotate: surface.unrotate() + x, y, z = surface.get_xyz_values() if flip: x = np.flip(x.transpose(), axis=0) @@ -30,6 +33,7 @@ def get_surface_fence(fence, surface): return surface.get_fence(fence) +# pylint: disable=too-many-arguments def make_surface_layer( surface, name="surface", @@ -38,6 +42,7 @@ def make_surface_layer( max_val=None, color=None, shader_type="soft-hillshading", + shadows=False, unit="", ): """Make NewLayeredMap surface image base layer @@ -53,9 +58,12 @@ def make_surface_layer( A surface layer that can be plotted in NewLayeredMap """ - zvalues = get_surface_arr(surface)[2] + zvalues = get_surface_arr(surface, clip_min=min_val, clip_max=max_val)[2] min_val = min_val if min_val is not None else np.nanmin(zvalues) max_val = max_val if max_val is not None else np.nanmax(zvalues) + if shader_type == "hillshading_shadows": + shader_type = "hillshading" + shadows = True img = Image.open(io.BytesIO(base64.b64decode(array_to_png(zvalues.copy())[22:]))) width, height = img.size if width * height >= 300 * 300: @@ -63,6 +71,22 @@ def make_surface_layer( else: ratio = (1000 ** 2) / (width * height) scale = np.sqrt(ratio).round(2) + color = ( + [ + "#440154", + "#482878", + "#3e4989", + "#31688e", + "#26828e", + "#1f9e89", + "#35b779", + "#6ece58", + "#b5de2b", + "#fde725", + ] + if color is None + else color + ) return { "name": name, "checked": True, @@ -74,36 +98,21 @@ def make_surface_layer( "type": "image", "url": array_to_png(zvalues.copy()), "colorScale": { - "colors": [ - "#440154", - "#482878", - "#3e4989", - "#31688e", - "#26828e", - "#1f9e89", - "#35b779", - "#6ece58", - "#b5de2b", - "#fde725", - ] - if color is None - else color, + "colors": color, "prefixZeroAlpha": False, "scaleType": "linear", - "cutPointMin": min_val, - "cutPointMax": max_val, }, "shader": { "type": shader_type, - "shadows": True, + "shadows": shadows, "shadowIterations": 128, "elevationScale": 1.0, - "pixelScale": 1000, + "pixelScale": 11000, "setBlackToAlpha": True, }, "bounds": [[surface.xmin, surface.ymin], [surface.xmax, surface.ymax]], - "minvalue": round(min_val, 4) if min_val else None, - "maxvalue": round(max_val, 4) if max_val else None, + "minvalue": round(np.nanmin(zvalues), 4), + "maxvalue": round(np.nanmax(zvalues), 4), "unit": str(unit), "imageScale": scale, } diff --git a/webviz_subsurface/plugins/_surface_viewer_fmu.py b/webviz_subsurface/plugins/_surface_viewer_fmu.py index 37e7e1169..5d52d0434 100644 --- a/webviz_subsurface/plugins/_surface_viewer_fmu.py +++ b/webviz_subsurface/plugins/_surface_viewer_fmu.py @@ -394,6 +394,10 @@ def layout(self): "value": "hillshading", "label": "Hillshading", }, + { + "value": "hillshading_shadows", + "label": "Hillshading with shadows", + }, ], value=None, persistence=True, @@ -438,6 +442,10 @@ def layout(self): "value": "hillshading", "label": "Hillshading", }, + { + "value": "hillshading_shadows", + "label": "Hillshading with shadows", + }, ], value=None, persistence=True, @@ -482,6 +490,10 @@ def layout(self): "value": "hillshading", "label": "Hillshading", }, + { + "value": "hillshading_shadows", + "label": "Hillshading with shadows", + }, ], value=None, persistence=True, @@ -616,12 +628,6 @@ def _set_base_layer( name="surface3", color=attribute_settings.get(data["attr"], {}).get("color"), shader_type=hillshade3, - min_val=attribute_settings.get(data2["attr"], {}).get( - "min", None - ), - max_val=attribute_settings.get(data2["attr"], {}).get( - "max", None - ), ) ) error_label = "" diff --git a/webviz_subsurface/plugins/_surface_with_grid_cross_section.py b/webviz_subsurface/plugins/_surface_with_grid_cross_section.py index 893d6dc6d..d6dd34afd 100644 --- a/webviz_subsurface/plugins/_surface_with_grid_cross_section.py +++ b/webviz_subsurface/plugins/_surface_with_grid_cross_section.py @@ -266,6 +266,10 @@ def surface_layout(self): "value": "hillshading", "label": "Hillshading", }, + { + "value": "hillshading_shadows", + "label": "Hillshading with shadows", + }, ], value=None, persistence=True, @@ -415,11 +419,6 @@ def _render_surface( grid = load_grid(get_path(self.gridfile)) gridparameter = load_grid_parameter(grid, get_path(gridparameter)) surface.slice_grid3d(grid, gridparameter) - surface.values = surface.values.filled(0) - if min_val is not None: - surface.values[surface.values < min_val] = min_val - if max_val is not None: - surface.values[surface.values > max_val] = max_val s_layer = make_surface_layer( surface, diff --git a/webviz_subsurface/plugins/_surface_with_seismic_cross_section.py b/webviz_subsurface/plugins/_surface_with_seismic_cross_section.py index 42939c72d..fb26d44b1 100644 --- a/webviz_subsurface/plugins/_surface_with_seismic_cross_section.py +++ b/webviz_subsurface/plugins/_surface_with_seismic_cross_section.py @@ -266,6 +266,10 @@ def surface_layout(self): "value": "hillshading", "label": "Hillshading", }, + { + "value": "hillshading_shadows", + "label": "Hillshading with shadows", + }, ], value=None, persistence=True, @@ -400,18 +404,12 @@ def _render_surface( min_val = None max_val = None color = None - if surface_type == "attribute": min_val = color_values[0] if color_values else None max_val = color_values[1] if color_values else None color = colorscale if colorscale else color cube = load_cube_data(get_path(cubepath)) surface.slice_cube(cube) - surface.values = surface.values.filled(0) - if min_val is not None: - surface.values[surface.values < min_val] = min_val - if max_val is not None: - surface.values[surface.values > max_val] = max_val s_layer = make_surface_layer( surface,