Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Perform local lat/lon check against GeoTIFF coverage masks to check for nodata before fetching from Rasdaman #553

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added geotiffs/air_freezing_index_Fdays.tif
Binary file not shown.
Binary file added geotiffs/air_thawing_index_Fdays.tif
Binary file not shown.
Binary file added geotiffs/annual_mean_temp.tif
Binary file not shown.
Binary file added geotiffs/annual_precip_totals_mm.tif
Binary file not shown.
Binary file added geotiffs/ardac_beaufort_daily_slie.tif
Binary file not shown.
Binary file added geotiffs/ardac_chukchi_daily_slie.tif
Binary file not shown.
Binary file added geotiffs/beetle_risk.tif
Binary file not shown.
Binary file added geotiffs/crrel_gipl_outputs.tif
Binary file not shown.
Binary file added geotiffs/degree_days_below_zero_Fdays.tif
Binary file not shown.
Binary file added geotiffs/dot_precip.tif
Binary file not shown.
Binary file added geotiffs/heating_degree_days_Fdays.tif
Binary file not shown.
Binary file added geotiffs/hsia_arctic_production.tif
Binary file not shown.
Binary file added geotiffs/hydrology.tif
Binary file not shown.
Binary file added geotiffs/iem_ar5_2km_taspr_seasonal.tif
Binary file not shown.
Binary file not shown.
Binary file added geotiffs/jan_min_max_mean_temp.tif
Binary file not shown.
Binary file added geotiffs/july_min_max_mean_temp.tif
Binary file not shown.
Binary file added geotiffs/mean_annual_snowfall_mm.tif
Binary file not shown.
Binary file added geotiffs/ncar12km_indicators_era_summaries.tif
Binary file not shown.
Binary file added geotiffs/tas_2km_historical.tif
Binary file not shown.
Binary file added geotiffs/tas_2km_projected.tif
Binary file not shown.
Binary file added geotiffs/wet_days_per_year.tif
Binary file not shown.
5 changes: 5 additions & 0 deletions luts.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,11 @@

bbox_offset = 0.000000001

# Coverages with non-EPSG:3338 projections
geotiff_projections = {
"hsia_arctic_production": "EPSG:3572",
}

landcover_names = {
0: {"type": "No Data at this location.", "color": "#ffffff"},
1: {"type": "Temperate or sub-polar needleleaf forest", "color": "#003d00"},
Expand Down
7 changes: 6 additions & 1 deletion routes/beetles.py
Original file line number Diff line number Diff line change
Expand Up @@ -367,9 +367,14 @@ def run_point_fetch_all_beetles(lat, lon):
Returns:
JSON-like dict of beetle risk for a single lat / lon point.
"""
validation = validate_latlon(lat, lon)
validation = validate_latlon(lat, lon, [beetle_coverage_id])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand Down
4 changes: 3 additions & 1 deletion routes/cmip6.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,9 @@ def run_fetch_cmip6_monthly_point_data(lat, lon, start_year=None, end_year=None)
if validation == 400:
return render_template("400/bad_request.html"), 400
cmip6_bbox = construct_latlon_bbox_from_coverage_bounds(metadata)
within_bounds = validate_latlon_in_bboxes(lat, lon, [cmip6_bbox])
within_bounds = validate_latlon_in_bboxes(
lat, lon, [cmip6_bbox], [cmip6_monthly_coverage_id]
)
if within_bounds == 422:
return (
render_template(
Expand Down
32 changes: 19 additions & 13 deletions routes/degree_days.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,12 @@ def run_fetch_dd_point_data(
Returns:
JSON-like dict of requested degree day data
"""
validation = validate_latlon(lat, lon)
if var_ep in var_ep_lu.keys():
cov_id_str = var_ep_lu[var_ep]["cov_id_str"]
else:
return render_template("400/bad_request.html"), 400

validation = validate_latlon(lat, lon, [cov_id_str])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 422:
Expand All @@ -394,25 +399,26 @@ def run_fetch_dd_point_data(
),
422,
)
elif validation == 404:
return (
render_template("404/no_data.html"),
404,
)
x, y = project_latlon(lat, lon, 3338)

if None not in [start_year, end_year]:
valid_year = validate_years(int(start_year), int(end_year))
if valid_year is not True:
return valid_year

if var_ep in var_ep_lu.keys():
cov_id_str = var_ep_lu[var_ep]["cov_id_str"]
try:
point_data = asyncio.run(
fetch_dd_point_data(x, y, cov_id_str, start_year, end_year)
)
except Exception as exc:
if hasattr(exc, "status") and exc.status == 404:
return render_template("404/no_data.html"), 404
return render_template("500/server_error.html"), 500
else:
return render_template("400/bad_request.html"), 400
try:
point_data = asyncio.run(
fetch_dd_point_data(x, y, cov_id_str, start_year, end_year)
)
except Exception as exc:
if hasattr(exc, "status") and exc.status == 404:
return render_template("404/no_data.html"), 404
return render_template("500/server_error.html"), 500

