ECOv003-L2T-STARS 1.0.1__py3-none-any.whl → 1.1.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ECOv003_L2T_STARS/BRDF/BRDF.py +57 -0
- ECOv003_L2T_STARS/BRDF/SZA.py +65 -0
- ECOv003_L2T_STARS/BRDF/__init__.py +1 -0
- ECOv003_L2T_STARS/BRDF/statistical_radiative_transport.txt +90 -0
- ECOv003_L2T_STARS/BRDF/version.txt +1 -0
- ECOv003_L2T_STARS/ECOv003_DL.py +527 -0
- ECOv003_L2T_STARS/ECOv003_DL.xml +47 -0
- ECOv003_L2T_STARS/ECOv003_L2T_STARS.py +162 -0
- ECOv003_L2T_STARS/ECOv003_L2T_STARS.xml +47 -0
- ECOv003_L2T_STARS/L2TSTARSConfig.py +188 -0
- ECOv003_L2T_STARS/L2T_STARS.py +489 -0
- ECOv003_L2T_STARS/LPDAAC/LPDAACDataPool.py +444 -0
- ECOv003_L2T_STARS/LPDAAC/__init__.py +9 -0
- ECOv003_L2T_STARS/LPDAAC/version.txt +1 -0
- ECOv003_L2T_STARS/Manifest.toml +2332 -0
- ECOv003_L2T_STARS/Project.toml +14 -0
- ECOv003_L2T_STARS/VIIRS/VIIRSDataPool.py +294 -0
- ECOv003_L2T_STARS/VIIRS/VIIRSDownloader.py +26 -0
- ECOv003_L2T_STARS/VIIRS/VIIRS_CMR_LOGIN.py +36 -0
- ECOv003_L2T_STARS/VIIRS/VNP09GA.py +1277 -0
- ECOv003_L2T_STARS/VIIRS/VNP43IA4.py +288 -0
- ECOv003_L2T_STARS/VIIRS/VNP43MA3.py +323 -0
- ECOv003_L2T_STARS/VIIRS/__init__.py +9 -0
- ECOv003_L2T_STARS/VIIRS/version.txt +1 -0
- ECOv003_L2T_STARS/VNP43NRT/VNP43NRT.py +863 -0
- ECOv003_L2T_STARS/VNP43NRT/__init__.py +1 -0
- ECOv003_L2T_STARS/VNP43NRT/process_VNP43NRT.jl +169 -0
- ECOv003_L2T_STARS/VNP43NRT/version.txt +1 -0
- ECOv003_L2T_STARS/VNP43NRT_jl/Manifest.toml +995 -0
- ECOv003_L2T_STARS/VNP43NRT_jl/Project.toml +15 -0
- ECOv003_L2T_STARS/VNP43NRT_jl/__init__.py +0 -0
- ECOv003_L2T_STARS/VNP43NRT_jl/instantiate.jl +25 -0
- ECOv003_L2T_STARS/VNP43NRT_jl/instantiate.py +13 -0
- ECOv003_L2T_STARS/VNP43NRT_jl/src/VNP43NRT.jl +411 -0
- ECOv003_L2T_STARS/VNP43NRT_jl/src/__init__.py +0 -0
- ECOv003_L2T_STARS/__init__.py +3 -0
- ECOv003_L2T_STARS/calibrate_fine_to_coarse.py +60 -0
- ECOv003_L2T_STARS/constants.py +38 -0
- ECOv003_L2T_STARS/daterange/__init__.py +1 -0
- ECOv003_L2T_STARS/daterange/daterange.py +35 -0
- ECOv003_L2T_STARS/generate_L2T_STARS_runconfig.py +249 -0
- ECOv003_L2T_STARS/generate_NDVI_coarse_directory.py +21 -0
- ECOv003_L2T_STARS/generate_NDVI_coarse_image.py +30 -0
- ECOv003_L2T_STARS/generate_NDVI_fine_directory.py +14 -0
- ECOv003_L2T_STARS/generate_NDVI_fine_image.py +28 -0
- ECOv003_L2T_STARS/generate_STARS_inputs.py +231 -0
- ECOv003_L2T_STARS/generate_albedo_coarse_directory.py +18 -0
- ECOv003_L2T_STARS/generate_albedo_coarse_image.py +30 -0
- ECOv003_L2T_STARS/generate_albedo_fine_directory.py +17 -0
- ECOv003_L2T_STARS/generate_albedo_fine_image.py +30 -0
- ECOv003_L2T_STARS/generate_filename.py +37 -0
- ECOv003_L2T_STARS/generate_input_staging_directory.py +23 -0
- ECOv003_L2T_STARS/generate_model_state_tile_date_directory.py +28 -0
- ECOv003_L2T_STARS/generate_output_directory.py +28 -0
- ECOv003_L2T_STARS/install_STARS_jl.py +43 -0
- ECOv003_L2T_STARS/instantiate_STARS_jl.py +38 -0
- ECOv003_L2T_STARS/load_prior.py +248 -0
- ECOv003_L2T_STARS/prior.py +56 -0
- ECOv003_L2T_STARS/process_ECOSTRESS_data_fusion_distributed_bias.jl +420 -0
- ECOv003_L2T_STARS/process_STARS_product.py +507 -0
- ECOv003_L2T_STARS/process_julia_data_fusion.py +110 -0
- ECOv003_L2T_STARS/retrieve_STARS_sources.py +101 -0
- ECOv003_L2T_STARS/runconfig.py +70 -0
- ECOv003_L2T_STARS/timer/__init__.py +1 -0
- ECOv003_L2T_STARS/timer/timer.py +77 -0
- ECOv003_L2T_STARS/version.py +8 -0
- ECOv003_L2T_STARS/version.txt +1 -0
- {ECOv003_L2T_STARS-1.0.1.dist-info → ecov003_l2t_stars-1.1.0.dist-info}/METADATA +30 -23
- ecov003_l2t_stars-1.1.0.dist-info/RECORD +73 -0
- {ECOv003_L2T_STARS-1.0.1.dist-info → ecov003_l2t_stars-1.1.0.dist-info}/WHEEL +1 -1
- ecov003_l2t_stars-1.1.0.dist-info/entry_points.txt +3 -0
- ecov003_l2t_stars-1.1.0.dist-info/top_level.txt +1 -0
- ECOv003_L2T_STARS-1.0.1.dist-info/RECORD +0 -5
- ECOv003_L2T_STARS-1.0.1.dist-info/top_level.txt +0 -1
- {ECOv003_L2T_STARS-1.0.1.dist-info → ecov003_l2t_stars-1.1.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,37 @@
|
|
1
|
+
from typing import Union
|
2
|
+
from os import makedirs
|
3
|
+
from os.path import join, dirname, abspath
|
4
|
+
from datetime import date
|
5
|
+
|
6
|
+
from dateutil import parser
|
7
|
+
|
8
|
+
def generate_filename(
|
9
|
+
directory: str, variable: str, date_UTC: Union[date, str], tile: str, cell_size: int
|
10
|
+
) -> str:
|
11
|
+
"""
|
12
|
+
Generates a standardized filename for a raster product and ensures its directory exists.
|
13
|
+
|
14
|
+
The filename format is STARS_{variable}_{YYYY-MM-DD}_{tile}_{cell_size}m.tif.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
directory (str): The base directory where the file will be saved.
|
18
|
+
variable (str): The name of the variable (e.g., "NDVI", "albedo").
|
19
|
+
date_UTC (Union[date, str]): The UTC date of the data. Can be a date object or a string.
|
20
|
+
tile (str): The HLS tile ID (e.g., 'H09V05').
|
21
|
+
cell_size (int): The spatial resolution in meters (e.g., 70, 490, 980).
|
22
|
+
|
23
|
+
Returns:
|
24
|
+
str: The full, standardized path to the generated filename.
|
25
|
+
"""
|
26
|
+
if isinstance(date_UTC, str):
|
27
|
+
date_UTC = parser.parse(date_UTC).date()
|
28
|
+
|
29
|
+
variable = str(variable)
|
30
|
+
timestamp = date_UTC.strftime("%Y-%m-%d")
|
31
|
+
tile = str(tile)
|
32
|
+
cell_size = int(cell_size)
|
33
|
+
filename = join(directory, f"STARS_{variable}_{timestamp}_{tile}_{cell_size}m.tif")
|
34
|
+
# Ensure the directory structure for the file exists
|
35
|
+
makedirs(dirname(filename), exist_ok=True)
|
36
|
+
|
37
|
+
return filename
|
@@ -0,0 +1,23 @@
|
|
1
|
+
from os import makedirs
|
2
|
+
from os.path import join
|
3
|
+
|
4
|
+
def generate_input_staging_directory(
|
5
|
+
input_staging_directory: str,
|
6
|
+
tile: str,
|
7
|
+
prefix: str) -> str:
|
8
|
+
"""
|
9
|
+
Generates a path for an input staging directory and ensures it exists.
|
10
|
+
|
11
|
+
This is used to organize temporary input files for the Julia processing.
|
12
|
+
|
13
|
+
Args:
|
14
|
+
input_staging_directory (str): The base input staging directory.
|
15
|
+
tile (str): The HLS tile ID.
|
16
|
+
prefix (str): A prefix for the sub-directory name (e.g., "NDVI_coarse").
|
17
|
+
|
18
|
+
Returns:
|
19
|
+
str: The full path to the created or existing staging directory.
|
20
|
+
"""
|
21
|
+
directory = join(input_staging_directory, f"{prefix}_{tile}")
|
22
|
+
makedirs(directory, exist_ok=True) # Create directory if it doesn't exist
|
23
|
+
return directory
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from typing import Union
|
2
|
+
from datetime import date
|
3
|
+
from os import makedirs
|
4
|
+
from os.path import join
|
5
|
+
|
6
|
+
from dateutil import parser
|
7
|
+
|
8
|
+
def generate_model_state_tile_date_directory(
|
9
|
+
model_directory: str, tile: str, date_UTC: Union[date, str]
|
10
|
+
) -> str:
|
11
|
+
"""
|
12
|
+
Generates a directory for storing model state files (e.g., priors, posteriors)
|
13
|
+
organized by tile and date, and ensures it exists.
|
14
|
+
|
15
|
+
Args:
|
16
|
+
model_directory (str): The base directory for model state files.
|
17
|
+
tile (str): The HLS tile ID.
|
18
|
+
date_UTC (Union[date, str]): The UTC date for the model state.
|
19
|
+
|
20
|
+
Returns:
|
21
|
+
str: The full path to the created or existing model state directory.
|
22
|
+
"""
|
23
|
+
if isinstance(date_UTC, str):
|
24
|
+
date_UTC = parser.parse(date_UTC).date()
|
25
|
+
|
26
|
+
directory = join(model_directory, tile, f"{date_UTC:%Y-%m-%d}")
|
27
|
+
makedirs(directory, exist_ok=True) # Create directory if it doesn't exist
|
28
|
+
return directory
|
@@ -0,0 +1,28 @@
|
|
1
|
+
from typing import Union
|
2
|
+
from datetime import date
|
3
|
+
from os import makedirs
|
4
|
+
from os.path import join
|
5
|
+
|
6
|
+
from dateutil import parser
|
7
|
+
|
8
|
+
def generate_output_directory(
|
9
|
+
working_directory: str,
|
10
|
+
date_UTC: Union[date, str],
|
11
|
+
tile: str) -> str:
|
12
|
+
"""
|
13
|
+
Generates a dated output directory for Julia model results and ensures it exists.
|
14
|
+
|
15
|
+
Args:
|
16
|
+
working_directory (str): The main working directory.
|
17
|
+
date_UTC (Union[date, str]): The UTC date for the output.
|
18
|
+
tile (str): The HLS tile ID.
|
19
|
+
|
20
|
+
Returns:
|
21
|
+
str: The full path to the created or existing output directory.
|
22
|
+
"""
|
23
|
+
if isinstance(date_UTC, str):
|
24
|
+
date_UTC = parser.parse(date_UTC).date()
|
25
|
+
|
26
|
+
directory = join(working_directory, f"julia_output_{date_UTC:%y.%m.%d}_{tile}")
|
27
|
+
makedirs(directory, exist_ok=True) # Create directory if it doesn't exist
|
28
|
+
return directory
|
@@ -0,0 +1,43 @@
|
|
1
|
+
import subprocess
|
2
|
+
import logging
|
3
|
+
|
4
|
+
logger = logging.getLogger(__name__)
|
5
|
+
|
6
|
+
def install_STARS_jl(
|
7
|
+
github_URL: str = "https://github.com/STARS-Data-Fusion/STARS.jl",
|
8
|
+
environment_name: str = "@ECOv003-L2T-STARS") -> subprocess.CompletedProcess:
|
9
|
+
"""
|
10
|
+
Installs the STARS.jl Julia package from GitHub into a specified Julia environment.
|
11
|
+
|
12
|
+
This function executes a Julia command to activate a given environment and
|
13
|
+
then develops (installs in editable mode) the STARS.jl package from its
|
14
|
+
GitHub repository.
|
15
|
+
|
16
|
+
Args:
|
17
|
+
github_URL (str, optional): The URL of the GitHub repository containing STARS.jl.
|
18
|
+
Defaults to "https://github.com/STARS-Data-Fusion/STARS.jl".
|
19
|
+
environment_name (str, optional): The name of the Julia environment to install
|
20
|
+
the package into. Defaults to "@ECOv003-L2T-STARS".
|
21
|
+
|
22
|
+
Returns:
|
23
|
+
subprocess.CompletedProcess: An object containing information about the
|
24
|
+
execution of the Julia command (return code, stdout, stderr).
|
25
|
+
"""
|
26
|
+
# Julia command to activate an environment and then add/develop a package from URL
|
27
|
+
julia_command = [
|
28
|
+
"julia",
|
29
|
+
"-e",
|
30
|
+
f'using Pkg; Pkg.activate("{environment_name}"); Pkg.develop(url="{github_URL}")',
|
31
|
+
]
|
32
|
+
|
33
|
+
# Execute the Julia command as a subprocess
|
34
|
+
result = subprocess.run(julia_command, capture_output=True, text=True, check=False)
|
35
|
+
|
36
|
+
if result.returncode == 0:
|
37
|
+
logger.info(
|
38
|
+
f"STARS.jl installed successfully in environment '{environment_name}'!"
|
39
|
+
)
|
40
|
+
else:
|
41
|
+
logger.error("Error installing STARS.jl:")
|
42
|
+
logger.error(result.stderr)
|
43
|
+
return result
|
@@ -0,0 +1,38 @@
|
|
1
|
+
import subprocess
|
2
|
+
import logging
|
3
|
+
|
4
|
+
logger = logging.getLogger(__name__)
|
5
|
+
|
6
|
+
def instantiate_STARS_jl(package_location: str) -> subprocess.CompletedProcess:
|
7
|
+
"""
|
8
|
+
Activates a Julia project at a given location and instantiates its dependencies.
|
9
|
+
|
10
|
+
This is necessary to ensure all required Julia packages for STARS.jl are
|
11
|
+
downloaded and ready for use within the specified project environment.
|
12
|
+
|
13
|
+
Args:
|
14
|
+
package_location (str): The directory of the Julia package (where Project.toml is located)
|
15
|
+
to activate and instantiate.
|
16
|
+
|
17
|
+
Returns:
|
18
|
+
subprocess.CompletedProcess: An object containing information about the
|
19
|
+
execution of the Julia command (return code, stdout, stderr).
|
20
|
+
"""
|
21
|
+
# Julia command to activate a specific package location and then instantiate its dependencies
|
22
|
+
julia_command = [
|
23
|
+
"julia",
|
24
|
+
"-e",
|
25
|
+
f'using Pkg; Pkg.activate("{package_location}"); Pkg.instantiate()',
|
26
|
+
]
|
27
|
+
|
28
|
+
# Execute the Julia command as a subprocess
|
29
|
+
result = subprocess.run(julia_command, capture_output=True, text=True, check=False)
|
30
|
+
|
31
|
+
if result.returncode == 0:
|
32
|
+
logger.info(
|
33
|
+
f"STARS.jl instantiated successfully in directory '{package_location}'!"
|
34
|
+
)
|
35
|
+
else:
|
36
|
+
logger.error("Error instantiating STARS.jl:")
|
37
|
+
logger.error(result.stderr)
|
38
|
+
return result
|
@@ -0,0 +1,248 @@
|
|
1
|
+
from os.path import exists
|
2
|
+
import logging
|
3
|
+
|
4
|
+
from ECOv003_granules import L2TSTARS
|
5
|
+
|
6
|
+
from .prior import Prior
|
7
|
+
from .generate_filename import generate_filename
|
8
|
+
from .generate_model_state_tile_date_directory import generate_model_state_tile_date_directory
|
9
|
+
|
10
|
+
logger = logging.getLogger(__name__)
|
11
|
+
|
12
|
+
def load_prior(
|
13
|
+
tile: str,
|
14
|
+
target_resolution: int,
|
15
|
+
model_directory: str,
|
16
|
+
L2T_STARS_prior_filename: str) -> Prior:
|
17
|
+
"""
|
18
|
+
Loads a prior L2T_STARS product if available and extracts its components.
|
19
|
+
|
20
|
+
This function attempts to load a previously generated L2T_STARS product
|
21
|
+
to use its NDVI and albedo mean, uncertainty, and bias as prior information
|
22
|
+
for the current data fusion run.
|
23
|
+
|
24
|
+
Args:
|
25
|
+
tile (str): The HLS tile ID.
|
26
|
+
target_resolution (int): The target resolution of the L2T_STARS product.
|
27
|
+
model_directory (str): The base directory for model state files.
|
28
|
+
L2T_STARS_prior_filename (str): The filename of the prior L2T_STARS product (zip file).
|
29
|
+
|
30
|
+
Returns:
|
31
|
+
Prior: A Prior object containing paths to the prior data components
|
32
|
+
and a flag indicating if a valid prior was loaded.
|
33
|
+
"""
|
34
|
+
using_prior = False
|
35
|
+
prior_date_UTC = None
|
36
|
+
prior_NDVI_filename = None
|
37
|
+
prior_NDVI_UQ_filename = None
|
38
|
+
prior_NDVI_bias_filename = None
|
39
|
+
prior_NDVI_bias_UQ_filename = None
|
40
|
+
prior_albedo_filename = None
|
41
|
+
prior_albedo_UQ_filename = None
|
42
|
+
prior_albedo_bias_filename = None
|
43
|
+
prior_albedo_bias_UQ_filename = None
|
44
|
+
|
45
|
+
# Check if a prior L2T_STARS product is specified and exists
|
46
|
+
if L2T_STARS_prior_filename is not None and exists(L2T_STARS_prior_filename):
|
47
|
+
logger.info(f"Loading prior L2T STARS product: {L2T_STARS_prior_filename}")
|
48
|
+
try:
|
49
|
+
# Initialize L2TSTARS object from the prior product
|
50
|
+
L2T_STARS_prior_granule = L2TSTARS(L2T_STARS_prior_filename)
|
51
|
+
prior_date_UTC = L2T_STARS_prior_granule.date_UTC
|
52
|
+
logger.info(f"Prior date: {cl.time(prior_date_UTC)}")
|
53
|
+
|
54
|
+
# Extract NDVI and albedo mean and uncertainty rasters
|
55
|
+
NDVI_prior_mean = L2T_STARS_prior_granule.NDVI
|
56
|
+
NDVI_prior_UQ = L2T_STARS_prior_granule.NDVI_UQ
|
57
|
+
albedo_prior_mean = L2T_STARS_prior_granule.albedo
|
58
|
+
albedo_prior_UQ = L2T_STARS_prior_granule.albedo_UQ
|
59
|
+
|
60
|
+
# Define the directory for storing prior model state files
|
61
|
+
prior_tile_date_directory = generate_model_state_tile_date_directory(
|
62
|
+
model_directory=model_directory, tile=tile, date_UTC=prior_date_UTC
|
63
|
+
)
|
64
|
+
|
65
|
+
# Generate and save filenames for all prior components
|
66
|
+
prior_NDVI_filename = generate_filename(
|
67
|
+
directory=prior_tile_date_directory,
|
68
|
+
variable="NDVI",
|
69
|
+
date_UTC=prior_date_UTC,
|
70
|
+
tile=tile,
|
71
|
+
cell_size=target_resolution,
|
72
|
+
)
|
73
|
+
NDVI_prior_mean.to_geotiff(prior_NDVI_filename)
|
74
|
+
|
75
|
+
prior_NDVI_UQ_filename = generate_filename(
|
76
|
+
directory=prior_tile_date_directory,
|
77
|
+
variable="NDVI.UQ",
|
78
|
+
date_UTC=prior_date_UTC,
|
79
|
+
tile=tile,
|
80
|
+
cell_size=target_resolution,
|
81
|
+
)
|
82
|
+
NDVI_prior_UQ.to_geotiff(prior_NDVI_UQ_filename)
|
83
|
+
|
84
|
+
# Note: Prior bias files might not always exist in older products.
|
85
|
+
# Assuming they could be extracted from L2T_STARS_prior_granule if present.
|
86
|
+
# For simplicity, these are placeholders and would need proper extraction logic
|
87
|
+
# from the L2TSTARS granule if they are actual components.
|
88
|
+
# For now, we set them based on `generate_filename` only if a bias layer is retrieved.
|
89
|
+
# If the bias layers are not explicitly part of `L2TSTARS` object, these will be None
|
90
|
+
# unless written explicitly during prior creation.
|
91
|
+
prior_NDVI_bias_filename = generate_filename(
|
92
|
+
directory=prior_tile_date_directory,
|
93
|
+
variable="NDVI.bias",
|
94
|
+
date_UTC=prior_date_UTC,
|
95
|
+
tile=tile,
|
96
|
+
cell_size=target_resolution,
|
97
|
+
)
|
98
|
+
# Assuming L2T_STARS_prior_granule has a .NDVI_bias attribute
|
99
|
+
if hasattr(L2T_STARS_prior_granule, "NDVI_bias") and L2T_STARS_prior_granule.NDVI_bias is not None:
|
100
|
+
L2T_STARS_prior_granule.NDVI_bias.to_geotiff(prior_NDVI_bias_filename)
|
101
|
+
else:
|
102
|
+
prior_NDVI_bias_filename = None # Set to None if not available
|
103
|
+
|
104
|
+
prior_NDVI_bias_UQ_filename = generate_filename(
|
105
|
+
directory=prior_tile_date_directory,
|
106
|
+
variable="NDVI.bias.UQ",
|
107
|
+
date_UTC=prior_date_UTC,
|
108
|
+
tile=tile,
|
109
|
+
cell_size=target_resolution,
|
110
|
+
)
|
111
|
+
# Assuming L2T_STARS_prior_granule has a .NDVI_bias_UQ attribute
|
112
|
+
if hasattr(L2T_STARS_prior_granule, "NDVI_bias_UQ") and L2T_STARS_prior_granule.NDVI_bias_UQ is not None:
|
113
|
+
L2T_STARS_prior_granule.NDVI_bias_UQ.to_geotiff(prior_NDVI_bias_UQ_filename)
|
114
|
+
else:
|
115
|
+
prior_NDVI_bias_UQ_filename = None # Set to None if not available
|
116
|
+
|
117
|
+
|
118
|
+
prior_albedo_filename = generate_filename(
|
119
|
+
directory=prior_tile_date_directory,
|
120
|
+
variable="albedo",
|
121
|
+
date_UTC=prior_date_UTC,
|
122
|
+
tile=tile,
|
123
|
+
cell_size=target_resolution,
|
124
|
+
)
|
125
|
+
albedo_prior_mean.to_geotiff(prior_albedo_filename)
|
126
|
+
|
127
|
+
prior_albedo_UQ_filename = generate_filename(
|
128
|
+
directory=prior_tile_date_directory,
|
129
|
+
variable="albedo.UQ",
|
130
|
+
date_UTC=prior_date_UTC,
|
131
|
+
tile=tile,
|
132
|
+
cell_size=target_resolution,
|
133
|
+
)
|
134
|
+
albedo_prior_UQ.to_geotiff(prior_albedo_UQ_filename)
|
135
|
+
|
136
|
+
prior_albedo_bias_filename = generate_filename(
|
137
|
+
directory=prior_tile_date_directory,
|
138
|
+
variable="albedo.bias",
|
139
|
+
date_UTC=prior_date_UTC,
|
140
|
+
tile=tile,
|
141
|
+
cell_size=target_resolution,
|
142
|
+
)
|
143
|
+
# Assuming L2T_STARS_prior_granule has a .albedo_bias attribute
|
144
|
+
if hasattr(L2T_STARS_prior_granule, "albedo_bias") and L2T_STARS_prior_granule.albedo_bias is not None:
|
145
|
+
L2T_STARS_prior_granule.albedo_bias.to_geotiff(prior_albedo_bias_filename)
|
146
|
+
else:
|
147
|
+
prior_albedo_bias_filename = None # Set to None if not available
|
148
|
+
|
149
|
+
prior_albedo_bias_UQ_filename = generate_filename(
|
150
|
+
directory=prior_tile_date_directory,
|
151
|
+
variable="albedo.bias.UQ",
|
152
|
+
date_UTC=prior_date_UTC,
|
153
|
+
tile=tile,
|
154
|
+
cell_size=target_resolution,
|
155
|
+
)
|
156
|
+
# Assuming L2T_STARS_prior_granule has a .albedo_bias_UQ attribute
|
157
|
+
if hasattr(L2T_STARS_prior_granule, "albedo_bias_UQ") and L2T_STARS_prior_granule.albedo_bias_UQ is not None:
|
158
|
+
L2T_STARS_prior_granule.albedo_bias_UQ.to_geotiff(prior_albedo_bias_UQ_filename)
|
159
|
+
else:
|
160
|
+
prior_albedo_bias_UQ_filename = None # Set to None if not available
|
161
|
+
|
162
|
+
|
163
|
+
using_prior = True # Mark that a prior was successfully loaded
|
164
|
+
except Exception as e:
|
165
|
+
logger.warning(f"Could not load prior L2T STARS product: {L2T_STARS_prior_filename}. Reason: {e}")
|
166
|
+
using_prior = False # Ensure using_prior is False if loading fails
|
167
|
+
|
168
|
+
# Verify that all expected prior files exist, otherwise disable using_prior
|
169
|
+
# This ensures a partial prior (e.g., only NDVI but not albedo) isn't used
|
170
|
+
if prior_NDVI_filename is not None and exists(prior_NDVI_filename):
|
171
|
+
logger.info(f"Prior NDVI ready: {prior_NDVI_filename}")
|
172
|
+
else:
|
173
|
+
logger.info(f"Prior NDVI not found: {prior_NDVI_filename}")
|
174
|
+
using_prior = False
|
175
|
+
|
176
|
+
if prior_NDVI_UQ_filename is not None and exists(prior_NDVI_UQ_filename):
|
177
|
+
logger.info(f"Prior NDVI UQ ready: {prior_NDVI_UQ_filename}")
|
178
|
+
else:
|
179
|
+
logger.info(f"Prior NDVI UQ not found: {prior_NDVI_UQ_filename}")
|
180
|
+
using_prior = False
|
181
|
+
|
182
|
+
if prior_NDVI_bias_filename is not None and exists(prior_NDVI_bias_filename):
|
183
|
+
logger.info(f"Prior NDVI bias ready: {prior_NDVI_bias_filename}")
|
184
|
+
else:
|
185
|
+
logger.info(f"Prior NDVI bias not found: {prior_NDVI_bias_filename}")
|
186
|
+
using_prior = False
|
187
|
+
|
188
|
+
if prior_NDVI_bias_UQ_filename is not None and exists(prior_NDVI_bias_UQ_filename):
|
189
|
+
logger.info(f"Prior NDVI bias UQ ready: {prior_NDVI_bias_UQ_filename}")
|
190
|
+
else:
|
191
|
+
logger.info(f"Prior NDVI bias UQ not found: {prior_NDVI_bias_UQ_filename}")
|
192
|
+
using_prior = False
|
193
|
+
|
194
|
+
if prior_albedo_filename is not None and exists(prior_albedo_filename):
|
195
|
+
logger.info(f"Prior albedo ready: {prior_albedo_filename}")
|
196
|
+
else:
|
197
|
+
logger.info(f"Prior albedo not found: {prior_albedo_filename}")
|
198
|
+
using_prior = False
|
199
|
+
|
200
|
+
if prior_albedo_UQ_filename is not None and exists(prior_albedo_UQ_filename):
|
201
|
+
logger.info(f"Prior albedo UQ ready: {prior_albedo_UQ_filename}")
|
202
|
+
else:
|
203
|
+
logger.info(f"Prior albedo UQ not found: {prior_albedo_UQ_filename}")
|
204
|
+
using_prior = False
|
205
|
+
|
206
|
+
if prior_albedo_bias_filename is not None and exists(prior_albedo_bias_filename):
|
207
|
+
logger.info(f"Prior albedo bias ready: {prior_albedo_bias_filename}")
|
208
|
+
else:
|
209
|
+
logger.info(f"Prior albedo bias not found: {prior_albedo_bias_filename}")
|
210
|
+
using_prior = False
|
211
|
+
|
212
|
+
if prior_albedo_bias_UQ_filename is not None and exists(
|
213
|
+
prior_albedo_bias_UQ_filename
|
214
|
+
):
|
215
|
+
logger.info(f"Prior albedo bias UQ ready: {prior_albedo_bias_UQ_filename}")
|
216
|
+
else:
|
217
|
+
logger.info(f"Prior albedo bias UQ not found: {prior_albedo_bias_UQ_filename}")
|
218
|
+
using_prior = False
|
219
|
+
|
220
|
+
# Final check: if any of the critical prior files are missing, do not use prior
|
221
|
+
if not all([prior_NDVI_filename, prior_NDVI_UQ_filename, prior_albedo_filename, prior_albedo_UQ_filename]):
|
222
|
+
logger.warning("One or more required prior (mean/UQ) files are missing. Prior will not be used.")
|
223
|
+
using_prior = False
|
224
|
+
prior_NDVI_filename = None
|
225
|
+
prior_NDVI_UQ_filename = None
|
226
|
+
prior_albedo_filename = None
|
227
|
+
prior_albedo_UQ_filename = None
|
228
|
+
|
229
|
+
# FIXME where are `prior_NDVI_flag_filename` and `prior_albedo_flag_filename` defined?
|
230
|
+
|
231
|
+
# Create and return the Prior object
|
232
|
+
prior = Prior(
|
233
|
+
using_prior=using_prior,
|
234
|
+
prior_date_UTC=prior_date_UTC,
|
235
|
+
L2T_STARS_prior_filename=L2T_STARS_prior_filename,
|
236
|
+
prior_NDVI_filename=prior_NDVI_filename,
|
237
|
+
prior_NDVI_UQ_filename=prior_NDVI_UQ_filename,
|
238
|
+
prior_NDVI_flag_filename=prior_NDVI_flag_filename,
|
239
|
+
prior_NDVI_bias_filename=prior_NDVI_bias_filename,
|
240
|
+
prior_NDVI_bias_UQ_filename=prior_NDVI_bias_UQ_filename,
|
241
|
+
prior_albedo_filename=prior_albedo_filename,
|
242
|
+
prior_albedo_UQ_filename=prior_albedo_UQ_filename,
|
243
|
+
prior_albedo_flag_filename=prior_albedo_flag_filename,
|
244
|
+
prior_albedo_bias_filename=prior_albedo_bias_filename,
|
245
|
+
prior_albedo_bias_UQ_filename=prior_albedo_bias_UQ_filename,
|
246
|
+
)
|
247
|
+
|
248
|
+
return prior
|
@@ -0,0 +1,56 @@
|
|
1
|
+
from datetime import date
|
2
|
+
|
3
|
+
class Prior:
|
4
|
+
"""
|
5
|
+
A data class to encapsulate information about a prior L2T_STARS product.
|
6
|
+
|
7
|
+
This class holds filenames and flags related to the use of a previous
|
8
|
+
STARS product as a 'prior' in the data fusion process. This can help
|
9
|
+
to constrain the solution and improve accuracy, especially when
|
10
|
+
observations for the current date are sparse.
|
11
|
+
|
12
|
+
Attributes:
|
13
|
+
using_prior (bool): True if a prior product is being used, False otherwise.
|
14
|
+
prior_date_UTC (date): The UTC date of the prior product.
|
15
|
+
L2T_STARS_prior_filename (str): Path to the prior L2T_STARS zip file.
|
16
|
+
prior_NDVI_filename (str): Path to the prior NDVI mean file.
|
17
|
+
prior_NDVI_UQ_filename (str): Path to the prior NDVI uncertainty (UQ) file.
|
18
|
+
prior_NDVI_flag_filename (str): Path to the prior NDVI flag file.
|
19
|
+
prior_NDVI_bias_filename (str): Path to the prior NDVI bias file.
|
20
|
+
prior_NDVI_bias_UQ_filename (str): Path to the prior NDVI bias uncertainty file.
|
21
|
+
prior_albedo_filename (str): Path to the prior albedo mean file.
|
22
|
+
prior_albedo_UQ_filename (str): Path to the prior albedo uncertainty (UQ) file.
|
23
|
+
prior_albedo_flag_filename (str): Path to the prior albedo flag file.
|
24
|
+
prior_albedo_bias_filename (str): Path to the prior albedo bias file.
|
25
|
+
prior_albedo_bias_UQ_filename (str): Path to the prior albedo bias uncertainty file.
|
26
|
+
"""
|
27
|
+
|
28
|
+
def __init__(
|
29
|
+
self,
|
30
|
+
using_prior: bool = False,
|
31
|
+
prior_date_UTC: date = None,
|
32
|
+
L2T_STARS_prior_filename: str = None,
|
33
|
+
prior_NDVI_filename: str = None,
|
34
|
+
prior_NDVI_UQ_filename: str = None,
|
35
|
+
prior_NDVI_flag_filename: str = None,
|
36
|
+
prior_NDVI_bias_filename: str = None,
|
37
|
+
prior_NDVI_bias_UQ_filename: str = None,
|
38
|
+
prior_albedo_filename: str = None,
|
39
|
+
prior_albedo_UQ_filename: str = None,
|
40
|
+
prior_albedo_flag_filename: str = None,
|
41
|
+
prior_albedo_bias_filename: str = None,
|
42
|
+
prior_albedo_bias_UQ_filename: str = None,
|
43
|
+
):
|
44
|
+
self.using_prior = using_prior
|
45
|
+
self.prior_date_UTC = prior_date_UTC
|
46
|
+
self.L2T_STARS_prior_filename = L2T_STARS_prior_filename
|
47
|
+
self.prior_NDVI_filename = prior_NDVI_filename
|
48
|
+
self.prior_NDVI_UQ_filename = prior_NDVI_UQ_filename
|
49
|
+
self.prior_NDVI_flag_filename = prior_NDVI_flag_filename
|
50
|
+
self.prior_NDVI_bias_filename = prior_NDVI_bias_filename
|
51
|
+
self.prior_NDVI_bias_UQ_filename = prior_NDVI_bias_UQ_filename
|
52
|
+
self.prior_albedo_filename = prior_albedo_filename
|
53
|
+
self.prior_albedo_UQ_filename = prior_albedo_UQ_filename
|
54
|
+
self.prior_albedo_flag_filename = prior_albedo_flag_filename
|
55
|
+
self.prior_albedo_bias_filename = prior_albedo_bias_filename
|
56
|
+
self.prior_albedo_bias_UQ_filename = prior_albedo_bias_UQ_filename
|