Skip to content
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
56 changes: 51 additions & 5 deletions computing/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -1512,25 +1512,71 @@ def generate_ndvi_timeseries(request):
def generate_zoi_to_gee(request):
print("Inside generate zoi layers")
try:
state = request.data.get("state").lower()
district = request.data.get("district").lower()
block = request.data.get("block").lower()
state = request.data.get("state")
district = request.data.get("district")
block = request.data.get("block")
gee_account_id = request.data.get("gee_account_id")
start_date = request.data.get("start_date") or request.data.get("startDate")
end_date = request.data.get("end_date") or request.data.get("endDate")
start_year = request.data.get("start_year") or request.data.get("startYear")
end_year = request.data.get("end_year") or request.data.get("endYear")

if not state or not district or not block:
return Response(
{"error": "state, district, and block are required."},
status=status.HTTP_400_BAD_REQUEST,
)

# Allow start_year/end_year as hydrological-year shorthand.
if not start_date and start_year is not None:
start_date = f"{int(start_year)}-07-01"
if not end_date and end_year is not None:
end_date = f"{int(end_year) + 1}-06-30"

if not start_date or not end_date:
return Response(
{
"error": (
"start_date and end_date are required (YYYY-MM-DD), "
"or provide start_year and end_year (hydrological years)."
)
},
status=status.HTTP_400_BAD_REQUEST,
)

from computing.zoi_layers.zoi import _resolve_zoi_time_window

try:
start_date, end_date, _, _ = _resolve_zoi_time_window(start_date, end_date)
except ValueError as exc:
return Response({"error": str(exc)}, status=status.HTTP_400_BAD_REQUEST)

state = state.lower()
district = district.lower()
block = block.lower()

generate_zoi.apply_async(
kwargs={
"state": state,
"district": district,
"block": block,
"gee_account_id": gee_account_id,
"start_date": start_date,
"end_date": end_date,
},
queue="waterbody",
)

return Response(
{"Success": "Successfully initiated"}, status=status.HTTP_200_OK
{
"Success": "Successfully initiated",
"start_date": start_date,
"end_date": end_date,
},
status=status.HTTP_200_OK,
)
except Exception as e:
print("Exception in generate_mining_to_gee api :: ", e)
print("Exception in generate_zoi_to_gee api :: ", e)
return Response({"Exception": e}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)


Expand Down
9 changes: 8 additions & 1 deletion computing/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,8 +353,15 @@ def get_agri_year_key(season_key):


def calculate_precipitation_season(
geojson_filepath, draught_asset_id, start_year=2017, end_year=2024
geojson_filepath, draught_asset_id, start_year=None, end_year=None
):
if start_year is None or end_year is None:
raise ValueError(
"start_year and end_year are required for calculate_precipitation_season."
)
start_year = int(start_year)
end_year = int(end_year)

# Load the GeoJSON file
with open(geojson_filepath, "r") as f:
feature_collection = json.load(f)
Expand Down
60 changes: 56 additions & 4 deletions computing/zoi_layers/zoi.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,47 @@
from datetime import datetime

from computing.zoi_layers.zoi1 import generate_zoi1
from computing.zoi_layers.zoi2 import generate_zoi_ci
from computing.zoi_layers.zoi3 import get_ndvi_for_zoi
from projects.models import Project
from utilities.gee_utils import ee_initialize, valid_gee_text, check_task_status
from waterrejuvenation.utils import wait_for_task_completion, delete_asset_on_GEE
from nrm_app.celery import app
from projects.models import Project
from utilities.gee_utils import ee_initialize, valid_gee_text


def _resolve_zoi_time_window(start_date=None, end_date=None):
"""
Validate and normalize ZOI date window.

Requires explicit start_date and end_date (YYYY-MM-DD). No year defaults —
callers must provide the analysis window.
"""
if not start_date or not end_date:
raise ValueError(
"start_date and end_date are required (YYYY-MM-DD). "
"Pass both parameters explicitly; no default date window is applied."
)

