Skip to content

Commit ea491ff

Browse files
committed
change TPI method
1 parent 091fe2d commit ea491ff

10 files changed

+420
-36
lines changed

pyosp/_tpi.py

+16-28
Original file line numberDiff line numberDiff line change
@@ -15,42 +15,30 @@ def __init__(self, point_coord, raster, radius):
1515
"""
1616
self.p = point_coord
1717
self.raster = raster
18-
self.geoTransform = self.raster.GetGeoTransform()
19-
self.radius = int(radius / self.geoTransform[1])
20-
21-
# change nodata to nan, assuming a small value was given
22-
self.rasterMatrix = self.raster.ReadAsArray()
23-
if not np.min(self.rasterMatrix) > -1e10:
24-
self.rasterMatrix[self.rasterMatrix < -1e10] = np.nan
18+
self.cols = raster.RasterXSize
19+
self.rows = raster.RasterYSize
20+
self.geoTransform = raster.GetGeoTransform()
21+
self.radiusInPixel = int(radius / self.geoTransform[1])
2522

2623
def point_position(self):
2724
x = int((self.p[0] - self.geoTransform[0]) / self.geoTransform[1])
2825
y = int((self.geoTransform[3] - self.p[1]) / -self.geoTransform[5])
2926
return y, x
3027

31-
def raster_window(self):
28+
def avg_window(self):
3229
py, px = self.point_position()
33-
34-
#pad nan to range out of raster
35-
rasterPad = np.pad(self.rasterMatrix, (self.radius+1,),
36-
mode='constant', constant_values=(np.nan,))
37-
38-
return rasterPad[py:(py+2*self.radius+1),
39-
px:(px+2*self.radius+1)]
30+
xmin = max(0, px-self.radiusInPixel)
31+
xmax = min(self.cols, px+self.radiusInPixel+1)
32+
ymin = max(0, py-self.radiusInPixel)
33+
ymax = min(self.rows, py+self.radiusInPixel+1)
34+
arr = self.raster.ReadAsArray(xoff=xmin, yoff=ymin, xsize=xmax-xmin, ysize=ymax-ymin)
35+
avg = (np.nansum(arr)-self.point_value()) / (arr.size-1)
36+
return avg
4037

4138
def point_value(self):
42-
return self.rasterMatrix[self.point_position()]
43-
44-
@property
45-
def index(self):
46-
outer = self.window * self.raster_window()
47-
inner = self.point_value()
48-
return inner - (np.nansum(outer)/np.count_nonzero(~np.isnan(outer)))
39+
py, px =self.point_position()
40+
return self.raster.ReadAsArray(xoff=px, yoff=py, xsize=1, ysize=1)[0]
4941

5042
@property
51-
def window(self):
52-
win = np.ones((2*self.radius+1, 2*self.radius+1))
53-
r_y, r_x = win.shape[0]//2, win.shape[1]//2
54-
win[r_y, r_x] = 0 # remove the central cell
55-
return win
56-
43+
def value(self):
44+
return self.point_value() - self.avg_window()

pyosp/cirsp/tpi_cir.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def _radial_lines(self):
6363
p = [self.center.x+dx, self.center.y+dy]
6464

6565
p_elev = Point_elevation(p, self.raster).value
66-
p_tpi= Tpi(p, self.raster, self.tpi_radius).index
66+
p_tpi= Tpi(p, self.raster, self.tpi_radius).value
6767

6868
if not (
6969
(self.rasterXmin <= p[0] <= self.rasterXmax) and

pyosp/curvsp/tpi_curv.py

+6-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from ..util import pairwise, progressBar
66
from .._tpi import Tpi
77
from .base_curv import Base_curv
8+
import gdal
89

910
class Tpi_curv(Base_curv):
1011
"""TPI-based swath profile characterization.
@@ -29,13 +30,13 @@ class Tpi_curv(Base_curv):
2930
def __init__(self, line, raster, width,
3031
tpi_radius, min_tpi=float("-inf"), max_tpi=float("inf"),
3132
line_stepsize=None, cross_stepsize=None):
32-
self.tpi_radius = tpi_radius
33+
self.tpi_radius = tpi_radius
3334
self.min_tpi = min_tpi
3435
self.max_tpi = max_tpi
35-
36+
3637
super(Tpi_curv,self).__init__(line, raster, width,
3738
line_stepsize, cross_stepsize)
38-
39+
3940
def __repr__(self):
4041
return("{}".format(self.__class__.__name__))
4142

@@ -104,8 +105,7 @@ def _swath_left(self, p1, p2, endPoint=False):
104105
if hw >= self.width/2:
105106
break
106107

107-
p_index = Tpi(p_left, self.raster, self.tpi_radius).index
108-
108+
p_index = Tpi(p_left, self.raster, self.tpi_radius).value
109109
if self.min_tpi <= p_index <= self.max_tpi:
110110
transect_temp.insert(0,p_left)
111111
else:
@@ -148,8 +148,7 @@ def _swath_right(self, p1, p2, endPoint=False):
148148
if hw >= self.width/2:
149149
break
150150

