1+ """
2+ Module: generate_PTJPLSM_raster_inputs.py
3+ ----------------------------------------
4+ This module provides a function to generate all required raster inputs for the PT-JPL-SM model.
5+ It loads or computes all necessary variables from spatial data sources and meteorological data,
6+ returning a dictionary of Raster objects that can be directly passed to the PTJPLSM model
7+ without requiring any side-loading of additional data.
8+ """
9+ import logging
10+ from typing import Dict , Union
11+ from datetime import datetime
12+
13+ import numpy as np
14+ import rasters as rt
15+ from rasters import Raster , RasterGeometry
16+ from GEOS5FP import GEOS5FP
17+
18+ from PTJPL import load_Topt , load_fAPARmax
19+ from soil_capacity_wilting import load_field_capacity , load_wilting_point
20+ from gedi_canopy_height import load_canopy_height
21+
22+ from .constants import *
23+
24+ logger = logging .getLogger (__name__ )
25+
26+ def generate_PTJPLSM_raster_inputs (
27+ time_UTC : datetime ,
28+ geometry : RasterGeometry ,
29+ GEOS5FP_connection : GEOS5FP = None ,
30+ resampling : str = RESAMPLING ,
31+ field_capacity_directory : str = None ,
32+ wilting_point_directory : str = None ,
33+ canopy_height_directory : str = None
34+ ) -> Dict [str , Raster ]:
35+ """
36+ Generate a dictionary of all required raster inputs for the PT-JPL-SM model.
37+
38+ This function loads or computes all variables needed by the PTJPLSM model to run
39+ without requiring any side-loading of additional data. It provides a complete set
40+ of input rasters that can be directly passed to the model.
41+
42+ Parameters
43+ ----------
44+ time_UTC : datetime
45+ UTC datetime for the observation
46+ geometry : RasterGeometry
47+ Spatial geometry defining the area and resolution for the rasters
48+ GEOS5FP_connection : GEOS5FP, optional
49+ GEOS-5 FP meteorological data connection. If None, a new connection will be created.
50+ resampling : str, optional
51+ Resampling method for spatial data (default from constants)
52+ field_capacity_directory : str, optional
53+ Directory containing field capacity data (default from soil_capacity_wilting)
54+ wilting_point_directory : str, optional
55+ Directory containing wilting point data (default from soil_capacity_wilting)
56+ canopy_height_directory : str, optional
57+ Directory containing canopy height data (default from gedi_canopy_height)
58+
59+ Returns
60+ -------
61+ Dict[str, Raster]
62+ Dictionary containing all required raster inputs for PTJPLSM:
63+ - 'Ta_C': Air temperature in Celsius
64+ - 'RH': Relative humidity (0-1)
65+ - 'soil_moisture': Soil moisture
66+ - 'SWin_Wm2': Incoming shortwave radiation
67+ - 'Topt_C': Optimal plant temperature
68+ - 'fAPARmax': Maximum fraction of absorbed PAR
69+ - 'field_capacity': Soil field capacity
70+ - 'wilting_point': Soil wilting point
71+ - 'canopy_height_meters': Canopy height in meters
72+
73+ Notes
74+ -----
75+ - This function loads all optional parameters that the PTJPLSM model can side-load,
76+ ensuring the model runs without additional data loading.
77+ - The returned rasters can be combined with observation-based inputs (NDVI, ST_C,
78+ emissivity, albedo) to provide a complete input set for PTJPLSM.
79+ - All rasters are resampled to match the provided geometry.
80+
81+ Example
82+ -------
83+ ```python
84+ from datetime import datetime
85+ from rasters import RasterGeometry
86+ from PTJPLSM.generate_PTJPLSM_raster_inputs import generate_PTJPLSM_raster_inputs
87+
88+ # Define spatial geometry and time
89+ geometry = RasterGeometry(...) # Your target geometry
90+ time_UTC = datetime(2023, 6, 15, 12, 0, 0)
91+
92+ # Generate all required inputs
93+ inputs = generate_PTJPLSM_raster_inputs(time_UTC, geometry)
94+
95+ # Add observation-based inputs (NDVI, ST_C, emissivity, albedo)
96+ # ... load your observation data ...
97+
98+ # Run PTJPLSM with complete inputs
99+ from PTJPLSM import PTJPLSM
100+ results = PTJPLSM(
101+ time_UTC=time_UTC,
102+ geometry=geometry,
103+ NDVI=NDVI, # from observations
104+ ST_C=ST_C, # from observations
105+ emissivity=emissivity, # from observations
106+ albedo=albedo, # from observations
107+ **inputs # all generated inputs
108+ )
109+ ```
110+ """
111+ logger .info (f"generating PTJPLSM raster inputs for { time_UTC } UTC" )
112+
113+ inputs = {}
114+
115+ # Create GEOS5FP connection if not provided
116+ if GEOS5FP_connection is None :
117+ logger .info ("creating GEOS-5 FP connection" )
118+ GEOS5FP_connection = GEOS5FP ()
119+
120+ # Load meteorological variables from GEOS-5 FP
121+ logger .info ("loading air temperature (Ta_C) from GEOS-5 FP" )
122+ inputs ['Ta_C' ] = GEOS5FP_connection .Ta_C (
123+ time_UTC = time_UTC ,
124+ geometry = geometry ,
125+ resampling = resampling
126+ )
127+
128+ logger .info ("loading relative humidity (RH) from GEOS-5 FP" )
129+ inputs ['RH' ] = GEOS5FP_connection .RH (
130+ time_UTC = time_UTC ,
131+ geometry = geometry ,
132+ resampling = resampling
133+ )
134+
135+ logger .info ("loading soil moisture (SM) from GEOS-5 FP" )
136+ inputs ['soil_moisture' ] = GEOS5FP_connection .SM (
137+ time_UTC = time_UTC ,
138+ geometry = geometry ,
139+ resampling = resampling
140+ )
141+
142+ logger .info ("loading incoming shortwave radiation (SWin_Wm2) from GEOS-5 FP" )
143+ inputs ['SWin_Wm2' ] = GEOS5FP_connection .SWin (
144+ time_UTC = time_UTC ,
145+ geometry = geometry ,
146+ resampling = resampling
147+ )
148+
149+ # Load vegetation parameters
150+ logger .info ("loading optimal temperature (Topt_C)" )
151+ inputs ['Topt_C' ] = load_Topt (geometry = geometry )
152+
153+ logger .info ("loading maximum fAPAR (fAPARmax)" )
154+ inputs ['fAPARmax' ] = load_fAPARmax (geometry = geometry )
155+
156+ # Load soil properties
157+ logger .info ("loading field capacity" )
158+ inputs ['field_capacity' ] = load_field_capacity (
159+ geometry = geometry ,
160+ directory = field_capacity_directory ,
161+ resampling = resampling
162+ )
163+
164+ logger .info ("loading wilting point" )
165+ inputs ['wilting_point' ] = load_wilting_point (
166+ geometry = geometry ,
167+ directory = wilting_point_directory ,
168+ resampling = resampling
169+ )
170+
171+ # Load canopy structure
172+ logger .info ("loading canopy height" )
173+ inputs ['canopy_height_meters' ] = load_canopy_height (
174+ geometry = geometry ,
175+ source_directory = canopy_height_directory ,
176+ resampling = resampling
177+ )
178+
179+ logger .info ("completed generating PTJPLSM raster inputs" )
180+
181+ return inputs
0 commit comments