Skip to content

Commit

Permalink
set up properly for situations with no ecoclasses due to lack of EDIT…
Browse files Browse the repository at this point in the history
… data. Dealing with a really weird bug where titiler is serving geology when I go to dome - I had previously uploaded the wrong boundary for dome so I believe its a titiler caching issue. Suspect it maaaay resolve when this push triggers a rebuild
  • Loading branch information
GondekNP committed Jan 17, 2024
1 parent b36dc41 commit e6af561
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 26 deletions.
42 changes: 27 additions & 15 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from pydantic import BaseModel
from google.cloud import logging
import tempfile
from typing import Tuple, List
from typing import Tuple, List, Any
from pydantic import BaseModel
import pandas as pd

Expand Down Expand Up @@ -104,7 +104,7 @@ def get_manifest(sfpt_client: SFTPClient = Depends(get_sftp_client)):

### API ENDPOINTS ###

@app.get("/api/available-cogs")
@app.get("/api/query-satellite/available-cogs")
def available_cogs(sftp_client: SFTPClient = Depends(get_sftp_client)):
try:
sftp_client.update_available_cogs()
Expand All @@ -120,15 +120,14 @@ def available_cogs(sftp_client: SFTPClient = Depends(get_sftp_client)):
return f"Error: {e}", 400

class AnaylzeBurnPOSTBody(BaseModel):
geojson: dict
geojson: Any
date_ranges: dict
fire_event_name: str
affiliation: str

@app.post("/api/analyze-burn")
@app.post("/api/query-satellite/analyze-burn")
def analyze_burn(body: AnaylzeBurnPOSTBody, sftp_client: SFTPClient = Depends(get_sftp_client)):
# geojson = json.loads(body.geojson)
geojson = body.geojson
geojson = json.loads(body.geojson)