151-
p_index = Tpi(p_right, self.raster, self.tpi_radius).index
152-
151+
p_index = Tpi(p_right, self.raster, self.tpi_radius).value
153152
if self.min_tpi <= p_index <= self.max_tpi:
154153
transect_temp.append(p_right)
155154
else:

pyosp/tests/__init__.py

Whitespace-only changes.

pyosp/tests/conftest.py

+109
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import pytest
4+
import os, sys
5+
from collections import namedtuple
6+
from pyosp import *
7+
8+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
9+
dat = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../datasets/")
10+
11+
homo_line = os.path.join(dat, 'homo_baseline.shp')
12+
homo_raster = os.path.join(dat, 'homo_mount.tif')
13+
14+
cir_center = os.path.join(dat, 'center.shp')
15+
cir_raster = os.path.join(dat, 'crater.tif')
16+
17+
@pytest.fixture(scope='module')
18+
def base_homo(**kwargs):
19+
def _base_homo(**kwargs):
20+
return Base_curv(line=homo_line, raster=homo_raster, width=100, **kwargs)
21+
22+
return _base_homo
23+
24+
@pytest.fixture(scope='module')
25+
def orig_homo(**kwargs):
26+
def _orig_homo(**kwargs):
27+
return Orig_curv(line=homo_line, raster=homo_raster, width=100, **kwargs)
28+
29+
return _orig_homo
30+
31+
@pytest.fixture(scope='module')
32+
def elev_homo(**kwargs):
33+
def _elev_homo(**kwargs):
34+
return Elev_curv(line=homo_line, raster=homo_raster, width=100,
35+
min_elev=0.01,
36+
**kwargs)
37+
38+
return _elev_homo
39+
40+
@pytest.fixture(scope='module')
41+
def slope_homo(**kwargs):
42+
def _slope_homo(**kwargs):
43+
return Slope_curv(line=homo_line, raster=homo_raster, width=100,
44+
min_slope=1,
45+
**kwargs)
46+
47+
return _slope_homo
48+
49+
@pytest.fixture(scope='module')
50+
def tpi_homo(**kwargs):
51+
def _tpi_homo(**kwargs):
52+
return Tpi_curv(line=homo_line, raster=homo_raster, width=100,
53+
tpi_radius=50, min_tpi=-5,
54+
**kwargs)
55+
56+
return _tpi_homo
57+
58+
@pytest.fixture(scope='module')
59+
def base_cir(**kwargs):
60+
def _base_cir(**kwargs):
61+
return Base_cir(cir_center, cir_raster, radius=80,
62+
ng_start=0, ng_end=300,
63+
ng_stepsize=1, radial_stepsize=None, **kwargs)
64+
65+
return _base_cir
66+
67+
@pytest.fixture(scope='module')
68+
def orig_cir(**kwargs):
69+
def _orig_cir(**kwargs):
70+
return Orig_cir(cir_center, cir_raster, radius=80,
71+
ng_start=0, ng_end=300,
72+
ng_stepsize=1, radial_stepsize=None, **kwargs)
73+
74+
return _orig_cir
75+
76+
@pytest.fixture(scope='module')
77+
def elev_cir(**kwargs):
78+
def _elev_cir(**kwargs):
79+
return Elev_cir(cir_center, cir_raster, radius=80,
80+
min_elev=4,
81+
ng_start=0, ng_end=300,
82+
ng_stepsize=1, radial_stepsize=None, **kwargs)
83+
84+
return _elev_cir
85+
86+
@pytest.fixture(scope='module')
87+
def slope_cir(**kwargs):
88+
def _slope_cir(**kwargs):
89+
return Slope_cir(cir_center, cir_raster, radius=80,
90+
min_slope=13,
91+
ng_start=0, ng_end=300,
92+
ng_stepsize=1, radial_stepsize=None, **kwargs)
93+
94+
return _slope_cir
95+
96+
@pytest.fixture(scope='module')
97+
def tpi_cir(**kwargs):
98+
def _tpi_cir(**kwargs):
99+
return Tpi_cir(cir_center, cir_raster, radius=80,
100+
tpi_radius=50, min_tpi=2,
101+
ng_start=0, ng_end=300,
102+
ng_stepsize=1, radial_stepsize=None, **kwargs)
103+
104+
return _tpi_cir
105+
106+
107+
108+
109+

pyosp/tests/test_cirBase.py

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import os, sys
4+
5+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
6+
dat = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../datasets/")
7+
8+
class TestBaseCir:
9+
10+
def test_initial(self, base_cir):
11+
"""Test the setup"""
12+
base = base_cir()
13+
assert base.radial_stepsize == base.raster.GetGeoTransform()[1]
14+
assert len(base.distance) == base.radius // base.radial_stepsize + 1
15+

