ECOv003-L2T-STARS 1.0.1__py3-none-any.whl → 1.2.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 +169 -0
- ECOv003_L2T_STARS/ECOv003_L2T_STARS.xml +47 -0
- ECOv003_L2T_STARS/L2TSTARSConfig.py +190 -0
- ECOv003_L2T_STARS/L2T_STARS.py +503 -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 +1278 -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 +250 -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.2.0.dist-info}/METADATA +31 -24
- ecov003_l2t_stars-1.2.0.dist-info/RECORD +73 -0
- {ECOv003_L2T_STARS-1.0.1.dist-info → ecov003_l2t_stars-1.2.0.dist-info}/WHEEL +1 -1
- ecov003_l2t_stars-1.2.0.dist-info/entry_points.txt +3 -0
- ecov003_l2t_stars-1.2.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.2.0.dist-info/licenses}/LICENSE +0 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
[deps]
|
2
|
+
Dates = "ade2ca70-3891-5945-98fb-dc099432e06a"
|
3
|
+
DelimitedFiles = "8bb1440f-4735-579b-a4ab-409b98df4dab"
|
4
|
+
Distributed = "8ba89e20-285c-5b6f-9357-94700520ee1b"
|
5
|
+
Glob = "c27321d9-0574-5035-807b-f59d2c89b15c"
|
6
|
+
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
|
7
|
+
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
|
8
|
+
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
|
9
|
+
Logging = "56ddb016-857b-54e1-b83d-db4d58db5568"
|
10
|
+
OpenSSL = "4d8831e6-92b7-49fb-bdf8-b643e874388c"
|
11
|
+
Pkg = "44cfe95a-1eb2-52ea-b672-e2afdf69b78f"
|
12
|
+
Rasters = "a3a2b9e3-a471-40c9-b274-f788e487c689"
|
13
|
+
STARSDataFusion = "70ccc657-289f-4534-a407-e03a16fd1153"
|
14
|
+
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
|
@@ -0,0 +1,294 @@
|
|
1
|
+
import json
|
2
|
+
import logging
|
3
|
+
import posixpath
|
4
|
+
from datetime import date
|
5
|
+
from datetime import datetime
|
6
|
+
from os import makedirs
|
7
|
+
from os.path import basename, splitext, abspath, expanduser
|
8
|
+
from os.path import join
|
9
|
+
from typing import List, Union
|
10
|
+
|
11
|
+
import colored_logging as cl
|
12
|
+
import h5py
|
13
|
+
import numpy as np
|
14
|
+
import pandas as pd
|
15
|
+
import rasters as rt
|
16
|
+
|
17
|
+
from dateutil import parser
|
18
|
+
from shapely.geometry import Point, Polygon
|
19
|
+
|
20
|
+
from rasters import RasterGrid, Raster
|
21
|
+
|
22
|
+
from modland import find_modland_tiles, generate_modland_grid, parsehv
|
23
|
+
|
24
|
+
from ..daterange import date_range
|
25
|
+
from ..LPDAAC import LPDAACDataPool
|
26
|
+
|
27
|
+
|
28
|
+
logger = logging.getLogger(__name__)
|
29
|
+
|
30
|
+
|
31
|
+
def parse_VIIRS_product(filename: str) -> str:
|
32
|
+
return str(basename(filename).split(".")[0])
|
33
|
+
|
34
|
+
|
35
|
+
def parse_VIIRS_date(filename: str) -> date:
|
36
|
+
return datetime.strptime(basename(filename).split(".")[1][1:], "%Y%j").date()
|
37
|
+
|
38
|
+
|
39
|
+
def parse_VIIRS_tile(filename: str) -> str:
|
40
|
+
return str(basename(filename).split(".")[2])
|
41
|
+
|
42
|
+
|
43
|
+
def parse_VIIRS_build(filename: str) -> int:
|
44
|
+
return int(basename(filename).split(".")[3])
|
45
|
+
|
46
|
+
|
47
|
+
DEFAULT_WORKING_DIRECTORY = "."
|
48
|
+
DEFAULT_PRODUCTS_DIRECTORY = "VIIRS_products"
|
49
|
+
|
50
|
+
|
51
|
+
class VIIRSGranule:
|
52
|
+
CLOUD_DATASET_NAME = "HDFEOS/GRIDS/VNP_Grid_1km_2D/Data Fields/SurfReflect_QF1_1"
|
53
|
+
|
54
|
+
def __init__(self, filename: str, working_directory: str = None, products_directory: str = None):
|
55
|
+
if working_directory is None:
|
56
|
+
working_directory = DEFAULT_WORKING_DIRECTORY
|
57
|
+
|
58
|
+
working_directory = abspath(expanduser(working_directory))
|
59
|
+
|
60
|
+
if products_directory is None:
|
61
|
+
products_directory = join(working_directory, DEFAULT_PRODUCTS_DIRECTORY)
|
62
|
+
|
63
|
+
products_directory = abspath(expanduser(products_directory))
|
64
|
+
|
65
|
+
self._filename = abspath(filename)
|
66
|
+
self._cloud_mask = None
|
67
|
+
self.working_directory = working_directory
|
68
|
+
self.products_directory = products_directory
|
69
|
+
|
70
|
+
def __repr__(self):
|
71
|
+
display_dict = {
|
72
|
+
"filename": self.filename,
|
73
|
+
"products_directory": self.products_directory
|
74
|
+
}
|
75
|
+
|
76
|
+
display_string = json.dumps(display_dict, indent=2)
|
77
|
+
|
78
|
+
return display_string
|
79
|
+
|
80
|
+
@property
|
81
|
+
def filename(self):
|
82
|
+
return self._filename
|
83
|
+
|
84
|
+
@property
|
85
|
+
def filename_base(self):
|
86
|
+
return basename(self.filename)
|
87
|
+
|
88
|
+
@property
|
89
|
+
def filename_stem(self) -> str:
|
90
|
+
return splitext(self.filename_base)[0]
|
91
|
+
|
92
|
+
@property
|
93
|
+
def tile(self):
|
94
|
+
return parse_VIIRS_tile(self.filename)
|
95
|
+
|
96
|
+
@property
|
97
|
+
def hv(self):
|
98
|
+
return parsehv(self.tile)
|
99
|
+
|
100
|
+
@property
|
101
|
+
def h(self):
|
102
|
+
return self.hv[0]
|
103
|
+
|
104
|
+
@property
|
105
|
+
def v(self):
|
106
|
+
return self.hv[1]
|
107
|
+
|
108
|
+
@property
|
109
|
+
def date_UTC(self):
|
110
|
+
return datetime.strptime(self.filename_base.split(".")[1][1:], "%Y%j")
|
111
|
+
|
112
|
+
@property
|
113
|
+
def grids(self) -> List[str]:
|
114
|
+
with h5py.File(self.filename, "r") as file:
|
115
|
+
return list(file["HDFEOS/GRIDS/"].keys())
|
116
|
+
|
117
|
+
def variables(self, grid: str) -> List[str]:
|
118
|
+
with h5py.File(self.filename, "r") as file:
|
119
|
+
return list(file[f"HDFEOS/GRIDS/{grid}/Data Fields/"].keys())
|
120
|
+
|
121
|
+
def dataset(
|
122
|
+
self,
|
123
|
+
filename: str,
|
124
|
+
dataset_name: str,
|
125
|
+
fill_value: int,
|
126
|
+
scale_factor: float) -> Raster:
|
127
|
+
tile = parse_VIIRS_tile(filename)
|
128
|
+
h, v = parsehv(tile)
|
129
|
+
|
130
|
+
with h5py.File(filename, "r") as f:
|
131
|
+
DN = np.array(f[dataset_name])
|
132
|
+
grid = generate_modland_grid(h, v, DN.shape[0])
|
133
|
+
logger.info(f"opening VIIRS file: {cl.file(self.filename)}")
|
134
|
+
logger.info(f"loading {cl.val(dataset_name)} at {cl.val(f'{grid.cell_size:0.2f} m')} resolution")
|
135
|
+
DN = Raster(DN, geometry=grid)
|
136
|
+
|
137
|
+
data = rt.where(DN == fill_value, np.nan, DN * scale_factor)
|
138
|
+
|
139
|
+
return data
|
140
|
+
|
141
|
+
def product_directory(self, product) -> Union[str, None]:
|
142
|
+
if self.products_directory is None:
|
143
|
+
return None
|
144
|
+
else:
|
145
|
+
return join(self.products_directory, product, f"{self.date_UTC:%Y.%m.%d}")
|
146
|
+
|
147
|
+
def product_filename(self, product: str) -> str:
|
148
|
+
if self.product_directory(product) is None:
|
149
|
+
raise ValueError("no product directory given")
|
150
|
+
|
151
|
+
return join(
|
152
|
+
self.product_directory(product),
|
153
|
+
f"{self.filename_stem}_{product}.tif"
|
154
|
+
)
|
155
|
+
|
156
|
+
|
157
|
+
class VIIRSDataPool(LPDAACDataPool):
|
158
|
+
DEFAULT_WORKING_DIRECTORY = "."
|
159
|
+
DEFAULT_DOWNLOAD_DIRECTORY = "VIIRS_download"
|
160
|
+
DEFAULT_PRODUCTS_DIRECTORY = "VIIRS_products"
|
161
|
+
DEFAULT_MOSAIC_DIRECTORY = "VIIRS_mosaics"
|
162
|
+
|
163
|
+
def __init__(
|
164
|
+
self,
|
165
|
+
username: str = None,
|
166
|
+
password: str = None,
|
167
|
+
remote: str = None,
|
168
|
+
working_directory: str = None,
|
169
|
+
download_directory: str = None,
|
170
|
+
products_directory: str = None,
|
171
|
+
mosaic_directory: str = None,
|
172
|
+
*args,
|
173
|
+
**kwargs):
|
174
|
+
super(VIIRSDataPool, self).__init__(
|
175
|
+
username=username,
|
176
|
+
password=password,
|
177
|
+
remote=remote,
|
178
|
+
*args,
|
179
|
+
**kwargs
|
180
|
+
)
|
181
|
+
|
182
|
+
if working_directory is None:
|
183
|
+
working_directory = self.DEFAULT_WORKING_DIRECTORY
|
184
|
+
|
185
|
+
working_directory = abspath(expanduser(working_directory))
|
186
|
+
|
187
|
+
if download_directory is None:
|
188
|
+
download_directory = join(working_directory, self.DEFAULT_DOWNLOAD_DIRECTORY)
|
189
|
+
|
190
|
+
download_directory = abspath(expanduser(download_directory))
|
191
|
+
|
192
|
+
if products_directory is None:
|
193
|
+
products_directory = join(working_directory, self.DEFAULT_PRODUCTS_DIRECTORY)
|
194
|
+
|
195
|
+
products_directory = abspath(expanduser(products_directory))
|
196
|
+
|
197
|
+
if mosaic_directory is None:
|
198
|
+
mosaic_directory = join(working_directory, self.DEFAULT_MOSAIC_DIRECTORY)
|
199
|
+
|
200
|
+
mosaic_directory = abspath(expanduser(mosaic_directory))
|
201
|
+
|
202
|
+
self.working_directory = working_directory
|
203
|
+
self.download_directory = download_directory
|
204
|
+
self.products_directory = products_directory
|
205
|
+
self.mosaic_directory = mosaic_directory
|
206
|
+
|
207
|
+
def __repr__(self):
|
208
|
+
display_dict = {
|
209
|
+
"download_directory": self.download_directory,
|
210
|
+
"products_directory": self.products_directory,
|
211
|
+
"mosaic_directory": self.mosaic_directory
|
212
|
+
}
|
213
|
+
|
214
|
+
display_string = json.dumps(display_dict, indent=2)
|
215
|
+
|
216
|
+
return display_string
|
217
|
+
|
218
|
+
def search(
|
219
|
+
self,
|
220
|
+
product: str,
|
221
|
+
start_date: date or datetime or str,
|
222
|
+
end_date: date or datetime or str = None,
|
223
|
+
build: str = None,
|
224
|
+
tiles: List[str] or str = None,
|
225
|
+
target_geometry: Point or Polygon or RasterGrid = None,
|
226
|
+
*args,
|
227
|
+
**kwargs) -> pd.DataFrame:
|
228
|
+
if tiles is None and target_geometry is not None:
|
229
|
+
tiles = find_modland_tiles(target_geometry)
|
230
|
+
|
231
|
+
if isinstance(tiles, str):
|
232
|
+
tiles = [tiles]
|
233
|
+
|
234
|
+
if isinstance(start_date, str):
|
235
|
+
start_date = parser.parse(start_date).date()
|
236
|
+
|
237
|
+
if end_date is None:
|
238
|
+
end_date = start_date
|
239
|
+
elif isinstance(end_date, str):
|
240
|
+
end_date = parser.parse(end_date).date()
|
241
|
+
|
242
|
+
rows = []
|
243
|
+
|
244
|
+
for acquisition_date in date_range(start_date, end_date):
|
245
|
+
date_URL = self.date_URL(
|
246
|
+
"VIIRS",
|
247
|
+
product,
|
248
|
+
acquisition_date,
|
249
|
+
build
|
250
|
+
)
|
251
|
+
|
252
|
+
logger.info(f"scanning LP-DAAC: {date_URL}")
|
253
|
+
|
254
|
+
if tiles is None:
|
255
|
+
listing = self.get_HTTP_listing(date_URL, pattern="*.h5")
|
256
|
+
else:
|
257
|
+
listing = []
|
258
|
+
|
259
|
+
for tile in tiles:
|
260
|
+
listing.extend(self.get_HTTP_listing(date_URL, pattern=f"*.{tile}.*.h5"))
|
261
|
+
|
262
|
+
URLs = sorted([
|
263
|
+
posixpath.join(date_URL, item)
|
264
|
+
for item
|
265
|
+
in listing
|
266
|
+
])
|
267
|
+
|
268
|
+
for URL in URLs:
|
269
|
+
tile = parse_VIIRS_tile(posixpath.basename(URL))
|
270
|
+
rows.append([acquisition_date, tile, URL])
|
271
|
+
|
272
|
+
df = pd.DataFrame(rows, columns=["date", "tile", "URL"])
|
273
|
+
|
274
|
+
return df
|
275
|
+
|
276
|
+
def download_URL(self, URL: str, download_location: str = None) -> str:
|
277
|
+
if download_location is None:
|
278
|
+
acquisition_date = parse_VIIRS_date(posixpath.basename(URL))
|
279
|
+
product = parse_VIIRS_product(posixpath.basename(URL))
|
280
|
+
|
281
|
+
download_location = join(
|
282
|
+
self.download_directory,
|
283
|
+
product,
|
284
|
+
f"{acquisition_date:%Y.%m.%d}"
|
285
|
+
)
|
286
|
+
|
287
|
+
makedirs(download_location, exist_ok=True)
|
288
|
+
|
289
|
+
filename = super(VIIRSDataPool, self).download_URL(
|
290
|
+
URL=URL,
|
291
|
+
download_location=download_location
|
292
|
+
)
|
293
|
+
|
294
|
+
return filename
|
@@ -0,0 +1,26 @@
|
|
1
|
+
|
2
|
+
from abc import ABC, abstractmethod
|
3
|
+
from datetime import date
|
4
|
+
|
5
|
+
from rasters import Raster, RasterGeometry
|
6
|
+
|
7
|
+
class VIIRSDownloaderAlbedo(ABC):
|
8
|
+
@abstractmethod
|
9
|
+
def albedo(
|
10
|
+
self,
|
11
|
+
date_UTC: date or str,
|
12
|
+
geometry: RasterGeometry,
|
13
|
+
filename: str = None,
|
14
|
+
resampling: str = None) -> Raster:
|
15
|
+
pass
|
16
|
+
|
17
|
+
|
18
|
+
class VIIRSDownloaderNDVI(ABC):
|
19
|
+
@abstractmethod
|
20
|
+
def NDVI(
|
21
|
+
self,
|
22
|
+
date_UTC: date or str,
|
23
|
+
geometry: RasterGeometry,
|
24
|
+
filename: str = None,
|
25
|
+
resampling: str = None) -> Raster:
|
26
|
+
pass
|
@@ -0,0 +1,36 @@
|
|
1
|
+
import netrc
|
2
|
+
import os
|
3
|
+
|
4
|
+
import earthaccess
|
5
|
+
|
6
|
+
_AUTH = None
|
7
|
+
|
8
|
+
class CMRServerUnreachable(Exception):
|
9
|
+
pass
|
10
|
+
|
11
|
+
def VIIRS_CMR_login() -> earthaccess.Auth:
|
12
|
+
"""
|
13
|
+
Login to Earthdata using netrc credentials if available, falling back to environment variables.
|
14
|
+
"""
|
15
|
+
# Only login to earthaccess once
|
16
|
+
global _AUTH
|
17
|
+
if _AUTH is not None:
|
18
|
+
return _AUTH
|
19
|
+
|
20
|
+
try:
|
21
|
+
# Attempt to use netrc for credentials
|
22
|
+
secrets = netrc.netrc()
|
23
|
+
auth = secrets.authenticators("urs.earthdata.nasa.gov")
|
24
|
+
if auth:
|
25
|
+
_AUTH = earthaccess.login(strategy="netrc") # Use strategy="netrc"
|
26
|
+
return _AUTH
|
27
|
+
|
28
|
+
# Fallback to environment variables if netrc fails
|
29
|
+
if "EARTHDATA_USERNAME" in os.environ and "EARTHDATA_PASSWORD" in os.environ:
|
30
|
+
_AUTH = earthaccess.login(strategy="environment")
|
31
|
+
return _AUTH
|
32
|
+
else:
|
33
|
+
raise CMRServerUnreachable("Missing netrc credentials or environment variables 'EARTHDATA_USERNAME' and 'EARTHDATA_PASSWORD'")
|
34
|
+
|
35
|
+
except Exception as e:
|
36
|
+
raise CMRServerUnreachable(e)
|