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,162 @@
|
|
1
|
+
import sys
|
2
|
+
import argparse
|
3
|
+
import logging
|
4
|
+
|
5
|
+
from .version import __version__
|
6
|
+
from .constants import *
|
7
|
+
from .L2T_STARS import L2T_STARS
|
8
|
+
|
9
|
+
# Initialize the logger for the module
|
10
|
+
logger = logging.getLogger(__name__)
|
11
|
+
|
12
|
+
|
13
|
+
def main():
|
14
|
+
"""
|
15
|
+
Main function for parsing command-line arguments and running the L2T_STARS PGE.
|
16
|
+
|
17
|
+
This function uses `argparse` for robust command-line argument parsing,
|
18
|
+
providing a clear interface for users to specify the run-configuration file
|
19
|
+
and other optional parameters.
|
20
|
+
"""
|
21
|
+
parser = argparse.ArgumentParser(
|
22
|
+
description="ECOSTRESS Collection 3 L2T_STARS PGE for generating Tiled Auxiliary NDVI and Albedo products.",
|
23
|
+
formatter_class=argparse.RawTextHelpFormatter, # Allows for more flexible help text formatting
|
24
|
+
epilog=f"L2T_STARS PGE Version: {__version__}\n\n"
|
25
|
+
"Example usage:\n"
|
26
|
+
" python {sys.argv[0]} --runconfig /path/to/RunConfig.xml\n"
|
27
|
+
" python {sys.argv[0]} --runconfig /path/to/RunConfig.xml --date 2023-01-15\n"
|
28
|
+
" python {sys.argv[0]} --runconfig /path/to/RunConfig.xml --sources-only\n"
|
29
|
+
)
|
30
|
+
|
31
|
+
# Positional argument for the runconfig file
|
32
|
+
parser.add_argument(
|
33
|
+
"runconfig",
|
34
|
+
type=str,
|
35
|
+
help="Path to the XML run-configuration file.",
|
36
|
+
)
|
37
|
+
|
38
|
+
# Optional arguments
|
39
|
+
parser.add_argument(
|
40
|
+
"--date",
|
41
|
+
type=str,
|
42
|
+
help="Target UTC date for product generation (YYYY-MM-DD). Overrides date in runconfig.",
|
43
|
+
metavar="YYYY-MM-DD"
|
44
|
+
)
|
45
|
+
parser.add_argument(
|
46
|
+
"--spinup-days",
|
47
|
+
type=int,
|
48
|
+
default=DEFAULT_SPINUP_DAYS,
|
49
|
+
help=f"Number of days for the VIIRS time-series spin-up. Defaults to {DEFAULT_SPINUP_DAYS} days.",
|
50
|
+
metavar="DAYS"
|
51
|
+
)
|
52
|
+
parser.add_argument(
|
53
|
+
"--target-resolution",
|
54
|
+
type=int,
|
55
|
+
default=DEFAULT_TARGET_RESOLUTION,
|
56
|
+
help=f"Desired output product resolution in meters. Defaults to {DEFAULT_TARGET_RESOLUTION}m.",
|
57
|
+
metavar="METERS"
|
58
|
+
)
|
59
|
+
parser.add_argument(
|
60
|
+
"--ndvi-resolution",
|
61
|
+
type=int,
|
62
|
+
default=DEFAULT_NDVI_RESOLUTION,
|
63
|
+
help=f"Resolution of coarse NDVI data in meters. Defaults to {DEFAULT_NDVI_RESOLUTION}m.",
|
64
|
+
metavar="METERS"
|
65
|
+
)
|
66
|
+
parser.add_argument(
|
67
|
+
"--albedo-resolution",
|
68
|
+
type=int,
|
69
|
+
default=DEFAULT_ALBEDO_RESOLUTION,
|
70
|
+
help=f"Resolution of coarse albedo data in meters. Defaults to {DEFAULT_ALBEDO_RESOLUTION}m.",
|
71
|
+
metavar="METERS"
|
72
|
+
)
|
73
|
+
parser.add_argument(
|
74
|
+
"--use-vnp43nrt",
|
75
|
+
action="store_true",
|
76
|
+
default=DEFAULT_USE_VNP43NRT,
|
77
|
+
help=f"Use VNP43NRT for VIIRS products. Defaults to {'True' if DEFAULT_USE_VNP43NRT else 'False'}.",
|
78
|
+
)
|
79
|
+
parser.add_argument(
|
80
|
+
"--no-vnp43nrt",
|
81
|
+
action="store_false",
|
82
|
+
dest="use_vnp43nrt", # This argument sets use_vnp43nrt to False
|
83
|
+
help="Do NOT use VNP43NRT for VIIRS products. Use VNP43IA4/VNP43MA3 instead.",
|
84
|
+
)
|
85
|
+
parser.add_argument(
|
86
|
+
"--calibrate-fine",
|
87
|
+
action="store_true",
|
88
|
+
default=DEFAULT_CALIBRATE_FINE,
|
89
|
+
help=f"Calibrate fine resolution HLS data to coarse resolution VIIRS data. Defaults to {'True' if DEFAULT_CALIBRATE_FINE else 'False'}.",
|
90
|
+
)
|
91
|
+
parser.add_argument(
|
92
|
+
"--sources-only",
|
93
|
+
action="store_true",
|
94
|
+
help="Only retrieve and stage source data (HLS, VIIRS); do not perform data fusion or generate final product.",
|
95
|
+
)
|
96
|
+
parser.add_argument(
|
97
|
+
"--no-remove-input-staging",
|
98
|
+
action="store_false",
|
99
|
+
dest="remove_input_staging",
|
100
|
+
default=True,
|
101
|
+
help="Do NOT remove the input staging directory after processing.",
|
102
|
+
)
|
103
|
+
parser.add_argument(
|
104
|
+
"--no-remove-prior",
|
105
|
+
action="store_false",
|
106
|
+
dest="remove_prior",
|
107
|
+
default=True,
|
108
|
+
help="Do NOT remove prior intermediate files after use.",
|
109
|
+
)
|
110
|
+
parser.add_argument(
|
111
|
+
"--no-remove-posterior",
|
112
|
+
action="store_false",
|
113
|
+
dest="remove_posterior",
|
114
|
+
default=True,
|
115
|
+
help="Do NOT remove posterior intermediate files after product generation.",
|
116
|
+
)
|
117
|
+
parser.add_argument(
|
118
|
+
"--threads",
|
119
|
+
type=str,
|
120
|
+
default="auto",
|
121
|
+
help='Number of Julia threads to use, or "auto". Defaults to "auto".',
|
122
|
+
metavar="COUNT"
|
123
|
+
)
|
124
|
+
parser.add_argument(
|
125
|
+
"--num-workers",
|
126
|
+
type=int,
|
127
|
+
default=4,
|
128
|
+
help=f"Number of Julia workers for distributed processing. Defaults to 4.",
|
129
|
+
metavar="COUNT"
|
130
|
+
)
|
131
|
+
parser.add_argument(
|
132
|
+
"--version",
|
133
|
+
action="version",
|
134
|
+
version=f"%(prog)s {__version__}",
|
135
|
+
help="Show program's version number and exit.",
|
136
|
+
)
|
137
|
+
|
138
|
+
args = parser.parse_args()
|
139
|
+
|
140
|
+
# Call the main L2T_STARS processing function with parsed arguments
|
141
|
+
exit_code = L2T_STARS(
|
142
|
+
runconfig_filename=args.runconfig,
|
143
|
+
date_UTC=args.date,
|
144
|
+
spinup_days=args.spinup_days,
|
145
|
+
target_resolution=args.target_resolution,
|
146
|
+
NDVI_resolution=args.ndvi_resolution,
|
147
|
+
albedo_resolution=args.albedo_resolution,
|
148
|
+
use_VNP43NRT=args.use_vnp43nrt,
|
149
|
+
calibrate_fine=args.calibrate_fine,
|
150
|
+
sources_only=args.sources_only,
|
151
|
+
remove_input_staging=args.remove_input_staging,
|
152
|
+
remove_prior=args.remove_prior,
|
153
|
+
remove_posterior=args.remove_posterior,
|
154
|
+
threads=args.threads,
|
155
|
+
num_workers=args.num_workers,
|
156
|
+
)
|
157
|
+
|
158
|
+
sys.exit(exit_code)
|
159
|
+
|
160
|
+
|
161
|
+
if __name__ == "__main__":
|
162
|
+
main()
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<input xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
3
|
+
xmlns:xalan="http://xml.apache.org/xslt"
|
4
|
+
xmlns:cas="http://oodt.jpl.nasa.gov/1.0/cas"
|
5
|
+
xsi:noNamespaceSchemaLocation="">
|
6
|
+
<group name="LogMetadata">
|
7
|
+
<vector name="CommandLineParameters">
|
8
|
+
<element>executable_filename</element>
|
9
|
+
<element>runconfig_filename</element>
|
10
|
+
<element>log_filename</element>
|
11
|
+
</vector>
|
12
|
+
</group>
|
13
|
+
<group name="JobIdentification">
|
14
|
+
<scalar name="ProductionLocation">ECOSTRESS Science Computing Facility</scalar>
|
15
|
+
<scalar name="TaskId">urn:ecostress:L2GL2TLSTETask</scalar>
|
16
|
+
<scalar name="ProcessingNode">processing_node</scalar>
|
17
|
+
<scalar name="ProductionDateTime">production_datetime</scalar>
|
18
|
+
<scalar name="JobId">job_ID</scalar>
|
19
|
+
<scalar name="WorkflowInstanceId">instance_ID</scalar>
|
20
|
+
</group>
|
21
|
+
<group name="InputFileGroup">
|
22
|
+
<scalar name="L2T_LSTE">L2T_LSTE_filename</scalar>
|
23
|
+
<scalar name="L2T_STARS_PRIOR">prior_L2T_STARS_filename</scalar>
|
24
|
+
</group>
|
25
|
+
<group name="StaticAuxiliaryFileGroup">
|
26
|
+
<scalar name="L2T_STARS_MODEL">model_directory</scalar>
|
27
|
+
<scalar name="L2T_STARS_INDICES">indices_directory</scalar>
|
28
|
+
<scalar name="L2T_STARS_SOURCES">sources_directory</scalar>
|
29
|
+
<scalar name="L2T_STARS_WORKING">working_directory</scalar>
|
30
|
+
</group>
|
31
|
+
<group name="PrimaryExecutable">
|
32
|
+
<scalar name="BuildID">build_ID</scalar>
|
33
|
+
<scalar name="FullPathname">executable_filename</scalar>
|
34
|
+
</group>
|
35
|
+
<group name="Geometry">
|
36
|
+
<scalar name="TileId">tile_ID</scalar>
|
37
|
+
<scalar name="SceneId">scene_ID</scalar>
|
38
|
+
<scalar name="OrbitNumber">orbit_number</scalar>
|
39
|
+
</group>
|
40
|
+
<group name="ProductPathGroup">
|
41
|
+
<scalar name="ProductCounter">product_counter</scalar>
|
42
|
+
<scalar name="ProductPath">output_directory</scalar>
|
43
|
+
</group>
|
44
|
+
<group name="PGENameGroup">
|
45
|
+
<scalar name="PGEName">L2T_STARS_PGE</scalar>
|
46
|
+
</group>
|
47
|
+
</input>
|
@@ -0,0 +1,188 @@
|
|
1
|
+
from os.path import exists
|
2
|
+
import logging
|
3
|
+
|
4
|
+
from dateutil import parser
|
5
|
+
|
6
|
+
import colored_logging as cl
|
7
|
+
|
8
|
+
from ECOv003_exit_codes import *
|
9
|
+
from ECOv003_granules import L2TLSTE
|
10
|
+
|
11
|
+
from .constants import *
|
12
|
+
from .runconfig import ECOSTRESSRunConfig
|
13
|
+
|
14
|
+
logger = logging.getLogger(__name__)
|
15
|
+
|
16
|
+
class L2TSTARSConfig(ECOSTRESSRunConfig):
|
17
|
+
"""
|
18
|
+
Parses and validates the L2T_STARS specific parameters from an XML run-configuration file.
|
19
|
+
|
20
|
+
This class extends the base ECOSTRESSRunConfig to extract paths, IDs,
|
21
|
+
and processing parameters relevant to the L2T_STARS product generation.
|
22
|
+
It performs validation to ensure all critical parameters are present.
|
23
|
+
"""
|
24
|
+
|
25
|
+
def __init__(self, filename: str):
|
26
|
+
"""
|
27
|
+
Initializes the L2TSTARSConfig by parsing the provided run-config XML file.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
filename (str): The path to the L2T_STARS run-configuration XML file.
|
31
|
+
|
32
|
+
Raises:
|
33
|
+
MissingRunConfigValue: If a required value is missing from the run-config.
|
34
|
+
UnableToParseRunConfig: If the run-config file cannot be parsed due to other errors.
|
35
|
+
"""
|
36
|
+
logger.info(f"Loading L2T_STARS run-config: {cl.file(filename)}")
|
37
|
+
# Read the run-config XML into a dictionary
|
38
|
+
runconfig = self.read_runconfig(filename)
|
39
|
+
|
40
|
+
try:
|
41
|
+
# Validate and extract working directory from StaticAuxiliaryFileGroup
|
42
|
+
if "StaticAuxiliaryFileGroup" not in runconfig:
|
43
|
+
raise MissingRunConfigValue(
|
44
|
+
f"Missing StaticAuxiliaryFileGroup in L2T_STARS run-config: {filename}"
|
45
|
+
)
|
46
|
+
if "L2T_STARS_WORKING" not in runconfig["StaticAuxiliaryFileGroup"]:
|
47
|
+
raise MissingRunConfigValue(
|
48
|
+
f"Missing StaticAuxiliaryFileGroup/L2T_STARS_WORKING in L2T_STARS run-config: {filename}"
|
49
|
+
)
|
50
|
+
self.working_directory = abspath(
|
51
|
+
runconfig["StaticAuxiliaryFileGroup"]["L2T_STARS_WORKING"]
|
52
|
+
)
|
53
|
+
logger.info(f"Working directory: {cl.dir(self.working_directory)}")
|
54
|
+
|
55
|
+
# Validate and extract sources directory
|
56
|
+
if "L2T_STARS_SOURCES" not in runconfig["StaticAuxiliaryFileGroup"]:
|
57
|
+
raise MissingRunConfigValue(
|
58
|
+
f"Missing StaticAuxiliaryFileGroup/L2T_STARS_SOURCES in L2T_STARS run-config: {filename}"
|
59
|
+
)
|
60
|
+
self.sources_directory = abspath(
|
61
|
+
runconfig["StaticAuxiliaryFileGroup"]["L2T_STARS_SOURCES"]
|
62
|
+
)
|
63
|
+
logger.info(f"Sources directory: {cl.dir(self.sources_directory)}")
|
64
|
+
|
65
|
+
# Validate and extract indices directory
|
66
|
+
if "L2T_STARS_INDICES" not in runconfig["StaticAuxiliaryFileGroup"]:
|
67
|
+
raise MissingRunConfigValue(
|
68
|
+
f"Missing StaticAuxiliaryFileGroup/L2T_STARS_INDICES in L2T_STARS run-config: {filename}"
|
69
|
+
)
|
70
|
+
self.indices_directory = abspath(
|
71
|
+
runconfig["StaticAuxiliaryFileGroup"]["L2T_STARS_INDICES"]
|
72
|
+
)
|
73
|
+
logger.info(f"Indices directory: {cl.dir(self.indices_directory)}")
|
74
|
+
|
75
|
+
# Validate and extract model directory
|
76
|
+
if "L2T_STARS_MODEL" not in runconfig["StaticAuxiliaryFileGroup"]:
|
77
|
+
raise MissingRunConfigValue(
|
78
|
+
f"Missing StaticAuxiliaryFileGroup/L2T_STARS_MODEL in L2T_STARS run-config: {filename}"
|
79
|
+
)
|
80
|
+
self.model_directory = abspath(
|
81
|
+
runconfig["StaticAuxiliaryFileGroup"]["L2T_STARS_MODEL"]
|
82
|
+
)
|
83
|
+
logger.info(f"Model directory: {cl.dir(self.model_directory)}")
|
84
|
+
|
85
|
+
# Validate and extract output directory from ProductPathGroup
|
86
|
+
if "ProductPathGroup" not in runconfig:
|
87
|
+
raise MissingRunConfigValue(
|
88
|
+
f"Missing ProductPathGroup in L2T_STARS run-config: {filename}"
|
89
|
+
)
|
90
|
+
if "ProductPath" not in runconfig["ProductPathGroup"]:
|
91
|
+
raise MissingRunConfigValue(
|
92
|
+
f"Missing ProductPathGroup/ProductPath in L2T_STARS run-config: {filename}"
|
93
|
+
)
|
94
|
+
self.output_directory = abspath(
|
95
|
+
runconfig["ProductPathGroup"]["ProductPath"]
|
96
|
+
)
|
97
|
+
logger.info(f"Output directory: {cl.dir(self.output_directory)}")
|
98
|
+
|
99
|
+
# Validate and extract input L2T_LSTE filename
|
100
|
+
if "InputFileGroup" not in runconfig:
|
101
|
+
raise MissingRunConfigValue(
|
102
|
+
f"Missing InputFileGroup in L2G_L2T_LSTE run-config: {filename}"
|
103
|
+
)
|
104
|
+
if "L2T_LSTE" not in runconfig["InputFileGroup"]:
|
105
|
+
raise MissingRunConfigValue(
|
106
|
+
f"Missing InputFileGroup/L2T_LSTE in L2T_STARS run-config: {filename}"
|
107
|
+
)
|
108
|
+
self.L2T_LSTE_filename = abspath(runconfig["InputFileGroup"]["L2T_LSTE"])
|
109
|
+
logger.info(f"L2T_LSTE file: {cl.file(self.L2T_LSTE_filename)}")
|
110
|
+
|
111
|
+
# Extract optional prior L2T_STARS filename
|
112
|
+
self.L2T_STARS_prior_filename = None
|
113
|
+
if "L2T_STARS_PRIOR" in runconfig["InputFileGroup"]:
|
114
|
+
prior_filename = runconfig["InputFileGroup"]["L2T_STARS_PRIOR"]
|
115
|
+
if prior_filename != "" and exists(prior_filename):
|
116
|
+
self.L2T_STARS_prior_filename = abspath(prior_filename)
|
117
|
+
logger.info(
|
118
|
+
f"L2T_STARS prior file: {cl.file(self.L2T_STARS_prior_filename)}"
|
119
|
+
)
|
120
|
+
|
121
|
+
# Extract geometry parameters (orbit, scene, tile)
|
122
|
+
self.orbit = int(runconfig["Geometry"]["OrbitNumber"])
|
123
|
+
logger.info(f"Orbit: {cl.val(self.orbit)}")
|
124
|
+
if "SceneId" not in runconfig["Geometry"]:
|
125
|
+
raise MissingRunConfigValue(
|
126
|
+
f"Missing Geometry/SceneId in L2T_STARS run-config: {filename}"
|
127
|
+
)
|
128
|
+
self.scene = int(runconfig["Geometry"]["SceneId"])
|
129
|
+
logger.info(f"Scene: {cl.val(self.scene)}")
|
130
|
+
if "TileId" not in runconfig["Geometry"]:
|
131
|
+
raise MissingRunConfigValue(
|
132
|
+
f"Missing Geometry/TileId in L2T_STARS run-config: {filename}"
|
133
|
+
)
|
134
|
+
self.tile = str(runconfig["Geometry"]["TileId"])
|
135
|
+
logger.info(f"Tile: {cl.val(self.tile)}")
|
136
|
+
|
137
|
+
# Extract production details
|
138
|
+
if "ProductionDateTime" not in runconfig["JobIdentification"]:
|
139
|
+
raise MissingRunConfigValue(
|
140
|
+
f"Missing JobIdentification/ProductionDateTime in L2T_STARS run-config {filename}"
|
141
|
+
)
|
142
|
+
self.production_datetime = parser.parse(
|
143
|
+
runconfig["JobIdentification"]["ProductionDateTime"]
|
144
|
+
)
|
145
|
+
logger.info(f"Production time: {cl.time(self.production_datetime)}")
|
146
|
+
|
147
|
+
# Extract build ID
|
148
|
+
if "BuildID" not in runconfig["PrimaryExecutable"]:
|
149
|
+
raise MissingRunConfigValue(
|
150
|
+
f"Missing PrimaryExecutable/BuildID in L2T_STARS run-config {filename}"
|
151
|
+
)
|
152
|
+
self.build = str(runconfig["PrimaryExecutable"]["BuildID"])
|
153
|
+
|
154
|
+
# Extract product counter
|
155
|
+
if "ProductCounter" not in runconfig["ProductPathGroup"]:
|
156
|
+
raise MissingRunConfigValue(
|
157
|
+
f"Missing ProductPathGroup/ProductCounter in L2T_STARS run-config {filename}"
|
158
|
+
)
|
159
|
+
self.product_counter = int(runconfig["ProductPathGroup"]["ProductCounter"])
|
160
|
+
|
161
|
+
# Get UTC time from the L2T_LSTE granule itself
|
162
|
+
l2t_lste_granule_obj = L2TLSTE(self.L2T_LSTE_filename)
|
163
|
+
time_UTC = l2t_lste_granule_obj.time_UTC
|
164
|
+
|
165
|
+
# Construct the full granule ID and paths for the output product
|
166
|
+
granule_ID = (
|
167
|
+
f"ECOv003_L2T_STARS_{self.tile}_{time_UTC:%Y%m%d}_{self.build}_"
|
168
|
+
f"{self.product_counter:02d}"
|
169
|
+
)
|
170
|
+
self.granule_ID = granule_ID
|
171
|
+
self.L2T_STARS_granule_directory = join(self.output_directory, granule_ID)
|
172
|
+
self.L2T_STARS_zip_filename = f"{self.L2T_STARS_granule_directory}.zip"
|
173
|
+
self.L2T_STARS_browse_filename = (
|
174
|
+
f"{self.L2T_STARS_granule_directory}.png"
|
175
|
+
)
|
176
|
+
|
177
|
+
except MissingRunConfigValue as e:
|
178
|
+
# Re-raise specific missing value errors
|
179
|
+
raise e
|
180
|
+
except ECOSTRESSExitCodeException as e:
|
181
|
+
# Re-raise custom ECOSTRESS exit code exceptions
|
182
|
+
raise e
|
183
|
+
except Exception as e:
|
184
|
+
# Catch any other parsing errors and raise a generic UnableToParseRunConfig
|
185
|
+
logger.exception(e)
|
186
|
+
raise UnableToParseRunConfig(
|
187
|
+
f"Unable to parse run-config file: {filename}"
|
188
|
+
)
|