ECOv003-L2T-STARS 1.2.0__py3-none-any.whl → 1.3.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.
@@ -259,7 +259,7 @@ def L2T_STARS(
259
259
  HLS_connection = HLS2CMR(
260
260
  working_directory=working_directory,
261
261
  download_directory=HLS_download_directory,
262
- products_directory=HLS_products_directory,
262
+ # products_directory=HLS_products_directory,
263
263
  target_resolution=target_resolution,
264
264
  )
265
265
  except CMRServerUnreachable as e:
@@ -1,6 +1,5 @@
1
- import base64
1
+ import netrc
2
2
  import hashlib
3
- import json
4
3
  import logging
5
4
  import os
6
5
  import posixpath
@@ -11,24 +10,27 @@ from datetime import date
11
10
  from fnmatch import fnmatch
12
11
  from http.cookiejar import CookieJar
13
12
  from os import makedirs, remove
14
- from os.path import abspath
15
13
  from os.path import dirname
16
14
  from os.path import exists
17
15
  from os.path import getsize
18
16
  from os.path import isdir
19
17
  from os.path import join
18
+ from os.path import abspath
19
+ from os.path import expanduser
20
20
  from time import sleep
21
21
  from typing import List, OrderedDict
22
- import netrc
22
+
23
23
  import requests
24
24
  import xmltodict
25
25
  from bs4 import BeautifulSoup
26
26
  from dateutil import parser
27
- from pycksum import cksum
27
+ from ..cksum import cksum
28
28
 
29
29
  import colored_logging as cl
30
30
 
31
- from ECOv003_exit_codes import *
31
+
32
+ class DownloadFailed(Exception):
33
+ pass
32
34
 
33
35
  CONNECTION_CLOSE = {
34
36
  "Connection": "close",
@@ -57,7 +59,7 @@ class LPDAACDataPool:
57
59
  DATE_REGEX = re.compile(r'^(19|20)\d\d[- /.](0[1-9]|1[012])[- /.](0[1-9]|[12][0-9]|3[01])$')
58
60
  DEFAULT_REMOTE = DEFAULT_REMOTE
59
61
 
60
- def __init__(self, username: str = None, password: str = None, remote: str = None, offline_ok: bool = False):
62
+ def __init__(self, username: str = None, password: str = None, remote: str = None, offline_ok: bool = True):
61
63
  if remote is None:
62
64
  remote = DEFAULT_REMOTE
63
65
 
@@ -66,15 +68,14 @@ class LPDAACDataPool:
66
68
  netrc_file = netrc.netrc()
67
69
  username, _, password = netrc_file.authenticators("urs.earthdata.nasa.gov")
68
70
  except Exception as e:
69
- logger.exception(e)
70
71
  logger.warning("netrc credentials not found for urs.earthdata.nasa.gov")
71
72
 
72
73
  if username is None or password is None:
73
74
  if not "LPDAAC_USERNAME" in os.environ or not "LPDAAC_PASSWORD" in os.environ:
74
- raise RuntimeError("Missing environment variable 'LPDAAC_USERNAME' or 'LPDAAC_PASSWORD'")
75
-
76
- username = os.environ["LPDAAC_USERNAME"]
77
- password = os.environ["LPDAAC_PASSWORD"]
75
+ logger.warning("missing environment variable 'LPDAAC_USERNAME' or 'LPDAAC_PASSWORD'")
76
+ else:
77
+ username = os.environ["LPDAAC_USERNAME"]
78
+ password = os.environ["LPDAAC_PASSWORD"]
78
79
 
79
80
  self._remote = remote
80
81
  self._username = username
@@ -86,14 +87,15 @@ class LPDAACDataPool:
86
87
 
87
88
  self._listings = {}
88
89
 
89
- try:
90
- self._authenticate()
91
- self._check_remote()
92
- except Exception as e:
93
- if self.offline_ok:
94
- logger.warning("unable to connect to LP-DAAC data pool")
95
- else:
96
- raise e
90
+ if not self.offline_ok:
91
+ try:
92
+ self._authenticate()
93
+ self._check_remote()
94
+ except Exception as e:
95
+ if self.offline_ok:
96
+ logger.warning("unable to connect to LP-DAAC data pool")
97
+ else:
98
+ raise e
97
99
 
98
100
  def _authenticate(self):
99
101
  try:
@@ -128,7 +130,7 @@ class LPDAACDataPool:
128
130
  raise ConnectionError(message)
129
131
 
130
132
  def _check_remote(self):
131
- logger.info(f"checking URL: {cl.URL(self.remote)}")
133
+ logger.debug(f"checking URL: {cl.URL(self.remote)}")
132
134
 
133
135
  try:
134
136
  response = requests.head(self.remote, headers=CONNECTION_CLOSE)
@@ -145,7 +147,7 @@ class LPDAACDataPool:
145
147
  raise LPDAACServerUnreachable(message)
146
148
 
147
149
  if status == 200:
148
- logger.info(
150
+ logger.debug(
149
151
  "remote verified with status " + cl.val(200) +
150
152
  " in " + cl.time(f"{duration:0.2f}") +
151
153
  " seconds: " + cl.URL(self.remote))
@@ -307,7 +309,7 @@ class LPDAACDataPool:
307
309
  else:
308
310
  metadata_filename = f"{download_location}.xml"
309
311
 
310
- makedirs(dirname(metadata_filename), exist_ok=True)
312
+ makedirs(abspath(dirname(expanduser(metadata_filename))), exist_ok=True)
311
313
 
312
314
  if XML_retries is None:
313
315
  XML_retries = XML_RETRIES
@@ -325,8 +327,8 @@ class LPDAACDataPool:
325
327
 
326
328
  while XML_retries > 0:
327
329
  XML_retries -= 1
328
- command = f"wget -nc -c --user {self._username} --password {self._password} -O {metadata_filename} {metadata_URL}"
329
- logger.info(command)
330
+ command = f"wget -nc -c --user {self._username} --password {self._password} -O {abspath(expanduser(metadata_filename))} {metadata_URL}"
331
+ # logger.info(command)
330
332
  os.system(command)
331
333
 
332
334
  if not exists(metadata_filename):
@@ -350,12 +352,12 @@ class LPDAACDataPool:
350
352
  continue
351
353
 
352
354
  try:
353
- with open(metadata_filename, "r") as file:
355
+ with open(abspath(expanduser(metadata_filename)), "r") as file:
354
356
  metadata = xmltodict.parse(file.read())
355
357
  except Exception as e:
356
358
  logger.warning(e)
357
359
  logger.warning(f"unable to parse metadata file: {metadata_filename}")
358
- os.remove(metadata_filename)
360
+ os.remove(abspath(expanduser(metadata_filename)))
359
361
  logger.warning(f"waiting {XML_timeout_seconds} for retry")
360
362
  sleep(XML_timeout_seconds)
361
363
  continue
@@ -372,7 +374,7 @@ class LPDAACDataPool:
372
374
 
373
375
  logger.info(
374
376
  f"metadata retrieved {checksum_type} checksum: {cl.val(remote_checksum)} size: {cl.val(remote_filesize)} URL: {cl.URL(metadata_URL)}")
375
- makedirs(dirname(filename), exist_ok=True)
377
+ makedirs(abspath(dirname(expanduser(filename))), exist_ok=True)
376
378
  logger.info(f"downloading {cl.URL(URL)} -> {cl.file(filename)}")
377
379
 
378
380
  # Use a temporary file for downloading
@@ -382,8 +384,8 @@ class LPDAACDataPool:
382
384
  download_retries -=1
383
385
 
384
386
  try:
385
- if exists(temporary_filename):
386
- temporary_filesize = self.get_local_filesize(temporary_filename)
387
+ if exists(abspath(expanduser(temporary_filename))):
388
+ temporary_filesize = self.get_local_filesize(abspath(expanduser(temporary_filename)))
387
389
 
388
390
  if temporary_filesize > remote_filesize:
389
391
  logger.warning(
@@ -391,11 +393,11 @@ class LPDAACDataPool:
391
393
  remove(temporary_filename)
392
394
 
393
395
  elif temporary_filesize == remote_filesize:
394
- local_checksum = self.get_local_checksum(temporary_filename, checksum_type=checksum_type)
396
+ local_checksum = self.get_local_checksum(abspath(expanduser(temporary_filename)), checksum_type=checksum_type)
395
397
 
396
398
  if local_checksum == remote_checksum:
397
399
  try:
398
- shutil.move(temporary_filename, filename)
400
+ shutil.move(abspath(expanduser(temporary_filename)), abspath(expanduser(filename)))
399
401
  except Exception as e:
400
402
  if exists(filename):
401
403
  logger.warning(f"unable to move temporary file: {temporary_filename}")
@@ -408,27 +410,27 @@ class LPDAACDataPool:
408
410
  else:
409
411
  logger.warning(
410
412
  f"removing corrupted file with local checksum {local_checksum} and remote checksum {remote_checksum}: {temporary_filename}")
411
- remove(temporary_filename)
413
+ remove(abspath(expanduser(temporary_filename)))
412
414
  else:
413
415
  logger.info(f"resuming incomplete download: {cl.file(temporary_filename)}")
414
416
 
415
- command = f"wget -nc -c --user {self._username} --password {self._password} -O {temporary_filename} {URL}"
416
- logger.info(command)
417
+ command = f"wget -nc -c --user {self._username} --password {self._password} -O {abspath(expanduser(temporary_filename))} {URL}"
418
+ # logger.info(command)
417
419
  os.system(command)
418
420
 
419
- if not exists(temporary_filename):
421
+ if not exists(abspath(expanduser(temporary_filename))):
420
422
  raise ConnectionError(f"unable to download URL: {URL}")
421
423
 
422
- local_filesize = self.get_local_filesize(temporary_filename)
423
- local_checksum = self.get_local_checksum(temporary_filename, checksum_type=checksum_type)
424
+ local_filesize = self.get_local_filesize(abspath(expanduser(temporary_filename)))
425
+ local_checksum = self.get_local_checksum(abspath(expanduser(temporary_filename)), checksum_type=checksum_type)
424
426
 
425
427
  if local_filesize != remote_filesize or local_checksum != remote_checksum:
426
- os.remove(temporary_filename)
428
+ os.remove(abspath(expanduser(temporary_filename)))
427
429
  raise ConnectionError(
428
430
  f"removing corrupted file with local filesize {local_filesize} remote filesize {remote_filesize} local checksum {local_checksum} remote checksum {remote_checksum}: {temporary_filename}")
429
431
 
430
432
  # Download successful, rename the temporary file to its proper name
431
- shutil.move(temporary_filename, filename)
433
+ shutil.move(abspath(expanduser(temporary_filename)), abspath(expanduser(filename)))
432
434
 
433
435
  logger.info(
434
436
  f"successful download with filesize {cl.val(local_filesize)} checksum {cl.val(local_checksum)}: {cl.file(filename)}")
@@ -24,10 +24,11 @@ from modland import generate_modland_grid
24
24
 
25
25
  from ECOv003_exit_codes import *
26
26
 
27
+ from ..login import login
27
28
  from ..daterange import get_date
28
29
  from ..LPDAAC.LPDAACDataPool import RETRIES
29
30
  from .VIIRSDataPool import VIIRSGranule
30
- from .VIIRS_CMR_LOGIN import CMRServerUnreachable, VIIRS_CMR_login
31
+ from ..exceptions import *
31
32
 
32
33
  NDVI_COLORMAP = LinearSegmentedColormap.from_list(
33
34
  name="NDVI",
@@ -1122,7 +1123,7 @@ class VNP09GA:
1122
1123
  self.products_directory = products_directory
1123
1124
  self.mosaic_directory = mosaic_directory
1124
1125
 
1125
- self.auth = VIIRS_CMR_login()
1126
+ self.auth = login()
1126
1127
 
1127
1128
  def add_granules(self, granules: List[earthaccess.search.DataGranule]):
1128
1129
  data = pd.DataFrame([
@@ -1,3 +1,3 @@
1
1
  from .version import __version__, __author__
2
- from .ECOv003_L2T_STARS import *
2
+ from .main import *
3
3
  from .ECOv003_DL import *
@@ -0,0 +1,66 @@
1
+ """
2
+ Pure Python implementation of POSIX cksum algorithm.
3
+
4
+ This module provides a replacement for the pycksum package that is compatible
5
+ with Python 3.12 and later versions.
6
+ """
7
+
8
+
9
+ def cksum(data_or_file):
10
+ """
11
+ Calculate POSIX cksum checksum for data or file-like object.
12
+
13
+ Args:
14
+ data_or_file: Either bytes data or a file-like object opened in binary mode
15
+
16
+ Returns:
17
+ int: The POSIX cksum checksum value
18
+ """
19
+ # Handle file-like objects
20
+ if hasattr(data_or_file, 'read'):
21
+ data = data_or_file.read()
22
+ else:
23
+ data = data_or_file
24
+
25
+ # Ensure we have bytes
26
+ if isinstance(data, str):
27
+ data = data.encode('utf-8')
28
+
29
+ # Initialize CRC with 0
30
+ crc = 0
31
+
32
+ # Process each byte of data
33
+ for byte in data:
34
+ # XOR the byte with the current CRC (shifted left 8 bits)
35
+ crc ^= byte << 24
36
+
37
+ # Process 8 bits
38
+ for _ in range(8):
39
+ if crc & 0x80000000: # If MSB is set
40
+ crc = (crc << 1) ^ 0x04c11db7 # CRC-32 polynomial
41
+ else:
42
+ crc = crc << 1
43
+ crc &= 0xffffffff # Keep it 32-bit
44
+
45
+ # Append the length in bytes as a big-endian value
46
+ length = len(data)
47
+ length_bytes = []
48
+ while length > 0:
49
+ length_bytes.insert(0, length & 0xff)
50
+ length >>= 8
51
+
52
+ # Process the length bytes
53
+ for byte in length_bytes:
54
+ crc ^= byte << 24
55
+ for _ in range(8):
56
+ if crc & 0x80000000:
57
+ crc = (crc << 1) ^ 0x04c11db7
58
+ else:
59
+ crc = crc << 1
60
+ crc &= 0xffffffff
61
+
62
+ # Final XOR and return as signed 32-bit integer equivalent
63
+ result = crc ^ 0xffffffff
64
+
65
+ # Convert to match expected return type (unsigned 32-bit integer)
66
+ return result
@@ -0,0 +1,2 @@
1
+ class CMRServerUnreachable(Exception):
2
+ pass
@@ -3,11 +3,11 @@ import logging
3
3
 
4
4
  logger = logging.getLogger(__name__)
5
5
 
6
- def install_STARS_jl(
7
- github_URL: str = "https://github.com/STARS-Data-Fusion/STARS.jl",
6
+ def install_STARSDataFusion_jl(
7
+ github_URL: str = "https://github.com/STARS-Data-Fusion/STARSDataFusion.jl",
8
8
  environment_name: str = "@ECOv003-L2T-STARS") -> subprocess.CompletedProcess:
9
9
  """
10
- Installs the STARS.jl Julia package from GitHub into a specified Julia environment.
10
+ Installs the STARSDataFusion.jl Julia package from GitHub into a specified Julia environment.
11
11
 
12
12
  This function executes a Julia command to activate a given environment and
13
13
  then develops (installs in editable mode) the STARS.jl package from its
@@ -35,7 +35,7 @@ def install_STARS_jl(
35
35
 
36
36
  if result.returncode == 0:
37
37
  logger.info(
38
- f"STARS.jl installed successfully in environment '{environment_name}'!"
38
+ f"STARSDataFusion.jl installed successfully in environment '{environment_name}'!"
39
39
  )
40
40
  else:
41
41
  logger.error("Error installing STARS.jl:")
@@ -3,11 +3,11 @@ import logging
3
3
 
4
4
  logger = logging.getLogger(__name__)
5
5
 
6
- def instantiate_STARS_jl(package_location: str) -> subprocess.CompletedProcess:
6
+ def instantiate_STARSDataFusion_jl(package_location: str) -> subprocess.CompletedProcess:
7
7
  """
8
8
  Activates a Julia project at a given location and instantiates its dependencies.
9
9
 
10
- This is necessary to ensure all required Julia packages for STARS.jl are
10
+ This is necessary to ensure all required Julia packages for STARSDataFusion.jl are
11
11
  downloaded and ready for use within the specified project environment.
12
12
 
13
13
  Args:
@@ -30,7 +30,7 @@ def instantiate_STARS_jl(package_location: str) -> subprocess.CompletedProcess:
30
30
 
31
31
  if result.returncode == 0:
32
32
  logger.info(
33
- f"STARS.jl instantiated successfully in directory '{package_location}'!"
33
+ f"STARSDataFusion.jl instantiated successfully in directory '{package_location}'!"
34
34
  )
35
35
  else:
36
36
  logger.error("Error instantiating STARS.jl:")
@@ -0,0 +1,61 @@
1
+ import logging
2
+ import netrc
3
+ import os
4
+
5
+ import earthaccess
6
+
7
+ from .exceptions import *
8
+
9
+ __author__ = "Evan Davis"
10
+
11
+ _AUTH = None
12
+
13
+ def login() -> earthaccess.Auth:
14
+ """
15
+ Login to Earthdata using environment variables if available, falling back to netrc credentials, then interactive login.
16
+ """
17
+ # Only login to earthaccess once
18
+ global _AUTH
19
+ if _AUTH is not None:
20
+ return _AUTH
21
+
22
+ # Check if we're in a testing environment where authentication should be skipped
23
+ if os.environ.get("SKIP_EARTHDATA_LOGIN", "").lower() in ("true", "1", "yes"):
24
+ # Return a mock auth object for testing
25
+ class MockAuth:
26
+ def __init__(self):
27
+ self.authenticated = True
28
+ _AUTH = MockAuth()
29
+ return _AUTH
30
+
31
+ # Temporarily suppress INFO logs from earthaccess during login
32
+ earthaccess_logger = logging.getLogger('earthaccess')
33
+ original_level = earthaccess_logger.level
34
+ earthaccess_logger.setLevel(logging.WARNING)
35
+
36
+ try:
37
+ # First priority: environment variables
38
+ if "EARTHDATA_USERNAME" in os.environ and "EARTHDATA_PASSWORD" in os.environ:
39
+ _AUTH = earthaccess.login(strategy="environment")
40
+ return _AUTH
41
+
42
+ # Second priority: netrc credentials
43
+ try:
44
+ secrets = netrc.netrc()
45
+ auth = secrets.authenticators("urs.earthdata.nasa.gov")
46
+ if auth:
47
+ _AUTH = earthaccess.login(strategy="netrc")
48
+ return _AUTH
49
+ except (FileNotFoundError, netrc.NetrcParseError):
50
+ # .netrc file doesn't exist or is malformed, continue to interactive login
51
+ pass
52
+
53
+ # Last resort: interactive login
54
+ _AUTH = earthaccess.login(strategy="interactive")
55
+ return _AUTH
56
+
57
+ except Exception as e:
58
+ raise CMRServerUnreachable(e)
59
+ finally:
60
+ # Restore original logging level
61
+ earthaccess_logger.setLevel(original_level)
@@ -4,7 +4,7 @@ from datetime import date
4
4
  from os.path import abspath, dirname, join, exists
5
5
  import logging
6
6
 
7
- from .instantiate_STARS_jl import instantiate_STARS_jl
7
+ from .instantiate_STARSDataFusion_jl import instantiate_STARSDataFusion_jl
8
8
 
9
9
  logger = logging.getLogger(__name__)
10
10
 
@@ -71,7 +71,7 @@ def process_julia_data_fusion(
71
71
  STARS_source_directory = abspath(dirname(__file__))
72
72
 
73
73
  # Instantiate Julia dependencies
74
- instantiate_STARS_jl(STARS_source_directory)
74
+ instantiate_STARSDataFusion_jl(STARS_source_directory)
75
75
 
76
76
  # Base Julia command with required arguments
77
77
  command = (
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ECOv003-L2T-STARS
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: ECOSTRESS Collection 3 JPL STARS Data Fusion Product Generating Executable (PGE)
5
5
  Author-email: "Gregory H. Halverson" <gregory.h.halverson@jpl.nasa.gov>
6
6
  Project-URL: Homepage, https://github.com/ECOSTRESS-Collection-3/ECOv003-L2T-STARS
@@ -21,7 +21,6 @@ Requires-Dist: matplotlib
21
21
  Requires-Dist: modland
22
22
  Requires-Dist: numpy
23
23
  Requires-Dist: pandas
24
- Requires-Dist: pycksum
25
24
  Requires-Dist: pytictoc
26
25
  Requires-Dist: rasters
27
26
  Requires-Dist: scikit-image
@@ -1,14 +1,15 @@
1
1
  ECOv003_L2T_STARS/ECOv003_DL.py,sha256=7ECuYIPMDsgptcAIcC2lgfvn-ljvPJHQ9tNPnMRxkIQ,24590
2
2
  ECOv003_L2T_STARS/ECOv003_DL.xml,sha256=TQxOlTJHnjcRf9RiAGVJe2mIS-ks6WL32Ze33z0_kxA,2032
3
- ECOv003_L2T_STARS/ECOv003_L2T_STARS.py,sha256=Jgiwd2TRCMq37FiEA-JECJZQKLBm34oytIWS9PG_x30,5891
4
3
  ECOv003_L2T_STARS/ECOv003_L2T_STARS.xml,sha256=Sg6GJx5PO1TVMIpGCDb4gatcShLRa6yBMwxwHKAWNKw,2084
5
4
  ECOv003_L2T_STARS/L2TSTARSConfig.py,sha256=pH5WAzjfUdlam8Ngi2hxmT8Sect5bi2D6cP9HbpM_Tw,8849
6
- ECOv003_L2T_STARS/L2T_STARS.py,sha256=3_eu2Yh8RZi5WQqat5sjwNfc2Kzhh-T_DhLAG5dn38A,25401
5
+ ECOv003_L2T_STARS/L2T_STARS.py,sha256=4LLRJOoMhJNtmfwj9x7c6FLA7G-CLUct5TegJtIu8P8,25403
7
6
  ECOv003_L2T_STARS/Manifest.toml,sha256=k6dzN8jpePGBIPqTkKFsYDv5ezV3DgO4ChHss_cI524,84043
8
7
  ECOv003_L2T_STARS/Project.toml,sha256=Ywo_YsreqwgpbuNP3NWMsXw3VY2m8NTUrBwKCyBUbuM,657
9
- ECOv003_L2T_STARS/__init__.py,sha256=C-Ut4I9wJrxVgLjpktu50trMuQNd73wS_gPJNxhp9UM,104
8
+ ECOv003_L2T_STARS/__init__.py,sha256=fdYigR4HXHd-NYUCafBD4GTqXUQV5LK337bJVN556fA,91
10
9
  ECOv003_L2T_STARS/calibrate_fine_to_coarse.py,sha256=2YQHo0hO5EuvGt6TOF_1WypiqNDAR5gjvs0cYe9F_vQ,2345
10
+ ECOv003_L2T_STARS/cksum.py,sha256=Cw3FHD39Osrb4c9Dc1jSUB1SZaxIJsWHqsNVeWwYokA,1823
11
11
  ECOv003_L2T_STARS/constants.py,sha256=5-cxFiiq_zDKIvkK8Bi2iVVzST-15ytdu4QAvlLz_OY,1996
12
+ ECOv003_L2T_STARS/exceptions.py,sha256=ypahdRaZVMIoQrHUIZXiwzDNeLaCH46rUAfs_8MHKBE,48
12
13
  ECOv003_L2T_STARS/generate_L2T_STARS_runconfig.py,sha256=gyU0-xjkC0bZcK9NeoFwLaXjNJhsSrVD2YnxLVLVLJs,11142
13
14
  ECOv003_L2T_STARS/generate_NDVI_coarse_directory.py,sha256=i1pFHFyMuj2e6aQ2wTgrF2-rAQXWe8LE2mbCRksj3c8,590
14
15
  ECOv003_L2T_STARS/generate_NDVI_coarse_image.py,sha256=9XBBV1FFqjxkEFnr61xr9R2tnHQAlx2XN9KzLN8RApc,1215
@@ -23,13 +24,15 @@ ECOv003_L2T_STARS/generate_filename.py,sha256=XppMoRiKBG1Rf-uWu95UCO1klK6uv5GdK9
23
24
  ECOv003_L2T_STARS/generate_input_staging_directory.py,sha256=TlFKYliu6BbfDGLlwD0nlt0AZzDwKWeEgeTtzmicElY,800
24
25
  ECOv003_L2T_STARS/generate_model_state_tile_date_directory.py,sha256=U9d7vcuA1Udq6tuyRKUIibfoOPsJKV5dp5AWT7qLcfc,939
25
26
  ECOv003_L2T_STARS/generate_output_directory.py,sha256=Dr1zX6ljYzxFgC9XkocYBiF5aMGggHJejtpI9hbLwlM,889
26
- ECOv003_L2T_STARS/install_STARS_jl.py,sha256=EBJYvEokDxVDW6UxcCCaGSbDVtUiUz29QJxntdMYqCM,1738
27
- ECOv003_L2T_STARS/instantiate_STARS_jl.py,sha256=x9N7r4sxUoydEOlSUXvh_w3YBcy9ln7H2V_mK1M-Czk,1407
27
+ ECOv003_L2T_STARS/install_STARSDataFusion_jl.py,sha256=XbB_T0mzHqpmhh3cjKT0FpgqHxaTtS3iE_IZw4iZGKc,1778
28
+ ECOv003_L2T_STARS/instantiate_STARSDataFusion_jl.py,sha256=B-N_tlSBY7DQ2gZK6mPtJ8WL8XCXA_edMDEOu2xldcs,1437
28
29
  ECOv003_L2T_STARS/load_prior.py,sha256=rVu3ImvReFxARalICCiZcMQ9ML_ehmQ9mc8HmXoHdm0,11335
30
+ ECOv003_L2T_STARS/login.py,sha256=zInQL33NibC8fNGzLw9qk0MDay71KYk87V-UsV-gkwA,1945
31
+ ECOv003_L2T_STARS/main.py,sha256=Jgiwd2TRCMq37FiEA-JECJZQKLBm34oytIWS9PG_x30,5891
29
32
  ECOv003_L2T_STARS/prior.py,sha256=fLE54pBIOG6sCas1G60nhn8LcHa2AqZ_eSY_J-MB4eM,2867
30
33
  ECOv003_L2T_STARS/process_ECOSTRESS_data_fusion_distributed_bias.jl,sha256=LrFBCQp4ovJ6wI-oIIbvpdZEiSQtt0YmScbPmxlaSoA,15400
31
34
  ECOv003_L2T_STARS/process_STARS_product.py,sha256=d26HdxcY9XBXa_MFCJfFm7BMCtmCaUrNdSVXiY0-D6Y,22406
32
- ECOv003_L2T_STARS/process_julia_data_fusion.py,sha256=D4zSkihn6EC19009gFD3lXXxiCjsJwTPx0rqE_Wvgyw,5237
35
+ ECOv003_L2T_STARS/process_julia_data_fusion.py,sha256=t0178tuQDYnei3jfgx8GbgW2Q0uwfcnFNOpnhr1PZFA,5267
33
36
  ECOv003_L2T_STARS/retrieve_STARS_sources.py,sha256=s6026PQ5PRQTPFgjrDa4vgbHa8OqUanBqn0Wdoq0DbA,3838
34
37
  ECOv003_L2T_STARS/runconfig.py,sha256=TLaB3w6Y0qEZPqMa-YXuUzKSACrdpKmrozUNLh70aQw,1519
35
38
  ECOv003_L2T_STARS/version.py,sha256=CcCeNt2pNqb8AQ_vHLUbLJciE8hxTMeGmN79vAYObYQ,354
@@ -39,13 +42,12 @@ ECOv003_L2T_STARS/BRDF/SZA.py,sha256=_J5ybmrg8ASVglXp4OvSoVutkDVeSxDBygfTe848sww
39
42
  ECOv003_L2T_STARS/BRDF/__init__.py,sha256=7HYw9eTuudpkgtpXAjFN1CpPjr6R9JsnW3bLtNBdRSM,20
40
43
  ECOv003_L2T_STARS/BRDF/statistical_radiative_transport.txt,sha256=KHIGS6afnY7m0CzHki4zeuwqttjK38jgZg8-oYDn68o,26999
41
44
  ECOv003_L2T_STARS/BRDF/version.txt,sha256=atlhOkVXmNbZLl9fOQq0uqcFlryGntaxf1zdKyhjXwY,5
42
- ECOv003_L2T_STARS/LPDAAC/LPDAACDataPool.py,sha256=OoJy2_W7tCJG7zJA6bfrozmyf4SKsa2ESjIsdJgfM_M,16439
45
+ ECOv003_L2T_STARS/LPDAAC/LPDAACDataPool.py,sha256=WqIy0wcHhje1Dx8Uq0e8W_BsEJOJIchO4DroaGMsKes,16887
43
46
  ECOv003_L2T_STARS/LPDAAC/__init__.py,sha256=o8qP8kTXyBp9dFKErVOwvcZuUo7BTVU0d5UyIsOKG8g,235
44
47
  ECOv003_L2T_STARS/LPDAAC/version.txt,sha256=2_CXjsK1h6XWGH_cxBzOn_LA647vrboOtR84QKtu60Y,5
45
48
  ECOv003_L2T_STARS/VIIRS/VIIRSDataPool.py,sha256=mht104y3ayLysElKf9IgaqX78I0Q-4NJJmfCxMgxDzs,8781
46
49
  ECOv003_L2T_STARS/VIIRS/VIIRSDownloader.py,sha256=NCf3ZItLIBkZOZugYHuQMurziAsH7LbhLKbg-ZbWC7g,616
47
- ECOv003_L2T_STARS/VIIRS/VIIRS_CMR_LOGIN.py,sha256=Osl7BPV6QsGKATFCmow0oDN-YA98SDBcLRCy3X9XaPQ,1094
48
- ECOv003_L2T_STARS/VIIRS/VNP09GA.py,sha256=hRJF47KLqCxerwjQQY3wfCbotxW2qAKbe1BxCleyUAo,44162
50
+ ECOv003_L2T_STARS/VIIRS/VNP09GA.py,sha256=9oCqSps3m8oGLcwQ-IuNV2KMiNLD1hSKYJHDIZIhCM8,44138
49
51
  ECOv003_L2T_STARS/VIIRS/VNP43IA4.py,sha256=3qZbDHoLVhoiSr4hoojMxXXuDSNKkN4B9Dan-WMApNs,9881
50
52
  ECOv003_L2T_STARS/VIIRS/VNP43MA3.py,sha256=T_1mxdg_SII0vXp_D422aAU7fE0-7TY46IZzRJPGJ1Q,11043
51
53
  ECOv003_L2T_STARS/VIIRS/__init__.py,sha256=PVyb97Bg5gVMdcyC7JpErQCjJWSrOFdHJH4rNE__eL8,264
@@ -65,9 +67,9 @@ ECOv003_L2T_STARS/daterange/__init__.py,sha256=54kYb9tmsm5twxMqjJKeD__5kGkNDz3Pp
65
67
  ECOv003_L2T_STARS/daterange/daterange.py,sha256=EHa2Xt9fiJ1gbX7aa_QV_br1rAXjg3pHrLSRasOsOhM,959
66
68
  ECOv003_L2T_STARS/timer/__init__.py,sha256=I_MQKp_aamBLUzZv0psEbRgs6GZLOJd4mmJ7bli0Ikc,21
67
69
  ECOv003_L2T_STARS/timer/timer.py,sha256=tn5e3NQmsh55Jp9Fstjf-8KJW4F8UIJs-d_ZLooFYE8,1610
68
- ecov003_l2t_stars-1.2.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
69
- ecov003_l2t_stars-1.2.0.dist-info/METADATA,sha256=VYXsZQfVGnh6vih-AXQ79DeXcr5GOTa81Di5trFdHMI,13306
70
- ecov003_l2t_stars-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
71
- ecov003_l2t_stars-1.2.0.dist-info/entry_points.txt,sha256=NuUuom7EwWtbe3ljZ6KxNbSheTFRnHVNT9rd16tuv0E,119
72
- ecov003_l2t_stars-1.2.0.dist-info/top_level.txt,sha256=lRivA5MjbrabH4sv-LUstMGaLZ865wRQPpz9Kh6-plg,18
73
- ecov003_l2t_stars-1.2.0.dist-info/RECORD,,
70
+ ecov003_l2t_stars-1.3.0.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
71
+ ecov003_l2t_stars-1.3.0.dist-info/METADATA,sha256=5QCrdCDDlS4j4S2Hy_9Og6g7sQdhj6iI_8J09erRWCU,13283
72
+ ecov003_l2t_stars-1.3.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
73
+ ecov003_l2t_stars-1.3.0.dist-info/entry_points.txt,sha256=EVVKltKsqXBc94JIu4IjVrMP0DPqaNEdQoAgcZOApQQ,106
74
+ ecov003_l2t_stars-1.3.0.dist-info/top_level.txt,sha256=lRivA5MjbrabH4sv-LUstMGaLZ865wRQPpz9Kh6-plg,18
75
+ ecov003_l2t_stars-1.3.0.dist-info/RECORD,,
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ ECOv003-DL = ECOv003_DL.ECOv003_DL:main
3
+ ECOv003-L2T-STARS = ECOv003_L2T_STARS.main:main
@@ -1,36 +0,0 @@
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)
@@ -1,3 +0,0 @@
1
- [console_scripts]
2
- ECOv003-DL = ECOv003_DL.ECOv003_DL:main
3
- ECOv003-L2T-STARS = ECOv003_L2T_STARS.ECOv003_L2T_STARS:main
File without changes