Skip to content

Commit f161bd6

Browse files
committed
migrate functions and add tests
1 parent 65a1515 commit f161bd6

2 files changed

Lines changed: 79 additions & 22 deletions

File tree

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import pytest
2+
import grass.script as gs
3+
from grass.tools import Tools
4+
from grass.jupyter.utils import *
5+
6+
7+
def test_get_region(session_with_data):
8+
"""Check that get_region returns a dictionary with region bounds"""
9+
region = get_region(env=session_with_data.env)
10+
11+
assert isinstance(region, dict)
12+
assert "north" in region
13+
assert "south" in region
14+
assert "east" in region
15+
assert "west" in region
16+
17+
def test_get_location_proj_string(tmp_path):
18+
"""Test that get_location_proj_string returns the projection of the environment in PROJ.4 format."""
19+
project = tmp_path / "test_project_proj"
20+
gs.create_project(project)
21+
with gs.setup.init(project):
22+
gs.run_command("g.proj", flags="c", epsg="4326")
23+
projection = get_location_proj_string()
24+
assert "+proj=" in projection
25+
26+
def test_reproject_region(session_with_data):
27+
"""Check that a region is correctly reprojected between two projections"""
28+
reg = {"north": 100000.0, "south": 0.0, "east": 100000.0, "west": 0.0, "rows": 10, "cols": 10}
29+
p_in = "+proj=merc +a=6378137 +b=6378137 +units=m +type=crs"
30+
p_out = "+proj=longlat +datum=WGS84 +type=crs"
31+
32+
res = reproject_region(reg, p_in, p_out, env=session_with_data.env)
33+
34+
assert isinstance(res, dict) and "north" in res
35+
assert res["north"] != reg["north"] and res["east"] != reg["east"]
36+
assert -90 <= res["north"] <= 90 and -180 <= res["east"] <= 180
37+
38+
def test_set_target_region(session_with_data, tmp_path):
39+
"""Check setting a target region in a newly created environment"""
40+
gisdbase = str(tmp_path)
41+
42+
# Helper to quickly spin up isolated GRASS locations
43+
def make_env(loc_name, epsg):
44+
_, env = gs.create_environment(gisdbase, loc_name, "PERMANENT")
45+
gs.create_location(gisdbase, loc_name, epsg=epsg, overwrite=True)
46+
full_env = session_with_data.env.copy()
47+
full_env["GISRC"] = env["GISRC"]
48+
return full_env
49+
50+
# 1. Setup Source and Target
51+
src_env = make_env("src_loc", "3857")
52+
tgt_env = make_env("tgt_loc", "4326")
53+
54+
# 2. Add data to source, then execute function
55+
Tools(env=src_env).g_region(n=1000, s=0, e=1000, w=0, rows=10, cols=10)
56+
set_target_region(src_env, tgt_env)
57+
58+
# 3. Verify
59+
res = get_region(env=tgt_env)
60+
assert isinstance(res, dict) and "north" in res and "south" in res

python/grass/jupyter/utils.py

Lines changed: 19 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def get_location_proj_string(env=None):
3535
return tools.g_proj(flags="fp", format="proj4").text
3636

3737

38-
def reproject_region(region, from_proj, to_proj):
38+
def reproject_region(region, from_proj, to_proj, env=None):
3939
"""Reproject boundary of region from one projection to another.
4040
4141
:param dict region: region to reproject as a dictionary with long key names
@@ -47,6 +47,7 @@ def reproject_region(region, from_proj, to_proj):
4747
:return dict region: reprojected region as a dictionary with long key names
4848
"""
4949
region = region.copy()
50+
tools = Tools(env=env)
5051
# reproject all corners, otherwise reproj. region may be underestimated
5152
# even better solution would be reprojecting vector region like in r.import
5253
proj_input = (
@@ -55,28 +56,25 @@ def reproject_region(region, from_proj, to_proj):
5556
f"{region['east']} {region['south']}\n"
5657
f"{region['west']} {region['south']}\n"
5758
)
58-
proc = gs.start_command(
59-
"m.proj",
60-
input="-",
61-
separator=" , ",
62-
proj_in=from_proj,
63-
proj_out=to_proj,
64-
flags="d",
65-
stdin=gs.PIPE,
66-
stdout=gs.PIPE,
67-
stderr=gs.PIPE,
68-
)
69-
proj_output, stderr = proc.communicate(proj_input)
70-
if proc.returncode:
71-
raise RuntimeError(
72-
_("Encountered error while running m.proj: {}").format(stderr)
59+
60+
with tempfile.NamedTemporaryFile(mode="w+t") as temp_file:
61+
temp_file.write(proj_input)
62+
temp_file.flush()
63+
64+
tools = Tools(env=env)
65+
result = tools.m_proj(
66+
input=temp_file.name,
67+
separator=",",
68+
proj_in=from_proj,
69+
proj_out=to_proj,
70+
flags="d",
7371
)
74-
output = proj_output.splitlines()
72+
output = result.text.splitlines()
7573
# get the largest bbox
7674
latitude_list = []
7775
longitude_list = []
7876
for row in output:
79-
longitude, latitude, unused = row.split(" ")
77+
longitude, latitude, unused = row.split(",")
8078
longitude_list.append(float(longitude))
8179
latitude_list.append(float(latitude))
8280
region["east"] = max(longitude_list)
@@ -355,17 +353,16 @@ def set_target_region(src_env, tgt_env):
355353
region = get_region(env=src_env)
356354
from_proj = get_location_proj_string(src_env)
357355
to_proj = get_location_proj_string(env=tgt_env)
358-
new_region = reproject_region(region, from_proj, to_proj)
356+
new_region = reproject_region(region, from_proj, to_proj, env=src_env)
359357
# Set region to match original region extent
360-
gs.run_command(
361-
"g.region",
358+
tools = Tools(env=tgt_env)
359+
tools.g_region(
362360
n=new_region["north"],
363361
s=new_region["south"],
364362
e=new_region["east"],
365363
w=new_region["west"],
366364
rows=new_region["rows"],
367365
cols=new_region["cols"],
368-
env=tgt_env,
369366
)
370367

371368

0 commit comments

Comments
 (0)