Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

grass.jupyter: fix resolution handling for InteractiveMap #2376

Merged
merged 3 commits into from May 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
10 changes: 10 additions & 0 deletions python/grass/jupyter/interactivemap.py
Expand Up @@ -165,6 +165,16 @@ def __init__(
folium documentation:
https://python-visualization.github.io/folium/modules.html

Raster and vector data are always reprojected to Pseudo-Mercator.
With use_region=True or saved_region=myregion, the region extent
is reprojected and the number of rows and columns of that region
is kept the same. This region is then used for reprojection.
By default, use_region is False, which results in the
reprojection of the entire raster in its native resolution.
The reprojected resolution is estimated with r.proj.
Vector data are always reprojected without any clipping,
i.e., region options don't do anything.

:param int height: height in pixels of figure (default 400)
:param int width: width in pixels of figure (default 400)
:param str tiles: map tileset to use
Expand Down
27 changes: 26 additions & 1 deletion python/grass/jupyter/region.py
Expand Up @@ -17,6 +17,7 @@

from .utils import (
get_map_name_from_d_command,
estimate_resolution,
set_target_region,
get_rendering_size,
)
Expand All @@ -39,23 +40,36 @@ def __init__(self, use_region, saved_region, src_env, tgt_env):
self._saved_region = saved_region
self._src_env = src_env
self._tgt_env = tgt_env
self._resolution = None
# [SW, NE]: inverted to easily expand based on data, see _set_bbox
self._bbox = [[90, 180], [-90, -180]]
if self._use_region:
# tgt region already set
# tgt region already set, set resolution
self._resolution = self._get_psmerc_region_resolution()
self._set_bbox(self._src_env)
if self._saved_region:
self._src_env["GRASS_REGION"] = gs.region_env(
region=self._saved_region, env=self._src_env
)
set_target_region(src_env=self._src_env, tgt_env=self._tgt_env)
self._resolution = self._get_psmerc_region_resolution()
self._set_bbox(self._src_env)

@property
def bbox(self):
"""Bbox property for accessing maximum bounding box of all rendered layers."""
return self._bbox

@property
def resolution(self):
"""Resolution to be used for reprojection."""
return self._resolution

def _get_psmerc_region_resolution(self):
"""Get region resolution (average ns and ew) of psmerc mapset"""
reg = gs.region(env=self._tgt_env)
return (reg["nsres"] + reg["ewres"]) / 2

def set_region_from_raster(self, raster):
"""Sets computational region for rendering.

Expand All @@ -71,8 +85,19 @@ def set_region_from_raster(self, raster):
if self._use_region or self._saved_region:
# target region and bbox already set
return
# set target location region extent
self._src_env["GRASS_REGION"] = gs.region_env(raster=raster, env=self._src_env)
set_target_region(src_env=self._src_env, tgt_env=self._tgt_env)
# set resolution based on r.proj estimate
env_info = gs.gisenv(env=self._src_env)
name, mapset = raster.split("@")
self._resolution = estimate_resolution(
raster=name,
mapset=mapset,
location=env_info["LOCATION_NAME"],
dbase=env_info["GISDBASE"],
env=self._tgt_env,
)
self._set_bbox(self._src_env)

def set_bbox_vector(self, vector):
Expand Down
16 changes: 4 additions & 12 deletions python/grass/jupyter/reprojection_renderer.py
Expand Up @@ -21,7 +21,6 @@
import grass.script as gs
from .map import Map
from .utils import (
estimate_resolution,
get_location_proj_string,
get_region,
reproject_region,
Expand Down Expand Up @@ -99,13 +98,6 @@ def render_raster(self, name):
self._region_manager.set_region_from_raster(full_name)
# Reproject raster into WGS84/epsg3857 location
env_info = gs.gisenv(env=self._src_env)
resolution = estimate_resolution(
raster=name,
mapset=mapset,
location=env_info["LOCATION_NAME"],
dbase=env_info["GISDBASE"],
env=self._psmerc_env,
)
tgt_name = full_name.replace("@", "_")
gs.run_command(
"r.proj",
Expand All @@ -114,15 +106,15 @@ def render_raster(self, name):
mapset=mapset,
location=env_info["LOCATION_NAME"],
dbase=env_info["GISDBASE"],
resolution=resolution,
resolution=self._region_manager.resolution,
env=self._psmerc_env,
)
# Write raster to png file with Map
region_info = gs.region(env=self._src_env)
raster_info = gs.raster_info(tgt_name, env=self._psmerc_env)
filename = os.path.join(self._tmp_dir.name, f"{tgt_name}.png")
img = Map(
width=region_info["cols"],
height=region_info["rows"],
width=int(raster_info["cols"]),
height=int(raster_info["rows"]),
env=self._psmerc_env,
filename=filename,
use_region=True,
Expand Down
7 changes: 6 additions & 1 deletion python/grass/jupyter/utils.py
Expand Up @@ -131,7 +131,10 @@ def setup_location(name, path, epsg, src_env):


def set_target_region(src_env, tgt_env):
"""Set target region based on source region"""
"""Set target region based on source region.

Number of rows and columns is preserved.
"""
region = get_region(env=src_env)
from_proj = get_location_proj_string(src_env)
to_proj = get_location_proj_string(env=tgt_env)
Expand All @@ -143,6 +146,8 @@ def set_target_region(src_env, tgt_env):
s=new_region["south"],
e=new_region["east"],
w=new_region["west"],
rows=new_region["rows"],
cols=new_region["cols"],
env=tgt_env,
)

Expand Down