pyosp/tests/test_cirSP.py

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import pytest
4+
import os, sys
5+
import pyosp
6+
import numpy as np
7+
8+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
9+
dat = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../datasets/")
10+
11+
class TestCir:
12+
def test_elev_cir(self, elev_cir):
13+
"""
14+
Data INSIDE of border should fall in geo-parameter range.
15+
OUTSIDE should not.
16+
"""
17+
elev = elev_cir()
18+
lines = elev.lines
19+
20+
p_in = [x[-1] for x in lines[90:181]]
21+
gradient = [np.radians(ng) for ng in range(90,181)]
22+
p_dat_in = []
23+
p_dat_out = []
24+
for ind, point in enumerate(p_in):
25+
p_out = [point[0] + np.cos(gradient[ind])*elev.radial_stepsize,
26+
point[1] + np.sin(gradient[ind])*elev.radial_stepsize]
27+
28+
dat_in = pyosp.Point_elevation(point, elev.raster).value
29+
dat_out = pyosp.Point_elevation(p_out, elev.raster).value
30+
31+
p_dat_in.append(dat_in)
32+
p_dat_out.append(dat_out)
33+
34+
assert all(i < 4 for i in p_dat_out)
35+
36+
def test_slope_cir(self, slope_cir):
37+
"""
38+
Data INSIDE of border should fall in geo-parameter range.
39+
OUTSIDE should not.
40+
"""
41+
slope = slope_cir()
42+
lines = slope.lines
43+
cell_res = slope.raster.GetGeoTransform()[1]
44+
45+
p_in = [x[-1] for x in lines[90:181]]
46+
gradient = [np.radians(ng) for ng in range(90,181)]
47+
p_dat_in = []
48+
p_dat_out = []
49+
for ind, point in enumerate(p_in):
50+
p_out = [point[0] + np.cos(gradient[ind])*slope.radial_stepsize,
51+
point[1] + np.sin(gradient[ind])*slope.radial_stepsize]
52+
53+
dat_in = pyosp.Geo_slope(point, slope.raster, cell_res).value
54+
dat_out = pyosp.Geo_slope(p_out, slope.raster, cell_res).value
55+
56+
p_dat_in.append(dat_in)
57+
p_dat_out.append(dat_out)
58+
59+
assert all(i < 13 for i in p_dat_out)
60+
61+
def test_tpi_cir(self, tpi_cir):
62+
"""
63+
Data INSIDE of border should fall in geo-parameter range.
64+
OUTSIDE should not.
65+
"""
66+
tpi = tpi_cir()
67+
lines = tpi.lines
68+
69+
p_in = [x[-1] for x in lines[90:181]]
70+
gradient = [np.radians(ng) for ng in range(90,181)]
71+
p_dat_in = []
72+
p_dat_out = []
73+
for ind, point in enumerate(p_in):
74+
p_out = [point[0] + np.cos(gradient[ind])*tpi.radial_stepsize,
75+
point[1] + np.sin(gradient[ind])*tpi.radial_stepsize]
76+
77+
dat_in = pyosp.Tpi(point, tpi.raster, tpi.tpi_radius).value
78+
dat_out = pyosp.Tpi(p_out, tpi.raster, tpi.tpi_radius).value
79+
p_dat_in.append(dat_in)
80+
p_dat_out.append(dat_out)
81+
82+
assert all(i < 2 for i in p_dat_out)

pyosp/tests/test_curvBase.py

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import pytest
4+
import os, sys
5+
from pyosp import point_coords
6+
7+
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
8+
dat = os.path.join(os.path.dirname(os.path.abspath(__file__)), "../datasets/")
9+
10+
class TestBaseHomo:
11+
# @pytest.mark.parametrize('base_homo', [
12+
# dict(line_stepsize=None, cross_stepsize=None),
13+
# dict(line_stepsize=100)
14+
# ], indirect=True)
15+
def test_initial(self, base_homo):
16+
"""Test the setup"""
17+
base = base_homo(line_stepsize=None, cross_stepsize=None)
18+
assert base.line_stepsize == base.cell_res
19+
assert base.cross_stepsize == base.cell_res
20+
assert len(base.distance) == base.line.length // base.line_stepsize + 1
21+
assert len(base.line_p) == len(base.distance)
22+
23+
def test_segment(self, base_homo):
24+
"""Test the start and end of chosen segment:
25+
start == line.length / 2
26+
end == line.length / 4
27+
"""
28+
start_end = os.path.join(dat, 'homo_start_end.shp')
29+
coords = point_coords(start_end)
30+
base = base_homo(line_stepsize=None, cross_stepsize=None)
31+
start_ind, end_ind = base._segment(coords[1], coords[0])
32+
assert abs(start_ind-len(base.distance)/4) <= 3
33+
assert abs(end_ind-len(base.distance)/2) <= 3
34+
35+
# if given values are distances
36+
start_distance = base.distance[len(base.distance)//4]
37+
end_distance = base.distance[len(base.distance)//2]
38+
start_ind, end_ind = base._segment(start_distance, end_distance)
39+
assert abs(start_ind-len(base.distance)/4) <= 3
40+
assert abs(end_ind-len(base.distance)/2) <= 3
41+
42+

0 commit comments

Comments
 (0)