date_ranges = body.date_ranges
fire_event_name = body.fire_event_name
Expand Down Expand Up @@ -170,7 +169,7 @@ def analyze_burn(body: AnaylzeBurnPOSTBody, sftp_client: SFTPClient = Depends(ge
return f"Error: {e}", 400

class QuerySoilPOSTBody(BaseModel):
geojson: dict
geojson: Any
fire_event_name: str
affiliation: str

Expand Down Expand Up @@ -203,30 +202,43 @@ def get_ecoclass_info(ecoclassid: str = Query(...)):
@app.post("/api/query-soil/analyze-ecoclass")
def analyze_ecoclass(body: QuerySoilPOSTBody, sftp_client: SFTPClient = Depends(get_sftp_client)):
fire_event_name = body.fire_event_name
geojson = body.geojson
geojson = json.loads(body.geojson)
affiliation = body.affiliation

try:
mapunit_gdf = sdm_get_esa_mapunitid_poly(geojson)
# mu_pair_tuples = [(musynm, nationalmusym) for musynm, nationalmusym, __mukey in mapunit_gdf.index.to_list()]
mu_polygon_keys = mapunit_gdf.mupolygonkey.to_list()
mu_polygon_keys = [mupolygonkey for __musym, __nationalmusym, __mukey, mupolygonkey in mapunit_gdf.index]
mrla_df = sdm_get_ecoclassid_from_mu_info(mu_polygon_keys)

# join mapunitids with link table for ecoclassids
mapunit_with_ecoclassid_df = mapunit_gdf.join(mrla_df).set_index('ecoclassid')

edit_ecoclass_df_row_dicts = []
for ecoclass_id in mrla_df['ecoclassid'].unique():
ecoclass_ids = mrla_df['ecoclassid'].unique()

n_ecoclasses = len(ecoclass_ids)
n_within_edit = 0

for ecoclass_id in ecoclass_ids:
edit_success, edit_ecoclass_json = edit_get_ecoclass_info(ecoclass_id)
if edit_success:
n_within_edit += 1
logger.log_text(f"Success: {ecoclass_id} exists within EDIT backend")
edit_ecoclass_df_row_dict = edit_ecoclass_json['generalInformation']['dominantSpecies']
edit_ecoclass_df_row_dict['ecoclassid'] = ecoclass_id
edit_ecoclass_df_row_dicts.append(edit_ecoclass_df_row_dict)
else:
logger.log_text(f"Missing: {edit_ecoclass_json} doesn't exist within EDIT backend")
edit_ecoclass_df = pd.DataFrame(edit_ecoclass_df_row_dicts).set_index('ecoclassid')

# join mapunitids with link table for ecoclassids
mapunit_with_ecoclassid_df = mapunit_gdf.join(mrla_df).set_index('ecoclassid')
mapunit_with_ecoclassid_df.drop(['spatialversion', 'MLRA', 'MLRA_Name'], axis = 'columns', inplace = True)
logger.log_text(f"Found {n_within_edit} of {n_ecoclasses} ecoclasses ({100*round(n_within_edit/n_ecoclasses, 2)}%) within EDIT backend")

if n_within_edit > 0:
edit_ecoclass_df = pd.DataFrame(edit_ecoclass_df_row_dicts).set_index('ecoclassid')
else:
# Populate with empty dataframe, for consistency's sake (so that the frontend doesn't have to handle this case)
edit_ecoclass_df = pd.DataFrame([], columns=
['dominantTree1', 'dominantShrub1', 'dominantHerb1', 'dominantTree2','dominantShrub2', 'dominantHerb2']
)

# join ecoclassids with edit ecoclass info, to get spatial ecoclass info
edit_ecoclass_geojson = mapunit_with_ecoclassid_df.join(edit_ecoclass_df, how='left').to_json()
Expand Down
17 changes: 9 additions & 8 deletions src/lib/query_soil.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import geopandas as gpd
import pandas as pd
import json
import time
from shapely.geometry import shape
from shapely.ops import transform
import xml.etree.ElementTree as ET
Expand Down Expand Up @@ -106,7 +107,8 @@ def sdm_get_esa_mapunitid_poly(geojson, backoff_max = 200, backoff_value = 0, ba
mapunit_gdf['musym'] = mapunit_gdf['musym'].astype(str)
mapunit_gdf['nationalmusym'] = mapunit_gdf['nationalmusym'].astype(str)
mapunit_gdf['mukey'] = mapunit_gdf['mukey'].astype(str)
mapunit_gdf.set_index(['musym', 'nationalmusym', 'mukey'], inplace=True)
mapunit_gdf['mupolygonkey'] = mapunit_gdf['mupolygonkey'].astype(str)
mapunit_gdf.set_index(['musym', 'nationalmusym', 'mukey', 'mupolygonkey'], inplace=True)

return mapunit_gdf

Expand All @@ -119,6 +121,7 @@ def sdm_get_esa_mapunitid_poly(geojson, backoff_max = 200, backoff_value = 0, ba
print(f"Backoff: {backoff_value}")
if backoff_value < backoff_max:
backoff_value += backoff_increment
time.sleep(backoff_value)
return sdm_get_esa_mapunitid_poly(geojson, backoff_value=backoff_value)
else:
raise Exception("SDM Refused Traffic. Backoff max reached.")
Expand All @@ -145,11 +148,6 @@ def sdm_get_ecoclassid_from_mu_info(mu_polygon_keys):
INNER JOIN coecoclass ON c.cokey = coecoclass.cokey AND coecoclass.ecoclassref = 'Ecological Site Description Database'
GROUP BY ecoclassid, ecoclassname, muname, mu.mukey, mup.mupolygonkey, mu.musym, mu.nationalmusym, legend.areasymbol, legend.areaname
"""
# mu_pairs = [mu_info.mu_pair for mu_info in mu_info_list]

# TODO: Hacky SQL 98 solution to lack of tuples (should revist)
# conditions = ' OR '.join("(musym = {} AND nationalmusym = '{}')".format(nationalmusym, musym) for nationalmusym, musym in mu_info_list)
# query = SQL_QUERY.format(conditions)
in_mu_polygon_keys_list = ','.join([str(key) for key in mu_polygon_keys])
query = SQL_QUERY.format(in_mu_polygon_keys_list)
query = ' '.join(query.split()) # remove newlines and extra spaces
Expand All @@ -169,7 +167,8 @@ def sdm_get_ecoclassid_from_mu_info(mu_polygon_keys):
mu_info_df['mukey'] = mu_info_df['mukey'].astype(str)
mu_info_df['musym'] = mu_info_df['musym'].astype(str)
mu_info_df['nationalmusym'] = mu_info_df['nationalmusym'].astype(str)
mu_info_df.set_index(['musym', 'nationalmusym', 'mukey'], inplace=True)
mu_info_df['mupolygonkey'] = mu_info_df['mupolygonkey'].astype(str)
mu_info_df.set_index(['musym', 'nationalmusym', 'mukey', 'mupolygonkey'], inplace=True)

return mu_info_df
else:
Expand All @@ -183,14 +182,16 @@ def edit_get_ecoclass_info(ecoclass_id):
response = requests.get(edit_endpoint_fmt)

if response.status_code == 200:
print(f"Successfully obtained from EDIT database: {ecoclass_id}")

edit_json = json.loads(response.content)

# Add hyperlink to EDIT human readable page
edit_json['hyperlink'] = f"https://edit.jornada.nmsu.edu/catalogs/esd/{geoUnit}/{ecoclass_id}"

return True, edit_json
elif response.status_code == 404:
print(f"EcoClass ID not found within EDIT database:, {ecoclass_id}")
print(f"EcoClass ID not found within EDIT database: {ecoclass_id}")
return False, {"error": f"EcoClass ID not found within EDIT database: {ecoclass_id}"}
else:
print("Error:", response.status_code)
Expand Down
7 changes: 4 additions & 3 deletions src/static/upload.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,13 @@

<div id="ecoclass-analysis-loading" style="display: none;">
<img src="/static/spinner.gif" alt="Analyzing ecoclassification... depending on AOI size, this may take several minutes." />
<script>
</div>

<div id="ecoclass-analysis-success" style="display: none;">
<img src="/static/checkmark.png" alt="EDIT Ecoclass Analysis Success!" />
</div>

<script>
$("#fire-analysis-form").on("submit", function(event) {
event.preventDefault();

Expand Down Expand Up @@ -74,7 +75,7 @@

// Make a request to analyze the burn
$.ajax({
url: '/api/analyze-burn',
url: '/api/query-satellite/analyze-burn',
type: 'post',
dataType: 'json',
contentType: 'application/json',
Expand All @@ -97,7 +98,7 @@

// Make a request to analyze the ecoclassification
$.ajax({
url: '/api/analyze-ecoclass',
url: '/api/query-soil/analyze-ecoclass',
type: 'post',
dataType: 'json',
contentType: 'application/json',
Expand Down

0 comments on commit e6af561

Please sign in to comment.