start_date = str(start_date).strip()
end_date = str(end_date).strip()

try:
start_dt = datetime.strptime(start_date, "%Y-%m-%d")
end_dt = datetime.strptime(end_date, "%Y-%m-%d")
except ValueError as exc:
raise ValueError("start_date and end_date must be in YYYY-MM-DD format.") from exc

if start_dt > end_dt:
raise ValueError("start_date must be less than or equal to end_date.")

# ZOI CI/NDVI use hydrological years (July -> June), represented by start-year.
start_year = start_dt.year if start_dt.month >= 7 else start_dt.year - 1
end_year = end_dt.year if end_dt.month >= 7 else end_dt.year - 1
if start_year > end_year:
raise ValueError(
"Provided date window does not contain a valid hydrological year."
)

return start_date, end_date, start_year, end_year


@app.task()
Expand All @@ -18,6 +55,8 @@ def generate_zoi(
app_type="MWS",
gee_account_id=None,
proj_id=None,
start_date=None,
end_date=None,
):
print(f"gee account id {gee_account_id}")
ee_initialize(gee_account_id)
Expand All @@ -31,6 +70,10 @@ def generate_zoi(
asset_folder_list = [proj_obj.name.lower()]
asset_suffix = f"{proj_obj.name}_{proj_obj.id}".lower()

start_date, end_date, start_year, end_year = _resolve_zoi_time_window(
start_date, end_date
)

generate_zoi1(
state,
district,
Expand All @@ -41,6 +84,8 @@ def generate_zoi(
app_type,
gee_account_id,
proj_id,
start_date=start_date,
end_date=end_date,
)

generate_zoi_ci(
Expand All @@ -52,10 +97,13 @@ def generate_zoi(
app_type,
gee_account_id,
proj_id,
start_date=start_date,
end_date=end_date,
start_year=start_year,
end_year=end_year,
)

if proj_id:

get_ndvi_for_zoi(
state=state,
district=district,
Expand All @@ -65,4 +113,8 @@ def generate_zoi(
app_type=app_type,
gee_account_id=gee_account_id,
proj_id=proj_id,
start_date=start_date,
end_date=end_date,
start_year=start_year,
end_year=end_year,
)
47 changes: 31 additions & 16 deletions computing/zoi_layers/zoi1.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@
ee_initialize,
valid_gee_text,
get_gee_dir_path,
is_gee_asset_exists,
export_vector_asset_to_gee,
make_asset_public,
check_task_status,
Expand All @@ -36,6 +35,7 @@
calculate_zoi_area,
wait_for_task_completion,
delete_asset_on_GEE,
_waterbody_area_ha,
)
from computing.surface_water_bodies.swb import sync_asset_to_db_and_geoserver

Expand All @@ -50,8 +50,14 @@ def generate_zoi1(
app_type="MWS",
gee_account_id=None,
proj_id=None,
start_date=None,
end_date=None,
):
print("insdie zoi")
if not start_date or not end_date:
raise ValueError(
"start_date and end_date are required for ZOI generation (YYYY-MM-DD)."
)
ee_initialize(gee_account_id)
description = "swb3_" + asset_suffix
asset_id = (
Expand All @@ -74,15 +80,12 @@ def generate_zoi1(
+ description_zoi
)
delete_asset_on_GEE(asset_id_zoi)
start_date = "2017-07-01"
end_date = "2025-06-30"
zoi_fc = roi.map(compute_zoi)
zoi_fc = ee.FeatureCollection(zoi_fc)
zoi_rings = zoi_fc.filter(ee.Filter.gt("zoi_wb", 0)).map(create_ring)
if not is_gee_asset_exists(asset_id_zoi):
zoi_task = export_vector_asset_to_gee(zoi_rings, description_zoi, asset_id_zoi)
check_task_status([zoi_task])
make_asset_public(asset_id_zoi)
zoi_task = export_vector_asset_to_gee(zoi_rings, description_zoi, asset_id_zoi)
check_task_status([zoi_task])
make_asset_public(asset_id_zoi)
if state and district and block:
layer_name = f"waterbodies_zoi_{asset_suffix}"
print(layer_name)
Expand All @@ -103,13 +106,6 @@ def generate_zoi1(
sync_project_fc_to_geoserver(zoi_rings, proj_obj.name, layer_name, "zoi_layers")


def _waterbody_area_ha(feature):
"""Area in hectares; use geometry when area_ored is missing (e.g. water rej layers)."""
geom_area_ha = ee.Number(feature.geometry().area(maxError=1)).divide(10000)
stored_area = feature.get("area_ored")
return ee.Number(ee.Algorithms.If(stored_area, stored_area, geom_area_ha))


def compute_zoi(feature):

area_of_wb = _waterbody_area_ha(feature)
Expand All @@ -136,13 +132,32 @@ def y_large_bodies(area):
.add(s.multiply(y_large_bodies(area_of_wb)).round())
)

return feature.set("zoi_wb", zoi)
return feature.set("zoi_wb", zoi).set(
"UID",
ee.Algorithms.If(
feature.get("UID"),
feature.get("UID"),
ee.Algorithms.If(
feature.get("uid"),
feature.get("uid"),
feature.get("MWS_UID"),
),
),
)


def create_ring(feature):
geom = feature.geometry() # can be point or polygon
zoi = ee.Number(feature.get("zoi_wb"))
uid = feature.get("UID")
uid = ee.Algorithms.If(
feature.get("UID"),
feature.get("UID"),
ee.Algorithms.If(
feature.get("uid"),
feature.get("uid"),
feature.get("MWS_UID"),
),
)

# Make circle buffer from centroid
centroid = geom.centroid()
Expand Down
31 changes: 19 additions & 12 deletions computing/zoi_layers/zoi2.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,20 @@ def generate_zoi_ci(
gee_account_id=None,
proj_id=None,
roi=None,
start_date=None,
end_date=None,
start_year=None,
end_year=None,
):
from computing.cropping_intensity.cropping_intensity import (
generate_cropping_intensity,
)

if not start_date or not end_date or start_year is None or end_year is None:
raise ValueError(
"start_date, end_date, start_year, and end_year are required for ZOI CI."
)

if state and district and block:
asset_suffix = (
valid_gee_text(district.lower()) + "_" + valid_gee_text(block.lower())
Expand All @@ -46,6 +55,14 @@ def generate_zoi_ci(
+ description_ci
)
delete_asset_on_GEE(asset_id_ci)
description_zoi_ci = f"cropping_intensity_zoi_{asset_suffix}"
asset_id_zoi_ci = (
get_gee_dir_path(
asset_folder_list, asset_path=GEE_PATHS[app_type]["GEE_ASSET_PATH"]
)
+ description_zoi_ci
)
delete_asset_on_GEE(asset_id_zoi_ci)
if roi:
roi = ee.FeatureCollection(roi)
else:
Expand All @@ -56,20 +73,10 @@ def generate_zoi_ci(
asset_folder_list=asset_folder_list,
asset_suffix=asset_suffix,
app_type=app_type,
start_year=2017,
end_year=2024,
start_year=start_year,
end_year=end_year,
gee_account_id=gee_account_id,
)
start_date = "2017-07-01"
end_date = "2025-06-30"
description_zoi_ci = f"cropping_intensity_zoi_{asset_suffix}"

asset_id_zoi_ci = (
get_gee_dir_path(
asset_folder_list, asset_path=GEE_PATHS[app_type]["GEE_ASSET_PATH"]
)
+ description_zoi_ci
)
if state and district and block:
layer_name = f"waterbodies_zoi_{asset_suffix}"
layer_at_geoserver = sync_asset_to_db_and_geoserver(
Expand Down
Loading