Skip to content

Commit d1def5e

Browse files
authored
grass.jupyter: fix resolution handling for InteractiveMap (#2376)
1 parent 0b22155 commit d1def5e

File tree

4 files changed

+46
-14
lines changed

4 files changed

+46
-14
lines changed

python/grass/jupyter/interactivemap.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,16 @@ def __init__(
165165
folium documentation:
166166
https://python-visualization.github.io/folium/modules.html
167167
168+
Raster and vector data are always reprojected to Pseudo-Mercator.
169+
With use_region=True or saved_region=myregion, the region extent
170+
is reprojected and the number of rows and columns of that region
171+
is kept the same. This region is then used for reprojection.
172+
By default, use_region is False, which results in the
173+
reprojection of the entire raster in its native resolution.
174+
The reprojected resolution is estimated with r.proj.
175+
Vector data are always reprojected without any clipping,
176+
i.e., region options don't do anything.
177+
168178
:param int height: height in pixels of figure (default 400)
169179
:param int width: width in pixels of figure (default 400)
170180
:param str tiles: map tileset to use

python/grass/jupyter/region.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
from .utils import (
1919
get_map_name_from_d_command,
20+
estimate_resolution,
2021
set_target_region,
2122
get_rendering_size,
2223
)
@@ -39,23 +40,36 @@ def __init__(self, use_region, saved_region, src_env, tgt_env):
3940
self._saved_region = saved_region
4041
self._src_env = src_env
4142
self._tgt_env = tgt_env
43+
self._resolution = None
4244
# [SW, NE]: inverted to easily expand based on data, see _set_bbox
4345
self._bbox = [[90, 180], [-90, -180]]
4446
if self._use_region:
45-
# tgt region already set
47+
# tgt region already set, set resolution
48+
self._resolution = self._get_psmerc_region_resolution()
4649
self._set_bbox(self._src_env)
4750
if self._saved_region:
4851
self._src_env["GRASS_REGION"] = gs.region_env(
4952
region=self._saved_region, env=self._src_env
5053
)
5154
set_target_region(src_env=self._src_env, tgt_env=self._tgt_env)
55+
self._resolution = self._get_psmerc_region_resolution()
5256
self._set_bbox(self._src_env)
5357

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

63+
@property
64+
def resolution(self):
65+
"""Resolution to be used for reprojection."""
66+
return self._resolution
67+
68+
def _get_psmerc_region_resolution(self):
69+
"""Get region resolution (average ns and ew) of psmerc mapset"""
70+
reg = gs.region(env=self._tgt_env)
71+
return (reg["nsres"] + reg["ewres"]) / 2
72+
5973
def set_region_from_raster(self, raster):
6074
"""Sets computational region for rendering.
6175
@@ -71,8 +85,19 @@ def set_region_from_raster(self, raster):
7185
if self._use_region or self._saved_region:
7286
# target region and bbox already set
7387
return
88+
# set target location region extent
7489
self._src_env["GRASS_REGION"] = gs.region_env(raster=raster, env=self._src_env)
7590
set_target_region(src_env=self._src_env, tgt_env=self._tgt_env)
91+
# set resolution based on r.proj estimate
92+
env_info = gs.gisenv(env=self._src_env)
93+
name, mapset = raster.split("@")
94+
self._resolution = estimate_resolution(
95+
raster=name,
96+
mapset=mapset,
97+
location=env_info["LOCATION_NAME"],
98+
dbase=env_info["GISDBASE"],
99+
env=self._tgt_env,
100+
)
76101
self._set_bbox(self._src_env)
77102

78103
def set_bbox_vector(self, vector):

python/grass/jupyter/reprojection_renderer.py

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import grass.script as gs
2222
from .map import Map
2323
from .utils import (
24-
estimate_resolution,
2524
get_location_proj_string,
2625
get_region,
2726
reproject_region,
@@ -99,13 +98,6 @@ def render_raster(self, name):
9998
self._region_manager.set_region_from_raster(full_name)
10099
# Reproject raster into WGS84/epsg3857 location
101100
env_info = gs.gisenv(env=self._src_env)
102-
resolution = estimate_resolution(
103-
raster=name,
104-
mapset=mapset,
105-
location=env_info["LOCATION_NAME"],
106-
dbase=env_info["GISDBASE"],
107-
env=self._psmerc_env,
108-
)
109101
tgt_name = full_name.replace("@", "_")
110102
gs.run_command(
111103
"r.proj",
@@ -114,15 +106,15 @@ def render_raster(self, name):
114106
mapset=mapset,
115107
location=env_info["LOCATION_NAME"],
116108
dbase=env_info["GISDBASE"],
117-
resolution=resolution,
109+
resolution=self._region_manager.resolution,
118110
env=self._psmerc_env,
119111
)
120112
# Write raster to png file with Map
121-
region_info = gs.region(env=self._src_env)
113+
raster_info = gs.raster_info(tgt_name, env=self._psmerc_env)
122114
filename = os.path.join(self._tmp_dir.name, f"{tgt_name}.png")
123115
img = Map(
124-
width=region_info["cols"],
125-
height=region_info["rows"],
116+
width=int(raster_info["cols"]),
117+
height=int(raster_info["rows"]),
126118
env=self._psmerc_env,
127119
filename=filename,
128120
use_region=True,

python/grass/jupyter/utils.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,10 @@ def setup_location(name, path, epsg, src_env):
131131

132132

133133
def set_target_region(src_env, tgt_env):
134-
"""Set target region based on source region"""
134+
"""Set target region based on source region.
135+
136+
Number of rows and columns is preserved.
137+
"""
135138
region = get_region(env=src_env)
136139
from_proj = get_location_proj_string(src_env)
137140
to_proj = get_location_proj_string(env=tgt_env)
@@ -143,6 +146,8 @@ def set_target_region(src_env, tgt_env):
143146
s=new_region["south"],
144147
e=new_region["east"],
145148
w=new_region["west"],
149+
rows=new_region["rows"],
150+
cols=new_region["cols"],
146151
env=tgt_env,
147152
)
148153

0 commit comments

Comments
 (0)