Skip to content

Commit

Permalink
Merge branch 'OSGeo:main' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
a0x8o authored Apr 3, 2024
2 parents 43794ba + d32ece4 commit 3d5a31a
Show file tree
Hide file tree
Showing 4 changed files with 272 additions and 41 deletions.
174 changes: 174 additions & 0 deletions imagery/i.pca/testsuite/test_pca.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
"""
Name: i.pca test
Purpose: Tests i.pca.
Author: Hamed Elgizery - [email protected]
Copyright: (C) 2024 by Hamed Elgizery and the GRASS Development Team
Licence: This program is free software under the GNU General Public
License (>=v2). Read the file COPYING that comes with GRASS
for details.
"""
from grass.gunittest.case import TestCase


class TestReport(TestCase):
@classmethod
def setUpClass(cls):
"""Use temporary region settings"""
cls.runModule("g.region", raster="lsat7_2002_10@PERMANENT")
cls.use_temp_region()

@classmethod
def tearDownClass(cls):
cls.runModule(
"g.remove",
flags="f",
type="raster",
name="lsat7_2002_pca.1,lsat7_2002_pca.2,lsat7_2002_pca.3,lsat7_2002_pca.4,lsat7_2002_pca.6",
)
cls.del_temp_region()

def test_pca_sample(self):
"""Testing pca sample"""
self.assertModule(
"i.pca",
input="lsat7_2002_10,lsat7_2002_20,lsat7_2002_30,lsat7_2002_40,lsat7_2002_50,lsat7_2002_70",
output="lsat7_2002_pca",
)

lsat7_2002_pca_info_out = """north=228513
south=214975.5
east=645012
west=629992.5
nsres=28.5
ewres=28.5
rows=475
cols=527
cells=250325
datatype=CELL
ncats=0
comments=\"Eigen values, (vectors), and [percent importance]:PC1 4334.35 ( 0.2824, 0.3342, 0.5092,-0.0087, 0.5264, 0.5217) [83.04%]PC2 588.31 ( 0.2541, 0.1885, 0.2923,-0.7428,-0.5110,-0.0403) [11.27%]PC3 239.22 ( 0.3801, 0.3819, 0.2681, 0.6238,-0.4000,-0.2980) [ 4.58%]PC4 32.85 ( 0.1752,-0.0191,-0.4053, 0.1593,-0.4435, 0.7632) [ 0.63%]PC5 20.73 (-0.6170,-0.2514, 0.6059, 0.1734,-0.3235, 0.2330) [ 0.40%]PC6 4.08 (-0.5475, 0.8021,-0.2282,-0.0607,-0.0208, 0.0252) [ 0.08%]i.pca input=\"lsat7_2002_10,lsat7_2002_20,lsat7_2002_30,lsat7_2002_40\,lsat7_2002_50,lsat7_2002_70\" output=\"lsat7_2002_pca\" rescale=0,255 \percent=99" """

lsat7_2002_pca_univar_out = [
"""n=250325
null_cells=0
cells=250325
min=0
max=255
range=255
mean=60.6958074503146
mean_of_abs=60.6958074503146
stddev=32.8850846003739
variance=1081.42878917375
coeff_var=54.1801583697417
sum=15193678
first_quartile=36
median=51
third_quartile=77
percentile_90=101""",
"""n=250325
null_cells=0
cells=250325
min=0
max=255
range=255
mean=106.099418755618
mean_of_abs=106.099418755618
stddev=26.4487056926998
variance=699.534032819051
coeff_var=24.928228639612
sum=26559337
first_quartile=88
median=104
third_quartile=121
percentile_90=137""",
"""n=250325
null_cells=0
cells=250325
min=0
max=255
range=255
mean=74.1768980325577
mean_of_abs=74.1768980325577
stddev=14.1956266450161
variance=201.515815844691
coeff_var=19.1375307158104
sum=18568332
first_quartile=67
median=74
third_quartile=81
percentile_90=88""",
"""n=250325
null_cells=0
cells=250325
min=0
max=255
range=255
mean=113.285145311096
mean_of_abs=113.285145311096
stddev=10.689092045444
variance=114.256688755974
coeff_var=9.43556369733241
sum=28358104
first_quartile=109
median=114
third_quartile=118
percentile_90=122""",
"""n=250325
null_cells=0
cells=250325
min=0
max=255
range=255
mean=110.346713272745
mean_of_abs=110.346713272745
stddev=8.43087149474902
variance=71.0795941609716
coeff_var=7.64034672596938
sum=27622541
first_quartile=106
median=110
third_quartile=114
percentile_90=118""",
"""n=250325
null_cells=0
cells=250325
min=0
max=255
range=255
mean=115.238465994208
mean_of_abs=115.238465994208
stddev=8.97064489504434
variance=80.4724698329851
coeff_var=7.78441887233665
sum=28847069
first_quartile=110
median=115
third_quartile=121
percentile_90=126""",
]

for i in range(1, 7):
# Asserting the results givien from r.info
self.assertRasterFitsInfo(
raster=f"lsat7_2002_pca.{i}",
reference=lsat7_2002_pca_info_out,
precision=3,
)

# Asserting the results givien from r.univar
univar_out = lsat7_2002_pca_univar_out[i - 1]
self.assertModuleKeyValue(
"r.univar",
flags="eg",
map=f"lsat7_2002_pca.{i}",
reference=univar_out,
precision=3,
sep="=",
)


if __name__ == "__main__":
from grass.gunittest.main import test

test()
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,4 @@ timeout = 300