# if preview, return unabridged tidy package as CSV
# the preview arg is only used for CSV generation and should never occur with additional request args
Expand Down
7 changes: 6 additions & 1 deletion routes/hydrology.py
Original file line number Diff line number Diff line change
Expand Up @@ -362,9 +362,14 @@ def hydro_about():

@routes.route("/hydrology/point/<lat>/<lon>")
def run_get_hydrology_point_data(lat, lon, summarize=None, preview=None):
validation = validate_latlon(lat, lon)
validation = validate_latlon(lat, lon, [hydrology_coverage_id])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand Down
11 changes: 9 additions & 2 deletions routes/indicators.py
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,9 @@ def run_fetch_cmip6_indicators_point_data(lat, lon):
if validation == 400:
return render_template("400/bad_request.html"), 400
cmip6_bbox = construct_latlon_bbox_from_coverage_bounds(cmip6_metadata)
within_bounds = validate_latlon_in_bboxes(lat, lon, [cmip6_bbox])
within_bounds = validate_latlon_in_bboxes(
lat, lon, [cmip6_bbox], [cmip6_indicators_coverage_id]
)
if within_bounds == 422:
return (
render_template(
Expand Down Expand Up @@ -399,9 +401,14 @@ def run_fetch_base_indicators_point_data(lat, lon):
Notes:
example request: http://localhost:5000/indicators/base/point/65.06/-146.16
"""
validation = validate_latlon(lat, lon)
validation = validate_latlon(lat, lon, [indicators_coverage_id])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand Down
12 changes: 11 additions & 1 deletion routes/landfastice.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,17 @@ def run_point_fetch_all_landfastice(lat, lon):
# now construct bboxes to check if the point is within any coverage extent
beaufort_bbox = construct_latlon_bbox_from_coverage_bounds(beaufort_meta)
chukchi_bbox = construct_latlon_bbox_from_coverage_bounds(chukchi_meta)
within_bounds = validate_latlon_in_bboxes(lat, lon, [beaufort_bbox, chukchi_bbox])
within_bounds = validate_latlon_in_bboxes(
lat,
lon,
[beaufort_bbox, chukchi_bbox],
[beaufort_daily_slie_id, chukchi_daily_slie_id],
)
if within_bounds == 404:
return (
render_template("404/no_data.html"),
404,
)
if within_bounds == 422:
return (
render_template(
Expand Down
7 changes: 6 additions & 1 deletion routes/permafrost.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,9 +475,14 @@ async def fetch_gipl_1km_point_data(x, y, start_year, end_year, summarize, ncr):
async def run_fetch_gipl_1km_point_data(
lat, lon, start_year=None, end_year=None, summarize=None, preview=None, ncr=False
):
validation = validate_latlon(lat, lon)
validation = validate_latlon(lat, lon, coverages=[gipl_1km_coverage_id])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand Down
7 changes: 6 additions & 1 deletion routes/seaice.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,14 @@ def run_point_fetch_all_seaice(lat, lon):
Returns:
JSON-like dict of sea ice concentration data
"""
validation = validate_seaice_latlon(lat, lon)
validation = validate_seaice_latlon(lat, lon, [seaice_coverage_id])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand Down
7 changes: 6 additions & 1 deletion routes/snow.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,14 @@ def run_point_fetch_all_sfe(lat, lon, summarize=None, preview=None):
Returns:
JSON-like dict of SFE data
"""
validation = validate_latlon(lat, lon)
validation = validate_latlon(lat, lon, [sfe_coverage_id])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand Down
70 changes: 41 additions & 29 deletions routes/taspr.py
Original file line number Diff line number Diff line change
Expand Up @@ -1073,9 +1073,6 @@ def run_fetch_mmm_point_data(var_ep, lat, lon, cov_id, start_year, end_year):
Returns:
JSON-like dict of data at provided latitude and longitude
"""
if validate_latlon(lat, lon) is not True:
return None

x, y = project_latlon(lat, lon, 3338)

point_data_list = asyncio.run(
Expand All @@ -1092,7 +1089,7 @@ def run_fetch_mmm_point_data(var_ep, lat, lon, cov_id, start_year, end_year):
return point_pkg


async def run_fetch_tas_2km_point_data(lat, lon):
async def run_fetch_tas_2km_point_data(lat, lon, coverages):
"""Run the async tas/pr data requesting for a single point
and return data as json

Expand All @@ -1103,16 +1100,11 @@ async def run_fetch_tas_2km_point_data(lat, lon):
Returns:
JSON-like dict of data at provided latitude and longitude
"""
if validate_latlon(lat, lon) is not True:
return None

x, y = project_latlon(lat, lon, 3338)

tasks = []
for coverage in ["historical", "projected"]:
tasks.append(
asyncio.create_task(fetch_wcs_point_data(x, y, f"tas_2km_{coverage}"))
)
for coverage in coverages:
tasks.append(asyncio.create_task(fetch_wcs_point_data(x, y, coverage)))
results = await asyncio.gather(*tasks)

point_pkg = package_tas_2km_point_data(results)
Expand All @@ -1133,8 +1125,7 @@ def run_fetch_var_point_data(var_ep, lat, lon):
Returns:
JSON-like dict of data at provided latitude and longitude
"""
if validate_latlon(lat, lon) is not True:
return None
cov_ids, summary_decades = make_fetch_args()

varname = var_ep_lu[var_ep]
# get the coordinate value for the specified variable
Expand All @@ -1150,7 +1141,6 @@ def run_fetch_var_point_data(var_ep, lat, lon):
# order of listing: CRU (1950-2009), AR5 2040-2069 summary,
# AR5 2070-2099 summary, AR5 seasonal data
# query CRU baseline summary
cov_ids, summary_decades = make_fetch_args()
point_data_list = asyncio.run(
fetch_point_data(x, y, var_coord, cov_ids, summary_decades)
)
Expand Down Expand Up @@ -1456,17 +1446,6 @@ def mmm_point_data_endpoint(
example request: http://localhost:5000/jan/65.0628/-146.1627
"""

validation = validate_latlon(lat, lon)
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 422:
return (
render_template(
"422/invalid_latlon.html", west_bbox=WEST_BBOX, east_bbox=EAST_BBOX
),
422,
)

if month is not None:
if month == "jan":
cov_id = "jan_min_max_mean_temp"
Expand All @@ -1487,6 +1466,22 @@ def mmm_point_data_endpoint(
if validation == 400:
return render_template("400/bad_request.html"), 400

validation = validate_latlon(lat, lon, [cov_id])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
"422/invalid_latlon.html", west_bbox=WEST_BBOX, east_bbox=EAST_BBOX
),
422,
)

# validate request args before fetching data
if len(request.args) == 0:
pass # no additional request args will be passed to the run_fetch_mmm_point_data function
Expand Down Expand Up @@ -1584,9 +1579,15 @@ def tas_2km_point_data_endpoint(lat, lon):
example request: http://localhost:5000/tas2km/point/65.0628/-146.1627
"""

validation = validate_latlon(lat, lon)
coverages = ["tas_2km_historical", "tas_2km_projected"]
validation = validate_latlon(lat, lon, coverages)
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand All @@ -1605,7 +1606,7 @@ def tas_2km_point_data_endpoint(lat, lon):
return render_template("400/bad_request.html"), 400

try:
point_pkg = asyncio.run(run_fetch_tas_2km_point_data(lat, lon))
point_pkg = asyncio.run(run_fetch_tas_2km_point_data(lat, lon, coverages))
except Exception as exc:
if hasattr(exc, "status") and exc.status == 404:
return render_template("404/no_data.html"), 404
Expand Down Expand Up @@ -1637,9 +1638,15 @@ def point_data_endpoint(lat, lon):
example request: http://localhost:5000/temperature/point/65.0628/-146.1627
"""

validation = validate_latlon(lat, lon)
cov_ids, _ = make_fetch_args()
validation = validate_latlon(lat, lon, cov_ids)
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand Down Expand Up @@ -1745,9 +1752,14 @@ def taspr_area_data_endpoint(var_id):

@routes.route("/precipitation/frequency/point/<lat>/<lon>")
def proj_precip_point(lat, lon):
validation = validate_latlon(lat, lon)
validation = validate_latlon(lat, lon, [dot_precip_coverage_id])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand Down
7 changes: 6 additions & 1 deletion routes/wet_days_per_year.py
Original file line number Diff line number Diff line change
Expand Up @@ -306,9 +306,14 @@ def run_fetch_wet_days_per_year_point_data(
Notes:
example request: http://localhost:5000/mmm/wet_days_per_year/all/65/-147
"""
validation = validate_latlon(lat, lon)
validation = validate_latlon(lat, lon, ["wet_days_per_year"])
if validation == 400:
return render_template("400/bad_request.html"), 400
if validation == 404:
return (
render_template("404/no_data.html"),
404,
)
if validation == 422:
return (
render_template(
Expand Down
Loading