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.
Files changed (75) hide show
  1. ECOv003_L2T_STARS/BRDF/BRDF.py +57 -0
  2. ECOv003_L2T_STARS/BRDF/SZA.py +65 -0
  3. ECOv003_L2T_STARS/BRDF/__init__.py +1 -0
  4. ECOv003_L2T_STARS/BRDF/statistical_radiative_transport.txt +90 -0
  5. ECOv003_L2T_STARS/BRDF/version.txt +1 -0
  6. ECOv003_L2T_STARS/ECOv003_DL.py +527 -0
  7. ECOv003_L2T_STARS/ECOv003_DL.xml +47 -0
  8. ECOv003_L2T_STARS/ECOv003_L2T_STARS.py +169 -0
  9. ECOv003_L2T_STARS/ECOv003_L2T_STARS.xml +47 -0
  10. ECOv003_L2T_STARS/L2TSTARSConfig.py +190 -0
  11. ECOv003_L2T_STARS/L2T_STARS.py +503 -0
  12. ECOv003_L2T_STARS/LPDAAC/LPDAACDataPool.py +444 -0
  13. ECOv003_L2T_STARS/LPDAAC/__init__.py +9 -0
  14. ECOv003_L2T_STARS/LPDAAC/version.txt +1 -0
  15. ECOv003_L2T_STARS/Manifest.toml +2332 -0
  16. ECOv003_L2T_STARS/Project.toml +14 -0
  17. ECOv003_L2T_STARS/VIIRS/VIIRSDataPool.py +294 -0
  18. ECOv003_L2T_STARS/VIIRS/VIIRSDownloader.py +26 -0
  19. ECOv003_L2T_STARS/VIIRS/VIIRS_CMR_LOGIN.py +36 -0
  20. ECOv003_L2T_STARS/VIIRS/VNP09GA.py +1278 -0
  21. ECOv003_L2T_STARS/VIIRS/VNP43IA4.py +288 -0
  22. ECOv003_L2T_STARS/VIIRS/VNP43MA3.py +323 -0
  23. ECOv003_L2T_STARS/VIIRS/__init__.py +9 -0
  24. ECOv003_L2T_STARS/VIIRS/version.txt +1 -0
  25. ECOv003_L2T_STARS/VNP43NRT/VNP43NRT.py +863 -0
  26. ECOv003_L2T_STARS/VNP43NRT/__init__.py +1 -0
  27. ECOv003_L2T_STARS/VNP43NRT/process_VNP43NRT.jl +169 -0
  28. ECOv003_L2T_STARS/VNP43NRT/version.txt +1 -0
  29. ECOv003_L2T_STARS/VNP43NRT_jl/Manifest.toml +995 -0
  30. ECOv003_L2T_STARS/VNP43NRT_jl/Project.toml +15 -0
  31. ECOv003_L2T_STARS/VNP43NRT_jl/__init__.py +0 -0
  32. ECOv003_L2T_STARS/VNP43NRT_jl/instantiate.jl +25 -0
  33. ECOv003_L2T_STARS/VNP43NRT_jl/instantiate.py +13 -0
  34. ECOv003_L2T_STARS/VNP43NRT_jl/src/VNP43NRT.jl +411 -0
  35. ECOv003_L2T_STARS/VNP43NRT_jl/src/__init__.py +0 -0
  36. ECOv003_L2T_STARS/__init__.py +3 -0
  37. ECOv003_L2T_STARS/calibrate_fine_to_coarse.py +60 -0
  38. ECOv003_L2T_STARS/constants.py +38 -0
  39. ECOv003_L2T_STARS/daterange/__init__.py +1 -0
  40. ECOv003_L2T_STARS/daterange/daterange.py +35 -0
  41. ECOv003_L2T_STARS/generate_L2T_STARS_runconfig.py +249 -0
  42. ECOv003_L2T_STARS/generate_NDVI_coarse_directory.py +21 -0
  43. ECOv003_L2T_STARS/generate_NDVI_coarse_image.py +30 -0
  44. ECOv003_L2T_STARS/generate_NDVI_fine_directory.py +14 -0
  45. ECOv003_L2T_STARS/generate_NDVI_fine_image.py +28 -0
  46. ECOv003_L2T_STARS/generate_STARS_inputs.py +231 -0
  47. ECOv003_L2T_STARS/generate_albedo_coarse_directory.py +18 -0
  48. ECOv003_L2T_STARS/generate_albedo_coarse_image.py +30 -0
  49. ECOv003_L2T_STARS/generate_albedo_fine_directory.py +17 -0
  50. ECOv003_L2T_STARS/generate_albedo_fine_image.py +30 -0
  51. ECOv003_L2T_STARS/generate_filename.py +37 -0
  52. ECOv003_L2T_STARS/generate_input_staging_directory.py +23 -0
  53. ECOv003_L2T_STARS/generate_model_state_tile_date_directory.py +28 -0
  54. ECOv003_L2T_STARS/generate_output_directory.py +28 -0
  55. ECOv003_L2T_STARS/install_STARS_jl.py +43 -0
  56. ECOv003_L2T_STARS/instantiate_STARS_jl.py +38 -0
  57. ECOv003_L2T_STARS/load_prior.py +250 -0
  58. ECOv003_L2T_STARS/prior.py +56 -0
  59. ECOv003_L2T_STARS/process_ECOSTRESS_data_fusion_distributed_bias.jl +420 -0
  60. ECOv003_L2T_STARS/process_STARS_product.py +507 -0
  61. ECOv003_L2T_STARS/process_julia_data_fusion.py +110 -0
  62. ECOv003_L2T_STARS/retrieve_STARS_sources.py +101 -0
  63. ECOv003_L2T_STARS/runconfig.py +70 -0
  64. ECOv003_L2T_STARS/timer/__init__.py +1 -0
  65. ECOv003_L2T_STARS/timer/timer.py +77 -0
  66. ECOv003_L2T_STARS/version.py +8 -0
  67. ECOv003_L2T_STARS/version.txt +1 -0
  68. {ECOv003_L2T_STARS-1.0.1.dist-info → ecov003_l2t_stars-1.2.0.dist-info}/METADATA +31 -24
  69. ecov003_l2t_stars-1.2.0.dist-info/RECORD +73 -0
  70. {ECOv003_L2T_STARS-1.0.1.dist-info → ecov003_l2t_stars-1.2.0.dist-info}/WHEEL +1 -1
  71. ecov003_l2t_stars-1.2.0.dist-info/entry_points.txt +3 -0
  72. ecov003_l2t_stars-1.2.0.dist-info/top_level.txt +1 -0
  73. ECOv003_L2T_STARS-1.0.1.dist-info/RECORD +0 -5
  74. ECOv003_L2T_STARS-1.0.1.dist-info/top_level.txt +0 -1
  75. {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)