[tool.bandit]
exclude_dirs = ["./testsuite", "*/tests/*", "*/testsuite/*", "utils/test_generate_last_commit_file.py"]
skips = ["B324","B110", "B101", "B112", "B404"]
skips = ["B324","B110", "B101", "B112", "B311", "B404"]
106 changes: 66 additions & 40 deletions python/grass/script/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,11 @@
import random
import shlex
from tempfile import NamedTemporaryFile
from pathlib import Path

from .utils import KeyValue, parse_key_val, basename, encode, decode, try_remove
from grass.exceptions import ScriptError, CalledModuleError
from grass.grassdb.manage import resolve_mapset_path


# subprocess wrapper that uses shell on Windows
Expand Down Expand Up @@ -1697,9 +1699,16 @@ def mapsets(search_path=False, env=None):
# interface to `g.proj -c`


def create_location(
dbase,
location,
def create_location(*args, **kwargs):
if "location" in kwargs:
kwargs["name"] = kwargs["location"]
del kwargs["location"]
return create_project(*args, **kwargs)


def create_project(
path,
name=None,
epsg=None,
proj4=None,
filename=None,
Expand All @@ -1709,44 +1718,34 @@ def create_location(
desc=None,
overwrite=False,
):
"""Create new location
"""Create new project
Raise ScriptError on error.
:param str dbase: path to GRASS database
:param str location: location name to create
:param epsg: if given create new location based on EPSG code
:param proj4: if given create new location based on Proj4 definition
:param str filename: if given create new location based on georeferenced file
:param str wkt: if given create new location based on WKT definition
:param str path: path to GRASS database or project; if path to database, project
name must be specified with name parameter
:param str name: project name to create
:param epsg: if given create new project based on EPSG code
:param proj4: if given create new project based on Proj4 definition
:param str filename: if given create new project based on georeferenced file
:param str wkt: if given create new project based on WKT definition
(can be path to PRJ file or WKT string)
:param datum: GRASS format datum code
:param datum_trans: datum transformation parameters (used for epsg and proj4)
:param desc: description of the location (creates MYNAME file)
:param bool overwrite: True to overwrite location if exists(WARNING:
ALL DATA from existing location ARE DELETED!)
:param desc: description of the project (creates MYNAME file)
:param bool overwrite: True to overwrite project if exists (WARNING:
ALL DATA from existing project ARE DELETED!)
"""
# create dbase if not exists
if not os.path.exists(dbase):
os.mkdir(dbase)
# Add default mapset to project path if needed
if not name:
path = os.path.join(path, "PERMANENT")

# check if location already exists
if os.path.exists(os.path.join(dbase, location)):
if not overwrite:
warning(_("Location <%s> already exists. Operation canceled.") % location)
return
else:
warning(
_("Location <%s> already exists and will be overwritten") % location
)
shutil.rmtree(os.path.join(dbase, location))
# resolve dbase, location and mapset
mapset_path = resolve_mapset_path(path=path, location=name)

stdin = None
kwargs = dict()
if datum:
kwargs["datum"] = datum
if datum_trans:
kwargs["datum_trans"] = datum_trans
# create dbase if not exists
if not os.path.exists(mapset_path.directory):
os.mkdir(mapset_path.directory)

# Lazy-importing to avoid circular dependencies.
# pylint: disable=import-outside-toplevel
Expand All @@ -1761,16 +1760,38 @@ def create_location(
if epsg or proj4 or filename or wkt:
# The names don't really matter here.
tmp_gisrc, env = create_environment(
dbase, "<placeholder>", "<placeholder>", env=env
mapset_path.directory, mapset_path.location, mapset_path.mapset, env=env
)

# check if location already exists
if Path(mapset_path.directory, mapset_path.location).exists():
if not overwrite:
fatal(
_("Location <%s> already exists. Operation canceled.")
% mapset_path.location,
env=env,
)
warning(
_("Location <%s> already exists and will be overwritten")
% mapset_path.location,
env=env,
)
shutil.rmtree(os.path.join(mapset_path.directory, mapset_path.location))

stdin = None
kwargs = dict()
if datum:
kwargs["datum"] = datum
if datum_trans:
kwargs["datum_trans"] = datum_trans

if epsg:
ps = pipe_command(
"g.proj",
quiet=True,
flags="t",
epsg=epsg,
location=location,
location=mapset_path.location,
stderr=PIPE,
env=env,
**kwargs,
Expand All @@ -1781,7 +1802,7 @@ def create_location(
quiet=True,
flags="t",
proj4=proj4,
location=location,
location=mapset_path.location,
stderr=PIPE,
env=env,
**kwargs,
Expand All @@ -1791,28 +1812,33 @@ def create_location(
"g.proj",
quiet=True,
georef=filename,
location=location,
location=mapset_path.location,
stderr=PIPE,
env=env,
)
elif wkt:
if os.path.isfile(wkt):
ps = pipe_command(
"g.proj", quiet=True, wkt=wkt, location=location, stderr=PIPE, env=env
"g.proj",
quiet=True,
wkt=wkt,
location=mapset_path.location,
stderr=PIPE,
env=env,
)
else:
ps = pipe_command(
"g.proj",
quiet=True,
wkt="-",
location=location,
location=mapset_path.location,
stderr=PIPE,
stdin=PIPE,
env=env,
)
stdin = encode(wkt)
else:
_create_location_xy(dbase, location)
_create_location_xy(mapset_path.directory, mapset_path.location)

if epsg or proj4 or filename or wkt:
error = ps.communicate(stdin)[1]
Expand All @@ -1821,7 +1847,7 @@ def create_location(
if ps.returncode != 0 and error:
raise ScriptError(repr(error))

_set_location_description(dbase, location, desc)
_set_location_description(mapset_path.directory, mapset_path.location, desc)


def _set_location_description(path, location, text):
Expand Down
Loading

0 comments on commit 3d5a31a

Please sign in to comment.