Skip to content

Commit 40261a0

Browse files
committed
fix: traceback errors-geo
-fixed distance calculation errors associated with coordinate system transformation. -added top depth input to rank function
1 parent c24137a commit 40261a0

File tree

6 files changed

+110
-101
lines changed

6 files changed

+110
-101
lines changed

Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,10 @@ process_bulk_test_results_us:
5757
python -m soil_id.tests.us.process_bulk_test_results $(RESULTS_FILE)
5858

5959
generate_bulk_test_results_global:
60-
python -m soil_id.tests.us.generate_bulk_test_results
60+
python -m soil_id.tests.global.generate_bulk_test_results
6161

6262
process_bulk_test_results_global:
63-
python -m soil_id.tests.us.process_bulk_test_results $(RESULTS_FILE)
63+
python -m soil_id.tests.global.process_bulk_test_results $(RESULTS_FILE)
6464

6565
# Donwload Munsell CSV, SHX, SHP, SBX, SBN, PRJ, DBF
6666
download-soil-data:

soil_id/db.py

Lines changed: 19 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,6 @@
2727
# local libraries
2828
import soil_id.config
2929

30-
from .utils import get_target_utm_srid
31-
32-
3330
def get_datastore_connection():
3431
"""
3532
Establish a connection to the datastore using app configurations.
@@ -208,9 +205,11 @@ def get_hwsd2_profile_data(conn, hwsd2_mu_select):
208205
logging.error(f"Error querying PostgreSQL: {err}")
209206
return pd.DataFrame()
210207

208+
211209
def extract_hwsd2_data(lon, lat, buffer_dist, table_name):
212210
"""
213-
Fetches HWSD soil data from a PostGIS table within a given buffer around a point.
211+
Fetches HWSD soil data from a PostGIS table within a given buffer around a point,
212+
performing distance and intersection calculations directly on geographic coordinates.
214213
215214
Parameters:
216215
lon (float): Longitude of the problem point.
@@ -221,35 +220,30 @@ def extract_hwsd2_data(lon, lat, buffer_dist, table_name):
221220
Returns:
222221
DataFrame: Merged data from hwsdv2 and hwsdv2_data.
223222
"""
224-
# Determine target UTM SRID as an integer (e.g., 32642)
225-
target_srid = get_target_utm_srid(lat, lon)
226-
227223
# Use a single connection for both queries.
228224
with get_datastore_connection() as conn:
229225
# Compute the buffer polygon (in WKT) around the problem point.
226+
# Here, we use the geography type to compute a buffer in meters,
227+
# then cast it back to geometry in EPSG:4326.
230228
buffer_query = """
231229
WITH buffer AS (
232230
SELECT ST_AsText(
233-
ST_Transform(
234-
ST_Buffer(
235-
ST_Transform(
236-
ST_SetSRID(ST_Point(%s, %s), 4326),
237-
%s
238-
),
239-
%s
240-
),
241-
4326
242-
)
231+
ST_Buffer(
232+
ST_SetSRID(ST_Point(%s, %s), 4326)::geography,
233+
%s
234+
)::geometry
243235
) AS wkt
244236
)
245237
SELECT wkt FROM buffer;
246238
"""
247239
with conn.cursor() as cur:
248-
cur.execute(buffer_query, (lon, lat, target_srid, buffer_dist))
240+
cur.execute(buffer_query, (lon, lat, buffer_dist))
249241
buffer_wkt = cur.fetchone()[0]
250242
print("Buffer WKT:", buffer_wkt)
251243

252244
# Build the main query that uses the computed buffer.
245+
# Distance is computed by casting geometries to geography,
246+
# which returns the geodesic distance in meters.
253247
main_query = f"""
254248
WITH valid_geom AS (
255249
SELECT
@@ -261,19 +255,19 @@ def extract_hwsd2_data(lon, lat, buffer_dist, table_name):
261255
)
262256
SELECT
263257
hwsd2,
264-
ST_AsEWKB(ST_Transform(geom, {target_srid})) AS geom,
258+
ST_AsEWKB(geom) AS geom,
265259
ST_Distance(
266-
ST_Transform(geom, {target_srid}),
267-
ST_Transform(ST_SetSRID(ST_Point({lon}, {lat}), 4326), {target_srid})
260+
geom::geography,
261+
ST_SetSRID(ST_Point({lon}, {lat}), 4326)::geography
268262
) AS distance,
269263
ST_Intersects(
270-
ST_Transform(geom, {target_srid}),
271-
ST_Transform(ST_SetSRID(ST_Point({lon}, {lat}), 4326), {target_srid})
264+
geom,
265+
ST_SetSRID(ST_Point({lon}, {lat}), 4326)
272266
) AS pt_intersect
273267
FROM valid_geom
274268
WHERE ST_Intersects(
275-
ST_Transform(geom, {target_srid}),
276-
ST_Transform(ST_SetSRID(ST_Point({lon}, {lat}), 4326), {target_srid})
269+
geom,
270+
ST_SetSRID(ST_Point({lon}, {lat}), 4326)
277271
);
278272
"""
279273

soil_id/global_soil.py

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -79,12 +79,15 @@ class SoilListOutputData:
7979
##################################################################################################
8080
def list_soils_global(lon, lat):
8181
# Extract HWSD2 Data
82-
hwsd2_data = extract_hwsd2_data(
83-
lon,
84-
lat,
85-
table_name="hwsdv2",
86-
buffer_dist=10000,
87-
)
82+
try:
83+
hwsd2_data = extract_hwsd2_data(
84+
lon,
85+
lat,
86+
table_name="hwsdv2",
87+
buffer_dist=10000,
88+
)
89+
except KeyError:
90+
return("Soil map information is not available at this location")
8891

8992
# Component Data
9093
mucompdata_pd = hwsd2_data[["hwsd2", "fao90_name", "distance", "share", "compid"]]
@@ -556,7 +559,8 @@ def rank_soils_global(
556559
lat,
557560
list_output_data: SoilListOutputData,
558561
soilHorizon,
559-
horizonDepth,
562+
topDepth,
563+
bottomDepth,
560564
rfvDepth,
561565
lab_Color,
562566
bedrock,
@@ -568,7 +572,8 @@ def rank_soils_global(
568572
soil_df = pd.DataFrame(
569573
{
570574
"soilHorizon": soilHorizon,
571-
"horizonDepth": horizonDepth,
575+
"top": topDepth,
576+
"bottom": bottomDepth,
572577
"rfvDepth": rfvDepth,
573578
"lab_Color": lab_Color,
574579
}
@@ -577,15 +582,9 @@ def rank_soils_global(
577582
# Drop rows where all values are NaN
578583
soil_df.dropna(how="all", inplace=True)
579584

580-
# Set the bottom of each horizon
581-
soil_df["bottom"] = soil_df["horizonDepth"]
582-
583585
# Replace NaNs with None for consistency
584586
# soil_df.fillna(value=None, inplace=True)
585587

586-
# Calculate the top depth for each horizon
587-
soil_df["top"] = [0] + soil_df["horizonDepth"].iloc[:-1].tolist()
588-
589588
# Adjust the bottom depth based on bedrock depth
590589
if bedrock is not None:
591590
if bedrock is not soil_df.empty and soil_df["bottom"].iloc[-1] > bedrock:
@@ -596,9 +595,6 @@ def rank_soils_global(
596595
# Set the bottom depth of the last row to the bedrock depth
597596
soil_df.at[last_valid_index, "bottom"] = bedrock
598597

599-
# Drop the original horizonDepth column
600-
soil_df.drop(columns=["horizonDepth"], inplace=True)
601-
602598
# Filter out rows without valid horizon data
603599
relevant_columns = ["soilHorizon", "rfvDepth", "lab_Color"]
604600
soil_df_slice = soil_df.dropna(how="all", subset=relevant_columns)
@@ -623,8 +619,8 @@ def rank_soils_global(
623619
# Convert soil properties to lists
624620
soilHorizon = soil_df.soilHorizon.tolist()
625621
rfvDepth = soil_df.rfvDepth.tolist()
626-
horizonDepthB = [int(x) for x in soil_df.bottom.tolist()]
627-
horizonDepthT = [int(x) for x in soil_df.top.tolist()]
622+
bottom = [int(x) for x in soil_df.bottom.tolist()]
623+
top = [int(x) for x in soil_df.top.tolist()]
628624
lab_Color = soil_df.lab_Color
629625

630626
# Generate user specified percent clay, sand, and rfv distributions
@@ -635,17 +631,17 @@ def rank_soils_global(
635631
p_sandpct_intpl = [
636632
spt[i]
637633
for i in range(len(soilHorizon))
638-
for _ in range(horizonDepthT[i], horizonDepthB[i])
634+
for _ in range(top[i], bottom[i])
639635
]
640636
p_claypct_intpl = [
641637
cpt[i]
642638
for i in range(len(soilHorizon))
643-
for _ in range(horizonDepthT[i], horizonDepthB[i])
639+
for _ in range(top[i], bottom[i])
644640
]
645641
p_cfg_intpl = [
646642
p_cfg[i]
647643
for i in range(len(soilHorizon))
648-
for _ in range(horizonDepthT[i], horizonDepthB[i])
644+
for _ in range(top[i], bottom[i])
649645
]
650646

651647
# Length of interpolated texture and RF depth
@@ -657,7 +653,7 @@ def rank_soils_global(
657653
if not lab_Color.isnull().all():
658654
lab_Color = [[np.nan, np.nan, np.nan] if x is None else x for x in lab_Color]
659655
lab_Color = pd.DataFrame(lab_Color)
660-
pedon_LAB = pedon_color(lab_Color, horizonDepth)
656+
pedon_LAB = pedon_color(lab_Color, top, bottom)
661657

662658
if not np.isnan(pedon_LAB).all():
663659
refs = {
@@ -840,8 +836,8 @@ def rank_soils_global(
840836
dis_max = max(map(np.nanmax, dis_mat_list))
841837

842838
# Apply depth weight
843-
depth_weight = np.concatenate([np.repeat(0.2, 20), np.repeat(1.0, 80)])
844-
depth_weight = depth_weight[: len(soil_matrix)]
839+
depth_weight = np.concatenate([np.repeat(0.2, 20), np.repeat(1.0, 180)])
840+
depth_weight = depth_weight[soil_matrix.index]
845841

846842
# Infill NaN data
847843
for idx, dis_mat in enumerate(dis_mat_list):

soil_id/tests/global/generate_bulk_test_results.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@
6060
lat=lat,
6161
lon=lon,
6262
list_output_data=list_result,
63-
horizonDepth=pedon["BOTDEP"].values.tolist(),
63+
topDepth=pedon["TOPDEP"].values.tolist(),
64+
bottomDepth=pedon["BOTDEP"].values.tolist(),
6465
soilHorizon=pedon["textClass"].values.tolist(),
6566
rfvDepth=pedon["RFV"].values.tolist(),
6667
lab_Color=pedon[["L", "A", "B"]].values.tolist(),

soil_id/tests/global/test_global.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ def test_soil_location():
3838
item["lat"],
3939
list_output_data=list_soils_result,
4040
soilHorizon=["Loam"],
41-
horizonDepth=[15],
41+
topDepth=[15],
42+
bottomDepth=[45],
4243
rfvDepth=[20],
4344
lab_Color=[[41.23035939, 3.623018224, 13.27654356]],
4445
bedrock=None,

0 commit comments

Comments
 (0)