From 57ac5381e5bb5d4fba4030903cf9167dce146148 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Mon, 31 Jul 2023 18:53:08 +0000 Subject: [PATCH 01/63] wip inheritance method for modularizing authentication --- icepyx/core/auth.py | 80 ++++++++++++++++++++++++++++++++++++++++ icepyx/core/query.py | 68 +++++++--------------------------- icepyx/core/variables.py | 5 +-- 3 files changed, 95 insertions(+), 58 deletions(-) create mode 100644 icepyx/core/auth.py diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py new file mode 100644 index 000000000..a615398f3 --- /dev/null +++ b/icepyx/core/auth.py @@ -0,0 +1,80 @@ +import earthaccess + + +class EarthdataAuth(): + """ + This class stores methods related to logging into Earthdata. It is inherited by + any other module that requires authentication. + """ + def __init__( + self, + _session=None, + _s3login_credentials=None, + ): + self._session = _session + self._s3login_credentials = _s3login_credentials + + def __str__(self): + if self._session: + repr_string = "EarthdataAuth obj with session initialized" + else: + repr_string = "EarthdataAuth obj without session initialized" + return repr_string + + def session_started(): + # return True/False if there is a session + pass + + def s3credentials_created(): + # return True/False if there are s3 credentials + pass + + def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None: + """ + Authenticate with NASA Earthdata to enable data ordering and download. + + Generates the needed authentication sessions and tokens, including for cloud access. + Authentication is completed using the [earthaccess library](https://nsidc.github.io/earthaccess/). + Methods for authenticating are: + 1. Storing credentials as environment variables ($EARTHDATA_LOGIN and $EARTHDATA_PASSWORD) + 2. Entering credentials interactively + 3. Storing credentials in a .netrc file (not recommended for security reasons) + More details on using these methods is available in the [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth). + The input parameters listed here are provided for backwards compatibility; + before earthaccess existed, icepyx handled authentication and required these inputs. + + Parameters + ---------- + uid : string, default None + Deprecated keyword for Earthdata login user ID. + email : string, default None + Deprecated keyword for backwards compatibility. + s3token : boolean, default False + Deprecated keyword to generate AWS s3 ICESat-2 data access credentials + kwargs : key:value pairs + Keyword arguments to be passed into earthaccess.login(). + + Examples + -------- + >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP + >>> reg_a.earthdata_login() # doctest: +SKIP + Enter your Earthdata Login username: ___________________ + + EARTHDATA_USERNAME and EARTHDATA_PASSWORD are not set in the current environment, try setting them or use a different strategy (netrc, interactive) + No .netrc found in /Users/username + + """ + + auth = earthaccess.login(**kwargs) + if auth.authenticated: + self._auth = auth + self._session = auth.get_session() + + if s3token == True: + self._s3login_credentials = auth.get_s3_credentials(daac="NSIDC") + + if uid != None or email != None: + warnings.warn( + "The user id (uid) and/or email keyword arguments are no longer required.", + DeprecationWarning, + ) diff --git a/icepyx/core/query.py b/icepyx/core/query.py index b2041cbd4..839e69d94 100644 --- a/icepyx/core/query.py +++ b/icepyx/core/query.py @@ -1,5 +1,4 @@ import datetime as dt -import earthaccess import geopandas as gpd import json import matplotlib.pyplot as plt @@ -22,6 +21,7 @@ import icepyx.core.spatial as spat import icepyx.core.temporal as tp from icepyx.core.visualization import Visualize +from icepyx.core.auth import EarthdataAuth class GenQuery: @@ -234,6 +234,7 @@ def __init__( cycles=None, tracks=None, files=None, # NOTE: if you end up implemeting this feature here, use a better variable name than "files" + auth=None, **kwargs, ): @@ -276,6 +277,8 @@ def __init__( self._prod, cycles=self.cycles, tracks=self.tracks ) + # authenticat + super(EarthdataAuth).__init__() # ---------------------------------------------------------------------- # Properties @@ -687,14 +690,16 @@ def order_vars(self): if hasattr(self, "_cust_options"): self._order_vars = Variables( self._source, - session=self._session, + _session=self._session, + _s3login_credentials = self._s3login_credentials, product=self.product, avail=self._cust_options["variables"], ) else: self._order_vars = Variables( self._source, - session=self._session, + _session=self._session, + _s3login_credentials = self._s3login_credentials, product=self.product, version=self._version, ) @@ -727,7 +732,10 @@ def file_vars(self): if not hasattr(self, "_file_vars"): if self._source == "file": - self._file_vars = Variables(self._source, product=self.product) + self._file_vars = Variables(self._source, + _session = self._session, + _s3login_credentials = self._s3login_credentials, + product=self.product) return self._file_vars @@ -898,57 +906,7 @@ def show_custom_options(self, dictview=False): pprint.pprint(self._cust_options[k]) # ---------------------------------------------------------------------- - # Methods - Login and Granules (NSIDC-API) - - def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None: - """ - Authenticate with NASA Earthdata to enable data ordering and download. - - Generates the needed authentication sessions and tokens, including for cloud access. - Authentication is completed using the [earthaccess library](https://nsidc.github.io/earthaccess/). - Methods for authenticating are: - 1. Storing credentials as environment variables ($EARTHDATA_LOGIN and $EARTHDATA_PASSWORD) - 2. Entering credentials interactively - 3. Storing credentials in a .netrc file (not recommended for security reasons) - More details on using these methods is available in the [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth). - The input parameters listed here are provided for backwards compatibility; - before earthaccess existed, icepyx handled authentication and required these inputs. - - Parameters - ---------- - uid : string, default None - Deprecated keyword for Earthdata login user ID. - email : string, default None - Deprecated keyword for backwards compatibility. - s3token : boolean, default False - Deprecated keyword to generate AWS s3 ICESat-2 data access credentials - kwargs : key:value pairs - Keyword arguments to be passed into earthaccess.login(). - - Examples - -------- - >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP - Enter your Earthdata Login username: ___________________ - - EARTHDATA_USERNAME and EARTHDATA_PASSWORD are not set in the current environment, try setting them or use a different strategy (netrc, interactive) - No .netrc found in /Users/username - - """ - - auth = earthaccess.login(**kwargs) - if auth.authenticated: - self._auth = auth - self._session = auth.get_session() - - if s3token == True: - self._s3login_credentials = auth.get_s3_credentials(daac="NSIDC") - - if uid != None or email != None: - warnings.warn( - "The user id (uid) and/or email keyword arguments are no longer required.", - DeprecationWarning, - ) + # Methods - Granules (NSIDC-API) # DevGoal: check to make sure the see also bits of the docstrings work properly in RTD def avail_granules(self, ids=False, cycles=False, tracks=False, cloud=False): diff --git a/icepyx/core/variables.py b/icepyx/core/variables.py index 58e5a1e8f..3666a0357 100644 --- a/icepyx/core/variables.py +++ b/icepyx/core/variables.py @@ -3,6 +3,7 @@ import pprint import icepyx.core.is2ref as is2ref +from icepyx.core.auth import EarthdataAuth # DEVGOAL: use h5py to simplify some of these tasks, if possible! @@ -18,7 +19,7 @@ def list_of_dict_vals(input_dict): # REFACTOR: class needs better docstrings # DevNote: currently this class is not tested -class Variables: +class Variables(EarthdataAuth): """ Get, create, interact, and manipulate lists of variables and variable paths contained in ICESat-2 products. @@ -50,7 +51,6 @@ def __init__( vartype, avail=None, wanted=None, - session=None, product=None, version=None, path=None, @@ -62,7 +62,6 @@ def __init__( self.product = product self._avail = avail self.wanted = wanted - self._session = session # DevGoal: put some more/robust checks here to assess validity of inputs From 703d832f0803d1b94790e53a32455d90d0494f1c Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 1 Aug 2023 14:23:08 +0000 Subject: [PATCH 02/63] add nsidc_s3 option to Variables class --- icepyx/core/variables.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/icepyx/core/variables.py b/icepyx/core/variables.py index 58e5a1e8f..da64deae2 100644 --- a/icepyx/core/variables.py +++ b/icepyx/core/variables.py @@ -1,7 +1,9 @@ -import numpy as np import os import pprint +import numpy as np +import parse + import icepyx.core.is2ref as is2ref # DEVGOAL: use h5py to simplify some of these tasks, if possible! @@ -26,7 +28,7 @@ class Variables: Parameters ---------- vartype : string - One of ['order', 'file'] to indicate the source of the input variables. + One of ['order', 'file', 'nsidc-s3'] to indicate the source of the input variables. This field will be auto-populated when a variable object is created as an attribute of a query object. avail : dictionary, default None @@ -56,7 +58,7 @@ def __init__( path=None, ): - assert vartype in ["order", "file"], "Please submit a valid variables type flag" + assert vartype in ["order", "file", "nsidc-s3"], "Please submit a valid variables type flag" self._vartype = vartype self.product = product @@ -72,6 +74,14 @@ def __init__( elif self._vartype == "file": # DevGoal: check that the list or string are valid dir/files self.path = path + elif self._vartype == "nsidc-s3": + # Grab metadata from s3 path + template = ('s3://nsidc-cumulus-prod-protected/ATLAS/{product}/{version}/' + '{year}/{month}/{day}/{filename}') + s3_pathinfo = parse.parse(template, path) + self._version = s3_pathinfo['version'] + self._product = s3_pathinfo['product'] + self.path = path # @property # def wanted(self): @@ -99,7 +109,7 @@ def avail(self, options=False, internal=False): # return self._avail # else: if not hasattr(self, "_avail") or self._avail == None: - if self._vartype == "order": + if self._vartype in ["order", "nsidc-s3"]: self._avail = is2ref._get_custom_options( self._session, self.product, self._version )["variables"] From 9d09ff9658c4fdf958a80253d60bfb1e8cbfa365 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 1 Aug 2023 17:07:58 +0000 Subject: [PATCH 03/63] mvp remove intake from Read --- icepyx/core/read.py | 51 ++++++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index 5a497279a..5860e32dc 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -4,6 +4,7 @@ import numpy as np import xarray as xr +import h5py import icepyx.core.is2cat as is2cat import icepyx.core.is2ref as is2ref @@ -258,7 +259,7 @@ def __init__( catalog=None, out_obj_type=None, # xr.Dataset, ): - + # Note: maybe just don't add default values, so that Python enforces their existence? if data_source is None: raise ValueError("Please provide a data source.") else: @@ -271,10 +272,16 @@ def __init__( ) else: self._prod = is2ref._validate_product(product) - + + # TODO delete? seems like it just validates the pattern + # Does Read accept a directory right now? Why would there be multiple files in the list? + # seems like yes, it does accept a directory + # does it check, then, that all the files have the same version and product? pattern_ck, filelist = Read._check_source_for_pattern( data_source, filename_pattern ) + print('pattern_ck', pattern_ck) + print('filelist', filelist) assert pattern_ck # Note: need to check if this works for subset and non-subset NSIDC files (processed_ prepends the former) self._pattern = filename_pattern @@ -282,7 +289,8 @@ def __init__( # this is a first pass at getting rid of mixed product types and warning the user. # it takes an approach assuming the product name is in the filename, but needs reworking if we let multiple products be loaded # one way to handle this would be bring in the product info during the loading step and fill in product there instead of requiring it from the user - filtered_filelist = [file for file in filelist if self._prod in file] + filtered_filelist = [file for file in filelist if self._prod in Read._get_product_and_version(file)] + print('filtered', filtered_filelist) if len(filtered_filelist) == 0: warnings.warn( "Your filenames do not contain a product identifier (e.g. ATL06). " @@ -665,6 +673,13 @@ def _build_dataset_template(self, file): attrs=dict(data_product=self._prod), ) return is2ds + + def _get_product_and_version(filepath): + # TODO either persist this info or remove 'version', since it isn't necessary right now + with h5py.File(filepath, 'r') as f: + product = f['METADATA']['DatasetIdentification'].attrs['shortName'].decode() + version = f['METADATA']['DatasetIdentification'].attrs['VersionID'].decode() + return product, version def _read_single_grp(self, file, grp_path): """ @@ -684,25 +699,10 @@ def _read_single_grp(self, file, grp_path): Xarray dataset with the specified group. """ - - try: - grpcat = is2cat.build_catalog( - file, self._pattern, self._source_type, grp_paths=grp_path - ) - ds = grpcat[self._source_type].read() - - # NOTE: could also do this with h5py, but then would have to read in each variable in the group separately - except ValueError: - grpcat = is2cat.build_catalog( - file, - self._pattern, - self._source_type, - grp_paths=grp_path, - extra_engine_kwargs={"phony_dims": "access"}, - ) - ds = grpcat[self._source_type].read() - - return ds + # I think this would fail if a group that has too high of a level of nesting + # is given. Consider this. + # TODO: update docstring + return xr.open_dataset(file, group=grp_path) def _build_single_file_dataset(self, file, groups_list): """ @@ -722,8 +722,11 @@ def _build_single_file_dataset(self, file, groups_list): ------- Xarray Dataset """ - - file_product = self._read_single_grp(file, "/").attrs["identifier_product_type"] + # why do we do get the product twice? is it important to us that the user tells us + # correctly their product? Do we trust the metadata or the filename more? + # Also revisit the semantics of this. Not sure if it makes semantic sense for this + # to be a class method + file_product, _ = Read._get_product_and_version(file) assert ( file_product == self._prod ), "Your product specification does not match the product specification within your files." From 4564b3b7fa0e0c762a51ead546dd68fac24e7b2d Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Thu, 3 Aug 2023 01:37:45 +0000 Subject: [PATCH 04/63] outline of mixin method of authentication --- icepyx/core/auth.py | 54 ++++++++++++++++++++++++++++------------ icepyx/core/query.py | 30 +++++++++++----------- icepyx/core/variables.py | 12 ++++++--- 3 files changed, 60 insertions(+), 36 deletions(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index a615398f3..66a77d070 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -1,33 +1,54 @@ +import copy + import earthaccess -class EarthdataAuth(): +class EarthdataAuthMixin(): """ This class stores methods related to logging into Earthdata. It is inherited by any other module that requires authentication. """ - def __init__( - self, - _session=None, - _s3login_credentials=None, - ): - self._session = _session - self._s3login_credentials = _s3login_credentials + def __init__(self, auth=None): + self._auth = copy.deepcopy(auth) + # initializatin of session and s3 creds is not allowed because those are generated + # from the auth object + self._session = None + self._s3login_credentials = None def __str__(self): - if self._session: + if self.session: repr_string = "EarthdataAuth obj with session initialized" else: repr_string = "EarthdataAuth obj without session initialized" return repr_string - - def session_started(): - # return True/False if there is a session - pass - def s3credentials_created(): - # return True/False if there are s3 credentials - pass + @property + def auth(self): + # Only login the first time .auth is accessed + if self._auth is None: + self._auth = earthaccess.login() + return self._auth + + @property + def session(self): + # Only generate a session the first time .session is accessed + if self._session is None: + if self._auth is None: + self._auth = earthaccess.login() + if self._auth.authenticated: + self._session = self._auth.get_session() + return self._session + + @property + def s3login_credentials(self): + # Only generate s3login_credentials the first time credentials are accessed + # TODO what if a user needs to regenerate after an hour? + if self._s3login_credentials is None: + if self._auth is None: + self._auth = earthaccess.login() + if self._auth.authenticated: + self._s3login_credentials = self._auth.get_s3_credentials(daac="NSIDC") + return self._s3login_credentials def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None: """ @@ -42,6 +63,7 @@ def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None More details on using these methods is available in the [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth). The input parameters listed here are provided for backwards compatibility; before earthaccess existed, icepyx handled authentication and required these inputs. + DevNote: Maintained for backward compatibility Parameters ---------- diff --git a/icepyx/core/query.py b/icepyx/core/query.py index 839e69d94..7b596b366 100644 --- a/icepyx/core/query.py +++ b/icepyx/core/query.py @@ -21,7 +21,7 @@ import icepyx.core.spatial as spat import icepyx.core.temporal as tp from icepyx.core.visualization import Visualize -from icepyx.core.auth import EarthdataAuth +from icepyx.core.auth import EarthdataAuthMixin class GenQuery: @@ -152,7 +152,7 @@ def __str__(self): # DevGoal: update docs throughout to allow for polygon spatial extent # Note: add files to docstring once implemented # DevNote: currently this class is not tested -class Query(GenQuery): +class Query(GenQuery, EarthdataAuthMixin): """ Query and get ICESat-2 data @@ -277,8 +277,8 @@ def __init__( self._prod, cycles=self.cycles, tracks=self.tracks ) - # authenticat - super(EarthdataAuth).__init__() + # initialize authentication properties + EarthdataAuthMixin.__init__(self) # ---------------------------------------------------------------------- # Properties @@ -690,16 +690,14 @@ def order_vars(self): if hasattr(self, "_cust_options"): self._order_vars = Variables( self._source, - _session=self._session, - _s3login_credentials = self._s3login_credentials, + auth = self.auth, product=self.product, avail=self._cust_options["variables"], ) else: self._order_vars = Variables( self._source, - _session=self._session, - _s3login_credentials = self._s3login_credentials, + auth=self.auth, product=self.product, version=self._version, ) @@ -733,9 +731,9 @@ def file_vars(self): if not hasattr(self, "_file_vars"): if self._source == "file": self._file_vars = Variables(self._source, - _session = self._session, - _s3login_credentials = self._s3login_credentials, - product=self.product) + auth=self.auth, + product=self.product, + ) return self._file_vars @@ -894,7 +892,7 @@ def show_custom_options(self, dictview=False): all(key in self._cust_options.keys() for key in keys) except AttributeError or KeyError: self._cust_options = is2ref._get_custom_options( - self._session, self.product, self._version + self.session, self.product, self._version ) for h, k in zip(headers, keys): @@ -1025,7 +1023,7 @@ def order_granules(self, verbose=False, subset=True, email=False, **kwargs): if "email" in self._reqparams.fmted_keys.keys() or email == False: self._reqparams.build_params(**self._reqparams.fmted_keys) elif email == True: - user_profile = self._auth.get_user_profile() + user_profile = self.auth.get_user_profile() self._reqparams.build_params( **self._reqparams.fmted_keys, email=user_profile["email_address"] ) @@ -1060,7 +1058,7 @@ def order_granules(self, verbose=False, subset=True, email=False, **kwargs): self.subsetparams(**kwargs), verbose, subset, - session=self._session, + session=self.session, geom_filepath=self._spatial._geom_file, ) @@ -1071,7 +1069,7 @@ def order_granules(self, verbose=False, subset=True, email=False, **kwargs): self.subsetparams(**kwargs), verbose, subset, - session=self._session, + session=self.session, geom_filepath=self._spatial._geom_file, ) @@ -1137,7 +1135,7 @@ def download_granules( ): self.order_granules(verbose=verbose, subset=subset, **kwargs) - self._granules.download(verbose, path, session=self._session, restart=restart) + self._granules.download(verbose, path, session=self.session, restart=restart) # DevGoal: add testing? What do we test, and how, given this is a visualization. # DevGoal(long term): modify this to accept additional inputs, etc. diff --git a/icepyx/core/variables.py b/icepyx/core/variables.py index 3666a0357..a2e69e3e9 100644 --- a/icepyx/core/variables.py +++ b/icepyx/core/variables.py @@ -3,7 +3,7 @@ import pprint import icepyx.core.is2ref as is2ref -from icepyx.core.auth import EarthdataAuth +from icepyx.core.auth import EarthdataAuthMixin # DEVGOAL: use h5py to simplify some of these tasks, if possible! @@ -19,7 +19,7 @@ def list_of_dict_vals(input_dict): # REFACTOR: class needs better docstrings # DevNote: currently this class is not tested -class Variables(EarthdataAuth): +class Variables(EarthdataAuthMixin): """ Get, create, interact, and manipulate lists of variables and variable paths contained in ICESat-2 products. @@ -54,10 +54,14 @@ def __init__( product=None, version=None, path=None, + auth=None, ): assert vartype in ["order", "file"], "Please submit a valid variables type flag" - + + # initialize authentication properties + EarthdataAuthMixin.__init__(self, auth=auth) + self._vartype = vartype self.product = product self._avail = avail @@ -100,7 +104,7 @@ def avail(self, options=False, internal=False): if not hasattr(self, "_avail") or self._avail == None: if self._vartype == "order": self._avail = is2ref._get_custom_options( - self._session, self.product, self._version + self.session, self.product, self._version )["variables"] elif self._vartype == "file": From 16b8d3f880a07b5c1b3bf2d6fd50176753d9bdf7 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 8 Aug 2023 15:15:56 +0000 Subject: [PATCH 05/63] add s3 credential timer and auth check --- icepyx/core/auth.py | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index 66a77d070..fd7202cf0 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -1,7 +1,11 @@ import copy +import datetime import earthaccess +class AuthenticationError(Exception): + pass + class EarthdataAuthMixin(): """ @@ -14,6 +18,7 @@ def __init__(self, auth=None): # from the auth object self._session = None self._s3login_credentials = None + self._s3_initial_ts = None # timer for 1h expiration on s3 credentials def __str__(self): if self.session: @@ -26,28 +31,39 @@ def __str__(self): def auth(self): # Only login the first time .auth is accessed if self._auth is None: - self._auth = earthaccess.login() + auth = earthaccess.login() + # check for a valid auth response + if auth.authenticated is False: + # would be nice to be able to push the error message from earthaccess to the user, + # but I can't find where that is stored in earthaccess auth object + raise AuthenticationError('Earthdata authentication failed. Check output for error message') + else: + self._auth = auth + return self._auth @property def session(self): # Only generate a session the first time .session is accessed if self._session is None: - if self._auth is None: - self._auth = earthaccess.login() - if self._auth.authenticated: - self._session = self._auth.get_session() + self._session = self.auth.get_session() return self._session @property def s3login_credentials(self): - # Only generate s3login_credentials the first time credentials are accessed - # TODO what if a user needs to regenerate after an hour? + + def set_s3_creds(): + ''' Store s3login creds from `auth`and reset the starting time for the 1 hour reset + clock''' + self._s3login_credentials = self.auth.get_s3_credentials(daac="NSIDC") + self._s3_initial_ts = datetime.datetime.now() + + # Only generate s3login_credentials the first time credentials are accessed, or if an hour + # has passed since the last login if self._s3login_credentials is None: - if self._auth is None: - self._auth = earthaccess.login() - if self._auth.authenticated: - self._s3login_credentials = self._auth.get_s3_credentials(daac="NSIDC") + set_s3_creds() + elif (datetime.datetime.now() - self._s3_initial_ts) >= datetime.timedelta(hours=1): + set_s3_creds() return self._s3login_credentials def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None: From 54aeda0b339eb1123d32097bf34dbe1fbfc4c204 Mon Sep 17 00:00:00 2001 From: Rachel Wegener <35503632+rwegener2@users.noreply.github.com> Date: Wed, 9 Aug 2023 11:12:46 -0400 Subject: [PATCH 06/63] Update icepyx/core/variables.py Co-authored-by: Jessica Scheick --- icepyx/core/variables.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icepyx/core/variables.py b/icepyx/core/variables.py index a2e69e3e9..db3983cd9 100644 --- a/icepyx/core/variables.py +++ b/icepyx/core/variables.py @@ -2,8 +2,8 @@ import os import pprint -import icepyx.core.is2ref as is2ref from icepyx.core.auth import EarthdataAuthMixin +import icepyx.core.is2ref as is2ref # DEVGOAL: use h5py to simplify some of these tasks, if possible! From 083426c0ab152c8034b85c60ccf6a8e5f6ef7419 Mon Sep 17 00:00:00 2001 From: Rachel Wegener <35503632+rwegener2@users.noreply.github.com> Date: Wed, 9 Aug 2023 11:12:56 -0400 Subject: [PATCH 07/63] Update icepyx/core/query.py Co-authored-by: Jessica Scheick --- icepyx/core/query.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icepyx/core/query.py b/icepyx/core/query.py index 7b596b366..d800a5a7d 100644 --- a/icepyx/core/query.py +++ b/icepyx/core/query.py @@ -18,10 +18,10 @@ # from icepyx.core.granules import Granules from icepyx.core.variables import Variables as Variables import icepyx.core.validate_inputs as val +from icepyx.core.auth import EarthdataAuthMixin import icepyx.core.spatial as spat import icepyx.core.temporal as tp from icepyx.core.visualization import Visualize -from icepyx.core.auth import EarthdataAuthMixin class GenQuery: From 76d3c968b1c9fd2c71b9276650788ba7a8423b92 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Wed, 9 Aug 2023 16:15:37 +0000 Subject: [PATCH 08/63] add docstrings to auth.py --- icepyx/core/auth.py | 43 ++++++++++++++++++++++++++++++++++++------- 1 file changed, 36 insertions(+), 7 deletions(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index fd7202cf0..ad728ba35 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -4,13 +4,35 @@ import earthaccess class AuthenticationError(Exception): + ''' + Raised when an error is encountered while authenticating Earthdata credentials + ''' pass class EarthdataAuthMixin(): """ - This class stores methods related to logging into Earthdata. It is inherited by - any other module that requires authentication. + This mixin class stores properties and methods related to logging into Earthdata. + It can be inherited by any other class that requires authentication. + + The class provides 3 properties: auth, session, and s3login_credentials. The method + earthdata_login() is included for backwards compatibility. + + The class can be created without any initialization parameters, and the properties will + be populated when they are called. It can alternately be initialized with an + earthaccess.auth.Auth object, which will then be used to create a session of + s3login_credentials as they are called. + + Parameters + ---------- + auth : earthaccess.auth.Auth, default None + Optional parameter to pass initialize an object with existing credentials + + Examples + -------- + >>> a = EarthdataAuthMixin() + >>> a.session + >>> a.s3login_credentials """ def __init__(self, auth=None): self._auth = copy.deepcopy(auth) @@ -29,13 +51,14 @@ def __str__(self): @property def auth(self): + ''' + Authentication object returned from earthaccess.login() which stores user authentication. + ''' # Only login the first time .auth is accessed if self._auth is None: auth = earthaccess.login() # check for a valid auth response if auth.authenticated is False: - # would be nice to be able to push the error message from earthaccess to the user, - # but I can't find where that is stored in earthaccess auth object raise AuthenticationError('Earthdata authentication failed. Check output for error message') else: self._auth = auth @@ -44,6 +67,9 @@ def auth(self): @property def session(self): + ''' + Earthaccess session object for connecting to Earthdata resources. + ''' # Only generate a session the first time .session is accessed if self._session is None: self._session = self.auth.get_session() @@ -51,10 +77,13 @@ def session(self): @property def s3login_credentials(self): - + ''' + A dictionary which stores login credentials for AWS s3 access. This property is accessed + if using AWS cloud data. + ''' + def set_s3_creds(): - ''' Store s3login creds from `auth`and reset the starting time for the 1 hour reset - clock''' + ''' Store s3login creds from `auth`and reset the last updated timestamp''' self._s3login_credentials = self.auth.get_s3_credentials(daac="NSIDC") self._s3_initial_ts = datetime.datetime.now() From e8c9060c0b7e8c08b52ddaad1c932c470e8846d1 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Mon, 14 Aug 2023 14:00:30 +0000 Subject: [PATCH 09/63] add comment to stop tests from running docstring on build --- icepyx/core/auth.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index ad728ba35..a96fad1f3 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -31,8 +31,8 @@ class EarthdataAuthMixin(): Examples -------- >>> a = EarthdataAuthMixin() - >>> a.session - >>> a.s3login_credentials + >>> a.session # doctest: +SKIP + >>> a.s3login_credentials # doctest: +SKIP """ def __init__(self, auth=None): self._auth = copy.deepcopy(auth) From 72c53473c527eb594c337e6de03ccef777dc4017 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Mon, 14 Aug 2023 14:27:04 +0000 Subject: [PATCH 10/63] fix user warning for giving an email parameter --- icepyx/core/auth.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index a96fad1f3..9f794a52b 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -1,5 +1,6 @@ import copy import datetime +import warnings import earthaccess @@ -131,7 +132,7 @@ def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None No .netrc found in /Users/username """ - + auth = earthaccess.login(**kwargs) if auth.authenticated: self._auth = auth @@ -143,5 +144,5 @@ def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None if uid != None or email != None: warnings.warn( "The user id (uid) and/or email keyword arguments are no longer required.", - DeprecationWarning, + DeprecationWarning, stacklevel=2 ) From 434bbf24d61305a50dcf2bd67e32231d58f2d0ac Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Mon, 14 Aug 2023 15:15:14 +0000 Subject: [PATCH 11/63] add tests for auth module --- icepyx/tests/conftest.py | 9 +++++++++ icepyx/tests/test_auth.py | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 icepyx/tests/test_auth.py diff --git a/icepyx/tests/conftest.py b/icepyx/tests/conftest.py index 8ec8f6cfb..fca31847a 100644 --- a/icepyx/tests/conftest.py +++ b/icepyx/tests/conftest.py @@ -29,3 +29,12 @@ def password(): @pytest.fixture(scope="session") def email(): return os.environ.get("EARTHDATA_EMAIL") + + +def pytest_configure(config): + # append to netrc file and set permissions level + args = ("icepyx_devteam", "urs.earthdata.nasa.gov", os.getenv("NSIDC_LOGIN")) + netrc_file = os.path.join(os.path.expanduser("~"), ".netrc") + with open(netrc_file, "a+") as f: + f.write("machine {1} login {0} password {2}\n".format(*args)) + os.chmod(netrc_file, 0o600) diff --git a/icepyx/tests/test_auth.py b/icepyx/tests/test_auth.py new file mode 100644 index 000000000..8e19ae933 --- /dev/null +++ b/icepyx/tests/test_auth.py @@ -0,0 +1,34 @@ +import pytest +import requests + +import earthaccess + +from icepyx.core.auth import EarthdataAuthMixin + + +@pytest.fixture() +def auth_instance(): + return EarthdataAuthMixin() + +# Test that .session creates a session +def test_get_session(auth_instance): + assert isinstance(auth_instance.session, requests.sessions.Session) + +# Test that .s3login_credentials creates a dict with the correct keys +def test_get_s3login_credentials(auth_instance): + assert isinstance(auth_instance.s3login_credentials, dict) + expected_keys = set(['accessKeyId', 'secretAccessKey', 'sessionToken', + 'expiration']) + assert set(auth_instance.s3login_credentials.keys()) == expected_keys + +# Test that earthdata_login generates an auth object +def test_login_function(auth_instance): + auth_instance.earthdata_login() + assert isinstance(auth_instance.auth, earthaccess.auth.Auth) + assert auth_instance.auth.authenticated + +# Test that earthdata_login raises a warning if email is provided +def test_depreciation_warning(auth_instance): + with pytest.warns(DeprecationWarning): + auth_instance.earthdata_login(email='me@gmail.com') + \ No newline at end of file From 7e8bf0fd88adec515fe64726d54f6ef098d174fb Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Mon, 14 Aug 2023 15:29:36 +0000 Subject: [PATCH 12/63] add warning message for use of earthdata_login --- icepyx/core/auth.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index 9f794a52b..4dff99a5a 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -132,6 +132,10 @@ def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None No .netrc found in /Users/username """ + warnings.warn( + "It is no longer required to explicitly run the `.earthdata_login()` method. Authentication will be performed by the module as needed.", + DeprecationWarning, stacklevel=2 + ) auth = earthaccess.login(**kwargs) if auth.authenticated: From e06765acd385cd2400bec5c4b74ab4f4e5fb3276 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Mon, 14 Aug 2023 15:30:19 +0000 Subject: [PATCH 13/63] remove .netrc creation and update existing tests to new auth method --- icepyx/tests/test_auth.py | 4 ++++ icepyx/tests/test_behind_NSIDC_API_login.py | 13 ++----------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/icepyx/tests/test_auth.py b/icepyx/tests/test_auth.py index 8e19ae933..35c48b716 100644 --- a/icepyx/tests/test_auth.py +++ b/icepyx/tests/test_auth.py @@ -8,6 +8,10 @@ @pytest.fixture() def auth_instance(): + ''' + An EarthdatAuthMixin object for each of the tests. Default scope is function + level, so a new instance should be created for each of the tests. + ''' return EarthdataAuthMixin() # Test that .session creates a session diff --git a/icepyx/tests/test_behind_NSIDC_API_login.py b/icepyx/tests/test_behind_NSIDC_API_login.py index cc4275225..a4dff74b2 100644 --- a/icepyx/tests/test_behind_NSIDC_API_login.py +++ b/icepyx/tests/test_behind_NSIDC_API_login.py @@ -20,16 +20,7 @@ def reg(): @pytest.fixture(scope="module") def session(reg): - - # append to netrc file and set permissions level - args = ("icepyx_devteam", "urs.earthdata.nasa.gov", os.getenv("NSIDC_LOGIN")) - netrc_file = os.path.join(os.path.expanduser("~"), ".netrc") - with open(netrc_file, "a+") as f: - f.write("machine {1} login {0} password {2}\n".format(*args)) - os.chmod(netrc_file, 0o600) - - reg.earthdata_login() - ed_obj = reg._session + ed_obj = reg.session yield ed_obj ed_obj.close() @@ -51,7 +42,7 @@ def test_get_custom_options_output(session): # NOTE: best this test can do at the moment is a successful download with no errors... def test_download_granules_with_subsetting(reg, session): path = "./downloads_subset" - reg._session = session + reg.session = session reg.order_granules() reg.download_granules(path) From 9e1f74551e1f6ecfd602e0603019912b08ccd02b Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Mon, 14 Aug 2023 16:07:41 +0000 Subject: [PATCH 14/63] undo changes to troubleshoot build --- icepyx/tests/test_auth.py | 1 - icepyx/tests/test_behind_NSIDC_API_login.py | 11 +++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/icepyx/tests/test_auth.py b/icepyx/tests/test_auth.py index 35c48b716..6ac77c864 100644 --- a/icepyx/tests/test_auth.py +++ b/icepyx/tests/test_auth.py @@ -35,4 +35,3 @@ def test_login_function(auth_instance): def test_depreciation_warning(auth_instance): with pytest.warns(DeprecationWarning): auth_instance.earthdata_login(email='me@gmail.com') - \ No newline at end of file diff --git a/icepyx/tests/test_behind_NSIDC_API_login.py b/icepyx/tests/test_behind_NSIDC_API_login.py index a4dff74b2..ff25cb441 100644 --- a/icepyx/tests/test_behind_NSIDC_API_login.py +++ b/icepyx/tests/test_behind_NSIDC_API_login.py @@ -20,7 +20,14 @@ def reg(): @pytest.fixture(scope="module") def session(reg): - ed_obj = reg.session + # append to netrc file and set permissions level + args = ("icepyx_devteam", "urs.earthdata.nasa.gov", os.getenv("NSIDC_LOGIN")) + netrc_file = os.path.join(os.path.expanduser("~"), ".netrc") + with open(netrc_file, "a+") as f: + f.write("machine {1} login {0} password {2}\n".format(*args)) + os.chmod(netrc_file, 0o600) + + ed_obj = reg._session yield ed_obj ed_obj.close() @@ -42,7 +49,7 @@ def test_get_custom_options_output(session): # NOTE: best this test can do at the moment is a successful download with no errors... def test_download_granules_with_subsetting(reg, session): path = "./downloads_subset" - reg.session = session + reg._session = session reg.order_granules() reg.download_granules(path) From a2a455fb698055b17548d6063e4ffccd9c8f28c3 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Mon, 14 Aug 2023 16:14:50 +0000 Subject: [PATCH 15/63] another baby commit to figure out what is breaking travis --- icepyx/tests/test_behind_NSIDC_API_login.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/icepyx/tests/test_behind_NSIDC_API_login.py b/icepyx/tests/test_behind_NSIDC_API_login.py index ff25cb441..a0adcf852 100644 --- a/icepyx/tests/test_behind_NSIDC_API_login.py +++ b/icepyx/tests/test_behind_NSIDC_API_login.py @@ -27,7 +27,7 @@ def session(reg): f.write("machine {1} login {0} password {2}\n".format(*args)) os.chmod(netrc_file, 0o600) - ed_obj = reg._session + ed_obj = reg.session yield ed_obj ed_obj.close() @@ -49,7 +49,7 @@ def test_get_custom_options_output(session): # NOTE: best this test can do at the moment is a successful download with no errors... def test_download_granules_with_subsetting(reg, session): path = "./downloads_subset" - reg._session = session + reg.session = session reg.order_granules() reg.download_granules(path) From 1aacb1dcf33722779b926e27f1748ccca911c171 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Mon, 14 Aug 2023 16:22:04 +0000 Subject: [PATCH 16/63] remove duplicate netrc creation --- icepyx/tests/test_behind_NSIDC_API_login.py | 7 ------- 1 file changed, 7 deletions(-) diff --git a/icepyx/tests/test_behind_NSIDC_API_login.py b/icepyx/tests/test_behind_NSIDC_API_login.py index a0adcf852..a4dff74b2 100644 --- a/icepyx/tests/test_behind_NSIDC_API_login.py +++ b/icepyx/tests/test_behind_NSIDC_API_login.py @@ -20,13 +20,6 @@ def reg(): @pytest.fixture(scope="module") def session(reg): - # append to netrc file and set permissions level - args = ("icepyx_devteam", "urs.earthdata.nasa.gov", os.getenv("NSIDC_LOGIN")) - netrc_file = os.path.join(os.path.expanduser("~"), ".netrc") - with open(netrc_file, "a+") as f: - f.write("machine {1} login {0} password {2}\n".format(*args)) - os.chmod(netrc_file, 0o600) - ed_obj = reg.session yield ed_obj ed_obj.close() From 50db05e4e7935cc0f82619251fd131e9c2d9c3f6 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 15 Aug 2023 14:54:04 +0000 Subject: [PATCH 17/63] update documentation for new auth procedure --- .../IS2_DEM_comparison_WIP.ipynb | 24 +-- .../IS2_cloud_data_access.ipynb | 28 ++- .../example_notebooks/IS2_data_access.ipynb | 175 +++++++++++++----- .../IS2_data_access2-subsetting.ipynb | 18 +- .../example_notebooks/IS2_data_read-in.ipynb | 20 +- .../IS2_data_variables.ipynb | 14 +- .../IS2_data_visualization.ipynb | 15 +- 7 files changed, 200 insertions(+), 94 deletions(-) diff --git a/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb b/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb index dc8256019..aac9c02f7 100644 --- a/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb +++ b/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb @@ -148,17 +148,6 @@ "### Log in to Earthdata" ] }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "earthdata_uid = 'Jessica.scheick'\n", - "email = 'jessica.scheick@maine.edu'\n", - "region_a.earthdata_login(earthdata_uid, email)" - ] - }, { "cell_type": "code", "execution_count": null, @@ -180,6 +169,17 @@ "region_a.granules.avail" ] }, + { + "cell_type": "markdown", + "metadata": { + "user_expressions": [] + }, + "source": [ + "```{admonition} Important Authentication Update\n", + "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "```" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -895,7 +895,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.9.4" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/doc/source/example_notebooks/IS2_cloud_data_access.ipynb b/doc/source/example_notebooks/IS2_cloud_data_access.ipynb index b54be1786..c205aa509 100644 --- a/doc/source/example_notebooks/IS2_cloud_data_access.ipynb +++ b/doc/source/example_notebooks/IS2_cloud_data_access.ipynb @@ -74,23 +74,35 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "## Log in to Earthdata and generate an s3 token\n", - "You can use icepyx's existing login functionality to generate your s3 data access token, which will be valid for *one* hour.\n", + "You can use icepyx's existing login functionality to generate your s3 data access token, which will be valid for *one* hour. The icepyx module will renew the token for you after an hour, but if viewing your token over the course of several hours you may notice the values will change.\n", "\n", - "We currently do not have this set up to automatically renew, but [earthaccess](https://nsidc.github.io/earthaccess/), which icepyx uses under the hood for authentication, is working on handling the limits imposed by expiring s3 tokens. If you're interested in working on helping icepyx and earthaccess address these challenges, please get in touch or submit a PR. Documentation/example testers are always appreciated (so you don't have to understand the code)!" + "You can access your s3 credentials using:" ] }, { "cell_type": "code", "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# uncommenting the line below will print your temporary login credentials\n", + "# reg.s3login_credentials" + ] + }, + { + "cell_type": "markdown", "metadata": { - "scrolled": true + "user_expressions": [] }, - "outputs": [], "source": [ - "reg.earthdata_login(s3token=True)" + "```{admonition} Important Authentication Update\n", + "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "```" ] }, { @@ -106,7 +118,7 @@ "metadata": {}, "outputs": [], "source": [ - "s3 = earthaccess.get_s3fs_session(daac='NSIDC', provider=reg._s3login_credentials)" + "s3 = earthaccess.get_s3fs_session(daac='NSIDC', provider=reg.s3login_credentials)" ] }, { @@ -176,7 +188,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.8" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/doc/source/example_notebooks/IS2_data_access.ipynb b/doc/source/example_notebooks/IS2_data_access.ipynb index 8c9bafa80..7af969523 100644 --- a/doc/source/example_notebooks/IS2_data_access.ipynb +++ b/doc/source/example_notebooks/IS2_data_access.ipynb @@ -19,7 +19,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "import icepyx as ipx\n", @@ -30,7 +32,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "---------------------------------\n", "\n", @@ -51,14 +55,15 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "## Key Steps for Programmatic Data Access\n", "\n", "There are several key steps for accessing data from the NSIDC API:\n", "1. Define your parameters (spatial, temporal, dataset, etc.)\n", "2. Query the NSIDC API to find out more information about the dataset\n", - "3. Log in to NASA Earthdata\n", "4. Define additional parameters (e.g. subsetting/customization options)\n", "5. Order your data\n", "6. Download your data\n", @@ -68,7 +73,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Create an ICESat-2 data object with the desired search parameters\n", "\n", @@ -103,7 +110,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# bounding box\n", @@ -115,7 +124,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# polygon vertices (here equivalent to the bounding box, above)\n", @@ -127,7 +138,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# bounding box with 'YYYY-DOY' date range (equivalent to 'YYYY-MM-DD' date ranges above)\n", @@ -139,7 +152,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# polygon vertices with datetime.datetime date ranges\n", @@ -155,7 +170,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# bounding box with dict containing date ranges\n", @@ -167,7 +184,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# polygon geospatial file (metadata match but no subset match)\n", @@ -188,7 +207,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "Create the data object using our inputs" ] @@ -196,7 +217,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "region_a = ipx.Query(short_name, spatial_extent, date_range)" @@ -205,7 +228,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# using orbital parameters with one of the above data products + spatial parameters\n", @@ -220,7 +245,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "These properties include visualization of the spatial extent on a map. The style of map you will see depends on whether or not you have a certain library, `geoviews`, installed. Under the hood, this is because the `proj` library must be installed with conda (it is not available from PyPI) to support some `geoviews` dependencies. With `geoviews`, this plotting function returns an interactive map. Otherwise, your spatial extent will plot on a static map using `matplotlib`." ] @@ -228,7 +255,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# print(region_a.spatial_extent)\n", @@ -237,7 +266,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "Formatted parameters and function calls allow us to see the the properties of the data object we have created." ] @@ -245,7 +276,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "print(region_a.product)\n", @@ -261,7 +294,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "There are also several optional inputs to allow the user finer control over their search. Start and end time are only valid inputs on a temporally limited search, and they are ignored if your `date_range` input is a datetime.datetime object.\n", "- `start_time` = start time to search for data on the start date. If no input is given, this defaults to 00:00:00.\n", @@ -279,7 +314,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "region_a = ipx.Query(short_name, spatial_extent, date_range, \\\n", @@ -294,7 +331,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "Alternatively, you can also just create the query object without creating named variables first:" ] @@ -302,7 +341,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "# region_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-01','2019-02-28'], \n", @@ -311,7 +352,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### More information about your query object\n", "In addition to viewing the stored object information shown above (e.g. product short name, start and end date and time, version, etc.), we can also request summary information about the data product itself or confirm that we have manually specified the latest version." @@ -320,7 +363,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "region_a.product_summary_info()\n", @@ -329,7 +374,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "If the summary does not provide all of the information you are looking for, or you would like to see information for previous versions of the data product, all available metadata for the collection product is available in a readable format." ] @@ -338,7 +385,8 @@ "cell_type": "code", "execution_count": null, "metadata": { - "scrolled": true + "scrolled": true, + "tags": [] }, "outputs": [], "source": [ @@ -347,7 +395,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Querying a data product\n", "In order to search the product collection for available data granules, we need to build our search parameters. This is done automatically behind the scenes when you run `region_a.avail_granules()`, but you can also build and view them by calling `region_a.CMRparams`. These are formatted as a dictionary of key:value pairs according to the [CMR documentation](https://cmr.earthdata.nasa.gov/search/site/docs/search/api.html)." @@ -356,7 +406,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "#build and view the parameters that will be submitted in our query\n", @@ -365,7 +417,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "Now that our parameter dictionary is constructed, we can search the CMR database for the available granules.\n", "Granules returned by the CMR metadata search are automatically stored within the data object.\n", @@ -377,7 +431,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "#search for available granules and provide basic summary info about them\n", @@ -387,7 +443,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "#get a list of granule IDs for the available granules\n", @@ -398,7 +456,8 @@ "cell_type": "code", "execution_count": null, "metadata": { - "scrolled": true + "scrolled": true, + "tags": [] }, "outputs": [], "source": [ @@ -408,10 +467,12 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Log in to NASA Earthdata\n", - "In order to download any data from NSIDC, we must first authenticate ourselves using a valid (free) Earthdata account. This creates and handles the required authentication to interface with the data at the DAAC (including ordering and download).\n", + "When downloading data from NSIDC, all users must login using a valid (free) Earthdata account. The process of authenticating is handled by icepyx by creating and handling the required authentication to interface with the data at the DAAC (including ordering and download). Authentication is completed as login-protected featuers are accessed. In order to allow icepyx to login for us we still have to make sure that we have made our Earthdata credentials available for icepyx to find.\n", "\n", "There are multiple ways to provide your Earthdata credentials via icepyx. Behind the scenes, icepyx is using the [earthaccess library](https://nsidc.github.io/earthaccess/). The [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth) automatically tries three primary mechanisms for logging in, all of which are supported by icepyx:\n", "- with `EARTHDATA_USERNAME` and `EARTHDATA_PASSWORD` environment variables (these are the same as the ones you might have set for icepyx previously)\n", @@ -421,21 +482,25 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "```{admonition} Important Authentication Update\n", - "Previously, icepyx required you to provide certain inputs to the `earthdata_login()` function, e.g. `region_a.earthdata_login(earthdata_uid, email).\n", - "These inputs are no longer required, but the keywords are still accepted for backwards compatibility.\n", + "Previously, icepyx required you to explicitly use the `earthdata_login()` function to login. Running this function is no longer required, but it is still available for backwards compatibility.\n", "```" ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "metadata": { + "user_expressions": [] + }, "source": [ - "region_a.earthdata_login()" + "```{admonition} Important Authentication Update\n", + "Previously, icepyx required you to provide certain inputs to the `earthdata_login()` function, e.g. `region_a.earthdata_login(earthdata_uid, email).\n", + "These inputs are no longer required, but the keywords are still accepted for backwards compatibility.\n", + "```" ] }, { @@ -465,7 +530,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "print(region_a.reqparams)\n", @@ -498,7 +565,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "region_a.subsetparams()" @@ -515,7 +584,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "region_a.order_granules()\n", @@ -525,7 +596,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "#view a short list of order IDs\n", @@ -543,7 +616,9 @@ { "cell_type": "code", "execution_count": null, - "metadata": {}, + "metadata": { + "tags": [] + }, "outputs": [], "source": [ "path = './download'\n", @@ -563,9 +638,9 @@ ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "icepyx-dev", "language": "python", - "name": "python3" + "name": "icepyx-dev" }, "language_info": { "codemirror_mode": { @@ -577,7 +652,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.10" + "version": "3.11.4" } }, "nbformat": 4, diff --git a/doc/source/example_notebooks/IS2_data_access2-subsetting.ipynb b/doc/source/example_notebooks/IS2_data_access2-subsetting.ipynb index 27838e014..5b617fc5c 100644 --- a/doc/source/example_notebooks/IS2_data_access2-subsetting.ipynb +++ b/doc/source/example_notebooks/IS2_data_access2-subsetting.ipynb @@ -2,7 +2,9 @@ "cells": [ { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "# Subsetting ICESat-2 Data\n", "This notebook ({nb-download}`download `) illustrates the use of icepyx for subsetting ICESat-2 data ordered through the NSIDC DAAC. We'll show how to find out what subsetting options are available and how to specify the subsetting options for your order.\n", @@ -67,12 +69,14 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "metadata": { + "user_expressions": [] + }, "source": [ - "region_a.earthdata_login()" + "```{admonition} Important Authentication Update\n", + "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "```" ] }, { @@ -361,7 +365,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.10" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index a543d03df..ba6d07151 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -139,21 +139,23 @@ { "cell_type": "code", "execution_count": null, - "id": "2bb83dfe", + "id": "e6f7c047", "metadata": {}, "outputs": [], "source": [ - "region_a.earthdata_login()" + "region_a.download_granules(path=path_root)" ] }, { - "cell_type": "code", - "execution_count": null, - "id": "e6f7c047", - "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "id": "04f62f30-b13c-4cfc-95b0-dd1e048f6a85", + "metadata": { + "user_expressions": [] + }, "source": [ - "region_a.download_granules(path=path_root)" + "```{admonition} Important Authentication Update\n", + "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "```" ] }, { @@ -670,7 +672,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/doc/source/example_notebooks/IS2_data_variables.ipynb b/doc/source/example_notebooks/IS2_data_variables.ipynb index 568027550..65b91f279 100644 --- a/doc/source/example_notebooks/IS2_data_variables.ipynb +++ b/doc/source/example_notebooks/IS2_data_variables.ipynb @@ -120,12 +120,14 @@ ] }, { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "metadata": { + "user_expressions": [] + }, "source": [ - "region_a.earthdata_login()" + "```{admonition} Important Authentication Update\n", + "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "```" ] }, { @@ -773,7 +775,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.10.12" } }, "nbformat": 4, diff --git a/doc/source/example_notebooks/IS2_data_visualization.ipynb b/doc/source/example_notebooks/IS2_data_visualization.ipynb index 8b2f7b05f..7f65c4f85 100644 --- a/doc/source/example_notebooks/IS2_data_visualization.ipynb +++ b/doc/source/example_notebooks/IS2_data_visualization.ipynb @@ -193,7 +193,6 @@ "metadata": {}, "outputs": [], "source": [ - "region.earthdata_login()\n", "region.order_granules()\n", "\n", "#view a short list of order IDs\n", @@ -203,6 +202,18 @@ "region.download_granules(path)" ] }, + { + "cell_type": "markdown", + "id": "10cc8fef-7a43-41c4-ab22-6f551ad68659", + "metadata": { + "user_expressions": [] + }, + "source": [ + "```{admonition} Important Authentication Update\n", + "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "```" + ] + }, { "cell_type": "markdown", "id": "textile-casting", @@ -253,7 +264,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.9" + "version": "3.10.12" } }, "nbformat": 4, From f44ead3f45aeb81b34bb922449e4956dc6dbbe98 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 15 Aug 2023 15:04:37 +0000 Subject: [PATCH 18/63] remove earthdata_login function from docstrings --- icepyx/core/query.py | 7 +------ icepyx/core/variables.py | 4 ---- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/icepyx/core/query.py b/icepyx/core/query.py index d800a5a7d..8564388db 100644 --- a/icepyx/core/query.py +++ b/icepyx/core/query.py @@ -597,7 +597,6 @@ def reqparams(self): {'page_size': 2000} >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP >>> reg_a.order_granules() # doctest: +SKIP >>> reg_a.reqparams # doctest: +SKIP {'page_size': 2000, 'page_num': 1, 'request_mode': 'async', 'include_meta': 'Y', 'client_string': 'icepyx'} @@ -679,7 +678,6 @@ def order_vars(self): Examples -------- >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP >>> reg_a.order_vars # doctest: +SKIP """ @@ -723,7 +721,7 @@ def file_vars(self): Examples -------- >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP + >>> reg_a.file_vars # doctest: +SKIP """ @@ -844,7 +842,6 @@ def show_custom_options(self, dictview=False): Examples -------- >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP >>> reg_a.show_custom_options(dictview=True) # doctest: +SKIP Subsetting options [{'id': 'ICESAT2', @@ -1002,7 +999,6 @@ def order_granules(self, verbose=False, subset=True, email=False, **kwargs): Examples -------- >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP >>> reg_a.order_granules() # doctest: +SKIP order ID: [###############] [order status output] @@ -1113,7 +1109,6 @@ def download_granules( Examples -------- >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP >>> reg_a.download_granules('/path/to/download/folder') # doctest: +SKIP Beginning download of zipped output... Data request [##########] of x order(s) is complete. diff --git a/icepyx/core/variables.py b/icepyx/core/variables.py index db3983cd9..d46561f46 100644 --- a/icepyx/core/variables.py +++ b/icepyx/core/variables.py @@ -87,7 +87,6 @@ def avail(self, options=False, internal=False): Examples -------- >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28'], version='5') # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP >>> reg_a.order_vars.avail() # doctest: +SKIP ['ancillary_data/atlas_sdp_gps_epoch', 'ancillary_data/control', @@ -159,7 +158,6 @@ def parse_var_list(varlist, tiered=True, tiered_vars=False): Examples -------- >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28'], version='1') # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP >>> var_dict, paths = reg_a.order_vars.parse_var_list(reg_a.order_vars.avail()) # doctest: +SKIP >>> var_dict # doctest: +SKIP {'atlas_sdp_gps_epoch': ['ancillary_data/atlas_sdp_gps_epoch'], @@ -423,7 +421,6 @@ def append(self, defaults=False, var_list=None, beam_list=None, keyword_list=Non Examples -------- >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP To add all variables related to a specific ICESat-2 beam @@ -556,7 +553,6 @@ def remove(self, all=False, var_list=None, beam_list=None, keyword_list=None): Examples -------- >>> reg_a = ipx.Query('ATL06',[-55, 68, -48, 71],['2019-02-20','2019-02-28']) # doctest: +SKIP - >>> reg_a.earthdata_login() # doctest: +SKIP To clear the list of wanted variables From 12e21ba0018887c5b36e3a92fe416ade157048b0 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 15 Aug 2023 15:05:07 +0000 Subject: [PATCH 19/63] remove missed instance of earthdata_login in docs --- doc/source/example_notebooks/IS2_data_access.ipynb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_access.ipynb b/doc/source/example_notebooks/IS2_data_access.ipynb index 7af969523..3e3ea2660 100644 --- a/doc/source/example_notebooks/IS2_data_access.ipynb +++ b/doc/source/example_notebooks/IS2_data_access.ipynb @@ -40,12 +40,10 @@ "\n", "## Quick-Start Guide\n", "\n", - "The entire process of getting ICESat-2 data (from query to download) can ultimately be accomplished in three minimal lines of code:\n", + "The entire process of getting ICESat-2 data (from query to download) can ultimately be accomplished in two minimal lines of code:\n", "\n", "`region_a = ipx.Query(short_name, spatial_extent, date_range)`\n", "\n", - "`region_a.earthdata_login()`\n", - "\n", "`region_a.download_granules(path)`\n", "\n", "where the function inputs are described in more detail below.\n", From 10bc7347a5e85a9e391a380278abfffa19cac0a2 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 15 Aug 2023 15:09:35 +0000 Subject: [PATCH 20/63] attempt add auth to API reference --- doc/source/user_guide/documentation/icepyx.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/user_guide/documentation/icepyx.rst b/doc/source/user_guide/documentation/icepyx.rst index 56ff7f496..52dabdca4 100644 --- a/doc/source/user_guide/documentation/icepyx.rst +++ b/doc/source/user_guide/documentation/icepyx.rst @@ -23,4 +23,5 @@ Diagrams are updated automatically after a pull request (PR) is approved and bef query read quest + auth components From 8033ed4fccdd521529f337779c402620bb0448c7 Mon Sep 17 00:00:00 2001 From: Rachel Wegener <35503632+rwegener2@users.noreply.github.com> Date: Tue, 22 Aug 2023 09:07:50 -0400 Subject: [PATCH 21/63] Update icepyx/core/auth.py Co-authored-by: Jessica Scheick --- icepyx/core/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index 4dff99a5a..d30757d64 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -27,7 +27,7 @@ class EarthdataAuthMixin(): Parameters ---------- auth : earthaccess.auth.Auth, default None - Optional parameter to pass initialize an object with existing credentials + Optional parameter to initialize an object with existing credentials. Examples -------- From f1fa0df15d9208641ed1bdfbe6a853cee19daf5d Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 13:28:58 +0000 Subject: [PATCH 22/63] alphabetize ordering --- icepyx/core/query.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/icepyx/core/query.py b/icepyx/core/query.py index 8564388db..e8f1d8e7c 100644 --- a/icepyx/core/query.py +++ b/icepyx/core/query.py @@ -10,17 +10,17 @@ import warnings import icepyx.core.APIformatting as apifmt +from icepyx.core.auth import EarthdataAuthMixin import icepyx.core.granules as granules from icepyx.core.granules import Granules as Granules import icepyx.core.is2ref as is2ref # QUESTION: why doesn't from granules import Granules as Granules work, since granules=icepyx.core.granules? # from icepyx.core.granules import Granules -from icepyx.core.variables import Variables as Variables -import icepyx.core.validate_inputs as val -from icepyx.core.auth import EarthdataAuthMixin import icepyx.core.spatial as spat import icepyx.core.temporal as tp +import icepyx.core.validate_inputs as val +from icepyx.core.variables import Variables as Variables from icepyx.core.visualization import Visualize From 6cdddbfced5735984e748748d0dadc9daeafc615 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 13:30:53 +0000 Subject: [PATCH 23/63] add warning to dev log --- icepyx/core/auth.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index d30757d64..297e6a5d2 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -109,7 +109,7 @@ def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None More details on using these methods is available in the [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth). The input parameters listed here are provided for backwards compatibility; before earthaccess existed, icepyx handled authentication and required these inputs. - DevNote: Maintained for backward compatibility + DevNote: This method is maintained for backward compatibility. It is no longer required to explicitly run `.earthdata_login()`. Authentication will be performed by the module as needed when `.session` or `.s3login_credentials` are accessed. Parameters ---------- From b7b8b7e007162702c325803577f266021bb2407f Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 13:39:09 +0000 Subject: [PATCH 24/63] add auth to components docs --- doc/source/user_guide/documentation/components.rst | 8 ++++++++ doc/source/user_guide/documentation/icepyx.rst | 1 - 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/doc/source/user_guide/documentation/components.rst b/doc/source/user_guide/documentation/components.rst index 7a1a171e4..b4b658385 100644 --- a/doc/source/user_guide/documentation/components.rst +++ b/doc/source/user_guide/documentation/components.rst @@ -10,6 +10,14 @@ APIformatting :members: :undoc-members: :show-inheritance: + +EarthdataAuthMixin +------------------ + +.. automodule:: icepyx.core.auth + :members: + :undoc-members: + :show-inheritance: granules -------- diff --git a/doc/source/user_guide/documentation/icepyx.rst b/doc/source/user_guide/documentation/icepyx.rst index 52dabdca4..56ff7f496 100644 --- a/doc/source/user_guide/documentation/icepyx.rst +++ b/doc/source/user_guide/documentation/icepyx.rst @@ -23,5 +23,4 @@ Diagrams are updated automatically after a pull request (PR) is approved and bef query read quest - auth components From 97fda0755eb7c7b1f52645cc551953d42c93fe02 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 13:57:13 +0000 Subject: [PATCH 25/63] add more detail to auth string --- icepyx/core/auth.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index 297e6a5d2..480946a4c 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -14,10 +14,12 @@ class AuthenticationError(Exception): class EarthdataAuthMixin(): """ This mixin class stores properties and methods related to logging into Earthdata. - It can be inherited by any other class that requires authentication. + It can be inherited by any other class that requires authentication. For + example, the `Query` class inherits this one, and so a Query object has the + `.session` property. - The class provides 3 properties: auth, session, and s3login_credentials. The method - earthdata_login() is included for backwards compatibility. + The class provides several properties relevant for authentication. The method + `earthdata_login()` is included for backwards compatibility. The class can be created without any initialization parameters, and the properties will be populated when they are called. It can alternately be initialized with an @@ -109,7 +111,8 @@ def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None More details on using these methods is available in the [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth). The input parameters listed here are provided for backwards compatibility; before earthaccess existed, icepyx handled authentication and required these inputs. - DevNote: This method is maintained for backward compatibility. It is no longer required to explicitly run `.earthdata_login()`. Authentication will be performed by the module as needed when `.session` or `.s3login_credentials` are accessed. + + **DevNote:** This method is maintained for backward compatibility. It is no longer required to explicitly run `.earthdata_login()`. Authentication will be performed by the module as needed when `.session` or `.s3login_credentials` are accessed. Parameters ---------- From 1172e9ed3aa2c00278fc047ef419d63d18ce3c19 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 14:37:31 +0000 Subject: [PATCH 26/63] add authentication explainer --- doc/source/contributing/icepyx_internals.rst | 66 ++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 doc/source/contributing/icepyx_internals.rst diff --git a/doc/source/contributing/icepyx_internals.rst b/doc/source/contributing/icepyx_internals.rst new file mode 100644 index 000000000..61108ca1d --- /dev/null +++ b/doc/source/contributing/icepyx_internals.rst @@ -0,0 +1,66 @@ +`icepyx` Internals +================== + +Authentication +-------------- +Authentication in icepyx is handled using a Mixin class. A Mixin class is a class +which defines functionality that may be desired by multiple other classes within +a library. For example, at this time both the Query and Variables classes need +to be able to authenticate. Instead of defining the same properties and +functionality twice, icepyx has an `EarthdataAuthMixin` class that is inherited +by both modules. + +**Property Access** + +Even though they aren't explicity defined in the `__init__` method, properties +like `.session` are accessible on a Query object because they are inherited. The +code that indicates this to Python is `EarthdataAuthMixin.__init__(self)`. + +For example: + +```python +import icepyx as ipx + +region_a = ipx.Query('ATL06',[-45, 74, -44,75],['2019-11-30','2019-11-30'], \ + start_time='00:00:00', end_time='23:59:59') + +# authentication can be accessed via the Query object +region_a.session +region_a.s3login_credentials +``` + +**Adding authentication to a new class** + +To add authentication to an additional icepyx class, one needs to add the Mixin +to the class. To do this: + +1. Add the `EarthdataAuthMixin` class to the `class` constructor (and import the mixin) +2. Add the `EarthdataAuthMixin` init method with in the init method of the new class `EarthdataAuthMixin.__init__(self)` +3. Access the properties using the _public_ properties (Ex. `self.session`, not `self._session`.) + +A minimal example of the new class (saved in `icepyx/core/newclass.py`) would be: + +```python +from icepyx.core.auth import EarthdataAuthMixin + +class MyNewClass(EarthdataAuthMixin): + def __init__(self): + self.mynewclassproperty = True + + EarthdataAuthMixin.__init__(self) + + def my_exciting_new_method(self): + # This method requires login + s = self.session + print(s) + return 'We authenticated inside the method!' +``` +The class would then be accessible with: +``` +from icepyx.core.newclass import MyNewClass + +n = MyNewClass() + +n.session + +``` \ No newline at end of file From abd950a97b6eca5f0d4fc80db9a01a1f84cd4634 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 14:47:43 +0000 Subject: [PATCH 27/63] add internals to index.rst --- doc/source/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/index.rst b/doc/source/index.rst index 1071d7072..719f528b2 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -145,6 +145,7 @@ ICESat-2 datasets to enable scientific discovery. contributing/contributors_link contributing/contribution_guidelines contributing/how_to_contribute + contributing/icepyx_internals contributing/attribution_link contributing/development_plan contributing/release_guide From 8c3545bc8957c83a4f64691a4c9611e10898f934 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 14:52:59 +0000 Subject: [PATCH 28/63] match formatting --- doc/source/contributing/icepyx_internals.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/contributing/icepyx_internals.rst b/doc/source/contributing/icepyx_internals.rst index 61108ca1d..60582b86b 100644 --- a/doc/source/contributing/icepyx_internals.rst +++ b/doc/source/contributing/icepyx_internals.rst @@ -1,4 +1,4 @@ -`icepyx` Internals +icepyx Internals ================== Authentication From 90354e64a65b57acad88373ecee75264a00a474b Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 14:55:32 +0000 Subject: [PATCH 29/63] update code block formatting --- doc/source/contributing/icepyx_internals.rst | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/doc/source/contributing/icepyx_internals.rst b/doc/source/contributing/icepyx_internals.rst index 60582b86b..7ba8cccdd 100644 --- a/doc/source/contributing/icepyx_internals.rst +++ b/doc/source/contributing/icepyx_internals.rst @@ -18,7 +18,8 @@ code that indicates this to Python is `EarthdataAuthMixin.__init__(self)`. For example: -```python +.. code-block:: python + import icepyx as ipx region_a = ipx.Query('ATL06',[-45, 74, -44,75],['2019-11-30','2019-11-30'], \ @@ -27,7 +28,7 @@ region_a = ipx.Query('ATL06',[-45, 74, -44,75],['2019-11-30','2019-11-30'], \ # authentication can be accessed via the Query object region_a.session region_a.s3login_credentials -``` + **Adding authentication to a new class** @@ -40,7 +41,8 @@ to the class. To do this: A minimal example of the new class (saved in `icepyx/core/newclass.py`) would be: -```python +.. code-block:: python + from icepyx.core.auth import EarthdataAuthMixin class MyNewClass(EarthdataAuthMixin): @@ -54,13 +56,14 @@ class MyNewClass(EarthdataAuthMixin): s = self.session print(s) return 'We authenticated inside the method!' -``` + + The class would then be accessible with: -``` + +.. code-block:: python + from icepyx.core.newclass import MyNewClass n = MyNewClass() n.session - -``` \ No newline at end of file From 7fedc2dd4ca3c28381f76378241daf98fdaf053f Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 15:00:41 +0000 Subject: [PATCH 30/63] continue to update formatting --- doc/source/contributing/icepyx_internals.rst | 56 ++++++++++---------- 1 file changed, 28 insertions(+), 28 deletions(-) diff --git a/doc/source/contributing/icepyx_internals.rst b/doc/source/contributing/icepyx_internals.rst index 7ba8cccdd..a7ad479f0 100644 --- a/doc/source/contributing/icepyx_internals.rst +++ b/doc/source/contributing/icepyx_internals.rst @@ -7,27 +7,27 @@ Authentication in icepyx is handled using a Mixin class. A Mixin class is a clas which defines functionality that may be desired by multiple other classes within a library. For example, at this time both the Query and Variables classes need to be able to authenticate. Instead of defining the same properties and -functionality twice, icepyx has an `EarthdataAuthMixin` class that is inherited +functionality twice, icepyx has an EarthdataAuthMixin class that is inherited by both modules. **Property Access** -Even though they aren't explicity defined in the `__init__` method, properties -like `.session` are accessible on a Query object because they are inherited. The -code that indicates this to Python is `EarthdataAuthMixin.__init__(self)`. +Even though they aren't explicity defined in the init method, properties +like ``.session`` are accessible on a Query object because they are inherited. The +code that indicates this to Python is ``EarthdataAuthMixin.__init__(self)``. For example: .. code-block:: python -import icepyx as ipx + import icepyx as ipx -region_a = ipx.Query('ATL06',[-45, 74, -44,75],['2019-11-30','2019-11-30'], \ - start_time='00:00:00', end_time='23:59:59') + region_a = ipx.Query('ATL06',[-45, 74, -44,75],['2019-11-30','2019-11-30'], \ + start_time='00:00:00', end_time='23:59:59') -# authentication can be accessed via the Query object -region_a.session -region_a.s3login_credentials + # authentication can be accessed via the Query object + region_a.session + region_a.s3login_credentials **Adding authentication to a new class** @@ -35,35 +35,35 @@ region_a.s3login_credentials To add authentication to an additional icepyx class, one needs to add the Mixin to the class. To do this: -1. Add the `EarthdataAuthMixin` class to the `class` constructor (and import the mixin) -2. Add the `EarthdataAuthMixin` init method with in the init method of the new class `EarthdataAuthMixin.__init__(self)` -3. Access the properties using the _public_ properties (Ex. `self.session`, not `self._session`.) +1. Add the EarthdataAuthMixin class to the ``class`` constructor (and import the mixin) +2. Add the EarthdataAuthMixin init method with in the init method of the new class ``EarthdataAuthMixin.__init__(self)`` +3. Access the properties using the **public** properties (Ex. ``self.session``, not ``self._session``.) -A minimal example of the new class (saved in `icepyx/core/newclass.py`) would be: +A minimal example of the new class (saved in ``icepyx/core/newclass.py``) would be: .. code-block:: python -from icepyx.core.auth import EarthdataAuthMixin + from icepyx.core.auth import EarthdataAuthMixin -class MyNewClass(EarthdataAuthMixin): - def __init__(self): - self.mynewclassproperty = True - - EarthdataAuthMixin.__init__(self) + class MyNewClass(EarthdataAuthMixin): + def __init__(self): + self.mynewclassproperty = True - def my_exciting_new_method(self): - # This method requires login - s = self.session - print(s) - return 'We authenticated inside the method!' + EarthdataAuthMixin.__init__(self) + + def my_exciting_new_method(self): + # This method requires login + s = self.session + print(s) + return 'We authenticated inside the method!' The class would then be accessible with: .. code-block:: python -from icepyx.core.newclass import MyNewClass + from icepyx.core.newclass import MyNewClass -n = MyNewClass() + n = MyNewClass() -n.session + n.session From e26c9a13c6c6d024968b1dc060742451ccfb5ca3 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 22 Aug 2023 15:07:56 +0000 Subject: [PATCH 31/63] add an additional example line --- doc/source/contributing/icepyx_internals.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/source/contributing/icepyx_internals.rst b/doc/source/contributing/icepyx_internals.rst index a7ad479f0..6832e4427 100644 --- a/doc/source/contributing/icepyx_internals.rst +++ b/doc/source/contributing/icepyx_internals.rst @@ -67,3 +67,4 @@ The class would then be accessible with: n = MyNewClass() n.session + n.my_exciting_new_method() From a31b092493e0c4be5354f25b0bf8026feb6b6f8f Mon Sep 17 00:00:00 2001 From: Rachel Wegener <35503632+rwegener2@users.noreply.github.com> Date: Wed, 23 Aug 2023 08:57:48 -0400 Subject: [PATCH 32/63] Update icepyx/tests/test_behind_NSIDC_API_login.py Co-authored-by: Jessica Scheick --- icepyx/tests/test_behind_NSIDC_API_login.py | 1 - 1 file changed, 1 deletion(-) diff --git a/icepyx/tests/test_behind_NSIDC_API_login.py b/icepyx/tests/test_behind_NSIDC_API_login.py index a4dff74b2..3e7b645d7 100644 --- a/icepyx/tests/test_behind_NSIDC_API_login.py +++ b/icepyx/tests/test_behind_NSIDC_API_login.py @@ -42,7 +42,6 @@ def test_get_custom_options_output(session): # NOTE: best this test can do at the moment is a successful download with no errors... def test_download_granules_with_subsetting(reg, session): path = "./downloads_subset" - reg.session = session reg.order_granules() reg.download_granules(path) From ab3de31a3b3097f601a0f669d139270e13ef04d4 Mon Sep 17 00:00:00 2001 From: Rachel Wegener <35503632+rwegener2@users.noreply.github.com> Date: Wed, 23 Aug 2023 11:47:01 -0400 Subject: [PATCH 33/63] Update doc/source/contributing/icepyx_internals.rst Co-authored-by: Jessica Scheick --- doc/source/contributing/icepyx_internals.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/contributing/icepyx_internals.rst b/doc/source/contributing/icepyx_internals.rst index 6832e4427..cd51c3dce 100644 --- a/doc/source/contributing/icepyx_internals.rst +++ b/doc/source/contributing/icepyx_internals.rst @@ -1,5 +1,5 @@ icepyx Internals -================== +================ Authentication -------------- From 3aab79a492d45ed333aa84e19908c90f3d960dc3 Mon Sep 17 00:00:00 2001 From: Rachel Wegener <35503632+rwegener2@users.noreply.github.com> Date: Wed, 23 Aug 2023 11:47:09 -0400 Subject: [PATCH 34/63] Update doc/source/contributing/icepyx_internals.rst Co-authored-by: Jessica Scheick --- doc/source/contributing/icepyx_internals.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/contributing/icepyx_internals.rst b/doc/source/contributing/icepyx_internals.rst index cd51c3dce..e224be3ce 100644 --- a/doc/source/contributing/icepyx_internals.rst +++ b/doc/source/contributing/icepyx_internals.rst @@ -36,7 +36,7 @@ To add authentication to an additional icepyx class, one needs to add the Mixin to the class. To do this: 1. Add the EarthdataAuthMixin class to the ``class`` constructor (and import the mixin) -2. Add the EarthdataAuthMixin init method with in the init method of the new class ``EarthdataAuthMixin.__init__(self)`` +2. Add the EarthdataAuthMixin init method within the init method of the new class ``EarthdataAuthMixin.__init__(self)`` 3. Access the properties using the **public** properties (Ex. ``self.session``, not ``self._session``.) A minimal example of the new class (saved in ``icepyx/core/newclass.py``) would be: From ade942fde832d5d8fde0ca9c82fc4c2d6a7e4b35 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Wed, 23 Aug 2023 16:04:55 +0000 Subject: [PATCH 35/63] move auth description text to EarthdataAuthMixin class --- icepyx/core/auth.py | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index 480946a4c..0994a7549 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -13,13 +13,19 @@ class AuthenticationError(Exception): class EarthdataAuthMixin(): """ - This mixin class stores properties and methods related to logging into Earthdata. - It can be inherited by any other class that requires authentication. For + This mixin class generates the needed authentication sessions and tokens, including for NASA Earthdata cloud access. + Authentication is completed using the [earthaccess library](https://nsidc.github.io/earthaccess/). + Methods for authenticating are: + 1. Storing credentials as environment variables ($EARTHDATA_LOGIN and $EARTHDATA_PASSWORD) + 2. Entering credentials interactively + 3. Storing credentials in a .netrc file (not recommended for security reasons) + More details on using these methods is available in the [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth). + The input parameters listed here are provided for backwards compatibility; + before earthaccess existed, icepyx handled authentication and required these inputs. + + This class can be inherited by any other class that requires authentication. For example, the `Query` class inherits this one, and so a Query object has the - `.session` property. - - The class provides several properties relevant for authentication. The method - `earthdata_login()` is included for backwards compatibility. + `.session` property. The method `earthdata_login()` is included for backwards compatibility. The class can be created without any initialization parameters, and the properties will be populated when they are called. It can alternately be initialized with an @@ -101,18 +107,9 @@ def set_s3_creds(): def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None: """ Authenticate with NASA Earthdata to enable data ordering and download. - - Generates the needed authentication sessions and tokens, including for cloud access. - Authentication is completed using the [earthaccess library](https://nsidc.github.io/earthaccess/). - Methods for authenticating are: - 1. Storing credentials as environment variables ($EARTHDATA_LOGIN and $EARTHDATA_PASSWORD) - 2. Entering credentials interactively - 3. Storing credentials in a .netrc file (not recommended for security reasons) - More details on using these methods is available in the [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth). - The input parameters listed here are provided for backwards compatibility; - before earthaccess existed, icepyx handled authentication and required these inputs. + Credential storage details are described in the EathdataAuthMixin class section. - **DevNote:** This method is maintained for backward compatibility. It is no longer required to explicitly run `.earthdata_login()`. Authentication will be performed by the module as needed when `.session` or `.s3login_credentials` are accessed. + **Note:** This method is maintained for backward compatibility. It is no longer required to explicitly run `.earthdata_login()`. Authentication will be performed by the module as needed when `.session` or `.s3login_credentials` are accessed. Parameters ---------- From f052b7632284621f4dfb9eade8bf2c5d03214673 Mon Sep 17 00:00:00 2001 From: Jessica Scheick Date: Thu, 24 Aug 2023 11:21:57 -0400 Subject: [PATCH 36/63] fix typo and double admonition in data access notebook --- .../example_notebooks/IS2_data_access.ipynb | 22 +++++-------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_access.ipynb b/doc/source/example_notebooks/IS2_data_access.ipynb index 3e3ea2660..17b5b5fac 100644 --- a/doc/source/example_notebooks/IS2_data_access.ipynb +++ b/doc/source/example_notebooks/IS2_data_access.ipynb @@ -470,7 +470,7 @@ }, "source": [ "### Log in to NASA Earthdata\n", - "When downloading data from NSIDC, all users must login using a valid (free) Earthdata account. The process of authenticating is handled by icepyx by creating and handling the required authentication to interface with the data at the DAAC (including ordering and download). Authentication is completed as login-protected featuers are accessed. In order to allow icepyx to login for us we still have to make sure that we have made our Earthdata credentials available for icepyx to find.\n", + "When downloading data from NSIDC, all users must login using a valid (free) Earthdata account. The process of authenticating is handled by icepyx by creating and handling the required authentication to interface with the data at the DAAC (including ordering and download). Authentication is completed as login-protected features are accessed. In order to allow icepyx to login for us we still have to make sure that we have made our Earthdata credentials available for icepyx to find.\n", "\n", "There are multiple ways to provide your Earthdata credentials via icepyx. Behind the scenes, icepyx is using the [earthaccess library](https://nsidc.github.io/earthaccess/). The [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth) automatically tries three primary mechanisms for logging in, all of which are supported by icepyx:\n", "- with `EARTHDATA_USERNAME` and `EARTHDATA_PASSWORD` environment variables (these are the same as the ones you might have set for icepyx previously)\n", @@ -485,19 +485,7 @@ }, "source": [ "```{admonition} Important Authentication Update\n", - "Previously, icepyx required you to explicitly use the `earthdata_login()` function to login. Running this function is no longer required, but it is still available for backwards compatibility.\n", - "```" - ] - }, - { - "cell_type": "markdown", - "metadata": { - "user_expressions": [] - }, - "source": [ - "```{admonition} Important Authentication Update\n", - "Previously, icepyx required you to provide certain inputs to the `earthdata_login()` function, e.g. `region_a.earthdata_login(earthdata_uid, email).\n", - "These inputs are no longer required, but the keywords are still accepted for backwards compatibility.\n", + "Previously, icepyx required you to explicitly use the `earthdata_login()` function to login. Running this function is no longer required, but it is still available for backwards compatibility. Note that the function no longer requires any (e.g. email, user ID) inputs.\n", "```" ] }, @@ -636,9 +624,9 @@ ], "metadata": { "kernelspec": { - "display_name": "icepyx-dev", + "display_name": "Python 3 (ipykernel)", "language": "python", - "name": "icepyx-dev" + "name": "python3" }, "language_info": { "codemirror_mode": { @@ -650,7 +638,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.11.4" + "version": "3.10.10" } }, "nbformat": 4, From 63b0275aa3de3e55785b426718beed542104ae39 Mon Sep 17 00:00:00 2001 From: Jessica Scheick Date: Thu, 24 Aug 2023 11:36:29 -0400 Subject: [PATCH 37/63] minor updates to auth module docstrings --- icepyx/core/auth.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index 0994a7549..5ada2d9c0 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -20,8 +20,6 @@ class EarthdataAuthMixin(): 2. Entering credentials interactively 3. Storing credentials in a .netrc file (not recommended for security reasons) More details on using these methods is available in the [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth). - The input parameters listed here are provided for backwards compatibility; - before earthaccess existed, icepyx handled authentication and required these inputs. This class can be inherited by any other class that requires authentication. For example, the `Query` class inherits this one, and so a Query object has the @@ -29,7 +27,7 @@ class EarthdataAuthMixin(): The class can be created without any initialization parameters, and the properties will be populated when they are called. It can alternately be initialized with an - earthaccess.auth.Auth object, which will then be used to create a session of + earthaccess.auth.Auth object, which will then be used to create a session or s3login_credentials as they are called. Parameters @@ -89,6 +87,9 @@ def s3login_credentials(self): ''' A dictionary which stores login credentials for AWS s3 access. This property is accessed if using AWS cloud data. + + Because s3 tokens are only good for one hour, this function will automatically check if an + hour has elapsed since the last token use and generate a new token if necessary. ''' def set_s3_creds(): From 1796a2c0427cce7606c869542bbd4a14d154d431 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Thu, 24 Aug 2023 19:01:08 +0000 Subject: [PATCH 38/63] combine auth warning messages --- .../IS2_DEM_comparison_WIP.ipynb | 2 + .../IS2_cloud_data_access.ipynb | 2 + .../example_notebooks/IS2_data_access.ipynb | 1303 ++++++++++++++++- .../IS2_data_access2-subsetting.ipynb | 4 +- .../example_notebooks/IS2_data_read-in.ipynb | 2 + .../IS2_data_variables.ipynb | 2 + .../IS2_data_visualization.ipynb | 2 + 7 files changed, 1278 insertions(+), 39 deletions(-) diff --git a/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb b/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb index aac9c02f7..e0efd86e7 100644 --- a/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb +++ b/doc/source/example_notebooks/IS2_DEM_comparison_WIP.ipynb @@ -177,6 +177,8 @@ "source": [ "```{admonition} Important Authentication Update\n", "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "\n", + "If you do choose to use the `earthdata_login()`, you will also note that certain inputs, such as `earthdata_uid` and `email`, are no longer required. e.g. `region_a.earthdata_login(earthdata_uid, email)` becomes `region_a.earthdata_login()`\n", "```" ] }, diff --git a/doc/source/example_notebooks/IS2_cloud_data_access.ipynb b/doc/source/example_notebooks/IS2_cloud_data_access.ipynb index c205aa509..8f57f75bd 100644 --- a/doc/source/example_notebooks/IS2_cloud_data_access.ipynb +++ b/doc/source/example_notebooks/IS2_cloud_data_access.ipynb @@ -102,6 +102,8 @@ "source": [ "```{admonition} Important Authentication Update\n", "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "\n", + "If you do choose to use the `earthdata_login()`, you will also note that certain inputs, such as `earthdata_uid` and `email`, are no longer required. e.g. `region_a.earthdata_login(earthdata_uid, email)` becomes `region_a.earthdata_login()`\n", "```" ] }, diff --git a/doc/source/example_notebooks/IS2_data_access.ipynb b/doc/source/example_notebooks/IS2_data_access.ipynb index 17b5b5fac..b1de99cec 100644 --- a/doc/source/example_notebooks/IS2_data_access.ipynb +++ b/doc/source/example_notebooks/IS2_data_access.ipynb @@ -18,11 +18,666 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/jovyan/envs/icepyx-dev/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", + " from .autonotebook import tqdm as notebook_tqdm\n" + ] + }, + { + "data": { + "application/javascript": [ + "(function(root) {\n", + " function now() {\n", + " return new Date();\n", + " }\n", + "\n", + " var force = true;\n", + " var py_version = '3.2.0'.replace('rc', '-rc.').replace('.dev', '-dev.');\n", + " var is_dev = py_version.indexOf(\"+\") !== -1 || py_version.indexOf(\"-\") !== -1;\n", + " var reloading = false;\n", + " var Bokeh = root.Bokeh;\n", + " var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n", + "\n", + " if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n", + " root._bokeh_timeout = Date.now() + 5000;\n", + " root._bokeh_failed_load = false;\n", + " }\n", + "\n", + " function run_callbacks() {\n", + " try {\n", + " root._bokeh_onload_callbacks.forEach(function(callback) {\n", + " if (callback != null)\n", + " callback();\n", + " });\n", + " } finally {\n", + " delete root._bokeh_onload_callbacks;\n", + " }\n", + " console.debug(\"Bokeh: all callbacks have finished\");\n", + " }\n", + "\n", + " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n", + " if (css_urls == null) css_urls = [];\n", + " if (js_urls == null) js_urls = [];\n", + " if (js_modules == null) js_modules = [];\n", + " if (js_exports == null) js_exports = {};\n", + "\n", + " root._bokeh_onload_callbacks.push(callback);\n", + "\n", + " if (root._bokeh_is_loading > 0) {\n", + " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", + " return null;\n", + " }\n", + " if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n", + " run_callbacks();\n", + " return null;\n", + " }\n", + " if (!reloading) {\n", + " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", + " }\n", + "\n", + " function on_load() {\n", + " root._bokeh_is_loading--;\n", + " if (root._bokeh_is_loading === 0) {\n", + " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", + " run_callbacks()\n", + " }\n", + " }\n", + " window._bokeh_on_load = on_load\n", + "\n", + " function on_error() {\n", + " console.error(\"failed to load \" + url);\n", + " }\n", + "\n", + " var skip = [];\n", + " if (window.requirejs) {\n", + " window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n", + " require([\"jspanel\"], function(jsPanel) {\n", + "\twindow.jsPanel = jsPanel\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-modal\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-tooltip\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-hint\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-layout\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-contextmenu\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"jspanel-dock\"], function() {\n", + "\ton_load()\n", + " })\n", + " require([\"gridstack\"], function(GridStack) {\n", + "\twindow.GridStack = GridStack\n", + "\ton_load()\n", + " })\n", + " require([\"notyf\"], function() {\n", + "\ton_load()\n", + " })\n", + " root._bokeh_is_loading = css_urls.length + 9;\n", + " } else {\n", + " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n", + " }\n", + "\n", + " var existing_stylesheets = []\n", + " var links = document.getElementsByTagName('link')\n", + " for (var i = 0; i < links.length; i++) {\n", + " var link = links[i]\n", + " if (link.href != null) {\n", + "\texisting_stylesheets.push(link.href)\n", + " }\n", + " }\n", + " for (var i = 0; i < css_urls.length; i++) {\n", + " var url = css_urls[i];\n", + " if (existing_stylesheets.indexOf(url) !== -1) {\n", + "\ton_load()\n", + "\tcontinue;\n", + " }\n", + " const element = document.createElement(\"link\");\n", + " element.onload = on_load;\n", + " element.onerror = on_error;\n", + " element.rel = \"stylesheet\";\n", + " element.type = \"text/css\";\n", + " element.href = url;\n", + " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", + " document.body.appendChild(element);\n", + " } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n", + " var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n", + " for (var i = 0; i < urls.length; i++) {\n", + " skip.push(urls[i])\n", + " }\n", + " } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n", + " var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n", + " for (var i = 0; i < urls.length; i++) {\n", + " skip.push(urls[i])\n", + " }\n", + " } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n", + " var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n", + " for (var i = 0; i < urls.length; i++) {\n", + " skip.push(urls[i])\n", + " }\n", + " } var existing_scripts = []\n", + " var scripts = document.getElementsByTagName('script')\n", + " for (var i = 0; i < scripts.length; i++) {\n", + " var script = scripts[i]\n", + " if (script.src != null) {\n", + "\texisting_scripts.push(script.src)\n", + " }\n", + " }\n", + " for (var i = 0; i < js_urls.length; i++) {\n", + " var url = js_urls[i];\n", + " if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n", + "\tif (!window.requirejs) {\n", + "\t on_load();\n", + "\t}\n", + "\tcontinue;\n", + " }\n", + " var element = document.createElement('script');\n", + " element.onload = on_load;\n", + " element.onerror = on_error;\n", + " element.async = false;\n", + " element.src = url;\n", + " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", + " document.head.appendChild(element);\n", + " }\n", + " for (var i = 0; i < js_modules.length; i++) {\n", + " var url = js_modules[i];\n", + " if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n", + "\tif (!window.requirejs) {\n", + "\t on_load();\n", + "\t}\n", + "\tcontinue;\n", + " }\n", + " var element = document.createElement('script');\n", + " element.onload = on_load;\n", + " element.onerror = on_error;\n", + " element.async = false;\n", + " element.src = url;\n", + " element.type = \"module\";\n", + " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", + " document.head.appendChild(element);\n", + " }\n", + " for (const name in js_exports) {\n", + " var url = js_exports[name];\n", + " if (skip.indexOf(url) >= 0 || root[name] != null) {\n", + "\tif (!window.requirejs) {\n", + "\t on_load();\n", + "\t}\n", + "\tcontinue;\n", + " }\n", + " var element = document.createElement('script');\n", + " element.onerror = on_error;\n", + " element.async = false;\n", + " element.type = \"module\";\n", + " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", + " element.textContent = `\n", + " import ${name} from \"${url}\"\n", + " window.${name} = ${name}\n", + " window._bokeh_on_load()\n", + " `\n", + " document.head.appendChild(element);\n", + " }\n", + " if (!js_urls.length && !js_modules.length) {\n", + " on_load()\n", + " }\n", + " };\n", + "\n", + " function inject_raw_css(css) {\n", + " const element = document.createElement(\"style\");\n", + " element.appendChild(document.createTextNode(css));\n", + " document.body.appendChild(element);\n", + " }\n", + "\n", + " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.2.0.min.js\", \"https://cdn.holoviz.org/panel/1.2.0/dist/panel.min.js\"];\n", + " var js_modules = [];\n", + " var js_exports = {};\n", + " var css_urls = [];\n", + " var inline_js = [ function(Bokeh) {\n", + " Bokeh.set_log_level(\"info\");\n", + " },\n", + "function(Bokeh) {} // ensure no trailing comma for IE\n", + " ];\n", + "\n", + " function run_inline_js() {\n", + " if ((root.Bokeh !== undefined) || (force === true)) {\n", + " for (var i = 0; i < inline_js.length; i++) {\n", + " inline_js[i].call(root, root.Bokeh);\n", + " }\n", + " // Cache old bokeh versions\n", + " if (Bokeh != undefined && !reloading) {\n", + "\tvar NewBokeh = root.Bokeh;\n", + "\tif (Bokeh.versions === undefined) {\n", + "\t Bokeh.versions = new Map();\n", + "\t}\n", + "\tif (NewBokeh.version !== Bokeh.version) {\n", + "\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n", + "\t}\n", + "\troot.Bokeh = Bokeh;\n", + " }} else if (Date.now() < root._bokeh_timeout) {\n", + " setTimeout(run_inline_js, 100);\n", + " } else if (!root._bokeh_failed_load) {\n", + " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", + " root._bokeh_failed_load = true;\n", + " }\n", + " root._bokeh_is_initializing = false\n", + " }\n", + "\n", + " function load_or_wait() {\n", + " // Implement a backoff loop that tries to ensure we do not load multiple\n", + " // versions of Bokeh and its dependencies at the same time.\n", + " // In recent versions we use the root._bokeh_is_initializing flag\n", + " // to determine whether there is an ongoing attempt to initialize\n", + " // bokeh, however for backward compatibility we also try to ensure\n", + " // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n", + " // before older versions are fully initialized.\n", + " if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n", + " root._bokeh_is_initializing = false;\n", + " root._bokeh_onload_callbacks = undefined;\n", + " console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n", + " load_or_wait();\n", + " } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n", + " setTimeout(load_or_wait, 100);\n", + " } else {\n", + " Bokeh = root.Bokeh;\n", + " bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n", + " root._bokeh_is_initializing = true\n", + " root._bokeh_onload_callbacks = []\n", + " if (!reloading && (!bokeh_loaded || is_dev)) {\n", + "\troot.Bokeh = undefined;\n", + " }\n", + " load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n", + "\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", + "\trun_inline_js();\n", + " });\n", + " }\n", + " }\n", + " // Give older versions of the autoload script a head-start to ensure\n", + " // they initialize before we start loading newer version.\n", + " setTimeout(load_or_wait, 100)\n", + "}(window));" + ], + "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n var py_version = '3.2.0'.replace('rc', '-rc.').replace('.dev', '-dev.');\n var is_dev = py_version.indexOf(\"+\") !== -1 || py_version.indexOf(\"-\") !== -1;\n var reloading = false;\n var Bokeh = root.Bokeh;\n var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n run_callbacks();\n return null;\n }\n if (!reloading) {\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n require([\"jspanel\"], function(jsPanel) {\n\twindow.jsPanel = jsPanel\n\ton_load()\n })\n require([\"jspanel-modal\"], function() {\n\ton_load()\n })\n require([\"jspanel-tooltip\"], function() {\n\ton_load()\n })\n require([\"jspanel-hint\"], function() {\n\ton_load()\n })\n require([\"jspanel-layout\"], function() {\n\ton_load()\n })\n require([\"jspanel-contextmenu\"], function() {\n\ton_load()\n })\n require([\"jspanel-dock\"], function() {\n\ton_load()\n })\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 9;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n var existing_stylesheets = []\n var links = document.getElementsByTagName('link')\n for (var i = 0; i < links.length; i++) {\n var link = links[i]\n if (link.href != null) {\n\texisting_stylesheets.push(link.href)\n }\n }\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n if (existing_stylesheets.indexOf(url) !== -1) {\n\ton_load()\n\tcontinue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } var existing_scripts = []\n var scripts = document.getElementsByTagName('script')\n for (var i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n\texisting_scripts.push(script.src)\n }\n }\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n var url = js_exports[name];\n if (skip.indexOf(url) >= 0 || root[name] != null) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.2.0.min.js\", \"https://cdn.holoviz.org/panel/1.2.0/dist/panel.min.js\"];\n var js_modules = [];\n var js_exports = {};\n var css_urls = [];\n var inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n\tvar NewBokeh = root.Bokeh;\n\tif (Bokeh.versions === undefined) {\n\t Bokeh.versions = new Map();\n\t}\n\tif (NewBokeh.version !== Bokeh.version) {\n\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n\t}\n\troot.Bokeh = Bokeh;\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n Bokeh = root.Bokeh;\n bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n if (!reloading && (!bokeh_loaded || is_dev)) {\n\troot.Bokeh = undefined;\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n\trun_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "application/javascript": [ + "\n", + "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", + " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", + "}\n", + "\n", + "\n", + " function JupyterCommManager() {\n", + " }\n", + "\n", + " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", + " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", + " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", + " comm_manager.register_target(comm_id, function(comm) {\n", + " comm.on_msg(msg_handler);\n", + " });\n", + " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", + " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", + " comm.onMsg = msg_handler;\n", + " });\n", + " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", + " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", + " var messages = comm.messages[Symbol.asyncIterator]();\n", + " function processIteratorResult(result) {\n", + " var message = result.value;\n", + " console.log(message)\n", + " var content = {data: message.data, comm_id};\n", + " var buffers = []\n", + " for (var buffer of message.buffers || []) {\n", + " buffers.push(new DataView(buffer))\n", + " }\n", + " var metadata = message.metadata || {};\n", + " var msg = {content, buffers, metadata}\n", + " msg_handler(msg);\n", + " return messages.next().then(processIteratorResult);\n", + " }\n", + " return messages.next().then(processIteratorResult);\n", + " })\n", + " }\n", + " }\n", + "\n", + " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", + " if (comm_id in window.PyViz.comms) {\n", + " return window.PyViz.comms[comm_id];\n", + " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", + " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", + " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", + " if (msg_handler) {\n", + " comm.on_msg(msg_handler);\n", + " }\n", + " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", + " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", + " comm.open();\n", + " if (msg_handler) {\n", + " comm.onMsg = msg_handler;\n", + " }\n", + " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", + " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", + " comm_promise.then((comm) => {\n", + " window.PyViz.comms[comm_id] = comm;\n", + " if (msg_handler) {\n", + " var messages = comm.messages[Symbol.asyncIterator]();\n", + " function processIteratorResult(result) {\n", + " var message = result.value;\n", + " var content = {data: message.data};\n", + " var metadata = message.metadata || {comm_id};\n", + " var msg = {content, metadata}\n", + " msg_handler(msg);\n", + " return messages.next().then(processIteratorResult);\n", + " }\n", + " return messages.next().then(processIteratorResult);\n", + " }\n", + " }) \n", + " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", + " return comm_promise.then((comm) => {\n", + " comm.send(data, metadata, buffers, disposeOnDone);\n", + " });\n", + " };\n", + " var comm = {\n", + " send: sendClosure\n", + " };\n", + " }\n", + " window.PyViz.comms[comm_id] = comm;\n", + " return comm;\n", + " }\n", + " window.PyViz.comm_manager = new JupyterCommManager();\n", + " \n", + "\n", + "\n", + "var JS_MIME_TYPE = 'application/javascript';\n", + "var HTML_MIME_TYPE = 'text/html';\n", + "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", + "var CLASS_NAME = 'output';\n", + "\n", + "/**\n", + " * Render data to the DOM node\n", + " */\n", + "function render(props, node) {\n", + " var div = document.createElement(\"div\");\n", + " var script = document.createElement(\"script\");\n", + " node.appendChild(div);\n", + " node.appendChild(script);\n", + "}\n", + "\n", + "/**\n", + " * Handle when a new output is added\n", + " */\n", + "function handle_add_output(event, handle) {\n", + " var output_area = handle.output_area;\n", + " var output = handle.output;\n", + " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", + " return\n", + " }\n", + " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", + " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", + " if (id !== undefined) {\n", + " var nchildren = toinsert.length;\n", + " var html_node = toinsert[nchildren-1].children[0];\n", + " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", + " var scripts = [];\n", + " var nodelist = html_node.querySelectorAll(\"script\");\n", + " for (var i in nodelist) {\n", + " if (nodelist.hasOwnProperty(i)) {\n", + " scripts.push(nodelist[i])\n", + " }\n", + " }\n", + "\n", + " scripts.forEach( function (oldScript) {\n", + " var newScript = document.createElement(\"script\");\n", + " var attrs = [];\n", + " var nodemap = oldScript.attributes;\n", + " for (var j in nodemap) {\n", + " if (nodemap.hasOwnProperty(j)) {\n", + " attrs.push(nodemap[j])\n", + " }\n", + " }\n", + " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", + " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", + " oldScript.parentNode.replaceChild(newScript, oldScript);\n", + " });\n", + " if (JS_MIME_TYPE in output.data) {\n", + " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", + " }\n", + " output_area._hv_plot_id = id;\n", + " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", + " window.PyViz.plot_index[id] = Bokeh.index[id];\n", + " } else {\n", + " window.PyViz.plot_index[id] = null;\n", + " }\n", + " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", + " var bk_div = document.createElement(\"div\");\n", + " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", + " var script_attrs = bk_div.children[0].attributes;\n", + " for (var i = 0; i < script_attrs.length; i++) {\n", + " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", + " }\n", + " // store reference to server id on output_area\n", + " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", + " }\n", + "}\n", + "\n", + "/**\n", + " * Handle when an output is cleared or removed\n", + " */\n", + "function handle_clear_output(event, handle) {\n", + " var id = handle.cell.output_area._hv_plot_id;\n", + " var server_id = handle.cell.output_area._bokeh_server_id;\n", + " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", + " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", + " if (server_id !== null) {\n", + " comm.send({event_type: 'server_delete', 'id': server_id});\n", + " return;\n", + " } else if (comm !== null) {\n", + " comm.send({event_type: 'delete', 'id': id});\n", + " }\n", + " delete PyViz.plot_index[id];\n", + " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", + " var doc = window.Bokeh.index[id].model.document\n", + " doc.clear();\n", + " const i = window.Bokeh.documents.indexOf(doc);\n", + " if (i > -1) {\n", + " window.Bokeh.documents.splice(i, 1);\n", + " }\n", + " }\n", + "}\n", + "\n", + "/**\n", + " * Handle kernel restart event\n", + " */\n", + "function handle_kernel_cleanup(event, handle) {\n", + " delete PyViz.comms[\"hv-extension-comm\"];\n", + " window.PyViz.plot_index = {}\n", + "}\n", + "\n", + "/**\n", + " * Handle update_display_data messages\n", + " */\n", + "function handle_update_output(event, handle) {\n", + " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", + " handle_add_output(event, handle)\n", + "}\n", + "\n", + "function register_renderer(events, OutputArea) {\n", + " function append_mime(data, metadata, element) {\n", + " // create a DOM node to render to\n", + " var toinsert = this.create_output_subarea(\n", + " metadata,\n", + " CLASS_NAME,\n", + " EXEC_MIME_TYPE\n", + " );\n", + " this.keyboard_manager.register_events(toinsert);\n", + " // Render to node\n", + " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", + " render(props, toinsert[0]);\n", + " element.append(toinsert);\n", + " return toinsert\n", + " }\n", + "\n", + " events.on('output_added.OutputArea', handle_add_output);\n", + " events.on('output_updated.OutputArea', handle_update_output);\n", + " events.on('clear_output.CodeCell', handle_clear_output);\n", + " events.on('delete.Cell', handle_clear_output);\n", + " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", + "\n", + " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", + " safe: true,\n", + " index: 0\n", + " });\n", + "}\n", + "\n", + "if (window.Jupyter !== undefined) {\n", + " try {\n", + " var events = require('base/js/events');\n", + " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", + " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", + " register_renderer(events, OutputArea);\n", + " }\n", + " } catch(err) {\n", + " }\n", + "}\n" + ], + "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "\n", + "
\n", + "\n", + "\n", + "\n", + " \n", + " \n", + "\n", + "\n", + "\n", + "\n", + "
\n" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "import icepyx as ipx\n", "import os\n", @@ -107,7 +762,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "tags": [] }, @@ -121,7 +776,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "tags": [] }, @@ -135,7 +790,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "tags": [] }, @@ -149,7 +804,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "tags": [] }, @@ -167,7 +822,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "metadata": { "tags": [] }, @@ -181,7 +836,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "tags": [] }, @@ -214,7 +869,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 8, "metadata": { "tags": [] }, @@ -225,11 +880,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ATL06\n", + "006\n", + "['03', '04', '05', '06', '07']\n", + "['0849', '0902']\n" + ] + } + ], "source": [ "# using orbital parameters with one of the above data products + spatial parameters\n", "region_a = ipx.Query(short_name, spatial_extent,\n", @@ -252,11 +918,30 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/jovyan/icepyx/icepyx/core/query.py:1165: FutureWarning: The geopandas.dataset module is deprecated and will be removed in GeoPandas 1.0. You can get the original 'naturalearth_lowres' data from https://www.naturalearthdata.com/downloads/110m-cultural-vectors/.\n", + " world = gpd.read_file(gpd.datasets.get_path(\"naturalearth_lowres\"))\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "# print(region_a.spatial_extent)\n", "region_a.visualize_spatial_extent()" @@ -273,11 +958,41 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ATL06\n", + "['No temporal parameters set']\n", + "['03', '04', '05', '06', '07']\n", + "['0849', '0902']\n", + "006\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/jovyan/icepyx/icepyx/core/query.py:1165: FutureWarning: The geopandas.dataset module is deprecated and will be removed in GeoPandas 1.0. You can get the original 'naturalearth_lowres' data from https://www.naturalearthdata.com/downloads/110m-cultural-vectors/.\n", + " world = gpd.read_file(gpd.datasets.get_path(\"naturalearth_lowres\"))\n" + ] + }, + { + "data": { + "image/png": "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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "print(region_a.product)\n", "print(region_a.temporal) # .dates, .start_time, .end_time can also be used for a piece of this information\n", @@ -311,11 +1026,34 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 12, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ATL06\n", + "['2019-10-01', '2019-10-05']\n", + "002\n", + "Extent type: polygon\n", + "Source file: ./supporting_files/simple_test_poly.gpkg\n", + "Coordinates: [-55.0, 68.0, -55.0, 71.0, -48.0, 71.0, -48.0, 68.0, -55.0, 68.0]\n", + "Start date and time: 2019-10-01 03:30:00\n", + "End date and time: 2019-10-05 21:30:00\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/jovyan/icepyx/icepyx/core/validate_inputs.py:25: UserWarning: You are using an old version of this product\n", + " warnings.warn(\"You are using an old version of this product\")\n" + ] + } + ], "source": [ "region_a = ipx.Query(short_name, spatial_extent, date_range, \\\n", " start_time='03:30:00', end_time='21:30:00', version='002')\n", @@ -338,7 +1076,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "metadata": { "tags": [] }, @@ -360,11 +1098,26 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "title : ATLAS/ICESat-2 L3A Land Ice Height V006\n", + "short_name : ATL06\n", + "version_id : 006\n", + "time_start : 2018-10-14T00:00:00.000Z\n", + "coordinate_system : CARTESIAN\n", + "summary : This data set (ATL06) provides geolocated, land-ice surface heights (above the WGS 84 ellipsoid, ITRF2014 reference frame), plus ancillary parameters that can be used to interpret and assess the quality of the height estimates. The data were acquired by the Advanced Topographic Laser Altimeter System (ATLAS) instrument on board the Ice, Cloud and land Elevation Satellite-2 (ICESat-2) observatory.\n", + "orbit_parameters : {}\n", + "006\n" + ] + } + ], "source": [ "region_a.product_summary_info()\n", "print(region_a.latest_version())" @@ -381,12 +1134,360 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "metadata": { "scrolled": true, "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'feed': {'entry': [{'archive_center': 'NASA NSIDC DAAC',\n", + " 'association_details': {'services': [{'concept_id': 'S2472217299-NSIDC_CPRD'}],\n", + " 'tools': [{'concept_id': 'TL1977971361-NSIDC_ECS'},\n", + " {'concept_id': 'TL2682629857-NSIDC_CPRD'},\n", + " {'concept_id': 'TL2746943302-NSIDC_CPRD'}]},\n", + " 'associations': {'services': ['S2472217299-NSIDC_CPRD'],\n", + " 'tools': ['TL1977971361-NSIDC_ECS',\n", + " 'TL2682629857-NSIDC_CPRD',\n", + " 'TL2746943302-NSIDC_CPRD']},\n", + " 'boxes': ['-90 -180 90 180'],\n", + " 'browse_flag': False,\n", + " 'cloud_hosted': True,\n", + " 'consortiums': ['GEOSS', 'EOSDIS'],\n", + " 'coordinate_system': 'CARTESIAN',\n", + " 'data_center': 'NSIDC_CPRD',\n", + " 'dataset_id': 'ATLAS/ICESat-2 L3A Land Ice Height V005',\n", + " 'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False,\n", + " 'id': 'C2153572614-NSIDC_CPRD',\n", + " 'links': [{'href': 'https://search.earthdata.nasa.gov/search?q=ATL06+V005',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.005',\n", + " 'hreflang': 'en-US',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#'},\n", + " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.005',\n", + " 'hreflang': 'en-US',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#'}],\n", + " 'online_access_flag': True,\n", + " 'orbit_parameters': {'inclination_angle': '92.0',\n", + " 'number_of_orbits': '0.071428571',\n", + " 'period': '96.8',\n", + " 'start_circular_latitude': '0.0',\n", + " 'swath_width': '36.0'},\n", + " 'organizations': ['NASA NSIDC DAAC',\n", + " 'NASA/GSFC/EOS/ESDIS'],\n", + " 'original_format': 'ISO19115',\n", + " 'platforms': ['ICESat-2'],\n", + " 'processing_level_id': 'Level 3',\n", + " 'service_features': {'esi': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False},\n", + " 'harmony': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False},\n", + " 'opendap': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False}},\n", + " 'short_name': 'ATL06',\n", + " 'summary': 'This data set (ATL06) provides geolocated, '\n", + " 'land-ice surface heights (above the WGS 84 '\n", + " 'ellipsoid, ITRF2014 reference frame), plus '\n", + " 'ancillary parameters that can be used to '\n", + " 'interpret and assess the quality of the '\n", + " 'height estimates. The data were acquired by '\n", + " 'the Advanced Topographic Laser Altimeter '\n", + " 'System (ATLAS) instrument on board the Ice, '\n", + " 'Cloud and land Elevation Satellite-2 '\n", + " '(ICESat-2) observatory.',\n", + " 'time_start': '2018-10-14T00:00:00.000Z',\n", + " 'title': 'ATLAS/ICESat-2 L3A Land Ice Height V005',\n", + " 'version_id': '005'},\n", + " {'archive_center': 'NASA NSIDC DAAC',\n", + " 'association_details': {'services': [{'concept_id': 'S1977894169-NSIDC_ECS'},\n", + " {'concept_id': 'S1568899363-NSIDC_ECS',\n", + " 'data': {'order_option': 'OO2700493442-NSIDC_ECS'}},\n", + " {'concept_id': 'S2013515292-NSIDC_ECS',\n", + " 'data': {'order_option': 'OO2700528732-NSIDC_ECS'}},\n", + " {'concept_id': 'S2008499525-NSIDC_ECS'}],\n", + " 'tools': [{'concept_id': 'TL2000645101-NSIDC_ECS'},\n", + " {'concept_id': 'TL1977971361-NSIDC_ECS'},\n", + " {'concept_id': 'TL2012682515-NSIDC_ECS'},\n", + " {'concept_id': 'TL1977912846-NSIDC_ECS'},\n", + " {'concept_id': 'TL1956547654-NSIDC_ECS'},\n", + " {'concept_id': 'TL2011654705-NSIDC_ECS'},\n", + " {'concept_id': 'TL1956087574-NSIDC_ECS'},\n", + " {'concept_id': 'TL1952642907-NSIDC_ECS'},\n", + " {'concept_id': 'TL1994100033-NSIDC_ECS'}]},\n", + " 'associations': {'services': ['S1977894169-NSIDC_ECS',\n", + " 'S1568899363-NSIDC_ECS',\n", + " 'S2013515292-NSIDC_ECS',\n", + " 'S2008499525-NSIDC_ECS'],\n", + " 'tools': ['TL2000645101-NSIDC_ECS',\n", + " 'TL1977971361-NSIDC_ECS',\n", + " 'TL2012682515-NSIDC_ECS',\n", + " 'TL1977912846-NSIDC_ECS',\n", + " 'TL1956547654-NSIDC_ECS',\n", + " 'TL2011654705-NSIDC_ECS',\n", + " 'TL1956087574-NSIDC_ECS',\n", + " 'TL1952642907-NSIDC_ECS',\n", + " 'TL1994100033-NSIDC_ECS']},\n", + " 'boxes': ['-90 -180 90 180'],\n", + " 'browse_flag': False,\n", + " 'cloud_hosted': False,\n", + " 'consortiums': ['GEOSS', 'EOSDIS'],\n", + " 'coordinate_system': 'CARTESIAN',\n", + " 'data_center': 'NSIDC_ECS',\n", + " 'dataset_id': 'ATLAS/ICESat-2 L3A Land Ice Height V005',\n", + " 'has_formats': True,\n", + " 'has_spatial_subsetting': True,\n", + " 'has_temporal_subsetting': True,\n", + " 'has_transforms': False,\n", + " 'has_variables': True,\n", + " 'id': 'C2144439155-NSIDC_ECS',\n", + " 'links': [{'href': 'https://n5eil01u.ecs.nsidc.org/ATLAS/ATL06.005/',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://search.earthdata.nasa.gov/search?q=ATL06+V005',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://openaltimetry.org/',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://nsidc.org/data/data-access-tool/ATL06/versions/5/',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.005',\n", + " 'hreflang': 'en-US',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#'},\n", + " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.005',\n", + " 'hreflang': 'en-US',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#'}],\n", + " 'online_access_flag': True,\n", + " 'orbit_parameters': {'inclination_angle': '92.0',\n", + " 'number_of_orbits': '0.071428571',\n", + " 'period': '96.8',\n", + " 'start_circular_latitude': '0.0',\n", + " 'swath_width': '36.0'},\n", + " 'organizations': ['NASA NSIDC DAAC',\n", + " 'NASA/GSFC/EOS/ESDIS'],\n", + " 'original_format': 'ISO19115',\n", + " 'platforms': ['ICESat-2'],\n", + " 'processing_level_id': 'Level 3',\n", + " 'service_features': {'esi': {'has_formats': True,\n", + " 'has_spatial_subsetting': True,\n", + " 'has_temporal_subsetting': True,\n", + " 'has_transforms': False,\n", + " 'has_variables': True},\n", + " 'harmony': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False},\n", + " 'opendap': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False}},\n", + " 'short_name': 'ATL06',\n", + " 'summary': 'This data set (ATL06) provides geolocated, '\n", + " 'land-ice surface heights (above the WGS 84 '\n", + " 'ellipsoid, ITRF2014 reference frame), plus '\n", + " 'ancillary parameters that can be used to '\n", + " 'interpret and assess the quality of the '\n", + " 'height estimates. The data were acquired by '\n", + " 'the Advanced Topographic Laser Altimeter '\n", + " 'System (ATLAS) instrument on board the Ice, '\n", + " 'Cloud and land Elevation Satellite-2 '\n", + " '(ICESat-2) observatory.',\n", + " 'time_start': '2018-10-14T00:00:00.000Z',\n", + " 'title': 'ATLAS/ICESat-2 L3A Land Ice Height V005',\n", + " 'version_id': '005'},\n", + " {'archive_center': 'NASA NSIDC DAAC',\n", + " 'association_details': {'services': [{'concept_id': 'S2472217299-NSIDC_CPRD'}],\n", + " 'tools': [{'concept_id': 'TL1977971361-NSIDC_ECS'},\n", + " {'concept_id': 'TL2682629857-NSIDC_CPRD'},\n", + " {'concept_id': 'TL2746943302-NSIDC_CPRD'}]},\n", + " 'associations': {'services': ['S2472217299-NSIDC_CPRD'],\n", + " 'tools': ['TL1977971361-NSIDC_ECS',\n", + " 'TL2682629857-NSIDC_CPRD',\n", + " 'TL2746943302-NSIDC_CPRD']},\n", + " 'boxes': ['-90 -180 90 180'],\n", + " 'browse_flag': False,\n", + " 'cloud_hosted': True,\n", + " 'consortiums': ['GEOSS', 'EOSDIS'],\n", + " 'coordinate_system': 'CARTESIAN',\n", + " 'data_center': 'NSIDC_CPRD',\n", + " 'dataset_id': 'ATLAS/ICESat-2 L3A Land Ice Height V006',\n", + " 'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False,\n", + " 'id': 'C2670138092-NSIDC_CPRD',\n", + " 'links': [{'href': 'https://search.earthdata.nasa.gov/search?q=ATL06+V006',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.006',\n", + " 'hreflang': 'en-US',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#'},\n", + " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.006',\n", + " 'hreflang': 'en-US',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#'}],\n", + " 'online_access_flag': True,\n", + " 'orbit_parameters': {},\n", + " 'organizations': ['NASA NSIDC DAAC',\n", + " 'NASA/GSFC/EOS/ESDIS'],\n", + " 'original_format': 'ISO19115',\n", + " 'platforms': ['ICESat-2'],\n", + " 'processing_level_id': 'Level 3',\n", + " 'service_features': {'esi': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False},\n", + " 'harmony': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False},\n", + " 'opendap': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False}},\n", + " 'short_name': 'ATL06',\n", + " 'summary': 'This data set (ATL06) provides geolocated, '\n", + " 'land-ice surface heights (above the WGS 84 '\n", + " 'ellipsoid, ITRF2014 reference frame), plus '\n", + " 'ancillary parameters that can be used to '\n", + " 'interpret and assess the quality of the '\n", + " 'height estimates. The data were acquired by '\n", + " 'the Advanced Topographic Laser Altimeter '\n", + " 'System (ATLAS) instrument on board the Ice, '\n", + " 'Cloud and land Elevation Satellite-2 '\n", + " '(ICESat-2) observatory.',\n", + " 'time_start': '2018-10-14T00:00:00.000Z',\n", + " 'title': 'ATLAS/ICESat-2 L3A Land Ice Height V006',\n", + " 'version_id': '006'},\n", + " {'archive_center': 'NASA NSIDC DAAC',\n", + " 'association_details': {'services': [{'concept_id': 'S1977894169-NSIDC_ECS'},\n", + " {'concept_id': 'S1568899363-NSIDC_ECS',\n", + " 'data': {'order_option': 'OO2700493442-NSIDC_ECS'}},\n", + " {'concept_id': 'S2013515292-NSIDC_ECS',\n", + " 'data': {'order_option': 'OO2700528970-NSIDC_ECS'}}],\n", + " 'tools': [{'concept_id': 'TL1977971361-NSIDC_ECS'},\n", + " {'concept_id': 'TL1952642907-NSIDC_ECS'},\n", + " {'concept_id': 'TL2011654705-NSIDC_ECS'},\n", + " {'concept_id': 'TL2012682515-NSIDC_ECS'},\n", + " {'concept_id': 'TL1977912846-NSIDC_ECS'},\n", + " {'concept_id': 'TL2000645101-NSIDC_ECS'},\n", + " {'concept_id': 'TL1956087574-NSIDC_ECS'}]},\n", + " 'associations': {'services': ['S1977894169-NSIDC_ECS',\n", + " 'S1568899363-NSIDC_ECS',\n", + " 'S2013515292-NSIDC_ECS'],\n", + " 'tools': ['TL1977971361-NSIDC_ECS',\n", + " 'TL1952642907-NSIDC_ECS',\n", + " 'TL2011654705-NSIDC_ECS',\n", + " 'TL2012682515-NSIDC_ECS',\n", + " 'TL1977912846-NSIDC_ECS',\n", + " 'TL2000645101-NSIDC_ECS',\n", + " 'TL1956087574-NSIDC_ECS']},\n", + " 'boxes': ['-90 -180 90 180'],\n", + " 'browse_flag': False,\n", + " 'cloud_hosted': False,\n", + " 'consortiums': ['GEOSS', 'EOSDIS'],\n", + " 'coordinate_system': 'CARTESIAN',\n", + " 'data_center': 'NSIDC_ECS',\n", + " 'dataset_id': 'ATLAS/ICESat-2 L3A Land Ice Height V006',\n", + " 'has_formats': True,\n", + " 'has_spatial_subsetting': True,\n", + " 'has_temporal_subsetting': True,\n", + " 'has_transforms': False,\n", + " 'has_variables': True,\n", + " 'id': 'C2564427300-NSIDC_ECS',\n", + " 'links': [{'href': 'https://n5eil01u.ecs.nsidc.org/ATLAS/ATL06.006/',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://search.earthdata.nasa.gov/search?q=ATL06+V006',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://openaltimetry.org/',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://nsidc.org/data/data-access-tool/ATL06/versions/6/',\n", + " 'hreflang': 'en-US',\n", + " 'length': '0.0KB',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", + " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.006',\n", + " 'hreflang': 'en-US',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#'},\n", + " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.006',\n", + " 'hreflang': 'en-US',\n", + " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#'}],\n", + " 'online_access_flag': True,\n", + " 'orbit_parameters': {},\n", + " 'organizations': ['NASA NSIDC DAAC',\n", + " 'NASA/GSFC/EOS/ESDIS'],\n", + " 'original_format': 'ISO19115',\n", + " 'platforms': ['ICESat-2'],\n", + " 'processing_level_id': 'Level 3',\n", + " 'service_features': {'esi': {'has_formats': True,\n", + " 'has_spatial_subsetting': True,\n", + " 'has_temporal_subsetting': True,\n", + " 'has_transforms': False,\n", + " 'has_variables': True},\n", + " 'harmony': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False},\n", + " 'opendap': {'has_formats': False,\n", + " 'has_spatial_subsetting': False,\n", + " 'has_temporal_subsetting': False,\n", + " 'has_transforms': False,\n", + " 'has_variables': False}},\n", + " 'short_name': 'ATL06',\n", + " 'summary': 'This data set (ATL06) provides geolocated, '\n", + " 'land-ice surface heights (above the WGS 84 '\n", + " 'ellipsoid, ITRF2014 reference frame), plus '\n", + " 'ancillary parameters that can be used to '\n", + " 'interpret and assess the quality of the '\n", + " 'height estimates. The data were acquired by '\n", + " 'the Advanced Topographic Laser Altimeter '\n", + " 'System (ATLAS) instrument on board the Ice, '\n", + " 'Cloud and land Elevation Satellite-2 '\n", + " '(ICESat-2) observatory.',\n", + " 'time_start': '2018-10-14T00:00:00.000Z',\n", + " 'title': 'ATLAS/ICESat-2 L3A Land Ice Height V006',\n", + " 'version_id': '006'}],\n", + " 'id': 'https://cmr.earthdata.nasa.gov:443/search/collections.json?short_name=ATL06',\n", + " 'title': 'ECHO dataset metadata',\n", + " 'updated': '2023-08-23T16:10:59.279Z'}}\n" + ] + } + ], "source": [ "region_a.product_all_info()" ] @@ -403,11 +1504,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "{'short_name': 'ATL06',\n", + " 'version': '002',\n", + " 'temporal': '2019-10-01T03:30:00Z,2019-10-05T21:30:00Z',\n", + " 'polygon': '-55.0,68.0,-48.0,68.0,-48.0,71.0,-55.0,71.0,-55.0,68.0'}" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "#build and view the parameters that will be submitted in our query\n", "region_a.CMRparams" @@ -428,11 +1543,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "ename": "AssertionError", + "evalue": "Your search returned no results; try different search parameters", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/icepyx/icepyx/core/query.py:951\u001b[0m, in \u001b[0;36mQuery.avail_granules\u001b[0;34m(self, ids, cycles, tracks, cloud)\u001b[0m\n\u001b[1;32m 950\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 951\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgranules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mavail\u001b[49m\n\u001b[1;32m 952\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mAttributeError\u001b[39;00m:\n", + "\u001b[0;31mAttributeError\u001b[0m: 'Granules' object has no attribute 'avail'", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[17], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m#search for available granules and provide basic summary info about them\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mregion_a\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mavail_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/icepyx/icepyx/core/query.py:953\u001b[0m, in \u001b[0;36mQuery.avail_granules\u001b[0;34m(self, ids, cycles, tracks, cloud)\u001b[0m\n\u001b[1;32m 951\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgranules\u001b[38;5;241m.\u001b[39mavail\n\u001b[1;32m 952\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mAttributeError\u001b[39;00m:\n\u001b[0;32m--> 953\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgranules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_avail\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mCMRparams\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreqparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 955\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ids \u001b[38;5;129;01mor\u001b[39;00m cycles \u001b[38;5;129;01mor\u001b[39;00m tracks \u001b[38;5;129;01mor\u001b[39;00m cloud:\n\u001b[1;32m 956\u001b[0m \u001b[38;5;66;03m# list of outputs in order of ids, cycles, tracks, cloud\u001b[39;00m\n\u001b[1;32m 957\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m granules\u001b[38;5;241m.\u001b[39mgran_IDs(\n\u001b[1;32m 958\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgranules\u001b[38;5;241m.\u001b[39mavail,\n\u001b[1;32m 959\u001b[0m ids\u001b[38;5;241m=\u001b[39mids,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 962\u001b[0m cloud\u001b[38;5;241m=\u001b[39mcloud,\n\u001b[1;32m 963\u001b[0m )\n", + "File \u001b[0;32m~/icepyx/icepyx/core/granules.py:251\u001b[0m, in \u001b[0;36mGranules.get_avail\u001b[0;34m(self, CMRparams, reqparams, cloud)\u001b[0m\n\u001b[1;32m 247\u001b[0m \u001b[38;5;66;03m# Collect results\u001b[39;00m\n\u001b[1;32m 248\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mavail\u001b[38;5;241m.\u001b[39mextend(results[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfeed\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mentry\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m 250\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m (\n\u001b[0;32m--> 251\u001b[0m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mavail) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m 252\u001b[0m ), \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mYour search returned no results; try different search parameters\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", + "\u001b[0;31mAssertionError\u001b[0m: Your search returned no results; try different search parameters" + ] + } + ], "source": [ "#search for available granules and provide basic summary info about them\n", "region_a.avail_granules()" @@ -440,11 +1573,25 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "ename": "AssertionError", + "evalue": "Your data object has no granules associated with it", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[18], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m#get a list of granule IDs for the available granules\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mregion_a\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mavail_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43mids\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/icepyx/icepyx/core/query.py:957\u001b[0m, in \u001b[0;36mQuery.avail_granules\u001b[0;34m(self, ids, cycles, tracks, cloud)\u001b[0m\n\u001b[1;32m 953\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgranules\u001b[38;5;241m.\u001b[39mget_avail(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mCMRparams, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreqparams)\n\u001b[1;32m 955\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ids \u001b[38;5;129;01mor\u001b[39;00m cycles \u001b[38;5;129;01mor\u001b[39;00m tracks \u001b[38;5;129;01mor\u001b[39;00m cloud:\n\u001b[1;32m 956\u001b[0m \u001b[38;5;66;03m# list of outputs in order of ids, cycles, tracks, cloud\u001b[39;00m\n\u001b[0;32m--> 957\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mgranules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgran_IDs\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 958\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgranules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mavail\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 959\u001b[0m \u001b[43m \u001b[49m\u001b[43mids\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mids\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 960\u001b[0m \u001b[43m \u001b[49m\u001b[43mcycles\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcycles\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 961\u001b[0m \u001b[43m \u001b[49m\u001b[43mtracks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtracks\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 962\u001b[0m \u001b[43m \u001b[49m\u001b[43mcloud\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcloud\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 963\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 964\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 965\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m granules\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgranules\u001b[38;5;241m.\u001b[39mavail)\n", + "File \u001b[0;32m~/icepyx/icepyx/core/granules.py:59\u001b[0m, in \u001b[0;36mgran_IDs\u001b[0;34m(grans, ids, cycles, tracks, dates, cloud)\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mgran_IDs\u001b[39m(grans, ids\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, cycles\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, tracks\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, dates\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, cloud\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m):\n\u001b[1;32m 39\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 40\u001b[0m \u001b[38;5;124;03m Returns a list of granule information for each granule dictionary in the input list of granule dictionaries.\u001b[39;00m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;124;03m Granule info may be from a list of those available from NSIDC (for ordering/download)\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 57\u001b[0m \u001b[38;5;124;03m Return a a list of AWS s3 urls for the available granules in the granule dictionary.\u001b[39;00m\n\u001b[1;32m 58\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 59\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(grans) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mYour data object has no granules associated with it\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;66;03m# regular expression for extracting parameters from file names\u001b[39;00m\n\u001b[1;32m 61\u001b[0m rx \u001b[38;5;241m=\u001b[39m re\u001b[38;5;241m.\u001b[39mcompile(\n\u001b[1;32m 62\u001b[0m \u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m(ATL\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(-\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)?_(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{4}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 63\u001b[0m \u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)_(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{4}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)_(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{3}\u001b[39;00m\u001b[38;5;124m)_(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(.*?).(.*?)$\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 64\u001b[0m )\n", + "\u001b[0;31mAssertionError\u001b[0m: Your data object has no granules associated with it" + ] + } + ], "source": [ "#get a list of granule IDs for the available granules\n", "region_a.avail_granules(ids=True)" @@ -452,12 +1599,23 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "metadata": { "scrolled": true, "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "#print detailed information about the returned search results\n", "region_a.granules.avail" @@ -485,7 +1643,13 @@ }, "source": [ "```{admonition} Important Authentication Update\n", +<<<<<<< Updated upstream "Previously, icepyx required you to explicitly use the `earthdata_login()` function to login. Running this function is no longer required, but it is still available for backwards compatibility. Note that the function no longer requires any (e.g. email, user ID) inputs.\n", +======= + "Previously, icepyx required you to explicitly use the `earthdata_login()` function to login. Running this function is no longer required, but it is still available for backwards compatibility. \n", + "\n", + "If you do choose to use the `earthdata_login()`, you will also note that certain inputs, such as `earthdata_uid` and `email`, are no longer required. e.g. `region_a.earthdata_login(earthdata_uid, email)` becomes `region_a.earthdata_login()`\n", +>>>>>>> Stashed changes "```" ] }, @@ -515,11 +1679,19 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'page_size': 2000}\n" + ] + } + ], "source": [ "print(region_a.reqparams)\n", "# region_a.reqparams['page_size'] = 9\n", @@ -528,7 +1700,9 @@ }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "#### Subsetting\n", "\n", @@ -550,18 +1724,32 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "{'time': '2019-10-01T03:30:00,2019-10-05T21:30:00',\n", + " 'Boundingshape': '{\"type\":\"FeatureCollection\",\"features\":[{\"id\":\"0\",\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-55.0,68.0],[-48.0,68.0],[-48.0,71.0],[-55.0,71.0],[-55.0,68.0]]]},\"bbox\":[-55.0,68.0,-48.0,71.0]}],\"bbox\":[-55.0,68.0,-48.0,71.0]}'}" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "region_a.subsetparams()" ] }, { "cell_type": "markdown", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Place the order\n", "Then, we can send the order to NSIDC using the order_granules function. Information about the granules ordered and their status will be printed automatically. Status information can also be emailed to the address associated with your EarthData account when the `email` kwarg is set to `True`. Additional information on the order, including request URLs, can be viewed by setting the optional keyword input 'verbose' to True." @@ -569,11 +1757,36 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "tags": [] }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "EARTHDATA_USERNAME and EARTHDATA_PASSWORD are not set in the current environment, try setting them or use a different strategy (netrc, interactive)\n", + "You're now authenticated with NASA Earthdata Login\n", + "Using token with expiration date: 10/13/2023\n", + "Using .netrc file for EDL\n" + ] + }, + { + "ename": "AssertionError", + "evalue": "Your search returned no results; try different search parameters", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[22], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mregion_a\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43morder_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;66;03m# region_a.order_granules(verbose=True, subset=False, email=False)\u001b[39;00m\n", + "File \u001b[0;32m~/icepyx/icepyx/core/query.py:1062\u001b[0m, in \u001b[0;36mQuery.order_granules\u001b[0;34m(self, verbose, subset, email, **kwargs)\u001b[0m\n\u001b[1;32m 1051\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39mplace_order(\n\u001b[1;32m 1052\u001b[0m tempCMRparams,\n\u001b[1;32m 1053\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreqparams,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1058\u001b[0m geom_filepath\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_spatial\u001b[38;5;241m.\u001b[39m_geom_file,\n\u001b[1;32m 1059\u001b[0m )\n\u001b[1;32m 1061\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1062\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_granules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mplace_order\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 1063\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mCMRparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1064\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreqparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1065\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msubsetparams\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1066\u001b[0m \u001b[43m \u001b[49m\u001b[43mverbose\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1067\u001b[0m \u001b[43m \u001b[49m\u001b[43msubset\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1068\u001b[0m \u001b[43m \u001b[49m\u001b[43msession\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msession\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1069\u001b[0m \u001b[43m \u001b[49m\u001b[43mgeom_filepath\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_spatial\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_geom_file\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1070\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/icepyx/icepyx/core/granules.py:315\u001b[0m, in \u001b[0;36mGranules.place_order\u001b[0;34m(self, CMRparams, reqparams, subsetparams, verbose, subset, session, geom_filepath)\u001b[0m\n\u001b[1;32m 309\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 310\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mDon\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt forget to log in to Earthdata using query.earthdata_login()\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 311\u001b[0m )\n\u001b[1;32m 313\u001b[0m base_url \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://n5eil02u.ecs.nsidc.org/egi/request\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m--> 315\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_avail\u001b[49m\u001b[43m(\u001b[49m\u001b[43mCMRparams\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mreqparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 317\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m subset \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[1;32m 318\u001b[0m request_params \u001b[38;5;241m=\u001b[39m apifmt\u001b[38;5;241m.\u001b[39mcombine_params(\n\u001b[1;32m 319\u001b[0m CMRparams, reqparams, {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124magent\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNO\u001b[39m\u001b[38;5;124m\"\u001b[39m}\n\u001b[1;32m 320\u001b[0m )\n", + "File \u001b[0;32m~/icepyx/icepyx/core/granules.py:251\u001b[0m, in \u001b[0;36mGranules.get_avail\u001b[0;34m(self, CMRparams, reqparams, cloud)\u001b[0m\n\u001b[1;32m 247\u001b[0m \u001b[38;5;66;03m# Collect results\u001b[39;00m\n\u001b[1;32m 248\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mavail\u001b[38;5;241m.\u001b[39mextend(results[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfeed\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mentry\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m 250\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m (\n\u001b[0;32m--> 251\u001b[0m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mavail) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m 252\u001b[0m ), \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mYour search returned no results; try different search parameters\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", + "\u001b[0;31mAssertionError\u001b[0m: Your search returned no results; try different search parameters" + ] + } + ], "source": [ "region_a.order_granules()\n", "# region_a.order_granules(verbose=True, subset=False, email=False)" @@ -620,6 +1833,20 @@ "* notebook contributors: Amy Steiker and Tyler Sutterley\n", "* source material: [NSIDC Data Access Notebook](https://github.com/ICESAT-2HackWeek/ICESat2_hackweek_tutorials/tree/master/03_NSIDCDataAccess_Steiker) by Amy Steiker and Bruce Wallin and [2020 Hackweek Data Access Notebook](https://github.com/ICESAT-2HackWeek/2020_ICESat-2_Hackweek_Tutorials/blob/main/06-07.Data_Access/02-Data_Access_rendered.ipynb) by Jessica Scheick and Amy Steiker" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/doc/source/example_notebooks/IS2_data_access2-subsetting.ipynb b/doc/source/example_notebooks/IS2_data_access2-subsetting.ipynb index 5b617fc5c..3fb878d95 100644 --- a/doc/source/example_notebooks/IS2_data_access2-subsetting.ipynb +++ b/doc/source/example_notebooks/IS2_data_access2-subsetting.ipynb @@ -75,7 +75,9 @@ }, "source": [ "```{admonition} Important Authentication Update\n", - "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "Previously, icepyx required you to explicitly use the `earthdata_login()` function to login. Running this function is no longer required, but it is still available for backwards compatibility. \n", + "\n", + "If you do choose to use the `earthdata_login()`, you will also note that certain inputs, such as `earthdata_uid` and `email`, are no longer required. e.g. `region_a.earthdata_login(earthdata_uid, email)` becomes `region_a.earthdata_login()`\n", "```" ] }, diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index ba6d07151..b00630935 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -155,6 +155,8 @@ "source": [ "```{admonition} Important Authentication Update\n", "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "\n", + "If you do choose to use the `earthdata_login()`, you will also note that certain inputs, such as `earthdata_uid` and `email`, are no longer required. e.g. `region_a.earthdata_login(earthdata_uid, email)` becomes `region_a.earthdata_login()`\n", "```" ] }, diff --git a/doc/source/example_notebooks/IS2_data_variables.ipynb b/doc/source/example_notebooks/IS2_data_variables.ipynb index 65b91f279..0265b18f8 100644 --- a/doc/source/example_notebooks/IS2_data_variables.ipynb +++ b/doc/source/example_notebooks/IS2_data_variables.ipynb @@ -127,6 +127,8 @@ "source": [ "```{admonition} Important Authentication Update\n", "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "\n", + "If you do choose to use the `earthdata_login()`, you will also note that certain inputs, such as `earthdata_uid` and `email`, are no longer required. e.g. `region_a.earthdata_login(earthdata_uid, email)` becomes `region_a.earthdata_login()`\n", "```" ] }, diff --git a/doc/source/example_notebooks/IS2_data_visualization.ipynb b/doc/source/example_notebooks/IS2_data_visualization.ipynb index 7f65c4f85..d28c951ab 100644 --- a/doc/source/example_notebooks/IS2_data_visualization.ipynb +++ b/doc/source/example_notebooks/IS2_data_visualization.ipynb @@ -211,6 +211,8 @@ "source": [ "```{admonition} Important Authentication Update\n", "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed in the [ICESat-2 Data Access Notebook](https://icepyx.readthedocs.io/en/latest/example_notebooks/IS2_data_access.html) example. The `.earthdata_login()` function is still available for backwards compatibility.\n", + "\n", + "If you do choose to use the `earthdata_login()`, you will also note that certain inputs, such as `earthdata_uid` and `email`, are no longer required. e.g. `region_a.earthdata_login(earthdata_uid, email)` becomes `region_a.earthdata_login()`\n", "```" ] }, From 4d7687b4f5035378a09bcb8da6662a89ce3140a1 Mon Sep 17 00:00:00 2001 From: Rachel Wegener <35503632+rwegener2@users.noreply.github.com> Date: Thu, 24 Aug 2023 15:04:55 -0400 Subject: [PATCH 39/63] switch s3token argument default to None Co-authored-by: Jessica Scheick --- icepyx/core/auth.py | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/icepyx/core/auth.py b/icepyx/core/auth.py index 5ada2d9c0..7c36126f9 100644 --- a/icepyx/core/auth.py +++ b/icepyx/core/auth.py @@ -105,7 +105,7 @@ def set_s3_creds(): set_s3_creds() return self._s3login_credentials - def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None: + def earthdata_login(self, uid=None, email=None, s3token=None, **kwargs) -> None: """ Authenticate with NASA Earthdata to enable data ordering and download. Credential storage details are described in the EathdataAuthMixin class section. @@ -118,7 +118,7 @@ def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None Deprecated keyword for Earthdata login user ID. email : string, default None Deprecated keyword for backwards compatibility. - s3token : boolean, default False + s3token : boolean, default None Deprecated keyword to generate AWS s3 ICESat-2 data access credentials kwargs : key:value pairs Keyword arguments to be passed into earthaccess.login(). @@ -138,15 +138,7 @@ def earthdata_login(self, uid=None, email=None, s3token=False, **kwargs) -> None DeprecationWarning, stacklevel=2 ) - auth = earthaccess.login(**kwargs) - if auth.authenticated: - self._auth = auth - self._session = auth.get_session() - - if s3token == True: - self._s3login_credentials = auth.get_s3_credentials(daac="NSIDC") - - if uid != None or email != None: + if uid != None or email != None or s3token != None: warnings.warn( "The user id (uid) and/or email keyword arguments are no longer required.", DeprecationWarning, stacklevel=2 From 38380443c5bd37c317f91cf065bc7b16b04fe843 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Thu, 24 Aug 2023 19:20:43 +0000 Subject: [PATCH 40/63] fix json error in data_access example notebook --- .../example_notebooks/IS2_data_access.ipynb | 1311 +---------------- 1 file changed, 43 insertions(+), 1268 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_access.ipynb b/doc/source/example_notebooks/IS2_data_access.ipynb index b1de99cec..c1c5ccb74 100644 --- a/doc/source/example_notebooks/IS2_data_access.ipynb +++ b/doc/source/example_notebooks/IS2_data_access.ipynb @@ -18,666 +18,11 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jovyan/envs/icepyx-dev/lib/python3.11/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", - " from .autonotebook import tqdm as notebook_tqdm\n" - ] - }, - { - "data": { - "application/javascript": [ - "(function(root) {\n", - " function now() {\n", - " return new Date();\n", - " }\n", - "\n", - " var force = true;\n", - " var py_version = '3.2.0'.replace('rc', '-rc.').replace('.dev', '-dev.');\n", - " var is_dev = py_version.indexOf(\"+\") !== -1 || py_version.indexOf(\"-\") !== -1;\n", - " var reloading = false;\n", - " var Bokeh = root.Bokeh;\n", - " var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n", - "\n", - " if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n", - " root._bokeh_timeout = Date.now() + 5000;\n", - " root._bokeh_failed_load = false;\n", - " }\n", - "\n", - " function run_callbacks() {\n", - " try {\n", - " root._bokeh_onload_callbacks.forEach(function(callback) {\n", - " if (callback != null)\n", - " callback();\n", - " });\n", - " } finally {\n", - " delete root._bokeh_onload_callbacks;\n", - " }\n", - " console.debug(\"Bokeh: all callbacks have finished\");\n", - " }\n", - "\n", - " function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n", - " if (css_urls == null) css_urls = [];\n", - " if (js_urls == null) js_urls = [];\n", - " if (js_modules == null) js_modules = [];\n", - " if (js_exports == null) js_exports = {};\n", - "\n", - " root._bokeh_onload_callbacks.push(callback);\n", - "\n", - " if (root._bokeh_is_loading > 0) {\n", - " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", - " return null;\n", - " }\n", - " if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n", - " run_callbacks();\n", - " return null;\n", - " }\n", - " if (!reloading) {\n", - " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", - " }\n", - "\n", - " function on_load() {\n", - " root._bokeh_is_loading--;\n", - " if (root._bokeh_is_loading === 0) {\n", - " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", - " run_callbacks()\n", - " }\n", - " }\n", - " window._bokeh_on_load = on_load\n", - "\n", - " function on_error() {\n", - " console.error(\"failed to load \" + url);\n", - " }\n", - "\n", - " var skip = [];\n", - " if (window.requirejs) {\n", - " window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n", - " require([\"jspanel\"], function(jsPanel) {\n", - "\twindow.jsPanel = jsPanel\n", - "\ton_load()\n", - " })\n", - " require([\"jspanel-modal\"], function() {\n", - "\ton_load()\n", - " })\n", - " require([\"jspanel-tooltip\"], function() {\n", - "\ton_load()\n", - " })\n", - " require([\"jspanel-hint\"], function() {\n", - "\ton_load()\n", - " })\n", - " require([\"jspanel-layout\"], function() {\n", - "\ton_load()\n", - " })\n", - " require([\"jspanel-contextmenu\"], function() {\n", - "\ton_load()\n", - " })\n", - " require([\"jspanel-dock\"], function() {\n", - "\ton_load()\n", - " })\n", - " require([\"gridstack\"], function(GridStack) {\n", - "\twindow.GridStack = GridStack\n", - "\ton_load()\n", - " })\n", - " require([\"notyf\"], function() {\n", - "\ton_load()\n", - " })\n", - " root._bokeh_is_loading = css_urls.length + 9;\n", - " } else {\n", - " root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n", - " }\n", - "\n", - " var existing_stylesheets = []\n", - " var links = document.getElementsByTagName('link')\n", - " for (var i = 0; i < links.length; i++) {\n", - " var link = links[i]\n", - " if (link.href != null) {\n", - "\texisting_stylesheets.push(link.href)\n", - " }\n", - " }\n", - " for (var i = 0; i < css_urls.length; i++) {\n", - " var url = css_urls[i];\n", - " if (existing_stylesheets.indexOf(url) !== -1) {\n", - "\ton_load()\n", - "\tcontinue;\n", - " }\n", - " const element = document.createElement(\"link\");\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.rel = \"stylesheet\";\n", - " element.type = \"text/css\";\n", - " element.href = url;\n", - " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", - " document.body.appendChild(element);\n", - " } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n", - " var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n", - " for (var i = 0; i < urls.length; i++) {\n", - " skip.push(urls[i])\n", - " }\n", - " } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n", - " var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n", - " for (var i = 0; i < urls.length; i++) {\n", - " skip.push(urls[i])\n", - " }\n", - " } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n", - " var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n", - " for (var i = 0; i < urls.length; i++) {\n", - " skip.push(urls[i])\n", - " }\n", - " } var existing_scripts = []\n", - " var scripts = document.getElementsByTagName('script')\n", - " for (var i = 0; i < scripts.length; i++) {\n", - " var script = scripts[i]\n", - " if (script.src != null) {\n", - "\texisting_scripts.push(script.src)\n", - " }\n", - " }\n", - " for (var i = 0; i < js_urls.length; i++) {\n", - " var url = js_urls[i];\n", - " if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n", - "\tif (!window.requirejs) {\n", - "\t on_load();\n", - "\t}\n", - "\tcontinue;\n", - " }\n", - " var element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.async = false;\n", - " element.src = url;\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " for (var i = 0; i < js_modules.length; i++) {\n", - " var url = js_modules[i];\n", - " if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n", - "\tif (!window.requirejs) {\n", - "\t on_load();\n", - "\t}\n", - "\tcontinue;\n", - " }\n", - " var element = document.createElement('script');\n", - " element.onload = on_load;\n", - " element.onerror = on_error;\n", - " element.async = false;\n", - " element.src = url;\n", - " element.type = \"module\";\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " document.head.appendChild(element);\n", - " }\n", - " for (const name in js_exports) {\n", - " var url = js_exports[name];\n", - " if (skip.indexOf(url) >= 0 || root[name] != null) {\n", - "\tif (!window.requirejs) {\n", - "\t on_load();\n", - "\t}\n", - "\tcontinue;\n", - " }\n", - " var element = document.createElement('script');\n", - " element.onerror = on_error;\n", - " element.async = false;\n", - " element.type = \"module\";\n", - " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", - " element.textContent = `\n", - " import ${name} from \"${url}\"\n", - " window.${name} = ${name}\n", - " window._bokeh_on_load()\n", - " `\n", - " document.head.appendChild(element);\n", - " }\n", - " if (!js_urls.length && !js_modules.length) {\n", - " on_load()\n", - " }\n", - " };\n", - "\n", - " function inject_raw_css(css) {\n", - " const element = document.createElement(\"style\");\n", - " element.appendChild(document.createTextNode(css));\n", - " document.body.appendChild(element);\n", - " }\n", - "\n", - " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.2.0.min.js\", \"https://cdn.holoviz.org/panel/1.2.0/dist/panel.min.js\"];\n", - " var js_modules = [];\n", - " var js_exports = {};\n", - " var css_urls = [];\n", - " var inline_js = [ function(Bokeh) {\n", - " Bokeh.set_log_level(\"info\");\n", - " },\n", - "function(Bokeh) {} // ensure no trailing comma for IE\n", - " ];\n", - "\n", - " function run_inline_js() {\n", - " if ((root.Bokeh !== undefined) || (force === true)) {\n", - " for (var i = 0; i < inline_js.length; i++) {\n", - " inline_js[i].call(root, root.Bokeh);\n", - " }\n", - " // Cache old bokeh versions\n", - " if (Bokeh != undefined && !reloading) {\n", - "\tvar NewBokeh = root.Bokeh;\n", - "\tif (Bokeh.versions === undefined) {\n", - "\t Bokeh.versions = new Map();\n", - "\t}\n", - "\tif (NewBokeh.version !== Bokeh.version) {\n", - "\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n", - "\t}\n", - "\troot.Bokeh = Bokeh;\n", - " }} else if (Date.now() < root._bokeh_timeout) {\n", - " setTimeout(run_inline_js, 100);\n", - " } else if (!root._bokeh_failed_load) {\n", - " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", - " root._bokeh_failed_load = true;\n", - " }\n", - " root._bokeh_is_initializing = false\n", - " }\n", - "\n", - " function load_or_wait() {\n", - " // Implement a backoff loop that tries to ensure we do not load multiple\n", - " // versions of Bokeh and its dependencies at the same time.\n", - " // In recent versions we use the root._bokeh_is_initializing flag\n", - " // to determine whether there is an ongoing attempt to initialize\n", - " // bokeh, however for backward compatibility we also try to ensure\n", - " // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n", - " // before older versions are fully initialized.\n", - " if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n", - " root._bokeh_is_initializing = false;\n", - " root._bokeh_onload_callbacks = undefined;\n", - " console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n", - " load_or_wait();\n", - " } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n", - " setTimeout(load_or_wait, 100);\n", - " } else {\n", - " Bokeh = root.Bokeh;\n", - " bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n", - " root._bokeh_is_initializing = true\n", - " root._bokeh_onload_callbacks = []\n", - " if (!reloading && (!bokeh_loaded || is_dev)) {\n", - "\troot.Bokeh = undefined;\n", - " }\n", - " load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n", - "\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", - "\trun_inline_js();\n", - " });\n", - " }\n", - " }\n", - " // Give older versions of the autoload script a head-start to ensure\n", - " // they initialize before we start loading newer version.\n", - " setTimeout(load_or_wait, 100)\n", - "}(window));" - ], - "application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n var py_version = '3.2.0'.replace('rc', '-rc.').replace('.dev', '-dev.');\n var is_dev = py_version.indexOf(\"+\") !== -1 || py_version.indexOf(\"-\") !== -1;\n var reloading = false;\n var Bokeh = root.Bokeh;\n var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n run_callbacks();\n return null;\n }\n if (!reloading) {\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n require([\"jspanel\"], function(jsPanel) {\n\twindow.jsPanel = jsPanel\n\ton_load()\n })\n require([\"jspanel-modal\"], function() {\n\ton_load()\n })\n require([\"jspanel-tooltip\"], function() {\n\ton_load()\n })\n require([\"jspanel-hint\"], function() {\n\ton_load()\n })\n require([\"jspanel-layout\"], function() {\n\ton_load()\n })\n require([\"jspanel-contextmenu\"], function() {\n\ton_load()\n })\n require([\"jspanel-dock\"], function() {\n\ton_load()\n })\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 9;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n var existing_stylesheets = []\n var links = document.getElementsByTagName('link')\n for (var i = 0; i < links.length; i++) {\n var link = links[i]\n if (link.href != null) {\n\texisting_stylesheets.push(link.href)\n }\n }\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n if (existing_stylesheets.indexOf(url) !== -1) {\n\ton_load()\n\tcontinue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.2.0/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.2.0/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } var existing_scripts = []\n var scripts = document.getElementsByTagName('script')\n for (var i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n\texisting_scripts.push(script.src)\n }\n }\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n var url = js_exports[name];\n if (skip.indexOf(url) >= 0 || root[name] != null) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.2.0.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.2.0.min.js\", \"https://cdn.holoviz.org/panel/1.2.0/dist/panel.min.js\"];\n var js_modules = [];\n var js_exports = {};\n var css_urls = [];\n var inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n\tvar NewBokeh = root.Bokeh;\n\tif (Bokeh.versions === undefined) {\n\t Bokeh.versions = new Map();\n\t}\n\tif (NewBokeh.version !== Bokeh.version) {\n\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n\t}\n\troot.Bokeh = Bokeh;\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n Bokeh = root.Bokeh;\n bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n if (!reloading && (!bokeh_loaded || is_dev)) {\n\troot.Bokeh = undefined;\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n\trun_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));" - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "application/javascript": [ - "\n", - "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", - " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", - "}\n", - "\n", - "\n", - " function JupyterCommManager() {\n", - " }\n", - "\n", - " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", - " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", - " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", - " comm_manager.register_target(comm_id, function(comm) {\n", - " comm.on_msg(msg_handler);\n", - " });\n", - " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", - " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", - " comm.onMsg = msg_handler;\n", - " });\n", - " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", - " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", - " var messages = comm.messages[Symbol.asyncIterator]();\n", - " function processIteratorResult(result) {\n", - " var message = result.value;\n", - " console.log(message)\n", - " var content = {data: message.data, comm_id};\n", - " var buffers = []\n", - " for (var buffer of message.buffers || []) {\n", - " buffers.push(new DataView(buffer))\n", - " }\n", - " var metadata = message.metadata || {};\n", - " var msg = {content, buffers, metadata}\n", - " msg_handler(msg);\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " return messages.next().then(processIteratorResult);\n", - " })\n", - " }\n", - " }\n", - "\n", - " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", - " if (comm_id in window.PyViz.comms) {\n", - " return window.PyViz.comms[comm_id];\n", - " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", - " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", - " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", - " if (msg_handler) {\n", - " comm.on_msg(msg_handler);\n", - " }\n", - " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", - " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", - " comm.open();\n", - " if (msg_handler) {\n", - " comm.onMsg = msg_handler;\n", - " }\n", - " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", - " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", - " comm_promise.then((comm) => {\n", - " window.PyViz.comms[comm_id] = comm;\n", - " if (msg_handler) {\n", - " var messages = comm.messages[Symbol.asyncIterator]();\n", - " function processIteratorResult(result) {\n", - " var message = result.value;\n", - " var content = {data: message.data};\n", - " var metadata = message.metadata || {comm_id};\n", - " var msg = {content, metadata}\n", - " msg_handler(msg);\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " return messages.next().then(processIteratorResult);\n", - " }\n", - " }) \n", - " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", - " return comm_promise.then((comm) => {\n", - " comm.send(data, metadata, buffers, disposeOnDone);\n", - " });\n", - " };\n", - " var comm = {\n", - " send: sendClosure\n", - " };\n", - " }\n", - " window.PyViz.comms[comm_id] = comm;\n", - " return comm;\n", - " }\n", - " window.PyViz.comm_manager = new JupyterCommManager();\n", - " \n", - "\n", - "\n", - "var JS_MIME_TYPE = 'application/javascript';\n", - "var HTML_MIME_TYPE = 'text/html';\n", - "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", - "var CLASS_NAME = 'output';\n", - "\n", - "/**\n", - " * Render data to the DOM node\n", - " */\n", - "function render(props, node) {\n", - " var div = document.createElement(\"div\");\n", - " var script = document.createElement(\"script\");\n", - " node.appendChild(div);\n", - " node.appendChild(script);\n", - "}\n", - "\n", - "/**\n", - " * Handle when a new output is added\n", - " */\n", - "function handle_add_output(event, handle) {\n", - " var output_area = handle.output_area;\n", - " var output = handle.output;\n", - " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", - " return\n", - " }\n", - " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", - " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", - " if (id !== undefined) {\n", - " var nchildren = toinsert.length;\n", - " var html_node = toinsert[nchildren-1].children[0];\n", - " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", - " var scripts = [];\n", - " var nodelist = html_node.querySelectorAll(\"script\");\n", - " for (var i in nodelist) {\n", - " if (nodelist.hasOwnProperty(i)) {\n", - " scripts.push(nodelist[i])\n", - " }\n", - " }\n", - "\n", - " scripts.forEach( function (oldScript) {\n", - " var newScript = document.createElement(\"script\");\n", - " var attrs = [];\n", - " var nodemap = oldScript.attributes;\n", - " for (var j in nodemap) {\n", - " if (nodemap.hasOwnProperty(j)) {\n", - " attrs.push(nodemap[j])\n", - " }\n", - " }\n", - " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", - " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", - " oldScript.parentNode.replaceChild(newScript, oldScript);\n", - " });\n", - " if (JS_MIME_TYPE in output.data) {\n", - " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", - " }\n", - " output_area._hv_plot_id = id;\n", - " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", - " window.PyViz.plot_index[id] = Bokeh.index[id];\n", - " } else {\n", - " window.PyViz.plot_index[id] = null;\n", - " }\n", - " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", - " var bk_div = document.createElement(\"div\");\n", - " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", - " var script_attrs = bk_div.children[0].attributes;\n", - " for (var i = 0; i < script_attrs.length; i++) {\n", - " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", - " }\n", - " // store reference to server id on output_area\n", - " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * Handle when an output is cleared or removed\n", - " */\n", - "function handle_clear_output(event, handle) {\n", - " var id = handle.cell.output_area._hv_plot_id;\n", - " var server_id = handle.cell.output_area._bokeh_server_id;\n", - " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", - " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", - " if (server_id !== null) {\n", - " comm.send({event_type: 'server_delete', 'id': server_id});\n", - " return;\n", - " } else if (comm !== null) {\n", - " comm.send({event_type: 'delete', 'id': id});\n", - " }\n", - " delete PyViz.plot_index[id];\n", - " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", - " var doc = window.Bokeh.index[id].model.document\n", - " doc.clear();\n", - " const i = window.Bokeh.documents.indexOf(doc);\n", - " if (i > -1) {\n", - " window.Bokeh.documents.splice(i, 1);\n", - " }\n", - " }\n", - "}\n", - "\n", - "/**\n", - " * Handle kernel restart event\n", - " */\n", - "function handle_kernel_cleanup(event, handle) {\n", - " delete PyViz.comms[\"hv-extension-comm\"];\n", - " window.PyViz.plot_index = {}\n", - "}\n", - "\n", - "/**\n", - " * Handle update_display_data messages\n", - " */\n", - "function handle_update_output(event, handle) {\n", - " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", - " handle_add_output(event, handle)\n", - "}\n", - "\n", - "function register_renderer(events, OutputArea) {\n", - " function append_mime(data, metadata, element) {\n", - " // create a DOM node to render to\n", - " var toinsert = this.create_output_subarea(\n", - " metadata,\n", - " CLASS_NAME,\n", - " EXEC_MIME_TYPE\n", - " );\n", - " this.keyboard_manager.register_events(toinsert);\n", - " // Render to node\n", - " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", - " render(props, toinsert[0]);\n", - " element.append(toinsert);\n", - " return toinsert\n", - " }\n", - "\n", - " events.on('output_added.OutputArea', handle_add_output);\n", - " events.on('output_updated.OutputArea', handle_update_output);\n", - " events.on('clear_output.CodeCell', handle_clear_output);\n", - " events.on('delete.Cell', handle_clear_output);\n", - " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", - "\n", - " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", - " safe: true,\n", - " index: 0\n", - " });\n", - "}\n", - "\n", - "if (window.Jupyter !== undefined) {\n", - " try {\n", - " var events = require('base/js/events');\n", - " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", - " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", - " register_renderer(events, OutputArea);\n", - " }\n", - " } catch(err) {\n", - " }\n", - "}\n" - ], - "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - }, - { - "data": { - "text/html": [ - "\n", - "
\n", - "\n", - "\n", - "\n", - " \n", - " \n", - "\n", - "\n", - "\n", - "\n", - "
\n" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "import icepyx as ipx\n", "import os\n", @@ -762,7 +107,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": { "tags": [] }, @@ -776,7 +121,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": { "tags": [] }, @@ -790,7 +135,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": { "tags": [] }, @@ -804,7 +149,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": { "tags": [] }, @@ -822,7 +167,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": { "tags": [] }, @@ -836,7 +181,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": { "tags": [] }, @@ -869,7 +214,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": { "tags": [] }, @@ -880,22 +225,11 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ATL06\n", - "006\n", - "['03', '04', '05', '06', '07']\n", - "['0849', '0902']\n" - ] - } - ], + "outputs": [], "source": [ "# using orbital parameters with one of the above data products + spatial parameters\n", "region_a = ipx.Query(short_name, spatial_extent,\n", @@ -918,30 +252,11 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jovyan/icepyx/icepyx/core/query.py:1165: FutureWarning: The geopandas.dataset module is deprecated and will be removed in GeoPandas 1.0. You can get the original 'naturalearth_lowres' data from https://www.naturalearthdata.com/downloads/110m-cultural-vectors/.\n", - " world = gpd.read_file(gpd.datasets.get_path(\"naturalearth_lowres\"))\n" - ] - }, - { - "data": { - "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYoAAAH5CAYAAACfyHl/AAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOy9d3Sc53mnfb3TAQx6772SIEiAvXeK6sXdsuW4e5XqxPFxsvmyzp6zyfHZtbOOkziObUWRiyLZKhTFIvYKECQaiQ6i90EHBpg+7/cH9n2EIQoBEiBBcK5zdEQAU56Zeee5n7v9bkmWZRkvXrx48eJlFlQPewFevHjx4mV54zUUXrx48eJlTryGwosXL168zInXUHjx4sWLlznxGgovXrx48TInXkPhxYsXL17mxGsovHjx4sXLnGge9gLuF7fbTVdXF/7+/kiS9LCX48WLFy+PBLIsMzY2RkxMDCrV3D7DI28ourq6iI+Pf9jL8OLFi5dHkvb2duLi4ua8zSNvKPz9/YHJFxsQEPCQV+PFixcvjwajo6PEx8eLPXQuHnlDoYSbAgICvIbCixcvXhbIfEL23mS2Fy9evHiZE6+h8OLFixcvc+I1FF68ePHiZU68hsKLFy9evMyJ11B48eLFi5c58RoKL168ePEyJ15D4cWLFy9e5sRrKLx48eLFy5x4DYUXL168eJkTr6Hw4sWLFy9z4jUUXrx48eJlTryGwosXL168zInXUHjx4sWLlznxGgovXrx48TInXkPhxYsXL17mxGsovHjx4sXLnHgNhRcvXrx4mZNHfsKdFy+zMT4+Tn9/PxMTE0xMTCBJEjqdDq1Wi06nE/82GAz4+/vPa9KXFy+PI15D4WVRcTgcDA0NYbfbcTgcBAYGYrVa6evrQ5Zl/Pz88PX1xc/PDz8/P7Ra7aI8ryzLNDQ0MD4+jlarxWq1curUKex2+7zuHxoaSl5eHrm5uQQFBS3Kmrx4WSl4DYWX+0KWZSRJoqSkhOLiYkwm04Lur9VqCQoKIjIyktWrV5Oeno5KNf+IqCzL1NTUcP78efr6+jz+FhMTw6pVq9Dr9eh0OgBcLhdOpxOn0yn+bbVa6ezs5OLFi5w9e5aEhARhNBbLkHnx8ijjNRRe7gmz2cyRI0doamoiMjKSrq4uoqOjyc/PJyAgAI1GgyRJjI2N4ePjQ0BAAJIkYbfbsdlsWK1W7HY7VqsVs9lMR0cHlZWVpKSk8IUvfGHW51UMg1arJS0tjdLSUo4ePUpERAS7d+8mODgYl8uF2+1Gp9NNCydpNBo0msnLXjEUBoMBo9FIUlIS7e3ttLW10dbWxujoKLt3717Kt9GLl0cCr6HwMi/sdjvl5eW0trYyMDCAyWRCr9eTlZVFa2sr/v7+bN68eZo3EBAQ4PGzj48PPj4+4mdZlhkbG6OpqYnh4WEmJiY4c+YM/f39DAwMMD4+DoAkSeTl5dHc3Ex3dzcwGS4aGBgAYOPGjej1eoA5PRKHw8GxY8dwOp1zvt7NmzezZcsW8fP4+Dhms5mwsDDUavXd3i4vXlYUXkPhZV40NDRw/PhxwsLCMBqNrFu3jpiYGPR6Penp6bjd7gWFjFwuF4WFhfT29gKg0+nQ6/X09PQwPDxMQEAA/v7+hIeHI0kSExMTXL16laCgIHbt2gXA7du3xeMdPXqU3bt3ExoaOufzajQaAgICGBwcnPN2Pj4+VFZW0tbWRnt7O0NDQ8CkEQoLC+OZZ54hLi5u3q/Xi5dHGa+h8DIrExMTXLlyBavVyvDwMDB5il+9erXH7dRq9YJP2d3d3cJIqNVq1q5dS3FxMRkZGaxevXrGCqSMjAz8/PzE38LCwpBlmc7OTq5du3ZXLwEmPZM9e/Z4/E7xavr7+xkbG+P27ducO3cOSZIICgoiJCSE9PR0fHx8GBwcpKamhlOnTvEHf/AHC3rNXhaGy+WitbWVkZERQkJCSExMfNhLemzxGgovM+J2u3nttdfo7+8Xv4uNjaWurg6tVuuRdFYS2vPFYrGIx1XCRWVlZcTExBAfHz/rYxmNxmm/kySJuLi4+zrdS5JEQEAAAQEBlJWVAbBu3Tri4+NFMtvpdNLU1ERDQwNut5v4+Ph7fr6Fory/DocDh8OBr6/vfT+mxWIRm3B/fz/j4+Oo1Wq2bdtGVFTUIqz6/jCZTLz11lsitAiwadMmDh48uCDP1cvi4DUUXmbk2rVr9Pf3k52dTUZGBm1tbZSVlaFSqaisrKSqqgpZlj3uk5GRQW5u7pyPOz4+ztmzZ4HJjd9sNpOUlMSqVaswGAxL9nrmy7p161i3bh0waRyGh4cZHR2lqqoKq9XK2rVr2b59O8HBwUu6DofDwfXr12lubqa1tVWUGZvNZqKjo1m1ahXr168XhnYh2O12fvCDH8z4t6GhIb761a/e7/Lvi8rKSn7/+98TGBjInj17CA4OprGxkeLiYgCeeOKJh7q+xxGvofAyIxcvXiQ5OZmcnBwAUlJSiIiIoL29nZaWFiYmJqbd5249C263m+LiYnx9fUlMTKSiooKMjAxycnKWXYLY7Xbz/vvvi58NBgOvvvoqISEhi/5cSvisurqa/Px8bt68SWNjI11dXajVamJjY3E4HEiSREZGBiaTidOnT3P69Gn+5m/+ZsEnbK1Wy7PPPsuRI0c8fp+fn8/mzZsX86XdEzdv3gQgPDxcvN9paWnA5AEmPDycgoKCh7a+xxGvofAyI5GRkSJmrySajUYj2dnZJCUlcezYMSRJIicnB61Wi9FoJDIy0uMxZFnGbrczNjZGXV0d/f39uN1uvvzlL2O32xkYGKC+vp7+/v5peYOHjSRJFBQUUFJSglqt5tvf/vaS9FSMjo7yxhtviFBcYWEhgNggXS4XbW1tZGdnExYWhkajQafTMTo6yujoKBaLBT8/vwU9pyRJrFu3jvT0dM6fP49Go2HHjh0Lfpyl4jOf+QwnT56krKyMVatWiXLm1NRURkdHOXbs2LLxQB8XvIbiMcVsNvPaa68RGRlJWlqaaExTeOqpp3jjjTf46KOPANi5cyfh4eHAZEVQTEwMXV1d1NTUcPjw4WlfWrPZzMmTJ8XPSrVSeno64eHhNDY2itLZxYi5LzZKIhsm34ularxzuVz09/eTlZVFbGwsTU1NxMXFER4eTk9PDyUlJdjtdmpraz1CfQaDgc997nP3tbkbjUaefvrpxXgZi4pKpWLz5s1cv36dK1eusGbNGoKCgpAkibCwMJqbm/nZz36G1Wpl69atbNmyZdl5pCsNr6FY4ciyzMWLF+nu7iYjI4N169YhSRJVVVUMDg6KKp7jx4+zZcsWfH19uXbtGqmpqXzqU5/iF7/4BYBHyKWrq0uERdRqteh6nsrUzf8Tn/gE6enpDA4OUlFRwa1btzCbzQQEBJCbm0tycvLSvxH3wO3btwkICCAvL2/JniM4OJiYmBgGBgbIyckhPz9f/C06OpodO3Zw4cIFHA4H+/fvJyUlhcDAQHx8fFa0NlVwcDBf/OIXef/99zl79iy+vr4EBwczMjKCSqXC4XAQFRXF2bNnqays5Mtf/vKM16GXxcFrKFY4N2/e5Pz58wDU1dURFBRESkoKWVlZnDhxAoD4+HhkWebSpUukpKQwPDxMRUUFlZWVrF+/npKSEmpqaggMDMRut4sYclBQEAUFBTPGyFUqFRs2bOD69etIksQbb7xBR0cHer2euLg4Nm7cKE6Jy5WRkREyMjKWvMpmz549/PrXv6ampkbkhGAymX7x4kVUKhUJCQnU1tYiSRJbt25d0vUsF5KSknj11VdpbW2lvr6e7u5uYmJiqK+vF6E4vV5PbW0tra2tpKenP+wlr1i8hmIFI8syLS0tSJKELMuEhIQQHR0NTJalJiQkMDQ0RF9fHw6HA5gMGcFkj0JPTw/BwcGsW7eO2tpa6urqgElvYWJigoGBAcbGxvD395/2vLdu3aKxsZGoqCgCAgLo6OggMjKSzZs3i5izl0nS0tLYu3cvZ8+eRZZlMjMz0Wg09PX1Ybfb2bVrFxcuXACgo6MDl8vFjh07HvKqHwwajYbU1FRSU1MBeOuttwCoqKgQxRNGo3HJq9Aed7zf2BWC0+nk6tWrjI+P09HRQUxMDAUFBZSXl4vbDA4OihO8wWAQDWNWq5WioiJqampIS0sjIiJCGIVTp06Rnp7Od77zHSwWCzqdjp/97Gei6qmwsJCnn37aI7/R0tJCQ0MDu3btYuvWrUiSxNq1a6moqODEiRMEBwejVqvx8fEhKyvrnko8HwSSJGG1Wh/Ic23fvh2z2UxxcTFOp5P09HRu3LhBaGioyI8oBvrcuXOPjaG4k6CgIDIyMoiKisJisYi+nsHBQcLCwh728lYsXkOxArBarbz55pu0t7fj7+/PyMgIFouFJ598kv3793Px4kWio6PZtWvXjJUiBoOB3bt3CwE8p9PJr371K3p7e3E6nSJu7uPjQ3d3t2hQS09Pp62tzSPJWlNTQ3V1NQA7duwQScbnnnuONWvW8J//+Z/09PSI27vdbtG3sNwwGo1UVlaydetW4YktFZIkERMTI/7d29uL3W7nS1/6Em63m76+PpqamigoKGDnzp1LupaFYrFYcDgc03S9loKDBw/idDp5/fXX6ejoICAggIGBAX7729/yzW9+c1rlnZfFwWsoHnGUTb2vr48dO3bg7+/PlStXhCu+bds2tm3bhtVq5fe//z3l5eUzVinJskx1dTXj4+PodDpaW1sJCAjA6XRy7Ngxzp8/T1ZWFpcuXUKn05GWlkZSUhJJSUnIsiy6h10ul3jM9vZ2kpKSxM8dHR3AZFgrMzMTrVa7LEMGFouF0tJSYdCampqW3FAA5Obm0tPTQ1FREVqtltDQUNGN/vzzzy/58y+Uuro6Tp06xcDAABqNhm9+85t31dq6X2RZ5urVq3R1dbFr1y40Gg1nzpwB4Kc//Sk5OTlIkoRGo2Ht2rUe15+Xe2dJDUVSUhKtra3Tfv/f/tt/45//+Z/ZvXu3iL0qfOMb3+CnP/3pUi5rRXH06FG6u7vZsWMHPT09XLx4EVmWsVqt/OhHP2L16tWsXbuWoqIimpubkWWZmJgYNm3aBEx+8Y4ePUpXV5fHSd/Hx4fx8XGhgxQYGMiFCxfEUKCGhgZMJhMOhwOz2YwkSURFRYnQVlxcnDghK2zZsoWWlhba2tpwuVz4+voyMDAgZkMo4ajAwMCHmuQeHBykp6eHmJgYPvGJTzywQUYqlYpDhw4RHx9PW1sbGRkZD+R550tfXx8lJSX09fVhMpkwm81ERkaSkpJCU1MTt27dWlRZdofDwdjYGOPj44SGhnL+/Hlu3LiBLMvExsaKUNNLL71EV1cXhYWFdHV1odPpsFqtVFRUkJeXx5NPPrmoFVETExP09fWh0+kICAhYNv0nS4kk36nDsIj09fV5nDArKys5cOAA586dE6GOjIwM/u7v/k7cxtfXd0Eu7OjoKIGBgYyMjDwQ13c5MTY2xg9/+ENgUn3V6XSyfft2KioqUKlUBAcH09XVhcPhICkpicbGRnQ6HXa7HT8/Pw4cOMCaNWvE+79t2zYiIiI4evQomzZtwtfXl7a2Nmpra1mzZg03b94kPj6e3NxczGYz3d3daLVatFqt+PJYrVb27dtHQUHBjJu9w+Hgd7/7HfX19bO+rtDQUNatW0dgYODSvHHzoLm5mbKyMg4fPsyGDRse2jqWA2azmfPnz1NaWorBYCA4OFgcJCwWCyMjI4SGhvLlL3/5vntiZFlmeHiY5uZmTp48KRLWkiShUqnIyMhAr9cTGRnpof0lyzIjIyPikKEUcty8eZPVq1fz3HPP3de6FEpKSjh+/LjY1yRJIj4+no0bN5KVlfVI9XMsZO9cUo9CadBS+Id/+AdSU1OFTDRMGoblIEL2KOLv78/nP/95KisrCQoKYvXq1XR1dTEyMsLevXsJDg4mLy+P4uJiGhsbgY+rSNrb26mvrycvLw+NRoPT6aSxsVHEeO12O83NzQwPDxMaGsrIyAgFBQXcvHmTnp4eAgMD0Wg0Hl4IICbVzeYRaLVaPvOZz9Da2opKpcLX1xe9Xo9Wq8Vut9Pb28vJkyc5c+YMGzZseKDie1NJTk6moaHhrnLkKxlZliktLRVNl7m5uURFRdHc3ExLSwtOp5PMzEyefvppUlNT79sL7Ovr43e/+52Ykujr68uGDRtQq9V0dHSQlpY2rcJOYWqDpPJzcnIyIyMjNDc339e6pnL16lXCw8PJzc3F5XIxNDREe3s7v/vd7wgICCAhIYGQkBCSkpJISEh4pAzHXDywHIXdbudXv/oV3/72tz0uqF//+tf86le/IioqimeeeYa/+Zu/mfNUYrPZsNls4ufR0dElXfdyJy0tTejgAHz44Yeo1Wrq6+ux2+3iSxcYGCjCPT4+PjgcDvGle/bZZykuLmZwcJCmpiYcDgc1NTXiZGa1WpEkifXr1xMSEkJPTw/j4+PY7XY2btwo6tmHhoa4fPky169fn7MqR5KkGWPHBoOBgIAAUlJS+NnPfkZbWxtxcXEPJQzV2NjI2NiYx7X2uPHmm29SX19PUlISubm59Pf3c+bMGbRaLZs2bWLDhg2L4sX39fVx5MgRuru78fX1ZcuWLQQGBuLr6ys++zsPnXdDlmUxrXDq9+N+cDqdDA0NkZCQgL+/PzabDZ1OR3R0NFVVVXR1dVFZWQlMaqXBpBxJZmbmojz/w+SBGYr33nuP4eFhvvSlL4nffe5znyMxMZGYmBhu3rzJd7/7Xerq6njnnXdmfZy///u/5/vf//4DWPGjgcPhwGaziTkNBw8e5Nq1awwPD3vMr5ZlGbPZjNlspq+vj9DQUCEAl5ubi0aj4ciRI5SXlxMSEsLw8LAoxwwLC6O/v59Lly4RFxdHdHQ0BoMBl8vF+Pg4vb29qFQqkdC+35JStVpNfn4+J06coLq6mlWrVt3X490LSq9HVlbWA3/u5UJ9fT2pqamsXbuWxsZGKioqyMzM5IUXXli0mL8sy7z//vuMjIyQnZ1NamrqfffZjI6OUl5eTl9fHzk5OTzzzDOLslaNRsOhQ4c4ceIEQ0ND0w6p69atY2JiQpSWw2QhxEowFEuao5jKoUOH0Ol0fPDBB7Pe5uzZs+zbt4/bt2+LBps7mcmjiI+Pf+xyFB988AF1dXWMj48jSRKBgYEkJCRgMBhIS0sTgm9KsUBQUBDbt28nOTmZwMDAGV1ip9MpZkibTCbOnz9Pd3c3KSkpaLVaenp6ZixOmEpqaiovvfSSx7jTe+X06dNcu3aNJ598csm0lmZibGyMkpISBgYGyMzM5DOf+cwDe+7lQmFhIR999BH79u3DZDJx69YtNm/ezMGDBxfVwzOZTPzrv/4r69evX5TBRGNjYyJU9vnPf37RvImp3Lx5k/LyclavXk1gYCButxu3201iYiIGg4Gmpiaam5vRaDRs37592Yaflk2OQqG1tZXTp0/P6SkAohJnLkOh1+uXbYPWg2RsbIyJiQny8/NRqVT09fXR1dWFzWajuLiYJ598ks2bNxMREYFerycpKcnjgh0eHsbtdgsNp/HxcU6dOkVKSgp2u53g4GDGxsYYHh6mtLQUmIwZv/jii/j7+9PS0iJObMnJyVRWVuLn58fw8DC1tbVEREQQGxt7X69xw4YNXL16lY6OjgeqB+VwOMTAnIfhzTxsysvL+eijj8jIyMBgMFBTU8PGjRs5dOjQfT92f38/FRUV9PT0oNPpRFK4q6trUQzFVG/25MmTHD16lKeffhqTyYS/vz+hoaGEh4eLg0dPTw/9/f3Ex8fj5+eHWq2+qyFcs2YNa9asoaOjg8LCQuLj49m0aZO4X0pKCikpKff9WpYTD8RQvPbaa0RERPDUU0/NeTuli/hB1Kw/6qxdu5aGhgZCQkIIDAwUXzJZlikqKuLYsWOoVKppuv2yLHPq1CkhZ33o0CE2btzIm2++SVdXFxUVFcBkvsBqtbJz505CQ0NpaWmhrKyMsbExTp06xdjYGAC9vb0cO3aMiYkJEapS2LZtG/v27bvnE2hgYCBpaWk0Nzc/EEMhyzLd3d2Mj49jNBrx9fW96yCmlYhybURFRVFbW4tarV60stfXX38du91OSEgIbrcbmPRCF2v+eHh4OM8//zxtbW1UVVVhs9n49a9/jVqtFkYpIiKCb33rW8Ck16oUesBkxd3LL79815LompoaISdSXV1NX1/fooW4liNLbiiUkZqvvPKKR+yxsbGR3/zmNzz55JOEhoZy8+ZN/uzP/oydO3eyZs2apV7WI095eTmBgYEeLqMsy9TU1NDV1QVM9ljU19eTmJhIXl4eZWVlVFdX093dLe6jaD11dHSQlJREeno6Fy5cwM/PD7fbTXh4OGazmaamJmJiYoQxT09Pp6GhgYGBARISEoiKiqK4uBhJksjPz+f27dtcuXIFX1/f+xKxKygo4M0332RoaOiBNOcpm2RsbOyym5HxIBgeHmZsbIzQ0FD0ej1NTU3s3bv3rqFEi8XCqVOnkCSJtLQ0UlNTMZvNOBwOj25pWZZJS0sjOzt7yV6DWq0mOTmZpKQkLl26RHx8PElJSTgcDpqbm6msrOTHP/4x/v7+9PX1ER0dTWJiIk6nk5qaGn75y1/yrW99a87XPDIy4vFze3v7kr2e5cCSG4rTp0/T1tbGl7/8ZY/f63Q6Tp8+zT/+4z8yPj5OfHw8L730Ev/9v//3pV7SI8/4+Di3b99m7dq14rSuTI9T5L9TUlJoaGigvr6e+vp6Ll++jMViASaTckpcddOmTfz85z8HJjWacnNz0Wq1jI6O4nA4GBkZ4dy5cxgMBrZt28bbb7/Nli1b8Pf3p6GhAUAoyHZ3d9PV1UVJSYlY69SE+r2Qnp5OUFAQNTU1S66a2traKvpMnnrqqcfSsz1z5gySJLFlyxZKSkoICAiY19S7ixcvUllZicFgoLS0lPT0dNrb27FarXzve99Dp9MhyzIajcajt2opkSTJQ+5Ep9ORmpqKWq1mYmICq9WK0WgkPj5ehEnDwsI4ceIEt2/fntWblGXZY5a3Xq/H19eXc+fOERMTQ0xMzKxlvI8qS24oDh48OG22MkxKW9/Zle1lftTW1gJ4dD43NjbS2dmJWq1m3759GAwGdDodkZGRmM1mysvLSU5Oprm5GafTyebNmykqKkKWZfz8/LBYLKxfvx6dTseePXs4duwYMDl60mAw8Md//MfcuHEDtVpNZGQkarVa1LUrMtwBAQHiZBUcHMz4+DgNDQ10dHTcc2hBpVIRGBg44+jVxcTpdE4zcI+bobBYLJhMJgICAnA4HHR3d/P888/PqwqpsbGR2NhYCgoKqKio8Dgg/PKXv2RsbAyLxYIsy7hcLlavXr2UL2VWNBrNnAlug8GAVqsVEwdnoq+vjxs3bpCTk0NQUBBDQ0MMDQ1RXFwsciRGo5HVq1cvSl5nOfBYaz253W76+/sJDg5+oFU190ttba2HVpPdbqeqqgqtVitqvOHj0s7g4GDi4uJwOp2i+UipS29vb+cP/uAP+M1vfkN5eTk+Pj6EhYXhdrtRq9WMjY2xatUqkXjUaDQiKX7nQB8fHx+MRiMJCQlkZmZit9spKirijTfe4Ctf+Qq+vr4e3bTzoa+vj9bWVtauXYvb7V6y2RAajUaMPgVISEhYkudZzhQVFdHf38/mzZvF+zyfTuuenh76+vpEb8zQ0JBHaKa3t5e0tDT8/PyoqKgQZdoLvRYeBMPDwzgcDmJjY7HZbLz99tvk5+cTFxdHe3s7aWlpjI+PA5PXTHR0tDhQyLKMxWJhaGiI3t5eioqKyMzMXBF6U4+1oTh//jyXLl3Cz8+Pw4cP31eFiyzLXL58GbvdTkFBwZLqA23cuJH33nuPU6dOsWnTJsbHx3G5XGKs5okTJ8jKyvK4QCVJQqvVEhsbi4+PDzqdDn9/f7q7u1m7di2vvPIKv/nNb7hx44YwQi6Xi8jISKqqqsjNzSUgIACbzUZbWxuxsbHTyv4SExM9KleUcNWRI0f413/9V1QqFV//+tcXpPA5NDQETOZkenp62LJly5IYCyXxuXPnTi5dukRDQwMbN25c9OdZTGw2G0NDQ0RGRi5KyaqPj48Iq4SEhKBSqWhsbJxzIJAiyRIUFERsbCxms1mEZZSGTZVKJQ4VkZGRVFZWLtuS0eDgYPz9/SksLMRqtdLY2EhjYyMqlQq3241WqxWzW5RrU0GSJHx9ffH19SUmJoaRkRHefvttPvOZzyyJwsDExAT/+q//yv79+5d0CiM85oZCORmMj49TXFx8T4bC7XZTUlJCS0sL1dXVaLVaLl++TH5+PpGRkaxdu3bRRzSmp6fz6quv8pvf/IbLly8jyzIpKSkkJycLJc07lVsVpsabjUYjbW1tOBwOtFotL7zwAkeOHMFms6HValGpVGzdupXLly9z9uxZoWB6/fp1jEajx3jU2dBqtWRmZuJyuejp6eGDDz7gxRdfnNd9ATIyMvjUpz7FqVOn6Onp4erVq2zbtm3Ru7WVcF5kZCShoaG0t7cvS0PR3NzMBx98gEqlYnh4GJfLRXp6Os8888x9x8Xz8/MZGhqitLQUu91Oamoq165dIzY2dtZ4/eXLlxkeHmbv3r1iLK6ymfr7+zM6Ourhrfv7+7Nly5b7WudSolKpyM3NFQq1ISEhJCcn43Q6iYiIEHms4ODgOb0tZRJhUVERr7/+OgUFBVgsFgYHBxkbGyMiIoKcnJz7ktj/6KOPMJvNnDp1ymsolpLNmzeLxNvhw4cXdF9ZlmlsbOTMmTP09vai1+tZt24dMTExfPjhh6L3oLS0lOjoaGE0ZpoHMV+U3oX8/Hx8fX05fPgwFy9eZPPmzSQnJwuhPb1eL8pg/fz8SE1NnfEUn5aWRmFhIa+99hqf/vSnCQwM5OWXXwYmJZsVCYWMjAzhLQUGBuJ0OtFqtaIT+24o8eiYmBiKi4v5yU9+Qm5uLs8+++y8TpY+Pj4csvwzGIAR8Dv/bwT8P8HAtvyfzPftmxVZlomIiMBkMlFaWookScuuV0eWZex2O++99x5qtZrg4GBiY2PR6/XcunWLH/7wh3z2s5+9L8VZnU7H4cOHsVqtYtwtTBakzGYozGYz/v7+ovpOp9MRExNDa2sro6Oj7Nu3b1GaLx8k0dHRbNmyhdLSUhITEz0OXAspl9br9UKks7KyUngbUVFRDA0NceTIETG8615QQndTx+cuFQ+sM3upeFjqsZcuXeLs2bMEBQWxbt06jxPy+Pg4er2e+vp6Ojs7kSSJ0dFR1Go1oaGhREZG4nK58Pf3Z8eOHXOeTOx2O9evX6eyslII8G3bto2oqCi6urrYt28fKpVKuPkffvihR1JW4aWXXprx8YeHhyksLMTtdvPpT38aX19fLl26REdHByEhIaxbtw5Zljlx4gQZGRlkZ2fz9ttv43Q6CQgIICkpifDwcPz9/VGr1TidTm7cuEFycvKMxsnlctHS0kJFRYXos5jPex1V+LXJUt3xcTRqNb7/T9p5MQyFIlE9lU984hPLotnO6XRSVFTEpUuXcDqdSJLEgQMHRL+MMuK2paWF9evXc/jw4fsOzTmdTvr6+hgdHWVsbIy4uDiioqJEUcrUw8GNGzc4duwYzz77rEh6V1dXU1NTA8CTTz75yBkKhZle72I+9pkzZ0hOTp5T2fbmzZuYTCaSkpKIj48XM1+UMKFyaLsXll1n9kpjdHSUc+fOkZmZyapVq6ZdSIo+fU5OjrD2FouF9vZ2xsbGaGxsRKvVMj4+TlFREWFhYRw+fJjk5GRxIShS4VeuXGFwcFCcvH18fLh69aq4iEtLS3G73WLsqJKkjo6OJiwsDJVKNWeHdFBQEBs2bKCwsJDCwkImJibo6OhArVYzMjJCTEwMer2eiYkJHA4HycnJfOc736GlpYVTp06Jk6ckSaJ6yuVy0dnZSUpKyjTXWq1Wk5qayvj4ODdu3BDDZ+ZC8VxUKhUOh2PSEBsMixbnDgsLIy8vj5GREVpaWgAWrQHsfrDZbPziF7+gv7+flJQU/Pz8CAkJwcfHhyNHjgCToU9Fc6isrIzh4WE+85nP3Nd7c2eSFiYNvDICNyMjg6ysLNLS0ggPDxc6Ykpezul0ApMNk4+qkYClMRB3PrbFYqG8vJzu7m7cbjcJCQkEBwczODhISkoKx48fx263c+XKFY/7Z2ZmsmPHjvtWP5gvXkNxD9TV1SHL8oKklX18fKaFBaxWKx9++CH9/f288cYbZGVl8eyzz/Lb3/5WlJn6+fmxb98+1Go1g4ODxMbGcv78eZFIczgcxMXFcfr0aerr61m/fj16vZ6+vj7CwsJITk6etmmMjIwwNDREUFAQfn5+okzZYrHQ0dFBfn4+TU1NWCwWSkpK2Lp1K8HBwVRVVdHf38/evXvJyMigvr6e8fFxwsPD6erqwul0snPnTlJSUqiurqawsJDIyMhpA4xgcqhVQ0MDt2/fvqvrHRUVhcvtptdkEt28qkX8Eut0OsLDw2loaCAoKIgvfOELD3UWBkwaxyNHjjA8PExKSgqtra2sWbOG0NBQurq6cLlcbNu2jdu3b9Pb2wtMhiKampr4z//8T1atWkVKSsqizZEeGBjAZDIRHBxMQ0MDpaWlpKamCqmKW7duCcVgJdn7OAz0uR8SEhK4desWdXV1BAYGIssyN27cEH9XmgAzMzOJj49nYGAAtVqN3W7n9u3b/PznP2fdunU89dRTS14c8FgbiuvXr9PQ0MALL7wwr5PPRx99RGdnJ+3t7SQmJt73aUkR8GtubmbDhg1cv36dH/3oR7jdbnbv3o3RaPQoR1W+eDt37sRmszE8PExERARarZb4+Hiqq6t55513RB6ksrKS7u5utm/fjtlsZmRkhI6ODo/ObGV0ZUJCAgcOHOCNN94Q+RUFJVn5/vvv09vby9tvv823vvUt3G43Pj4+bNiwQUh7+Pr6EhcXR0hICIWFhZSVlREdHe1hUJ1Op0geK02Ac5GRkYE5NpZxsxmny8XE/xNCXCy6u7spLi4mJCSEl19+eVk0SxUXF1NdXS0MMkx6j1VVVcDkiTQ0NFSEGSMjI9m6dSsmk4na2lpOnjyJ2+1mx44d7NmzZ97vlyzLlJeXi1GjRqOR9vZ2bt68SUxMDOPj4xw8eJCuri7Kysro6+sjISGBtrY2+vr6CA8PF8a8q6uL8vJy1q5du/hv0AogIyODqKgoVCqVyDdYLBZsNpuINmg0Gtra2sjJyfG4LlNSUmhubqa8vBytVrvgHOtCeawNRU9PDw0NDfzyl7/k5ZdfnvMU2dfXJ07I2dnZiy4dHBsbi9FopLW1lbCwsDlnD2s0GjQajceJLSoqisjISAYGBmhtbWVsbIyBgQH6+/t57733PO6rYDAYCAoKYmJigjVr1hAXF8eTTz4p1DcjIyNpbm4WiV0lpKDVarl06RLDw8Oiokuv1yNJktgk1Go1MTExdHV1cf78ebZs2SIMWH9/P+3t7SQkJMy7WsPo54fdbmekvw8fgw/cp6GQZZnBwUHa2tqEFPSLL7646BVq90J7ezsfffQRkiRx+/Ztj7+pVCosFosYOGW1WomKimLbtm3A5HUQFRWF0+nk9u3bXLp0iaGhIZ577jkxaOrf/u3fyMjIoKCggPT0dGFEzGYzR44cER33bW1twoNwu91IkiTyTjExMQQEBHDlyhX6+/vR6/XU1NQQHh5OYmIibW1twNKGb1YCd+YGfHx88PHxISgoiJSUFNra2mZsTpQkiZSUFEwmE319fUu+zsfaUABCyO6Xv/wlX/7yl2c1FkoprcPhICUlZUlq+QMDA+9L50qSJMLCwggLC6O3t5fLly8TFxfHunXr0Ol01NXVUVlZSUpKCunp6Zw7d46hoSHS0tLIysrC4XDQ1NQkkqZKc55yklm3bh1Go5GbN2/icrloa2sTVSCtra3IsixyMlarlcHBQSRJYmJigvPnz7N3717RLb5mzRpu3brFa6+9xvbt28nIyJhzU3E4HPT19eG3wFG5dzIxMUFxcTFmsxmbzYbRaGTv3r1s3759WWxqZrOZt956SxhcpRk0KyuLixcv4uvry/bt28VnotfrxdzxqYcAjUZDVlYWRqORGzduMDw8zOc+9zlxclWkXQ4ePMiWLVuoqanh6NGj4nkB8fllZGSg0WjESFwFo9HIrl27uHr1qocWV0REhPheLbfqsUeJtWvXilkxs/GgrtnH3lAYDAY2bdrEhQsXeOONN2ad+5uUlMSXv/xlfvvb33L9+vUlqeVfTJS5EUNDQxw/flx4AzApT7Fu3Try8/NpaWmhvr6ehoYGHA4HLpeLgIAAtFotNpuNqKgo4bko8WhFXE2WZZHw9PPzE/OOjUYjdXV12O12jEYjMTExNDQ00N7eLvI6iobTrVu3ePPNN3nyySfnnE1dnvw/OV57nKcPPM3wPZ763W43V65cQaVSiZLihISEZfU5njx5ErPZDEwagY0bN4r3PyMjg7q6OnG6h8kS74sXL3Lt2jXhVUwlLi4OX19frly5wkcffcRzzz1HaGgosiwzMTFBSUkJHR0dVFdXEx0dTX5+Pna7nc7OTkJDQ4mIiBCPNdNQIYPBwM6dO2lsbBQKv1arVUiumEymx3r40/0gSdJ9D3FaLJZGD+ERQzmlmc1mfvSjH9Hd3S0SclOJj4/nueeeo7e3d9qs6OXG+vXr2bp1K7GxseTk5IiNERCnwtjYWFGiGhsby6pVq9i8eTMbN24Uw6G2bNkybSNNSkrCbDYLDX9AzD1XNH4sFgtut5uxsTHi4+OJjo72EFKDSRmRvXv3kpiYyPnz5+ccO9rQ0EBYWNh9hYa6uroYHR3lk5/8JLt37yYxMXFZGYmRkRGqqqrQ6XRiWuHU8KLi7U499St/n8vDDQkJITMzk/LycsbHxxkYGGB0dBSXy4XBYKC6upqNGzeK8GBAQADZ2dkeRgKYddPSaDRkZmaKz0YJXcHH14WXR5vlYa6WAf7+/uTm5nLjxg1+9rOfAZNaRs8995zHZpKRkUFQUJA4wS10lu+DQqVSTStxjI6OJi0tbca46J0Jx61btzI+Pj7jBpSWlobFYhF5GlmWRZmsEsNOTExEo9EQFRVFVlaWKCeeiZycHD766CP+8R//kdzcXJ588slpt9HpdJjN5nvWe5Jlmfr6epKTk2eswprP/WFpXf3r16+j0WiQZZnw8PBpRnGm5+7o6ECWZZHr6evrY3BwkISEBI9iC8VLliSJqKgoenp6RNOkn5/foklM2Gw2mpqagMlrcCkmzHl58HgNxRSUDTQkJITo6GgqKiqIi4tj/fr1AEKCYnh4GJjUH9q/f/+yOpXOhUqlmnd839/ff9bqH61WS35+PleuXMFsNhMQEEBXVxdPP/20qOtOSkrir//6r4HJEbeSJHlMLRwZGaG1tRV/f3+Sk5PZsWMHZWVlYpbGnSglt/fSH+p2uyktLWVoaGjO4TKyLHPr1i3q6+vJzc0lJSWF27dvExkZyX/9139hMpl45plnyM/PX/Aa7obD4aCkpITIyEg6OjpmrI9XrrOp74HyeZpMJhITE7l27Ro2m43q6mqSkpLIyMhAq9WKU/4vf/lLBgYG0Gg0GAwGxsfHF1X+obGxUYQ5k5KSlkzE0cuD5bE2FKOjowwODnLhwgV27dpFYGAgMTExxMXFER8fj8Vi4cSJE0Ie49SpUx6b5+joKMPDww9koM5yQ9FugslY+vPPPz/rhnPr1i3i4+M9TsgVFRUMDAwgyzJhYWGEhITgcrlm9dAGBgbQ6/UL2nhkWaarq4uGhgYGBwd54YUX5pyU19TUxLvvvouPjw91dXVERUXR0dEBTIZ4VCoVH3zwwZIYioqKCmw2mwh5zuX19PX1iaq4iIgIdDodt2/fJikpidWrV1NSUkJQUBDd3d00NzeLjnlAhPciIyM9xncuFkpYLDY29r50jLwsLx5rQ6GUHvb391NVVUV8fDxbtmzB7XbT3NyM2WxGkiRqamo4c+YMaWlp5Obm0tfXx9jYGHq9flEasx4Vj2QqHR0dYt0zNag5HA6sVquYu32nbLfdbiczM5POzk5u3bpFTEwMZrNZeG93kpqaytWrV+nu7p5X6Kinp4eqqiqGh4eJiYnhs5/97JwqqDDZd6JSqcjJyaGhoYHu7m7y8/MZHh4mKyuLhoYGOjs7sdvti1pGK8syhYWFREdHYzKZiIyMnKYJ1tHRwbVr19Dr9VRVVYlwkVKyqvTGJCUl0dnZiVar5Rvf+AalpaX09PRQUVEhNIy6u7sJCQlZkutu9erVpKSkPFKy/V7uzmPtF071DhobGzl//ryQ6i4tLcXlcvHSSy+RkZEhTmUqlYrIyEjS0tKIj49/bF1rpepJlmUxpVBhdHSUH/zgB/zwhz/k3//932e8f1xcHLW1teTm5tLd3U15eTlZWVmzShKkpKSQlJREdXX1XddmtVopKirC39+fV155ha997Wt3NRIwKYugVqspKSkhISGB/fv3k5yczLp16/Dx8SElJQWr1TpNF+p+qaurY3BwkKCgIJxO5zTVX1mWqa6uJi0tje985ztERUWJqjaY9LamVur5+vpit9tpamrC7XaLarU1a9YgSRIxMTH3JU55N3x9fb2G4gHxoKT6Hs9d7v+hxMy/+93v8qUvfUnEie12OwCvvPIKWVlZREREcODAAVpaWujv72dsbIyhoSHOnDmz6JvGo4DdbhcVTMHBwajVan7xi1+Ixp+amhrcbjebN2+moKCAvLy8aUnNjIwMgoODKSkpYc2aNWi12rsKBObm5jIyMnLXL0dzczMqlYrPfvazCxoao2hJwWSF0Z2DdZQueeX6WCyuXLlCWFiYSDDf6TGNj48zNjbG+vXraW5upqenR3hwTqeTiYkJj0OPSqXCarXy7rvvcurUKS5dugTwQBqzvDwYhoaG6OjoEM2OS81jHXp69tlneeqpp9BoNMTExPDss89y4sQJOjs7Ac+Sw7Vr11JSUjJtfKuS2H5ccLvdVFVVoVarcblc5Ofno9FouHz5Mj//+c/59re/LUQMTSaTqICZmJggNzdXhDtUKhXbtm3j0qVLmEwmvvOd79zVO1O+EA6HY87Qj9VqJTQ0dMESK0lJSaSmpoqxslNLO+12Ozdu3ECj0bB9+/YFPe5cKKNit2zZQl1dHS6Xa1pIaGrn9NmzZ4mMjBTduhqNhrCwMI/RoyqVCrPZjMvlIiQkhImJCbRa7QNVV/aytJSWljI8PExoaOiMVYKLzWNtKO5saFm3bh3+/v589NFHomLDarViMBjQ6/V885vfpLGxEZg8tXZ2doryxEcxz7BQenp6KCoqwuVykZuby61bt9Bqtdy8eVOEnn784x/zta99jc7OTsbGxsjJyWFkZETIQOTl5Qm10YCAADIyMiguLmZiYuKuozEVddKxsbE5JU4cDsc9NSrpdDp2795NY2MjZrOZ8fFx/Pz86OnpESq9L7744qIpolqtVj744AMiIiJob29ncHAQo9HocS0ppcd6vZ6KigpkWWbDhg0et4mOjqa/v1+UDicnJ9PT0yNUZffv3y96JrysDFatWsWVK1c4cODAA9Eme6wNxUykpaWRlpbGyZMn+cEPfgBMzibIyclBpVKJWPfExASlpaWoVKrHxlCUl5cTFxfH7t27ef3114FJ8brBwUFxm4mJCXp6evjqV7/qcd+LFy9y7ty5SSVYl4uioiKSkpKE5Ed7ezvZ2dlzPn90dDR6vZ7u7u5ZDYUyB/1eK24U49XY2MiJEycwGo2YzWZSUlJ47rnnFu1ULssyx44dw2q1sn37ds6ePYtWq502/a2lpYWuri42bdrEtWvX2LFjx7RQw9jYGCqVSnhkiixJeXk5YWFhaLVab85ghREZGYmPjw+tra2Lrjs3E15DMQtTQxu/+93vxPSw+vp6fv/734s49VLNcF5u2O12xsfH2b17N0lJSezfv5+zZ88yODjIqlWrCA8Pp76+nsjIyBmnrCnaUt3d3aIzvKWlBZ1Oh0qlYmRk5K5rUKlUrF27ltLSUjIzM2fc/Gpra7FarTMKqc2HgIAAPvvZz2Kz2WhoaKCxsZHExETy8vIW7TDgcrk4cuQIt27dYsOGDRgMBux2O9nZ2R6GaGhoiPLycvLz82lubiYyMnJatzRMztNoaWmhrKxMGEi1Wk1BQcGirNfL8kOSJMLDw6mpqRFjCJaSlb/D3SN79uzhj/7oj0TcWkmK3rhxA5fLRVxcHM8888w9dfk+alitVk6ePAkgJvlt27aNT33qU2zevJmBgQHOnz+PxWLh2WefRaVS0dvbS3t7O7Isi/6I/fv309TURHl5OZs2bQImxencbve85yZs27YNt9s9TVUVJvNFtbW17Nq1y6Mj/V7Q6/WsXr2a5557jrVr1y6qkXjzzTeprKxk48aNJCQk4Ha7kWXZI6QlyzLXrl0jMjKSzZs3YzKZZu0BSUhIIDo6Wgxd8vLoYbVa6ezsnJfsPkxWFkZERDA8POwxNmCp8HoUcxASEsIrr7wifh4cHOT27dusWbPmsZImqK2tRZIk/uRP/kTkCWCynDQ6OpqioiJgcsN67bXXcLlcdHV1CdFAm82GJEl86UtfwtfXlw8//NAjXJWfnz+tz2I2/P39WbduHbdu3SIzM9PDmxsfH0eW5SVpiFssbt68ye3bt8U4W/i4aGJqNZeSI3nhhRfE5jHbICBJku45L+NleXDx4kXGxsbIzs6ecwa2UiqtzHNRfrfUeD2KBXDjxg10Ot2c3b0rDZvNRnNzM1u3bvUwEgp6vZ6IiAgSExPZsmULbW1tdHZ2IsuykCC3Wq0MDAzw9ttvk5eXx1e/+lWPedpbt25dUANbbm4uNpttWrhqqpzFcqWwsJCYmBiPiirFUEwV+1NeW1RUlAg3KcnpO+nt7aW/v5/ExMSlWraXRURRWb59+zZut1uUPwNzFnQMDw9z+fJl6urq2LNnD5/4xCfYu3fvAxmH6j2CLICOjg5CQ0MXFA+0WCxIkvTIVpwonsFsp3S9Xs+3vvUtAFHaGRoaSn9/P6GhoSJf0dfXx6VLlyguLmbz5s187nOfY2hoiObm5gVLoMTExKBWq+nr6/O4ryJTsRyGD82G3W4X4bupqNVq+vv7RW/PyMgIfn5+wovw8fHxaGpUcLvdYsrZveZlvDw4RkdHKS4uFgcBPz8/j4PNbN+F/v5+Ll68iNFo5OWXXxZNlA8Kr0exAGJjY+nt7cVqtc7r9hMTExw7doxz584Bk8lJZdbAo0JHRweJiYl3LV2Fyc3uu9/9Lp/61KcAPBrTwsPDiY6O5syZM/zbv/0bg4ODBAcHk5+fv+BiAI1GQ0ZGBrdv36arq0v0sij/n+qtLDd0Op3HbBCFoKAgD+l6xegq+QubzTajAVRKedetW/dYFFU86lRUVIhmUD8/P6qqqkS+TavVzvg9s1qtFBcXEx8fz5/8yZ88cCMBXkOxIHJycnC5XPNOOB0/fhyYzHXU1tZy9uxZzp8/P68Kn+WAy+Wir6/vrmWrU9Hr9eJUdOd8idzcXNLS0ujp6fHoEr6XGOuhQ4eAyVDOmTNnMJlMjIyMEBISsqw9itkMhcvl8ih7jY2NxWw209zcjNPpxO12e7yfY2NjtLS0UFlZib+//6LJhHtZOkwmEyaTiYMHD5KRkUFCQgIjIyMi2pCZmSmKJhwOB9XV1ZjNZoqKilCpVHziE59Y8uqm2fCGnubJO++8w61bt5Akibq6OtatW4darZ41gTg1TLBx40auX79OSEgIWq2Wc+fOkZ2dLWSenU4nJ06cYPfu3csqRGU2m5FlecHDZzQaDQEBASLuqmA0GklJSRHJcZgMnfz4xz8mLy+PPXv2zPs5AgMD+bM/+zNsNhtvv/02ZWVlqFQq4uLiFrTWB41er59xQJPNZvPQawoJCSE4OJiPPvqIb3zjG6KPIjg4WKjCwmQi+34rvLwsPbIsU1VVRXR0tOh7yM/Px2Kx0N7eTmxsLBkZGfT09DA+Pk5zczMjIyPU1NQgSRJf/vKXH0hj3Wx4PYp5ooSbJEmis7OTDz/8kKKiohlPw8pcA5j8witjQNVqNV/5yldYv349lZWV3LhxQ5S2jY+Pc+HCBex2O2fPnhXSFw8TZZzlvcioh4WFTTMU8PGUNCUsVVdXx8jICBcvXlzwcyiu+jPPPIPNZmN8fHzGHo7lhF6vn+ZROJ1ObDabhwKvJEmkpKRgMpmYmJjgwIED+Pr6cvXqVTo7O9m8eTN//ud/LjSivCwvXC4X3d3d4sDY29vL4OAg+/btE4ckZYiYRqMhKCiIc+fOceXKFcrLy5FlmWeffRaYrCZ82Acgr0cxT1588UVOnjxJYmIiZrNZyFjbbLZpXkBnZ6fQixocHGRwcJANGzawdetWtFotTzzxBNu3b0etVnP9+nUuXbqE0+nEbDZz4sQJHA4HY2NjDyUWORXFCC7U3XU6nXR1dc1Y8qoI6ylfoKlqsP39/fPup5hKWFgYf/mXf4larV72HfJ6vd5jzG5PTw9XrlwBmPZ5Dw4OEhISIuLWzz//PKWlpTQ0NFBUVCRCEhs3bnxwL8DLNOx2O319fQwMDIjhYF1dXWIP2Lhxo7gup+Yg2tvbuXnzJvn5+bS3twvl4LCwMHbt2oXRaCQwMHDG4ocHjdejmCcGg0E0X23fvl18qT/88EPOnj1LX18fVVVVOBwO7HY7kiSJJr3Dhw/z5JNPepSXGo1GfHx82LlzJ1/72tfE7x0OB9HR0TidzofuVSiGor6+fkF5hOrqaqxW64zKrUoFWEtLCw6Hg4aGBjGFrbKy8p7XqtFolr2RgMmQmeKpOZ1OysrKAMSmoKBIoUyVR5dlmdraWlJSUtixY4dIdi/n5P1K5+bNm3zwwQcUFRVhMpno6uri+vXrdHV18cILL6BSqWhraxPf5ZqaGnHfM2fOEBQURGxsLENDQ6xfv55XXnmFp556ShiUlJSUGcvSHzRej+IemepFDA0NidBJUlISQUFByLLM+vXr+fSnP33XvENERARPPPEEJ06cwMfHhy1btnDmzBlu3ry55LMD5iIoKIiQkBDef/99fH195x3W6e3tRavVziqel5qayq1bt/jFL36BzWYjPj4em83GzZs32bVr1yOx4c9ES0sLH3zwAaOjo+zcuZMdO3ZMu01gYCBWqxWLxUJjYyM2mw2j0ThNjqSwsHCaDIdirMPCwoiIiMDHxweVSuVttHtIDA4O0tDQwLZt21i/fr3Y0G02G06nEz8/P06ePEl/fz/x8fFs2rRJ9Ba1trbS2trK5s2baWtrw+12T5tbv5zwehT3SEZGBi+++CLPP/+8+J1Wq8XX15e6ujoCAgKIjo6e9ya/ceNGcnJysFgsnDx5kvHxcVwul8h1PAz8/PzYs2ePEOKbL+vXr8ftdlNfXz/j39PT00lISKC3t5fVq1cTFBREQkICQ0NDs87MfhS4ceMGg4ODOJ3OWWdWpKen4+/vz5kzZ6irq2Pbtm3k5ORMy1uYzWa2bt3qMRpWCeUVFhZitVofGS9qJSLLMhUVFURERLB3716PU79erxf9L3/6p3/K9773Pb74xS9SUFCATqdjdHSU06dPExQURExMDC0tLWRlZS1rGXivobhHNBoNubm55OXl8bd/+7dkZ2cTHBxMZWUlXV1djI6O8k//9E+zdtPeiSRJfOITn+DFF18kPz9flHj29vYu5cuYFwEBAQvqdlb6I1paWmYNWeXm5rJ582bhpYSHh2MwGKiqqlqUNT9oXC4X9fX1InzU3NxMW1vbtNsZjUa++MUvEhsby1NPPcWaNWvo6upibGxMGAuXyyVOpApms5kPP/xQqOaePn1ahDm9PHja2toYHBzkySefnLN/RavVevy9q6uL//t//y89PT2sXr1ahA+Xe4+V11AsAmazmZaWFkwmkzhFK6EEZRLcfJAkidzcXPbu3cuuXbuASTd2vg1+S0VQUBCtra0cP3583if+zMxMLBbLrIZSr9cTGxsrTsRKmWd1dfUDG++4mIyOjnoMVOrs7PSIR08lLCyML3zhC6SlpfGTn/yEjo4O4OOGQaV8dmq57FtvvUVVVRUDAwOo1WocDse8+3m8LC4Oh4PKykpycnIWLJvS19eH2+3m4MGDIre0du1aent7KS8vX4LVLg5eQ3GfyLLM6dOnsVqt+Pj4CB0oh8NBYmLigkZxTmXqBdjQ0LAYS71nwsLCGB8fp6ysjJ///OdcvHjxrpu5EiZZyATAmJgYRkZGHsmRncrrXLduHS+88ILoJZkNl8vFz3/+c/GzVqulv78f+LgUWzEUZrOZ9vZ24WFERESwb98+fHx8Zmze87K01NXV4XA4OHjw4ILvW1paSnBwsEdIOiIiArVavaw765fvyh4RSktLxeQxp9PJnj17WLduHWFhYXzyk5+85xhyZGQkWVlZwGQYY6pg3IMmOjqaJ554gqeffprMzEzOnTvHtWvX5ryPEj93uVzzfh7ltg9iBvBioxhOl8vF8PAwTqdzzkZFpcZeORBERkaK8N7w8LCYNwAfhx/j4+NJSEggMDAQX19fkpKSHknv61FmfHxcJLCnVqnNB7PZTFtbG2lpadP2BZfLtayLEpbvypY5sizT0NDA2bNn8ff3Z2xsjE9+8pPEx8eL5pj7TTTu3r2b2tpaHA4Hp0+fvqcTzGIgSZI4za5atQqHw8HZs2dJS0ubte/BZDIhy/Ks0tgzoRiKvr6+BX8JHzaJiYlotVp6e3tFSGiuslUlvKSE9SwWC0NDQ9y4cYPW1lYiIyNF+FJ5vKnS0v39/URGRuJ2u7l+/ToFBQXL+kS6Urh16xa+vr5s27ZtwfdVvM47Pc2KigrcbveynkLovbLukZKSEn77298yMTHB2NgYgYGBIuwkSdKiVKMoicvAwEDGxsYWlO9YSnJyctDr9fz0pz+dNQ5/8+ZN1Gr1ghro4uPjiYqK4ne/+92yTuzNhJI3qKysFKf8y5cvz3p75fpobm5GkiQGBgZwu920traSnJzM/v37xW2Vx1N6eBISEujv7xeJ/7a2Nj744IMZO+EfFLIsr3jvpr+/n87OTvbv339PemKKoZiae5Jlmba2No8IwnLEayjugZaWFj788EPxc1xcHF/84hcX3XXUaDSEhIQIEcGpHb0PE51Ox759+4iKiuL3v/89P//5zzly5IjILQwODnLt2jXS09MX1NUtSRLr169HlmU+/PDDR8ZYtLW18d5774mfk5KSSEhIoLGxcdb7KOG10dFR4XUpxmP37t0eg7GU5iudTkdkZCQbNmxAr9cjSRJPPfUUSUlJOJ3O+2pYvB9kWaawsJAjR45QUlKyIiuxZFnm5s2bREdHi1G+C2VsbAyNRuNhZKxWK3a7nV27ds3ad7Qc8BqKBdLd3c3rr78OTA6c+cpXvsJXvvKVJWuz//SnPy3+vRxa+RU0Gg0bNmwgKysLtVrNzZs3KS8vp6uri1/+8pcYDIZ7Gvqu1+vJy8vj9u3b/PjHP34gYx7vB1mWee2116ioqBChA5vNJnIOsxm7qKgoESpSNojg4GBeeeUV4uPj6ejo4O233+b69eu89dZbSJJEcXExnZ2dmM1mHA4Hfn5+GAwGITH+oPNYbrebtrY2zp49S3d3t+i4fxSLEe5GW1sbQ0NDbNmy5Z6jBTqdDpfL5eF5KdfAcokWzIbXUCyQo0ePApOnv1deeWVJxbpcLhcRERFEREQQEBCw7OSz1Wo1WVlZbNiwAa1Wi16v5/Lly9jtdnbv3n3PHlZCQgKHDx/G19dXzPJYrkwtaXQ4HBiNRq5cuSKqWN5///0Z76dWq8XG3tfXR1RUFEajkejoaMrKynjttdeoqanh2LFjWK1W4VX09/djMplwu92ihBomN5wHdZJ3uVyYTCauXLnC9evXmZiYICcnhwMHDgCTjYdKBZfZbOb999/3GH37KKKM8/3ggw/o7+8XXfXDw8OzioPeiZ+fn5gtApPXy5UrV9BqtQ9kSt394E1mL5CNGzcyMDDAxo0b5zXM5374x3/8R8xmM9HR0TgcDpxO57KtjHC73ahUKvLy8qipqcFqtd6X9IgSZlnOHoXFYuHUqVMev3vxxRd577336OnpIScnh8rKSux2+zQj73a7RVVTX1+fUID92c9+xuDgICkpKWRlZVFTU8PY2Bijo6NIksTt27fR6/VoNBrx/qpUKmJjY2lvb7/v930uXC4XxcXF9PT04Ha7kSSJ9PT0aaEYp9PJhQsXWL9+PTdu3BDv1aNMRkYGsbGxnDhxgn/+538GJr1CtVpNZ2fnnIUdCkqIURES7e3tZWhoiK997WvExMQs+Wu4H7wexQLJy8tj7969S24kABG2CA0NxW63U1dXt+TPea8YDAbMZrMo91yMxGpwcDBjY2PL1qvo7OzEYrGQl5eHWq1Gp9MxNDTE6OgoExMTYtb11K52t9vN5cuX+V//63/R19dHSEgI+fn55Ofns2HDBgYHB0lKSmLt2rX4+PiQn5/Prl27eOaZZ8jPz0eSJBwOB9u3b/dYS0pKinjspaKjo4Ouri7Cw8PZtGkTzz///DQjsW3bNnbv3g1MehZKmKaxsXHZJbt7enooLS2lqqpqXmE7Pz8/cX0nJCTQ09MjDm7z8ZiUPUPxKCwWCxqN5pGYJ7I8j6degMkTS09PD6GhoeTk5CxrHSSDwcDw8DB6vR6dTicUUu+H2NhYkpKSKCoqYteuXcuu/FM5QRqNRjZt2sTVq1f54IMPAPD39ycgIABJkujq6iIuLg63281//dd/ie59lUpFenq6SGxPLVaYKQ4eGhqKLMvk5OSIirg7WcrKJyWXEhMTM2vIVekdMRgMOBwOCgoKGBkZoa6ujqGhoWWTZzt//rxHXuD27dvs2rXrrkqtBQUFZGRk4O/vz8jICK2trcD8GksVj8JqtTIxMUF3dzf+/v6PhF7X8vrmefFg8+bNAIyMjODn54fVan2ojXdzERQURFdXF5IkERAQsCihBkmSiIiIwG63L8sO5MDAQDQajfAglC/85s2bhZcRGhrKuXPnqKyspLOzk/r6ejFaNi8vz6O5UOnIni28qJxIZ9qUlNkHS5kzU07C8xmU9NRTT/H8888THx9PVlaWMJjLgZ6eHgYGBkhNTeW5555j586dqNXqeQ3PUq7vOycLzkfTTafTodVqsVqtFBUVYTabPfJMyxmvoVjGKIJ55eXlZGRkYLFYRMx3uRESEsLY2BgjIyP4+PgsWmJV8SIW0uH9oBgaGsLpdGI0Gunu7iY+Ph6tVis6q2Eyp6XRaKirq6OzsxO1Wi0mBt452tJoNKLT6WYNY7S3twPMGAtXHmtwcHDJwk+KyOFCByVpNBp8fX2FMXvYKNeUkusJDw9nzZo1OByOBc2zn+oJzDTediaMRiNWq5WxsTF27NhBXl7ewhb/kPAaimWMj4+PiInGxsaydevWZaEmOxOhoaFIkkR1dTX9/f2LlsNRkrjLLewEiGE0vb299Pb2EhYWhsPh8OiwVUoilY0yKCiI27dvA0zrPpckyWOw0Z0onkZtbS2nT5+mpaUFmEwel5aWApN5rd7e3nsqt7RarYyMjMxolEdHR+np6SEsLOyeCipiY2Mxm8331RtTXV3Nu+++e98FDmFhYahUKo/XqYTyFGM8H6YehuabfwkICGBkZASn0/lQZ2AvFG+OYpnzyiuv4HQ6xeaz0LGkDwqDwUBSUhIfffQRMH0TvBf6+/uprq5Gq9UyMjIiksPLBWVzaGpq4uDBg+LnoaEhUek0Pj6OxWIhPj6e3//+9+K+kiTNWO4sSdKsm45SzWSz2VCpVJSUlFBSUiL+np+fT2hoKKdOnaKrq2vWPMZM9Pf3C7FHf39/tm/f7tFBrNVq0Wq1jI6O3lP1XXp6OvX19VRXV08Luc2XpqYm3G43hYWFBAcHs2XLlnuq8Kqrq8Ptdnt4Zr6+vuj1ejEjZT4MDQ2Jf8/X4w0ICKC1tRW1Wk18fPzCFv4QWdJj2v/4H/9DyFko/01tU7darbz66quEhoZiNBp56aWXlu2J+WEhSZIwEhEREVgslnm7uQ+anJwc8e+pA3fuhaqqKi5cuAAsn470O9mwYQPf/va3+eY3v8mWLVvENLqOjg4xE1wxBu+++67HfWeqm3c6nZhMJmw224y5KGXjjouL4/Dhwx7T72BSvFHxvBoaGuadz3I6nVy/fh2NRkNOTg7j4+OcO3dOJKFLS0vF3He73X5PHeAGgwGtVkt7eztHjx6lpaWFurq6eZ/ER0dHsdlsZGdnk5aWxtDQEOfPn1/wOmAyhObn5+ch2ihJElFRUfMuBnC73aJ4A+ZX9QQf6zytX7/+kdIzW3KPYtWqVZw+ffrjJ5xyEvmzP/szPvzwQ95++20CAwP5wz/8Q1588UUxbN6LJ4ooXFlZmcdwo+WCwWAQE/HuZ239/f3U1taKqi+j0Xjfhmep8Pf3FyEEJckbFxdHTU0NNpuNsbExj67p5ORkmpubZwzBTO3JOHr0KE888YTH+2gwGDAYDIyPj4uZ7IqC7FT10ezsbGpqaujs7LzrqdXpdFJVVcXExATbtm0jKiqKqKgoLly4wJkzZ5BlGbVaTXNzs7jPvUpNhIaGivdI8YQMBsO0mQ4tLS2UlZURGhpKbm4uwcHB4vQeEREhQnzKHI+F4Ha7mZiYIDU1ddrfQkJCaG1tnbHv5U5cLhdut5ugoCB6e3vnbShWr15NU1MTO3fuXPDaHyZLbig0Gs2McssjIyP84he/4De/+Q179+4F4LXXXiM7O5uioiJR8ePlY6qrq4HJKVn9/f13na71MFhI+aPFYqGyspKJiQkhIOjn50ddXR1RUVGiciooKOiRKCE8c+YMgNjAkpOTWbNmDUVFRTgcDlwuF7GxsTQ3N08LvRQWFjIxMcH69evp6uqiq6uLDz74gCeeeEKUVY6NjWG1Wj1CQjB5Gp56AEtNTaW+vp7i4mJKS0t56qmnZg0VHTt2DIfDQVBQkPieBgcHs2/fPi5cuEBsbCx5eXmcOHECq9VKUlIS6enp9/T+bNmyRXSVu1wuSktLaW5uJi4uToRUm5qaKCsrw2Aw0NfXx9mzZ9m1a5c4KIyOjhIWFoa/vz9Op5NTp04xPj4uQkl3bsBDQ0OUlJSwevVq4TG43e4Zw3LKab+/v/+uDXCK4VeuS7PZzMTExLTP5k6ioqL4+te/Po93a3mx5LtMQ0MDMTExpKSk8PnPf15UTpSUlOBwODxUMrOyskhISKCwsHDWx7PZbIyOjnr897ighHY0Gg12u91DdvpRpKamBpPJhL+/P729vdTV1VFcXIxarWbPnj2iAqWjo2PZS0DIsiwSoXFxcTz//PMcOHAAlUqF1Wpl/fr1aDQaUZF059TCwcFB/Pz8SEhIoKCgQMTep3rjjY2NQjhxLvR6PXv27MHPzw+n08kHH3zg4REojI+Pi7DenQcOf39/nn76aaEj9eSTT/L888+Tn59/z4cTlUpFVFQUMTExxMfHk5GRwcDAANeuXaO1tZWRkREqKioICQnh0KFDHDp0CK1Wy4ULFzh58iSAyFOlpaWRlJTE6OgoMTExJCcn09fX5zFj3u12c+nSJUZGRrhy5QrvvfeeSPrP5BUpBnk+Y3+n5iSU3ovlUv67FCypR7Fp0yb+4z/+g8zMTLq7u/n+97/Pjh07qKyspKenB51ON63BJTIycs467b//+7/n+9///lIue9ly6NAhTCYTAwMDyLJMbW0tMTExd20Suldqa2sZGxtjw4YNi/7YY2NjtLe3s2nTJhHacDqdPPnkk2zYsGGafPk//dM/8fLLL88YMlgOSJLEH/3RH2E2m0lISODv/u7vRPw9OztbjH0tKioCmJY/MBgMWCwW3G43Op2Op556ikuXLmEymfj973+PTqfDbrcTFBQ0r2qZwMBAnnjiCZqamqivr6e0tJSAgACPk7Qi3hcYGCh6O+Zisb3X7OxsWlpa6O7upru7G5VKhUajYfPmzWg0GoxGI3v37qWnp4fbt28TEREhqulUKhUFBQWsWbMGrVaLLMuMj49TX1+PXq/H7XZTX1+Pw+FgzZo13Lx5E5fLxeDgIGlpaTN6vgaDAX9/fxobGxkaGmLPnj2zrl0x9FOLD7q7uz1Uf1cSS2ooDh8+LP69Zs0aNm3aRGJiIm+99dY9xzm/973v8e1vf1v8PDo6+khVD9wPAQEBPPfcc/zHf/yHONGcP39+ybR9lITsYg/FsdlsXLp0CafTKfJRYWFh9Pf3c/nyZTZs2EBzczO+vr7s37+fa9eu0dvby5EjR/izP/uzRVvHYhMSEkJQUBBNTU2Eh4djMpnIzc0V/TCxsbHs3buXs2fPMjY2xrVr19iwYQMqlYqsrCyKioooLy9HlmXS09M9ymSVUsyFfg4pKSn4+flx+fLlaUUQys/bt29fsmvobhw6dIibN2/S2NiI2+1m69atHnuD0WgkLS1t1g1YKfSQJInMzEx6e3uFVxEcHExmZiaxsbHU19ej0WhIS0sTc2PuRJIk9u3bR11dHTU1NdTV1c2qgKwYCqWkGKCyspIdO3bc2xuxzHmg5bFBQUFkZGRw+/ZtDhw4gN1uZ3h42ONE3NvbO+cISb1e/0iOylws4uLiWLduHTdu3BBJzPHxcdHEtZgohuLkyZPk5eUtmnBZW1ubyD+kp6fT39+PTqcTirETExOUl5eTkpKCVqtl+/btXLlyhZ6eHoaGhpbktS4Gsizz7//+78Ij9vf3F0ZCITg4mKeeeoqzZ8/S2dkpjHBsbCx6vV70RijSEElJSRiNRtra2hgdHfXwJlpaWggODr5r9czQ0JCo6pmKw+GYtUz3QWGz2UROR6PRLKik907Cw8N59tlnGRsbw2KxEBMTgyRJuN1ubDYbSUlJd/VI1Wo12dnZ9Pb2UltbKwxFe3s7vr6+Yn1WqxVJkkSVVHh4+LIePHS/PFBDYTabaWxs5Atf+AIFBQVotVrOnDnDSy+9BEzWN7e1tbFly5YHuaxHjv3793P79m0h5ZCXl7ckLq8S3mpqaqKwsBC1Wk1AQACjo6PExsbeU0hKGQADk0nXnJwcTpw4QWpqquj47enpweFweIyM9Pf3p6enh46OjmVrKGDyoJOdnY2Pj8+sCXjl9B4cHCySzFPLnpOSkmhpacHX1xcfHx+PclSLxSLKVxXp661bt855uNLpdMiyLBR+FYaHh9FoNA+1IKKkpASbzSauq/b29vuKEGi12mlhpZ6eHmRZJiwsjL6+PkJDQ+d8zZIkkZCQQHl5OWNjY1y4cAGbzYbRaOTQoUPAZDGO0jwH8Oyzzy6pfMrDZkmvkL/4i7/gwoULtLS0cPXqVV544QXUajWf/exnCQwM5Ctf+Qrf/va3OXfuHCUlJfzBH/wBW7Zs8VY83QW9Xu/xZVBO/ouNJElkZ2fzxBNPkJCQgNFoZGhoCJVKRVtbm0ficL5M1SnKy8tjaGgIm83m0ROgxM7dbjcmkwmLxSI21/mIrz0sJEnCx8eHvr4+oqOjSUpKmvW2DoeDwcFBioqKGB8fF8nmNWvWsGrVKgAmJiaoqanx6D8ymUycOHFCGBVZlrl27dqszzM6Oio+pzs3R0W+XulXeRi4XC70ej379u3DaDRy/fp1IZq4WCjfj6KiIi5evDgvGRzFczt16pRI+Cuem9vtprOz06NvaDkfXhaDJfUoOjo6+OxnP8vAwADh4eFs376doqIiUer2ox/9CJVKxUsvvYTNZuPQoUP8y7/8y1IuacWQlJQkJCSUITFLhVqtFt6D1WpFq9WKL7TRaJw15jsTU0/HHR0dwmuY2lSnhEKmdh0rLPdJYC+99BLvvPMOV65cYe/evTN6Fbdu3RIih52dnR4aSC6Xy6OYIyoqim3btnHx4kXUajX5+fm0t7eTmJhISUkJTqcTp9M56xyKqqoqnE4n6enp0wxFYmKikFwxmUwPtPO9oaFBdLCrVCpUKhV79uzh6tWrVFdXTwvZ3Q/x8fHU1taKvF57ezvp6elzbu4hISHEx8fjdDoJCgqipqZGiAD29vZis9nIy8sTFZorOZENS+xRvPnmm3R1dYk45JtvvukRIzQYDPzzP/8zg4ODjI+P884778zpQnv5mKkX+YOctWswGIThCAkJoayszEPKYC6sVqtH6WFZWZlYe2VlJS6Xi46ODqqqqvijP/ojvva1r4keG4Xlro+TkpLCpz71KYaHh2fVJFLKKO98bUqyVWnGO3jwINu2bQMmQx3h4eEkJCSwbds24uLiiI6OFoaoo6NjWpez0o8BeITxpj7f4cOHUalUNDQ0cO3aNUpKSmhra1vy2RG1tbW0t7eLvgiYPCCkp6fjcrkWVaHBYDDwzDPP8Oyzz7J161aAOeeZw+R7s3HjRrZu3YrL5UKlUomQWFtbGxEREURGRoqSWqXHaaWyvLq1vMwbxQ3Oz89fsJrnYqBWq9m6dSuyLM97sNDUbuTo6GjcbreoWikuLubUqVP84he/4NatWwQFBRETE0NkZKTHSXm5dmhPJSEhgaioKNEzNBW3243ZbCYuLm6agXc6nRw7dkwMqFKM6sTEBHa7ncjISI/bR0dHiw29oqKC999/H4fDgdvt5urVq+K0O1MiW0Gj0SBJksj/tLS0cP369Xkb/3vF6XSSkJBAVlaWCLXBx9f1YvfNOJ1Ojh8/ztWrV4H5i/gBoiFU8ciUElv4OKxVVla2qOtdbnhFAR9RlPCMMhPhYaDX60UdeVtbGwkJCXPePiwsjKCgIOx2uziJSZIkKp2mxtqHhoYIDQ0lIyOD7373u5hMJhobGx+ZypLVq1dz7ty5aWqySv9ER0eHqPbRarUcPHiQS5cueTSQVlVVMTg4KBr57pyEdufn7nK5uHr1KoGBgfT29nLo0CHOnz9PYmLinOWvPj4+WCwWPvOZzxAREcGPfvSjJR1darfbRSf1nWFLpex0sXWQbt26hdVqpaCgAKPRKK6/+TAxMSE+Q4vFwsTExDSjvdLxehSPKIqheNgDfZ566ilg/q63xWKZFj7Kzc2ddrvy8nKPnyMiItiyZcuy07eajbS0NFwu17T5BhqNZlqfgNKBPNVIaLVaHA6HCAOp1eppm9vUz16n0/HCCy/Q399PY2MjBoOBVatW4XA45gxN9vb2Yjab2bhxI2lpaSKUNTWf0d/ff0+6SrOh5NRmkqKfKtuyWExMTNDW1kZYWBhJSUmEhYXNO1wryzIjIyNira2trWg0GpFDUa5l5XuwUvF6FI8oymnyYRsKvV5Peno6DQ0NdHZ2zqiKqtDS0oLNZiM8PByNRiP0fiYmJkhISECj0dDT04PdbmfdunUP8FUsPkpoY6YyzJSUFKqqqjzKmu+sIHM6naIJUa1WC7XSqRvo1FN3ZmamSPSnpKTQ1NTED3/4Q2D2qXeyLFNaWkp8fDwHDhygvb2d119/HZg0VG63m6KiIpFrUalU991LMzExQUVFBTBzvkk5udfU1JCbm3vPBwO32y2M9Pnz55EkyaNKaT709/dTV1eHy+USYb7m5mZyc3OFhzY2NkZkZORdZVUedbyG4hFFMRAPK+w0lVWrVtHQ0EBXV9c0Q3H+/HkGBwfFxqnX60lJSUGWZSoqKkRZaHp6uhgp+swzzyyb2cr3ivL5zDQ/RAmvTN10x8fHRQgOJjdx5eStSPSXlJSwZ88eYXz8/f1Rq9W4XC7i4uLE/OWpUtk6nW7WsNPg4CATExN86lOfEvIiOp2OwMBAAgICOHPmDKOjoyQlJdHb20txcTFPPPHEPXdxd3R0UFxcjCRJ5Ofnz/g44eHhhIeH09LSQktLC6mpqaxdu3bBz1VWVkZLS4uQ6d+zZ8+ChmkpqgFOp1P0VfT09AjhRvi4Uq+3t3deirOPMt7Q0yOKIumwHAYZqdVqNBrNNImI9vZ2BgYGiI+PJy8vj7y8PHbs2IFWq2VoaAhZljEYDAQEBNDT08Po6Cgvv/wy+fn5D+mVLB7KJjLT56Ns9BaLRSRtXS7XNOOozFOOjo5Gr9czPDzskTSVJEmoFKxdu5bs7Gz8/f1FH8fmzZtxOByzjiDt6enBYDCI5rLq6mr8/f3Ztm0bOp0Oi8VCXFwcBQUFbN++HVmW73kGBEz2wMiyzO7du2ctqVar1ezcuZMDBw4QHR1NU1PTPU20U0qMAwICWL9+/YInLrpcLlFW/Oyzz6LT6WhqaiI6OloY+KkGuaysTEjLr0S8huIRRTEUUxOlDxO9Xj/tS3Lz5k18fX0pKCgQej2BgYGYTCaKioqIj4/HarXidDqx2+18+ctfXraifwtlLo9CkYE4f/48586do7e3F19fX8xmM5/+9KfF7YxGowg7bdq0CUBsmsXFxbz77rtMTEywadMmcZrduHEjYWFhfPazn2X//v3k5ORQXFw84/wLf39/rFar8ORg+kAlJWcREBDA2rVrGR8fn1O0cy6UBPB8NlNlg9fr9RQWFi44xCrLMuHh4ezfv39aEcB80Ol0SJLE+Pg4Go1GvO6pISblPQsJCeHEiRO89dZb03JrKwWvoXhEWU4eBUwaCqU089q1a3z44YdYrVYyMzM94vRdXV1cvnyZhIQEIRo5MTHB/v37PUZTPio4nU5ef/11fvvb33L+/Hmqqqro6emhubkZlUo1LRwhy7LHZhwQEEBJSQnx8fEMDw97dJ63traKMbBK8tVms/HOO+/Q3t4uvImps5u3bdvGq6++KsJSzz33HAaDgZMnT04zFspEvOrqagoKCtBoNB4b8p3Ngkoe6dq1axw5coT33ntvQdLaylz1OxP8s6HT6SgoKECWZdGtP198fX3vq4tfmdOuhExbWlrQ6XQeY1IVQ7FhwwZSUlKA6arAK4WHH+D2ck8oX7aHpfp5J7IsiwqRjo4O1Go1kZGR0xKpjY2NxMXF8bnPfU4M8pEk6ZFNXp87d462tjYCAgJoa2vzmDOh1+uFIXc4HFRUVNDW1iY8im3bthEUFMSHH35IcHAwcXFxlJeXs2XLFgoLCz262AsLC9FqtTidTtLS0oQOVFFR0ZxemFarpaCggEuXLnHy5El8fHzYvn07AQEBaLVa/Pz8GBsbQ6/XEx4ePucmrlarhQ5VREQEg4ODlJSUEBUVNS1p39TURFVVFWvWrCE8PByDwSBkxOdrKODjxtLe3t55ewZjY2MMDw/fl2aUIrjZ3d1NX18fLS0tHsl1k8nEu+++K2Rb0tLSaG9vX9Ky4oeJ11A8oiiDbpaDR+F2u0WHrZJcz8vLmxaHdjqd9PX18cQTT6BWq1Gr1Xz1q199GEteFNxuN4WFhaSnp4sS35GREZxOJ93d3dTV1XH06FHCwsIIDAyko6ODbdu20dTURHp6OrGxsbz11lvAZDI7PDyc8vJyvvSlL1FeXu6x6Sin44CAANasWQNMliT7+vretZpnx44dXL16FZfLhc1m4/Tp0yQmJrJu3TpcLpfwHFJTU7ly5QoREREkJiYK4z8wMEBHRwd5eXmsWbOGNWvWIEkSnZ2dFBUVeYxcra+vp6mpSczWmKqrpIyEXUjSV6/X4+/vT0tLC3a7ndTUVCEjM5PkiFKpJUmSeJ8WitPp5P333xc/X7x4EaPRKHJGMClB4nQ6ycnJwWazcebMGXx9fVdM6PROvIbiEcXhcCwLIwGT+ksulwtfX1/OnTuHRqOZsYPaZrMhy/J9SUkvJ1QqFaGhoXR3d7N69WokSRIlq8HBwahUKjG7uru7G4PBwL59+9i3bx8wOfoXJk/9ra2tYv51TU0N3/jGN/jHf/zHac859X0dHR0V4Zy50Gq1vPrqq/z4xz8mLS2N+vp6Wlpa6O/vJyQkhMbGRg4cOMCePXswmUyUlZV56IcVFhZis9kYHx8XEhjwcXnrVJ2uqqoqEX5JTU0Vc76dTifV1dW43e67NmbeSVpaGpWVlXR0dIjmQ+W9UEafdnR0UF5ejt1uR5Zl8vLy7nkcwdTkeXR0tPjcppbzdnV1IcsyVVVVtLe3I8sy3/rWtx6onM6DxGsoHlFCQkIwm83IsvzQ50kr9fvKLOgtW7bMWGWiJN5/9atf8f/9f//fQ1/3YqBsqJcuXSI/P99jAltOTg7x8fE0NzfT0NAw7fUqcXclnJOVlUVMTAxHjx7lpZde4pOf/CRvv/22x30UaY3r169Pq2ZyOBycO3eOjo4OfH19efbZZ8UM5+DgYIxGIyqViv3799Pc3ExjYyNhYWF0dHQwMDAgjJ7L5RJzMZRGu+DgYLq7u7FYLGIzVAxCd3c3KSkpFBYWIssykZGRJCUlERIS4jFDurW1leHh4QWXkaakpJCSkoLdbsdkMqHVaunv76e2tpbTp0+Ln41GI6mpqYSGht6TwKHdbqe9vd0jIf3KK6/MaHAkSRIig6OjoyQnJ69YIwHeZPYji5+fH263+6E33MHHCfXAwEAOHz48q8cwda1TZw4/yihie319fR45BQV/f39yc3MJCwublqxXNtr8/HxcLhf19fXk5OTgdrs5evQoOTk5HptqcHAww8PDnDlzxsNIjI2NIcsyv/rVryguLgYmk69vvvmmeM9lWcZms1FbW4tKpRJhQcUgKLO5p1YkKf0bUVFRIrw1deqe0ik+OjpKT0+POGXHxsYSFxfnYSQqKioYHh4mKSlpQfIZU9HpdMTFxREZGUlOTo4QUOzv7yciIoIDBw6QnZ19zyq4586d8zASTz311KxeifK5BAUFsXv3bo+w1ErE61E8oijJw6VW+ZwPKSkpqNVqoqOjZwyHKWJ3SogiNzd3WTQKLgbR0dG4XC6hAXQnLpeLmpoa+vv72b9/v8ffUlJSqKmpITY2ls2bN3PlyhU0Gg05OTlUV1fT0NBAUlKSkHNXvAklX6GUJP/0pz8lNjaWtrY2du7cSXh4OAMDA1y8eJFf//rX5OXlUVtbKybaXbp0aVrSVSl59fHxEVVUyrXl5+cnTsvnz58nMzOT1atXo9VqiY2NpaurS4y0BSgtLUWtVosQU2VlJU1NTURERJCfn78onqQkSeTl5ZGdnU1dXR0ZGRkLHsDkcrnE9Wq1WkVVmKJfNpfUeUJCAhUVFYyMjLB9+/ZlEwZeKrwexSOKclJ8mNPJFNRqNSkpKbO63mfPnhVG4vOf/zwvvvjig1zekqKIMsqyPGNVTnNzM/X19WzdutVj4xkaGqKmpgaY9EZ27dpFZmYm1dXVREdHEx0dzdtvvy3USe8sbZUkSZz+LRYLJpOJzMxMkcMIDQ1l+/bt9PT08P7771NfX09aWhr5+fkelVnwsacyOjrqcTJW5OQzMzMJDAwkPz8fnU4nuulhctbDTB5CSUkJdrudrq4u6urqMBqN5ObmLnq4UafTkZubu+B8RHd3N++9956YfldRUYEkSRw8eHBeneBWqxW3240sy8t6mNZisTKOdY8hZrMZrVb7SJzMlQ7WPXv2iHrzlYLNZhOfwUynSqVL+sCBAx6/n9oo2dzcTEpKCs8//zw/+9nPqKioQKfTiSl4CorKa3BwsPAu1Go1oaGh7NixY9pzh4eHc/DgQZxOJzqdDpVKhdVqFZ6Cj48Phw8fxmq1cuzYMT744AOys7OByWa/HTt2eISPkpOTmZiY8JhAFxsbi6+vL2fPnvV47oCAAC5evChKYTdt2jTjTIyHgd1uF9VYbW1tqFQqOjo6SElJwWg0cvXqVVJTU+ecfdLb2ys8usHBwRVToDEbD/846uWeUCpJ7jwdLkfUajVbtmxh586dy8IDWkwUxVdFjmQqDoeD7u7uGcs0p3pfSq7CYDCwbds2+vv7RSObEiLSarUe4SIlRp6ZmUleXt6s69Nqtfj4+KBWq5EkCY1GIwyaxWLB6XSKfNHY2Jh4joKCAg8joRAQEIDb7fZogAsODp5mJI1GIyMjI6SmplJQULCsBk7V1NSI8JpGo6Gqqgq1Wk1eXh43btzAbDaze/fuOb0ftVqNj48PKpVqyWd3LAdW1rf2MSIjI8NDOG45IssyN2/exOVyLfp8geWA0mOgbBR3hmCUJPNMjV9TN6Gp3sWdjYfK3O2goCBhHJ599lnCw8MJCwsjOzt7QSd1rVbrESK7fv26mJn94osvCo9iJskPmBzNqtPpuH79uvjduXPnPIoT1q5dS19fH1qtlry8PJKSkpZNhZvL5aK1tVV0xzc3NzMyMiK6v9va2njiiSdmVdxV0Ov1OJ1ONBqNR3nwSsVrKB5R/Pz8kCTJQ75huVFRUUFDQwPAipwnPDQ0JHoZgGkncCW5PZORnM1QqFQq0tPTgUl58JdffhmVSkVERASxsbEYDAaSkpKw2Wz33Ccw1TPp7u4WXqm/v78wRrNdV1qtltzcXCwWC62trcDHJbsGgwGNRkN5eTk2m42goKBlYyBgMq9w+vRpHA6HR77o61//Om63W/RPzEc/TVGVtdvtM3peKw2voXhEUSbDKcnO5cjUucQrMYarbKaKzMSdYUDlpD/T/GdJkoRa7J2DmxQDEBgYKAoFent7UalUOJ1OUZGj9K8slJmKDvz9/fHx8cFoNJKTk+ORsL6TxMRE/Pz8qKiowOl0CnmOw4cPc+DAAQoKCjAYDPT19S2rMui2tjYsFgtf/OIXhRfw6U9/WhjHsLAw/P39PSYtzkZvb694bYs5ZGm54jUUjzAZGRl0d3cvixLZO5m6aWZmZj7ElSwdStxd6Ra+cwNWTtqzhd2+8Y1v8L3vfY+AgABsNhstLS20tbWJfgxFMTYrK4uBgQEiIyNFh7PJZLrncJ7BYECSJIxGo5DMnipmFxAQgCRJuN1uGhsbpxlASZJYv349DoeDM2fOkJiYKE7kx48fx+l0CuM538mHDwLFu4mLi2Pnzp385V/+JVlZWcKTmJiYYGxsDJPJNOcBTJZlTCYTExMTGAwGEhMTH8j6HyZeQ/EIk5OTw9jY2KIPol8MpoYuZpLzWAn4+fmRnJwsQjlTR5nCZMd6RETErN6UTqcTp9ni4mJef/11IesBH0t+x8TEIMuy+JwVmYx7jY07nU7UajWHDh0SxmhquMVut+N0OnnvvfcoLy/n+PHj03pEwsLCKCgowGw2C+9Dad67ffs2mzdvRqvVzthb8rCIiorC5XLx/vvvi8FG8HFV3tQpg8rfZqKhoQGLxYJKpSIxMXHFFWjMxMp/hSuY1NRUtFrtgiWYHwRTE6wrVSgN8OgCnlrZYzab6e7unlM6XZZlKisrGRkZERuq4n0dPnzYY5IdQF1dHTAZmtqwYQODg4MLUmKVZZn29nb6+/txuVy43W4hNWI2m0U+Sa1WY7FYRIhLpVJx6tSpaXMolD4O5f/K310uF0VFRTgcjmWVQ/P39ycrK4uqqiqOHz/OW2+9xZkzZzyq0pKTk/H3958x9OZyuejo6ODs2bOi036lN9opLP8ifC+zIkkSoaGhs1aoLBfuR+55uTN1o56YmBDhp+bmZiRJ4tChQ8DkJj06OsrIyIiYQ63RaETV2sGDB/H39xfGYKpwnp+fHzqdTmy6hw4dQqVSIUkSg4OD00JQbrcbSZJwOp2Mj4+j0+lobGycJoM+PDxMSEgIqamp9PX18e677/KHf/iHYk3Z2dnk5OQQHR1NYWEhJSUlPPXUU8CkIZxJskSr1WK1WkU4Z3h4WBik5UBsbKyQMfHx8aGwsJC9e/fyl3/5l/zwhz/EYDAQHBw843Cm0tJSjh07BsDOnTupra190Mt/aHgNxSNObGysOAkuNxISEmhra1vRpy5lkzYYDNy8eVM0w42OjrJmzRqMRiNnzpzh5s2bHqEpPz8/j47euro6XnnlFX7yk58AeFQ0SZJEZGQk7e3tJCYmin6NsLAwqqursdvt9PT04OPjQ35+PteuXZtzCl1UVBQ9PT2YzWZCQkLEgKDTp0/zv//3/0aWZeLi4oS+U1hYGKtXr6a0tJTS0lLy8/NFGGz//v309/dTU1NDeno6JpMJk8kknstut9PS0rJsGi2DgoLYv38/JpOJ6upqfHx8hBF3Op2YzWaMRiNtbW3T7qt47oGBgYSHh1NWVras+kOWkuVh5r3cM7GxsYyOji7LWm4l7LJSp37B5On+u9/9Ltu3b2dwcJDGxkZiYmJYu3YtW7du5ejRo1y5coWwsDC2bNkiGg8VuW6lT2Lz5s2EhobyrW99iw0bNkyrpNm7dy/gWSSwZ88eoqKiqKyspL+/n/b2dq5evephJCRJIiIiQvRHhIaGsm3bNlQqlYeh8vPz4+DBg+Tl5bF9+3Y2btzo8fwJCQmo1Wqam5ux2+3Ciw0MDCQ1NZWnn356RgkRrVZ7z9VZS0VgYCDd3d1ERUXx6quvolKpRAWTols20zXb1dVFdHQ0e/bsQZZlzGbziqzmmwmvoXjEUSoupp7ilgtKgnQ5xakXG0mSMBgMoi7faDTy0ksv8cQTT1BWVkZZWRl5eXmsW7eOmJgYYmJiCA8PF7IfSiWO8v+IiAiefPLJaf0HSUlJ/Mmf/AkbN24UOYHs7Gw+97nPkZqays6dO9m5cyc2m42srCyRJN+2bRs7duwQ10lUVBQwmUjv6uryKF/18fEhNTWVyMjIac+v6D7BZLK6pqZmxka//v5+tFotu3fvJjIyUuTQlITxcqC3t5e+vj7Wr18vvDOlVHmm5Pvg4CBXrlyhs7OT8PBwjy73lXxtT8VrKB5xQkJCiIyMFHMDlhPKZrMcpNCXGmWDMZvNvPHGGxw/fpyrV6+SlZU1bdIffGxElbna85k9rVar+eCDD/iHf/gHfvWrXyHLMlqtlpdffpk9e/aICqba2lp8fX3x9fUlMjJSPA98LO++evVqxsfH7+mAUVNTg1qtZs+ePdP+ZjQaPU7jeXl5WK1Wzpw5s2x6fqqqqkhMTPRIYivNgjabzWMo2MmTJ/mnf/onIcOuGBTldvcqmf6o4TUUK4CcnByhgrmcMJlMBAQEPBZfJiXcExERQV9fHyUlJURERLBq1aoZE7lKqFDJRcxnmM/UDbixsVHMnlB4//33RR4kJCTEI8k9tfsaPq5KW0hDnPIYkiSRlZU1oyClItENk55kTEwM8fHxomLoYWO32xkaGmLt2rUeXpNSEmy1WmlvbycuLg6z2cy1a9fIyMjgmWeeYefOncJQKHnB5ZJ7WWq8yewVQGhoKE6nk6GhIXEhP2w6OztpaWlh06ZNy0rGYano6OgQKq6yLHP06NE5wy2KB6JWq7Hb7fNKigYGBvJHf/RHvPPOO6jV6mmyKFMN0vj4uOiMVspdlceASa9AkqQ5y3dnWrNareb555+f9Tbd3d34+vpiMpm4dOkSISEhIhfS0dHx0JsvZVlGrVbT3d3tISeuGOH6+nrCwsLYt28fV69eFY2JZWVloqCgt7eXiYkJ9u7du2wUcZcar6FYASQkJODj48P58+fZtGmTaNR6WLjdbioqKkhNTRVJ2JWMLMu0tbWJngqlSmmuyqOOjg4kScLhcKDVakWy+W6EhITw1a9+dca/HTx4kICAAHbs2MH/+T//B5gs3w0ODhbluopBmpiYwM/Pb5ri7VxMTEzMWeY6ODjI+Pg4oaGhtLe3I0mSqCIyGo10dXVht9sXPAp1MdHr9eTk5FBcXMyOHTvE6Fq9Xi+GNn3mM5/B6XRSWFiIWq2mtLQUmMxtOBwOCgoKSElJEVVhjwPe0NMKwN/fnz/90z/F19eXGzduPPQKqJKSEiwWC7t3734k5mXcL+Xl5YyOjgo5DEAMM5qNkZERDAYDer0eh8MxrxzF3QgODubw4cMivq5SqfDz8+P27dv09PR4TIFTurMXwvj4+JyfZ1FRETDZSa7Mv3jmmWc4cODAshLOUxL6U6uxJEni29/+Nn/9139NaGiomFcxNTTncDgICQnhqaeeeqyMBHgNxYpBp9PxhS98AVmWH2pfhc1mo62tjT179nhsnCuV/v5+jh8/TmJioodUicFgmLMsWKPR4Ha7hfd3Z77hftcEk9IpFouFW7duERgYyOrVq8VtgoODRe/AQpjrEBIQEIBGoyEjIwM/Pz9cLpd4/OVUIq3kzO4s29VoNEiSRGdnJ2VlZTPed8OGDY9FKPVOvIZiBREZGUlubi7t7e33XNFyv3R2dgLTFVFXKlevXkWr1U4bn+nr64vb7Z61fDIkJASbzYbdbic8PJzq6mp+/etfz6gx5HQ6KSkpoa6ubl4b7s2bN0XZrnIyvnPORUJCArIsi89rvswmwT0xMUFvb6/o/1Bi90qHtjIDYznokqnVagICAmb14jo6OnC5XB5eg0aj4Wtf+5qoLHvc8BqKFUZsbCwTExOcOHGCS5cuPdBmJ7vdTlVVFXl5eUI9dCUjyzK1tbXEx8dPC8kouQBlZsOdKPpXdXV1YvO9ffs2r7/+OiUlJR63PXXqFEePHuXNN9/kxIkTd12XckBobW0VQ3nuVICNjIzEx8eHsrKyeUvASJI062la6VrOz88HJpPmKpWK27dvA5MlqbB8SqVDQ0Nn/WwUo2YymUSo7q/+6q+IiYl5LL0J8BqKFYePjw9ut1toBV26dOmBiQa2trbidDofiwQ2TA4AUmZYT2VsbEyc5GerZtLpdEJTaGhoCF9fX1588UVSUlI4evSoMPAWi4UbN26watUq0tLSuH79OtevX58z/9HW1ib+rkiGl5SUeBgLlUrF3r17cbvd8y5b9ff3nzX0ZLPZPJLlWq2W+Ph4IbWuNAkul07m8PBw+vv7ZxRVjIuLIyoqiv7+fiIiIvjOd77z2BoIBa+hWGEoBkKpLHG5XFy6dElo13z00Ue8++67vP/++4s+b7uzs5O0tLTHpmRQ2WSmzqFwOBxcu3aNiYkJcnNzReJ0JhISEnA4HFgsFjIyMpAkiVWrVgEfh/A6Oztxu93ExcWRlZVFeHg4x44d47/+679oamoCJjfhW7duTTsQREVFYTabkWVZzI6YGroyGAxotdp5j9PV6XRCdXYqAwMD3Lp1y8N4uVwuurq6RFWRr68vBoNhxqFJDwOl+7y+vn7a31QqlehvCQ0NXVaJ+IeF11CsMIxGIwaDwWO6nFar5fr167z77ruMjY0REBCA0+n00N+/X1wuF4ODgyty5OlsKBvsVK9hZGSEkZER4uPjPcZtzoRSmqrX6z0MvJ+fH8XFxYyOjnpIfOj1enbs2IFWq6W+vp433niDc+fO8eabb/LOO+/wL//yL1y8eFE8fk9PD1qtloMHD7J582asVuu0pLlarZ53OCgwMBC32+0RGjOZTJw/fx7wVAm22+04HA6RrDcajVit1mUj5aHT6fD19Z11PUrj4kL6TFYyXkOxwpAkSQy6UcjMzCQ3N5esrCxWrVrFxo0biY2NpaOjY9Fixna7HVmW73nq2qOIMrxman5CaaSbKhM+G4rXZzQaPZLEBQUFDA0N8e///u+iWW3q7AeHw0FqaiqrVq3i4sWLtLS0CDmKc+fOiccJCAjAbrej1+uJjY0lOTmZrq4uDz0jh8Mx7zxWYmIiPj4+HuEaJQdRUFDgISSolJUqMf41a9agUqmmeR4PC4fDgcPhmLUvRDHySs7lccdrKFYgSjJOwe12k5GRQXZ2NllZWfj7+5OdnY3b7V6wpv7w8DC3bt2ivr6eW7duCUOjbAyPQ9+EglICq7x2s9lMSUkJOp1uXidRxaO48z0LDw9nz549aDQajh49CnzcUa0YFKfTSVZWFps3b2b9+vWkp6ezadMmtm3bJh4nLS0NWZbFzG6lqW+qR6CEgu6czjcTbrcbp9Ppsd6BgQHCwsKECq6C8pxxcXHApFFMSUmhu7ubDz/8cF7Pt5R0d3djt9tFqO9ODh06xF/8xV88NmHUu+E1FCuQqf0LPj4+M7rXAQEB6PV6+vr6sFqtc1a+KMZAlmWuXLkijER9fT2nT5/mwoUL4pS4XITfHgTKJquUwLa1teF2uzlw4MC8BvUot5k6JU/BYDCwefNmDAYDq1evFs1xijegbGCxsbFCGTYsLIzAwEBhVJQktXJbHx8fUlJS6Ovrw2Kx4HK5xLVx6tQp0YE8GyaTCYfD4aFvpEhi3El7ezt6vd4jLJeXl4darcZms3H+/PmHWgGlfHazXa+SJD0WGmXz5fE5/j1GTDUUFotFVJ5MRZIkgoKCGBoa4tixY8iyzNq1az3GljqdToqLi+nu7kav15OWloYkSezYsYPdu3dz9uxZrly5wvj4OB0dHWi12gWN5nzUUTZZWZYpKiqis7OTwMDAecti+Pr6zllN4+fn5zESFT5W5J2pn+L48eMi8T0yMoLJZCI8PNzjVJyRkUFTUxMlJSXTcijNzc1zhlqUHghlhOvQ0BAOh0MkrBWcTicDAwPCm1BQvC9luFNdXd2sJ/qpjI+PI0nSoiaVQ0ND8ff3p6ysbJo35GU6Xo9iBRIYGOhxSh0bGxOicFOJiIgQuQWA6upqj783NDTQ19fH2rVrsdlsVFVVYbFY6O/vR6VSsWXLFnbt2kVGRgadnZ34+fnNaJRWKrdu3SI8PJyqqiq6urqIj49fUGmwSqVCpVLN+NlMvc1UlM1yptCNYjym9jusX7/ewxj5+vqSlJSEyWTi+vXr4vfPPfcc8HEuZCaUcNqNGzeoq6vDZDIRERHhIdcNiLzKnZ35imHNzMwkJCSE2traOUu37XY7p06d4sSJEx65l8VApVKh1WpX9PTFxcRrKFYgU2c1K8wUWkpLSxOnwTVr1mC320XJrNPppKmpiby8PJ577jm++93vCm9D6fL18/Nj9+7drF69mpGREfR6/ZxCeCuJlpYWWlpa0Gq1tLe3k5KSwsaNGxc8G1qSpAVJfSvGZaawjRJy6u3tFR7iTKfw7OxsIiMjPdaqeB1Tp97dSVhYmCgdXbduHQcPHmTHjh3TXnN/fz+SJE3LlSlVYj4+PuzatQuVSkV9ff2sr3/q+Fir1broMiB2u33ZlOsud7yGYoWSnJzskXScSa5ApVJx4MABnn76aeGBtLe3A1BWVobT6WTLli3AZMz85Zdf5m//9m9JT0/3eBxF40in09HT07Ogje9RRJZlCgsLCQwMJDg4GEmSpkl4LOSxFqsAQAn12O12jEajRxhxKj4+Pmzbto3Dhw8LWfrBwUEMBsOcFVAqlYqoqCjsdjshISGzNhO2tbXh4+MzY5JekiTKy8uByWu0p6dHeLKKCu/w8DBjY2O0trYSFxcnmvRu3ry5aHkNt9uN2Wz2JqvniddQrFAsFovHl6qlpWXGxJ1yQgwICEClUtHT08Po6ChtbW0cPnx4Xp20U4fiKJUxK5m33nqL+vr6RRla43a7Z9VPWihTcwJms3leBlvRLnI6nSQmJmIymeYsX123bt2swpOjo6OcP3+esbExj54KhYCAAPLz8xkaGqK2tpa1a9cSERFBfX09Z8+e5Z133uH69eucOXOGjz76CEmSWLdunSg1bmxsXDSVgZqaGoCHLsn/qOA1FCuUy5cvA5M1+hqNBpfLNWMXqoLSfzEwMEB3dzdarXZa7Hk2lA1JceOXS1PVUtDd3U1tbS15eXkkJyczNDR0X30BkiQtWkjlziqd+Qjw+fr6EhQURENDA6tXr2ZgYIDKyspZb68k6mdac2NjI4ODg/j4+JCVlTXj/ZOSkggLC6Ompob29na2bt1KRkaGR25LeY7IyEhRVmswGJAkadGm5JlMJrKzs6cl3L3MjNdQrFCUSo6YmBicTidhYWF3FX+LjIzE5XIxMjJCaGjovEMiSpJT2Tz6+/tFY9hKo6WlBbVaTUJCAp2dnSKkd69lwYsZepIkieDgYPR6PQaDYd7qwSkpKTQ1NZGUlMSuXbu4ffs2FouFnp4erl27Ni3ZrpRVT8XlctHW1kZwcDBPPvnknK9px44dGAwGiouLOXXqFDk5OaICS6/Xs3XrVuDjkGZtbS1WqxVZluctNzIXyjTImWaZe5kZb3nsCiU1NRWj0Si8iOHhYVwuFxMTE7OWGSoegdlsXlApojIXe2JiAkmSOHPmjPhC/+3f/u19vpLlRUdHB8HBwRQXF4umMpisGNuwYcM9PeZCE+BzERISgkqlIiIiYt6GIjo6Go1GQ1FREdu3b6ewsJDi4mIGBgaQZRk/Pz+PWRZRUVHTTvbj4+M4nc55jeJVqVQcPnyYuro6qqurKS0tFV3qNpuNs2fPApM5r5GREaE8q9VqF6WrW/ECZwqPeZmZJfUo/v7v/54NGzbg7+9PREQEzz//PHV1dR632b17tyjnU/775je/uZTLeixQq9V86lOfEj8HBQWh1Wrn7MRWqmaGhoYWFA6RJInY2FiGhoaQJMnj1Lcc5BoWi8HBQerq6oiIiGBgYAAfHx9hUJUk7EKY2si4WAQEBDA4OEh8fDyDg4PzylMYDAaio6NpaWlBlmVeeOEFMUJVq9V6eEttbW20trZOk2rx9/cnMDBw3qEhlUpFdnY24eHhtLe3c/v2bfH9j4qKIjU1lYSEBNra2pAkiWeeeWZec8Xnw+DgIFqtdsZGRy8zs6SG4sKFC7z66qsUFRVx6tQpHA4HBw8enOamf+1rX6O7u1v894Mf/GApl/XYEB8fz4EDB4BJqYWQkJA5NyWDwSC6fKeeludDXFycMDBK6ACYs6HsUaOmpkaEd5xOp5AZ12g0qNXqBYss9vT0IMuyGPazGAQGBiLLMgaDAVmWF5Qv6uzs5Je//CVZWVn88R//sWiom5oYb2xsRKfTsWvXLo/7SpJEQEDAgvMtO3fuFKNSZVlGlmViY2NZu3YtKpUKt9uNSqUSyrWL4X0NDg4SHR29qJ7cSmdJQ093Dln5j//4DyIiIigpKWHnzp3i976+vnPKMXu5d5TKHLfbLUoCZVmedQPPz8+ntbV1wV/4zMxMETKIiYnhS1/60qIlHpcLygQ3pbY/JiYGlUpFYGAgDoeD+vp6ent7iYyMnNfjRUREIEkSg4ODi3a6DQoKQqVSMTExgU6no6ura16GSBkDqniDU8M8w8PDnDx5klWrVjE+Po6fnx8Wi4Xx8XH6+vqIi4sjMDAQvV6P0+kUm/t88ff3Jy4uToRJ+/v7RY5tZGREjI01m83TejMWiizLDA4Okp+fv6DP6nHngZpURd7hzjjmr3/9a8LCwli9ejXf+973PNQt78RmszE6Ourxn5fZUWK/MFm33t/fL2ZTzIRKpSIuLm5e6qdTuXOj+/Wvfz2t3+JRx263o9FoRC5mzZo1bNq0iaysLBITE5EkiZs3b847lKTT6dBoNIsqe6JWqwkKCqK3t5eEhIR5d8qHh4d7rHuqd/SNb3yDxMREbty4gc1mY2hoSExQrK2tFaWmcXFxuN1umpubF7zuqddKW1sb7733Hj09PQwODhIUFERzczMul+u+E9AjIyNYrVZ0Oh0//elPp6kReJmZB5bMdrvd/Omf/inbtm3zSIx97nOfIzExkZiYGG7evMl3v/td6urqeOedd2Z8nL//+7/n+9///oNa9iPP1C+/0WgkLi6Orq4uEWKaCYvFck+Jvi9+8Yt0dXXR19eHw+Ggra1tRcWBR0ZGMBgMYrzo1Pe2sbERWZYZHR2lvb193oZWo9HQ0dFBXl7evDWi7kZISAjNzc2kpKTMe0b1nV6HMqEPJstuP/3pT9Pb28vx48dJSUkhNjYWo9HI7du3OXfuHA6HQ+QQ7qU8WjE2W7duZXR0lMrKShobG3G5XPj4+AiDd7/zIUwmExqNRigIdHd3e8zG9jIzD8yjePXVV6msrOTNN9/0+P3Xv/51Dh06RG5uLp///Of5z//8T959912PwTtT+d73vieGw4yMjIhOYi8zExwcLJqKSkpKyMzMpLe3d05NH5vNdk8CbMnJyWzbtk1UTylT2lYCfX199PT0oNFoZizRVKvVqNVqDAYDlZWV8+5OVzqDp27M94sy2U6ZHTGfSYZThf1+85vfeOSoFA80MjKSL33pS+zcuZPU1FQiIyNJTU3F5XJx9OhRPvjgA4B7KotW7uPr6yuaPJVkv7+/v3g/59LFuhtut5uWlhZSUlLEHI3FSpCvdB6IofjDP/xDjh49yrlz5+7a4KJ0iiof5J0oXcRT//MyOyqVSug+DQ0NiRCJMkZzJpxOp0fIaqEoYYSVZMRramrQarXY7fYZ8ztqtRpZllm3bh0Wi2XO93cqmzdvJjg4mN7e3jlDrgtBOXX7+Pig1WrnFV5RuqABmpqaPJr3Tp8+PaMEDHwcRna73QQHB5OcnDwvRdg7UU71o6OjHrkKmMwFKTmzqRP8FkpbWxtjY2OsWbNGGKHFLCRYySypoZBlmT/8wz/k3Xff5ezZs/OKLyo6MPebtPLyMfHx8SIE1NHRQW5uLm1tbbPG0t1u94JVNWVZxmKxiCqeuLi4aZUxjzItLS2EhYXR3d0t3rep759iKGJiYjAajdTU1MzrZK3RaIS0txK+am5uvqc4v4Jy+g4JCaGgoIDu7u553U/xInfs2CF6QnJzc5Flmddff33G16PT6YSByc3NJT8//568UcXD1Wg0HuvV6/UYjUZycnJmVdptbW29azOp0+mkpqaG7OxsD28vODh4wWt9HFlSQ/Hqq6/yq1/9it/85jf4+/vT09NDT0+P+LAbGxv5n//zf1JSUkJLSwtHjhzhi1/8Ijt37py3fISX+aGc2MbGxsjOzsZsNs8aS5ZleUFVKyUlJfzkJz/hBz/4AT/+8Y8ZGhriK1/5Crm5uYuy9uWAyWQiICBAbJZ+fn4eyqNTDevGjRtxOBzTeoZmQ6kOq6+v58KFC5SWllJaWjrvhrk7UT47ZWa11WqdV/hJ8SKqq6uFBxEbG8vGjRux2+20trbOeL+nn36aoKCgWcPF80Hpy7izOEURNgwMDCQpKcmjO1uWZXp6erhx4wbnzp2b9TXKskxdXR02m40DBw54eIRej2J+LKmh+Nd//VdGRkbYvXs30dHR4r//+q//AiZPI6dPn+bgwYNkZWXx53/+57z00ksi1ull8VDyFKtWrSI5ORmtVjvjSVOWZZxO57yF6pqbmzl69KhImjqdTn7yk59QUVGxeItfBihlnwpbtmzxkKnQaDTIsixCMCEhITQ0NNw1pj4yMkJ9fT3h4eGikQ8mvxvFxcVz5pJmQ6PREB4eTmlpqfAk59MMaDQaSUhIwGQyifCPWq3G398fX1/fWT9TlUrF1q1b6ezsvKf1KmtWq9WiC1thamOfEtLq7e1lYGCAI0eOcOXKFWCyIu3O+8JkuOmdd96htraWLVu2EBwc7GHgF0uQcaWzpFVPdysTjI+P58KFC0u5hCWnra2Nq1ev8uKLL95XXH+pSUtL46/+6q/EFyMuLm7Gihilmme+oadr1655/BwSEoLZbOa9994jKipqRdSpj42NYbPZPE6id17byvul5Hc2bdrEiRMnqK6upqCgYMbHlWWZkpISVCoVmzdvxmKxcPr0aQC2b9/OuXPnuHHjBlu3bp2WF7FarXMWC/j5+dHS0iI0meaj6CtJEhs2bCAzM5Nr164xOjpKZ2cnqampREVFzZl3UbwRm82GXq+/63PNhEqlmlYEMNUYK56SwWDgypUrOJ1OMjMzycjI4Pjx49O8YKfTKYYzvfTSS8LQeMPaC8fbmnif9Pb2UldXR0NDw7zc+4fJ1NNTcHDwjMlTlUolSkBnw263M/L/t/fmcW1dZ/7/517tC0ggse+72Qw2xsRrHC9xnMRxljaZtFm7TTNp+22TmU7b+U47aaffZCbdZtq0adImzUxm0jTN5sSJHce7DdgYG4xtjAGz7wgkAdp17+8PfvdEAiEWS0Lg8369eNnoXl0dXaTznPMsn8dkgtVqJe6VnTt3Ijk5GZ2dncjKyoJIJCIKtkudhoYGiEQiOJ1OMmFPnXgFQyGsqIUi0vb29hlrfa5du4bR0VEUFRVBKpVCo9EQl2tUVBTy8vLQ39/vM7FjZGQE1dXVM/60t7eT15gvkZGRpFOfkJZqs9mISJ8vzGYzGIZZUCMgnufR19c3LQbCMIxXOqzQtKmuro6cm5aWBqlUColEgo6ODtTU1JBKcmERc/PNN6OoqIj87QSjtpxco8GGigJeJ2vWrIFarcZf/vIX6HQ6fOMb31jsIc2JxMRE0pxoqtKnRqPxmeXCcRw+/fRTVFdXg+d5VFRU4J577oFMJkNeXh4qKirw4Ycf4ty5cwCAixcvori4eFpv5qVGfX093G432traZjUUDoeDPLZmzRrs27cPFy9e9JI1Ec67ePEi1Go1srOzyeOCMXc4HCgsLERfXx9puerpT4+NjZ21WdLp06fJeObbI0QweCqVCjzPY3R0lAStfVFQUIBPPvmExFucTuec/+4dHR2ora0lSRCZmZnYu3fvtFgZy7IoKirChQsXyGMjIyOIiIhAWVkZTp06hc7OTpLOKxKJ8NBDD/ls4PSDH/yAtkGdB3RHcZ0wDIO8vDykpKTAYDDgjTfeWBJCeDKZDDzP+8z3V6vVPn3alZWVqK6uJr0GhoeHsXLlSuTl5QEAEW/LzMyEWq2GVCrFG2+8ERBp6MVEWFVrtVro9XokJSVNE8UTjK3nqlgqlSI9PR19fX3T7kFzczNcLhfWrl3r9bhwXaEx0ObNmyESiVBdXe012YvFYkRERPj9USgUGBsbg0qlmncRnLDb1Gg0GBwchNVq9VuYFhkZiczMTBKI91f9PxWn0wmxWIxvfetbuO+++7wM51Sys7O9dsZ9fX1EO47neS9poCeeeGLGLn8SiYRqPc0DeqcCAMuyeOyxx0gP4ED39g0Gvb29EIvFPv3JcrkcY2Nj0wzetWvXkJCQgIKCAjIZ+WLNmjUYHx8nlcavvPLKku5NIbhh1q5di82bN+Omm26a5mLxtaMAgJKSEojFYlJ5DEyu1pubmxEVFTUtPVOr1RL9JwAk3mGxWHD+/Pl5jdtutyMyMhLp6enzNtZCEF6r1eLcuXOksZU/Nm3aBJlMBqlUOu0++MPlcoFlWbJbE4r/PIsABYSq//z8fKhUKvT09KC2thZXrlxBcnKyV8OkuXRnpMwNaigCBMuy+Ju/+RsAga2yDRaCaJwv9Ho97Hb7NFE/u90OqVSKiYkJjI2NkZ3EVPLz8xEfHw+z2Yy8vDxYrVZUV1djZGRkSe4uysrKpsmnT0UwFFMNIsuy0Ol0MBgM5FhTUxM4jvPZv4JhGOh0Oq+4Rnx8PNLS0tDZ2Ynq6uo5L0REIhHcbjeysrIwMjIyrzaiExMTZOK2WCzIyMiYVQk4LS0N//AP/4Cbb755zq4ujuNIwFyAYRjk5ub6dA1dvnwZLMtCq9Xi1ltvRVRUFIaHh2EwGLBq1SqyeJHJZMu+d3sooYYigAgf7P3794e9+0mv18PhcPicdHQ6HaRS6bS8eLvdDpFIRNwY/hR/hUm1qakJCoUChw8fxm9+8xu88MILePvtt8P+/ngikUggEon8Tn6+XE8CeXl54DgOZ8+ehcViQWtrK6Kjo2fckVkslmm6T6tWrYJSqSSZTnMpFBOLxbDb7SgtLYVOp5tzEZ/BYEBTUxNZFADArl275vRckUg0L2n5y5cvw2w2Y926dV6Pr1y5EiaTiQTlAaCmpgYGgwEcx2FoaAgsy8LlcpFMvby8PHz88ccAJj+rgp4T5fqhhiKAeH5BrkeTJhRkZmbC5XL5LOoSegt4rqCFFqme0g7+Js4nn3wS3/rWt/DEE0/g0Ucf9Tp28eJFnDlzJgDvInTMJp3tmR47lZiYGERFRaG3txdHjx4FAL/d8BwOxzSXIMuy2LJlC4BJIz9TT2pPBBciwzAoKioi/S/8MTg4iOPHj4NhGOJyA4LTV2RiYgJNTU245ZZbpolQFhQUQCQSkZ0Vx3Ho7Owku+CWlhbYbDayaNFoNBCJRGhsbPSSMKEEBmooAoggXZCenr4gGYNQkpCQgKSkJFy4cMHnFj0qKgrt7e2wWCzgeR5Hjx6Fy+UifbUB+H2PWq0WUVFRiI2NhUQiIRpfgmrt/v375+XHXmwUCoXf8fozFMBn/nabzYbNmzd7GVxPhIJHX25BhUIBkUg05x7bQjAbmDRWTqfT546H4zj09vaisrISJ06cgEgkwq233gqlUkmqseeTNSW4vGYzSt3d3RCJRETfzROGYZCSkkKkOYSdTV5eHikiFIvFxHhLJBLY7XbwPA+HwwGtVjuntqyUuUHTYwNIbGws7rzzzhl99+EEwzDYs2cPfvvb36Knp2eaLHZaWho6Ojrw/PPPIy4uDgMDAygoKIBcLsfBgwcBzLxiGxoawl//+lckJCRg06ZN+M1vfkOOecpAvPzyy1AqlbjllltIo5pwRSKR+J0sZ4pRCKxatQojIyNwOp1+g6zCa8xUtMYwzJzddkqlEuPj4zCbzcRVNT4+7jWB8jyPs2fPoqurixigqKgoyOVyTExMoKOjAyUlJfOSi1cqleA4btYK/56eHuTm5s4YK0tLSyOp2IIbKSYmBn19fZDJZEQOv6OjA8PDw+Temc3mWVNz3333XVy4cAEVFRW47bbb5vzeblTojiKAMAyDsrIyn9ka4UhMTAxSU1PR0NAwrW5Co9EQv/H4+Dg2bdoErVZLutgBM7sjrl27hsHBQdTX15PKWF8ITZSEuotwRiKR+A2OMgxDfOa+EDLMZnPhCLuWhVY3e5KUlASJRIL3338fsbGxEIlE06rxBwcH0dXVhfT0dOzZswdarZas3oXPxMaNG+flevKs0p4Js9mM0dFRv0qzKSkpsNvtmJiYIM2ihDa0drsdn3zyidfCY3h4mLiwbrnllhmvy/M8qcWYqixA8Q3dUdzgPPDAA3j99ddRXV2N22+/3SuIqtfrsWnTJkRHR2NwcBBVVVXkmD8fe2FhIWmDy/M87rrrLgwNDZHnP/3003C5XHjvvfdgtVqXRIXsXPo1Cy6X60EwNIGQg5FIJHA6nbh27RrEYjESExPR0tKCiYkJJCYmkr8ry7KkmE6j0aCnpwdmsxkXLlyAQqGYt8Kq4JL056praWmBSqXyG2sRWgjYbDZotVrwPA+LxTJj/K+jowOPP/74rEZNMITA9M6MFN9QQ3GDo1Qq8dBDD+HXv/41Lly4gPLycq8vmvBFmioj4W/Fq1ar8Xd/93cYHR1FTk4OuV5SUhImJibIjuuxxx4L8LsJHkIbVH/Mlhk1FwS30kxVw/NxPXlKqNhsNqxevRrvv/8+Wlpa0NLSApZlwXEclEolMYKRkZHo7Owkf+8nnnhi3hXMgqGYaUcxPj6Ojo4ObNmyxe+1Pa8juMuuXbuGpKQkdHR04M4770RVVRVJyGhsbMStt9466/iEYsK4uDiYzWa/PeQpk1DXEwVKpRK7du1CV1cXGhsbfabMCjsNwec826QZExOD3Nxcry9gYWHhtErkpYDT6cTExAQ4jvObzTbbjmIuE7xwTiCqhoeGhshuYHBw0Gv17Fll7VlIFxERQXpi6HS6BblRhdjVTDsKIR5y0003+b2O8HyxWEyyxXp6erBq1Srcfffd0wpGjUbjnPTWPJMxhB4qFP9QQ0EBMJm3vnnzZjQ2NhI5aafTSdITS0tLwTAMCdbeSKmH4+PjpKfBgQMHZuxEN5uhGB8fnyb9MRUhSykQ/bM5jiNGwGg0eqmm5ufnY8+ePVi/fj1KSkrI44LMeXZ2Nh577LEFrbTFYjHpBjgVnudhNBqhVqtnlfgWMp5GR0fJtaYa6qkGVWh85g+hPshut0OlUlEpjzlAXU8Uwi233AK1Wo2PPvoIDMOgv78fExMTKC4uRnNzs9fK68KFC2htbcX4+Di2b98+p+6FywG3240zZ86QmgZP5HL5jH0fOI6Dw+Hw6xPneR5XrlyBTCabUal1rq4nYWUttEMV6imkUikZA8uy0yS3e3t7UVZWhjvvvHPW1/CHQqGY5nrieR7nzp1Db28v7r333lmvIcQSPPtMuN1ur5qW2NhYdHR0QC6Xw2az4ejRo1i7dq3fyf/QoUMAJnWibpTP7fVCTSnFizVr1mDr1q1obW2FzWZDTk4OGhoaYLPZkJaWRjJaenp6cPXqVfT29uKNN94I+wLD60HYVW3btg1ZWVkwGAzo6urC6Ogozp8/j7q6Opw/fx5ms9mnS85kMpEsG3+xneHhYb/SKA0NDXOuPRFk4hUKBbRaLYk5sCw7Y595l8sFi8USkPager1+mlT9+Pg42tvbUVFRMacEhtTUVFK9LijlClLjAsnJyWBZluxO5lKRLbSe5Xneb1IG5TPojoLiBcMw2LRpExITExEVFQWVSoXnnnsOAJCRkQG9Xo/a2loUFRWR1pT79u3D22+/jYceemiRRx8cBJ96ZGQksrOz0dra6lVZ7jl5ea5Q6+rqMDw8TCZMrVbrV/ZEcDvNtMoV0lXz8/NnHbNg3EwmE1JTU1FbW4ve3l7YbDafMSiXy4XTp0+DZdmAyMKnpKSgqqrKK1AsuJKmynXMhFKpxDe/+U0YjUb09PSgrq5uWvBbMBKebqz29na/AoaebtOlksq+2FBDQfGJp0hbZGQkzGYzWJZFX18fxGIx8vLy4Ha78d577wGA325rSxmO43D+/HlERUWBZVmo1WqSLcQwDDIzM332haivr/fSytq+fTsiIyP9+vytVitYlvW5K3G5XBgfH0dqaqrfBkICQhzFs3fDkSNHoFarpxUFulwuHD9+HOPj47j//vvndP3ZSE1NxbFjxzA2NkZ2MIKBmk/7UYlEgpiYGCIn4yt2I6TNCszUKErAc8e0FJSewwHqeqLMipCdYrPZYDQayZfLU410JnfGUodhGHAc57WSFQLSt99+u08jwXEckWQXztdoNLMGhgVD4QvBX389shQtLS3QaDTTYgft7e0wGo14/PHH/faCmA/Cit7T/eTpHpovgsvTswais7MT+/fvh9Pp9Mp28jzHF56LoDfeeIP0G6HMDDUUlFm56aabEBMTg8rKSlgsFnAch/fee480ttfr9bNm8yxVGIZBYWEhDAYDPv30U3z66aekGG6meMPFixfBcRyysrKg0WhIbYXNZsPJkydx8uRJnyvZiIgIuFwunymeQjbVfOs0VCoVduzYgYSEBDAMA7vd7hVPunr1Kurr61FQUBDQXtJyuRwSicTrvQg7pYUYCsFFxHEcLBYLXC4Xzp49C6fT6RXc91S8nQnPToE2mw1vvvnmdde/LHeooaDMCsMwuP/++71ksYWJKy4uDjabzau38XJDr9fD6XTCZDLBZDIRGQxfE15rayuam5uh0+kQFxcHvV4Pq9UKjuNQWVmJgYEBDAwM4PDhw+js7ITNZkNNTQ3OnTuHixcvAoDPvhHChDvXSmIh6L1z505ERkZixYoV4Hkew8PDsFqtcLlcaGlpweXLl6FUKoOidzRVSFEwFAsRg/SMJVRVVeHixYvgeR5lZWXYsGED2XG43W4SC5kJh8Ph9VkeGBhAX1/fvMd0I0ENBWVO6PV6fOMb3yCuCYZhwDAMNm7cCLfbHRDJiXBlqmtCcKsMDAxMO1dI5RQCwjExMeA4DiaTCRMTE0hISEB2djZMJhNqamqwb98+dHZ2evWKuHz58rTrCqvmudY1CB0GhfM9+1/wPI9Lly6hvr4e6enp+OY3vxmUoO5UQyG41RYSF5BKpSQ+YTQaSfwnPj4e8fHxpCJbJBLN2k3RU55cYCl3YAwF1FBQ5oxUKsWDDz6IoqIi8DxPJkx/YnieCCvZpYbn6lOpVJJgqa+gKc/zyMrKIvdGkKGoqqqCy+WCUqlEbm4usrKyiOsqNzcXRUVFZCL0dY8EX/9c5eutVuu0xkhxcXHkWEtLC8rLy/HQQw8FpLjPF1MNhfC+5iqTPhVfcTDh+sK/DMPMKjnieR0h5lNdXb2kZO9DDTUUlHnBsizuvPNOSCQSMhG5XK5ZV7putxu//vWv8cc//pFUfi8VPCdci8VCdhhXr17Fe++9R3pZ22w2YgwEoqKiUFhYSNxPWq0WCoUCpaWl2LVrF7Zt24bi4mLk5eURYT5fMQphx+apljqVjo4O7N+/HwMDA7DZbNPqITxX8vn5+di0aZPXcbPZHND2oTqdzmvlLvx/oW5KX2oAQjxCcAcyDDMnQySc88gjj4BlWTQ3Ny+5z2UooYaCMm9kMhlWrlyJrq4ucBznJdo2E5cuXYLVakV/fz/ee++9WQOO4YRQ+1BWVgaZTOblZnO73ejs7AQw2fYVwLQcfs8mRZ6rXZFI5BVY9Zf7L8hn+9MyOnv2LCYmJnD+/HnwPD+tx4fgKlMoFNNiTm1tbfjlL3+JY8eOzXj9+ZKQkOBlfCYmJiCXyxe8g/HMCPv85z8PYHKR4nA4UFNTA6VSCZ1ONycRw8cff5zUBAmNkwT5Esp0qKGgLIi8vDxMTEyQIjB/kgmXL1/Gu+++6/WYUH+xFNBoNNDpdKitrYXdbkdUVBTuueceFBcXIyYmBi6XC1arFcPDw1AoFNP8/Y2NjWTH5e8+zdaTm2GYadXOngjXttvtkEgk08bhK/hut9vxzDPP4L/+678ALCzQPBNJSUngeZ6s9nmen7cSrSeeOxFBcHJiYgJ1dXVwuVxYt24dbDbbrO65uro6SKVSDA8P48SJEzh79iwA0B7bfqAFd5QFIeSiC41fZpoAa2pq8NFHH017vKWlBT09PUhKSiKPcRyHlpYW6HQ6v13gFoNdu3bh9ddfBwCsX7+eVDCLRCIMDQ3B7XbD4XBALpdjcHAQbW1tZIVqtVoRHx8/a8/qxsbGGY8JcthTGw95Ihgjl8sFvV4/zR0o/G61WmEymeB0OvE///M/5LhUKg1IwySBuLg4SKVSjIyMBKSIT8gGk8lkEIvFiI6OxujoKCnGGxsbg8Fg8Or1PRW32433338fOp0OsbGxGBwcJIFsf269Gx1qKCgLgmVZyGQyskq9fPnyNP0et9uNI0eOEN0f4Qt5zz33YO/evfjDH/6ApKQk5OXlobKykrhV8vPzcf/994f2Dc1CVlYW9Hr9tAZGwntqbGyExWKBTqdDR0cHuru7SQU3MNkK9eOPP55ReRaY7CEt4HK5vHzttbW1AEBajA4ODnq5qhwOh1d8wVddS0ZGBq5evQoA+M1vfgOXywWVSoWIiAjY7XaIRKKA9mUQOtIJbkaO465L0ru9vR3AZxll6enp5L5otVo0NDQgJibGbzMkwXgzDEP6WAjMJnt+I0NdT5QF4xks9TUBjI+Pw2q1ErkPAZZlkZmZCb1eT2oKPH3v4dpEZsWKFSRgXVtbi2vXrpFe40Kcoru7GzzPQyKRYM+ePcSoCEVu/vzznm6fqam3Qm2A2+3GBx984NWw5+OPP8a+ffsATGZFMQxDYhqeeGpEMQyD1atXY/v27SRWYbVaA144KRgKnudJp73rRYi9rF+/nsR4cnNzYbVasXv3br/uvWvXrgEAMjMzvSq0AUzrG0/5DGooKAvGc0K/evUqrFYrLBYL2tvbvfR3pFKpV8aNy+XCypUrcfPNN2PVqlWIjIzExo0byRdcSOMMNzIyMmC1WrF//360t7cT37gnPM+jq6sLTqcTLMsSf7ngVpprjMKzaMxoNMLtdpOVtHAvq6urUVdXR6rlgc8mUV8GSegTkZCQgN27dyMjI4NM3IIhD4RyrCdarZZ8LhwOB0Qi0bQahrki3DvBmEVHRxM59IaGBiQmJvo0kJ4cOHAAwKSREbLMgMlCxuVcC3S9UENBWTCeDeyFhvXvvPMOXnvtNfz+978nq+ypQVTPyTI1NRU7duxAXFwctm7dSnonhCOZmZmIi4sjbVF5nifB5aysLOzevZtMvIIRFf4V/OgzpYZ6Bqmzs7OJ1DjHcSSbynMSF5pItba2gmVZxMbGYs2aNQAm/xYzTXparRaDg4NeOzye54mh8czQCgQajQZWq9WrCdHx48cXdC0hOO/povOMuxQVFfl9vqfbz1NaRaVSYXBwEK+//vqSrPMJBdRQUBZMTk4OvvSlL5Hf9+/fTypmBwYGcOrUKcTExExzJc20qtZoNEhMTAxrOYXo6GjwPE8mcqvVSoybVCrF7t27vSYsIcvH7XYjKipqRteTYEiAz/zoExMTeO+999Dd3Y20tDSvjKGtW7dizZo1yMnJQUVFBTZt2oS0tDQSjJ4pFrBixQq43W6cO3cOPM+TALlw7alFetdLZGQkXC4Xurq6yGOeVejzQTBmNTU15DFPd50vgUZPqqurAQAbN24EAKIy4JklNTVuQZmEGgrKdZGcnDzjsbGxMeTk5CA+Ph5isZj05vaHVCpFT08PWUWHG5mZmQA+e9+C5pAQYxGC/DzPw+VyeUlq+1PYFQxFWloaRkdHwXEcDAYDeJ5HUlISSktLodVqiXSKRqNBWloaVq5c6RXUnq0+JTY2FllZWejq6sK5c+dgNptht9uhUCigVCoDXqUt1KB0dHSQDDeDwbCgRlfj4+MQi8WYmJggu1TBTZmTkzNre94TJ04AmHQ7AZM7iZSUFC9trbn03L4RoYaCcl14Sib4ypEXJgqtVgun0zlrjrsQUPzzn/8c0CrhQCG4f4QVu2AQPAsOBfeTzWZDREQE2VH5C+QODAwgPj7eS567qakJEokEa9asgVgshkKhIMbGV02EkF4stDydidLSUqSnp6O9vR2ffvopgMmdRDBSkqOjo8kuRyaTkd3kQlfugmtISBOOiorCvffeO6fWqkLjKcGg9PT0kJ2O8LlbiLLtjQA1FJTr5itf+QqAzwKiwsqRZVkySYpEojmlRnrmsgupnOGEkGUzNefes7jNYrGAYRgolcppsYCZEFxTguvn8OHDMJvNyMzM9DIwQgqnr5z/iYkJcBw3Jz2osrIypKamgmEYSCQSWCyWoCkA33rrrVCr1YiMjCSG09PVthA84w3FxcVz2gl9+9vfxhe/+EXyuyC9AgAlJSUAqKGYCWooKNdNfHw8fvCDH5DfhQnRc4ch5P8bDAa/O4WxsTGIRCJoNBq/BWiLRXR0NCIjI9HU1OQVe/F0K5nNZohEIrAsC4fD4Vf5leM49PT0gOM4REREeGU7xcXFTWt7qlarIRKJYDQap11LpVIhLi6O9GuYjcLCQvA8j+TkZJjN5jlLmM+X1atX4+mnn4ZcLiepw/7qSWbiscceI/+frYudL6bef0/35rlz5wBQFdmZoIaCEhAkEgl2796N/Px8fO5znwMAr25pwv+PHj1KfMUz4Xa7IRKJ0NzcfF0FWsGAYRiSXSQSiYhrzXPVb7Vaye+egXtfhuLIkSMkyKpUKkn9xPbt27Fx40af7ryYmBj09PRM86ezLIv8/HzwPO+VGTQTQvvalJQUcBwXNEMhIJVK4XK5wLLsgv6uaWlpJP21pqZmXpP6yMgIfve73+HKlSvkMU+jLNyLcK3hWWyooaAEjNWrV+P+++9HVFQUEhMTvQKriYmJKCwshE6ng8FgwMjIiM/A69DQEKKiopCcnAybzUaqccOJdevWQaVSQaFQEN+2p7vHZrORILZCofBKkfVM/TUYDGRnoFAoEBUVhdHRUchkMr+Fb8XFxeB5nuhseaLRaCCVSueUDNDd3e1VXR9sQ6FUKmG1WmG32xdcsyDc176+PiIfMxeam5sxODhIujICwBe+8IVpsY25yrjfaFBDQQkKarV6msDcihUrsHbtWgCTK+kDBw54rYpdLhc4jkNKSgqys7OhVCqxf/9+vP/++6ipqQmb3YVYLMa2bdswNjZG3GiebjKXy0V2Amq1mozbaDTi8OHDxC0kpBJv3boVO3fuBMuyMJvNs8YKIiIiIBKJfAoEisViJCcnz5pVZLVaMTIygoSEBIyOjiIiIiIozYs8SUxMJCm5aWlpC7qGZ5HcoUOH5twESYjpDA0Nkb9HTk4OioqKvPStgm0slyrUUFCChq8vsdC4R/BXe7oPBKMhaA6JxWIMDg6irq4OH3/8MX7729+GTUFUUVER1Go1BgcHERsb67W6j4iIIP0n+vr6wDAMKioq8MUvfhEul4u4OUwmE9RqNaKioohh4Xl+TkVvCoUCXV1dPoOvWq0Wbrfbb6qnMIYVK1ZgdHTUS5wxWCQkJCA3Nxd33333nPtzOxwONDc3k93n1MysuQj5Wa1WXL16FXFxcbDb7Thy5Ag5xjAMSRBIT09f1i19rwdqKChBQeg94Ivi4mJER0eTzCABtVoNiUSC8+fPw2KxwO12Q6lU4uabbyb9ngPZL+F6kEgk2Lx5M7q7u4lEidFoRH19PQYGBuB0OtHQ0IDh4WF88YtfxG233Ybs7GzExcWRjB+bzebTxeTpJ3c4HF4TvtVqxdmzZ8GyLJxOp8/iRCEu0tzc7HPsDocDXV1dkMlkUCqVMBqNfnthBAqxWIwHH3yQZBjNhcuXL+N///d/8fOf/xwHDhwgu9Ts7GzIZLI5Zca98cYbcLvdWLVqFfLy8nDixAmv3hObN29GaWkpNm/ePP83dYNADQUlKPhyPXlitVqhUCimBWuFeoT29naSsim4WGJiYnD27NmwyUwpKSmBRCJBd3c3OI7D4cOHyc6C53m0trbilltu8RKfi42NhdlsJllgvnYPwq6J53kcPnwY+/btw8TEBPr6+vDRRx+ho6MDZrMZDMPAYDDAZrN5ueU6OzvBMIzP+282m7Fv3z6MjIwgMTERo6OjcDqd05ochQtCTCIpKQmnT58miw+9Xo+YmJhZg/Y2m43USshkMlJc55l8wLIs9uzZg4yMjGC8hWUBNRSUoCCRSPymwXIcR4yEEJuwWCzEKAwODoLneaSmphIXVl5eHmw2G+rq6oI+/rkglUqJHATP88jJycHTTz+Nr3/968jIyMDatWuxbt06r+ekpqZiZGQE7777Lnie9ylvIuwgjEYjcbmcOXMGlZWVACaLzHbu3InIyEi0t7dj3759aGlpATA5MQr3rr29nRgui8UCg8FA0kDXrFmD0tJSDA4OQiqVhsT1tBDS09PBMAwiIyPB8zz6+vogk8kwPj4OhUIxa5rt4cOHyf+bmppgMpmQmJgYcJXc5Q7tR0EJChMTE36VUgV9JJ7nvYLaLMtCLBYT14BSqSQrY8GwHD9+HOXl5UF+B3Nj48aN6OjogM1mw+c//3mwLIu4uDg8/PDDPs9fsWIFDh06BJvNhsTExGmFZxqNBgMDA3C5XGT1W1BQgMuXLwOYlBARAroFBQWorq4Gz/Po7OxEUlISGhoaAEzKbjc3N+P8+fOIjo7Gxx9/TF4jNTWVBJMHBgaQnp7u92+1mKhUKqSlpWF4eBh6vR4XLlyATCaD0+kEwzCzBrOFhAEAJDVWaH1KmTvh+emgLHkiIyP96g4JzXKEhjnApJHYunUrRCIRcTGMjY2RwKfgZhgfHw+bDCiGYfDQQw/hK1/5ypx6LajVanz3u9/FD3/4Q6xatQoGgwGjo6PkuKBqevDgQTLp5+fnY+fOnUhKSkJhYSE5NzExEffeey/S09NhNBrx8ccfk3vkdDqxfv162Gw20qsCmDTQgpG12+0wGAxE4DBcKS4uxtDQEPR6Pdra2hAZGQmj0QiXy+U3zdbtdnvVSggxsKkNtiizQw0FJSgMDg767W0gHJuYmCC5/7t27SITpeAKaWpqIqtdz2rkhVT2hguCsF9paSlEIpHXrkIoKBPen/De1Wo1brrpJp8To6fxEOImZrMZ8fHxpM5DSAH1FHEUWrPm5OQE+B0GlpUrV0KhUMDhcEAmk4FhGAwNDUEkEs0oucHzPOrr6+FwOLBy5UoAk4ZDkC2hzA9qKCgBZ3h4GH19fX77JAvpmVqtllTqCrsInuchk8kgl8tht9vJROpwOMiXfCESDuGGSCRCRESEV1aTZ/pnbGzsvCa1tWvXkvoTYQItLy/HfffdRzKNPAO2vb29SEhICLi0eKARi8XIysqC0WhEamoqBgcHwXEcnE7ntEC+wNGjR/HBBx8gISEBNpsNDMMgNjbWb89xysxQQ0EJOMeOHYNYLPabKy9MiGazGXK5HE6nk/QZYBgGdrsder0eExMTRPJD0IEC4LPYbCkidATcu3cv3nvvPRJ8FYlEcLvdXjLlMyH46YVYjuDW80Q45rmT6+vr8ypgC2eSkpJgNBqh1+tht9shFouJRLqvzKdLly4hNTUV69atg8lkglQqJcWFvnSyKP6hhoIScAwGAxISEnzWUQiNcoSVstFoJAZFmNzEYjGpo5hKfHw8WJYN6+ZGc8XtdsPhcMDhcMDlcsHtdpN4Bc/zmJiYmJOkhHCfBX+8SqWaVaK9paUFUql0XjUNi0lRURFYlsXIyAjkcjlcLhfZHXj2k2hqasIzzzwDg8FAlGqFmh5BXtyX25LjOPA8j2eeeQb/9V//FZo3tYSghoISUIQUxpkmqpGRERw5cgSXLl0CwzCwWq0YHBz0qpCVyWTo6+sjxiAyMhLbt2/HqlWrUF5ejtjYWJLmuZTxnNiFWISgOhsfH08aCs2GkNkjCBS63W6/LiuLxYJr165h3bp1S6ZPtEqlQklJCfr6+rB161avzomexXNVVVXk/2NjY6itrcX4+DiUSiXZjZrNZkxMTBCXX2dnJ37yk5+Q1r1tbW20gdEUwsJQvPDCC0hPT4dcLkdFRQXOnDmz2EOiLBAhb39gYMBn6qJgQITOZK2trbh69SpUKhXJGhKCsyzLYvfu3dixYwc0Gg0yMzPBsixiYmL8FvMtFQSBwImJCTAMA4VCAbfbjfz8fJSXl/vtfe2JUGUt6BSZTCa/LqvGxkbI5XJimJcK8fHxpOVsbm4uiU14vlfPJIDOzk4iKpmamgqNRgOVSoXKykr8/ve/x7/927/h/PnzePPNNwF4GxxBxZcyyaIbijfffBNPPfUUfvSjH+HcuXMoKSnBzp07ae/aJco777wDYNIgVFVVTTMWQiWywWAg/RpYlsW2bdvIOYmJiUQoz9dEaTabwz4AOxeECU4kEkGn02HDhg3kd+G++ZIZn8rExAR0Oh0YhoHb7YbBYCANlqZis9nQ2dmJ9evXe4nhLQV0Oh14nvdqsiT0CxcQ7hfHcWAYBmvXrsXmzZuRnJyMoaEhTExMoL+/nxjpvXv3EuPimXwRLunX4cKiG4pf/OIX+OpXv4rHH38cBQUFePHFF6FUKvHKK68s9tAoC2B8fJwocvb392P//v1exwV3UnJyMrZv347Y2FisW7duWg1CVFSUT/88z/Po7++f1tBnKSLsim655RZs3LiRKL5GRUURV9RcJixBEwsA6bc9Uy/z9vZ2sCyL1atXB+IthBTB+FksFojFYsTGxuLatWtebjaXy4XExESsXLkSd955J1JSUogBGB4ehlwux4oVK6ZdOycnx6v5VLgWIC4Wi3o3HA4HamtrsX37dvIYy7LYvn27l6/RE7vdDrPZ7PVDCQ/Gx8fhcDigUqmwZcsWSCQSWK1Wr74BgmxFWVkZ1Go1Nm3aRNxQc0GQqa6vr8fx48eX9MpP+OwKcQghmK9UKomPfC4tPoHPJjYhG0yox5hKd3c38vPz5xT7CDciIyMhk8lIunRWVhaGhoa8XEYSiQQymQw5OTnTdqMWiwXR0dGkkPGee+7B7t27UVpait27d3vpbgkJFuPj43OWMl/OLKqhGB4ehtvtnjZRxMXFob+/3+dznn32WWg0GvIz0xeCEnoEd6FGo4Farcbu3bsBTE5OwmpZ6M8gCLXNF5ZlUVFRAblcjiNHjuDTTz9dsl9ko9EIsVhMXFBC6mp7ezsRPpxtQheypQQ3kmA4Z1oRm0ymJbsbE4lEKCwsRGdnJ3ieJ4bV080ml8vnHL8qKCgAx3EoLCxERESE165WIpFgYGAAP//5z/HSSy/d8Cm1S25/9f3vfx8mk4n8LHTCoQQeIQAouEEYhiETmHBMWBRcT7AwNjaWKLJWVlbizTffnDUdNBwZHByERqMhrhMhnXNsbIyskgU13ZkQdh6tra2oqalBfX09gOm9QITXYBjGS812qVFYWAiLxeLVNMqzR4lOp/PqIuiJZ8EmAPz0pz/Fvn378O6775LHhM9rQ0MDfv/73wOYdOft3bs34O9lKbGohkKv10MkEk2bNAYGBkiq31RkMhkiIyO9fijhQU9PD7RarVdAUVjdCb0RWJb1K70wV4QvfF5eHlpaWvD2228vyZ2Fp+uMYRiIRCI4nU40NzdDoVDMGrQX7q/FYkF3dzdZFU/tReGplrpUUmJ9IbiEjEYjkUb3bESUkJAAs9k8rcPf2NgYent7UVRUNO2anjusr33ta/jKV75CKr63bt2KzMxMr1qNG5FFNRRSqRRlZWU4dOgQeYzjOBw6dGiaPDMl/BF0eARGR0fB8zw0Gg3MZjNxp3Acd93BwoSEBOzYsQNFRUVYu3YtGhsbidT2UiE+Ph4mkwkcx8Fut2NkZIRIU1gsljn1R/AsPMzOzsaePXug0Whw+fJlL1FGweAs9Q5uCoWCiAKKxWKkpaURORhgctKXSCTTOt8JE70ggChoiel0Otxxxx3kvOjoaCQlJaGgoADR0dGorKyERCKB3W4Hz/N4++238a//+q9E8v1GYdFdT0899RRefvllvPbaa2hsbMQTTzyBiYkJPP7444s9NMo84TgOo6OjJNjY2dkJlmXJl3Pv3r04duzYnOsD/CH0KAAm02lVKhVOnjy5pMQCExMT4Xa7YTabce7cORw5cgQcxxGXylz6SnvuzIQdlZBme/78ebJjaWtrg0gkwoMPPhjotxFyEhISSMwgIiICvb29pHhRoVBArVZPa27F8zzpCgiAdPS7+eabfRYnqlQq7N69GzabDQ0NDXA6nTh//jwuXryIyMhIHDx4cE7d9ZZysoUni24oHnjgAfzsZz/DD3/4Q5SWlqKurg779++fVyYMJTwQdgmVlZWwWq3o7OyERqNBQkICcYkIRiSQ7g9BpqGrqwsvvvgi2tvbl0Q2XFJSEsRiMdra2rx6biuVSrAsOyf5Dk9/vBDUVSgUyMnJwcDAAHp6esDzPNra2pCenu5X0XepkJKSQtKABVfU22+/TY5LJJJpvdUFQyEkyQi7ralJMw6HA62trbBardOaOR0/fhwJCQm45ZZbEB8fjzfeeAOffPLJjMago6MDP/3pT5eF3ExYNC76xje+gW984xuLPQzKdbJlyxacO3cOMTExOHr0KDiOQ0lJCcRiMe644w5YrVYcP34cNpst4MVe2dnZkEgkGBwcxGuvvQYA2Lp1q1cxVrghFouRnp5OXGarVq2CRCLB0NDQnF1zM+2gioqK0NHRgbq6OkRFRWFiYgIFBQUBG/tikpaWRrSe9Ho9SkpK0NDQAIfDAalUCqlUimvXrsFqtUKv1yMzMxMOhwNyuZxoaQmNoK5duwZgMing3LlzuHbtGpFEEdzfer0ew8PDMJlMyMnJAcMwWLduHd577z1UVVVBqVSSToeemEwmuN1uvPTSS/jhD3+4pOXNF31HQVk+CKs0mUwGi8WCVatWEZVYsVjsJakdaENRUlKCgoICbN68GRs2bEBGRgaOHTvmlWMfjngGUnmeR0pKyrwmFM9q4qnZPoWFhbDb7SRteanHJwSSkpKgVqtJbEKlUoHjOPLZEvqa9PX1oaGhASdPniQtX6fuqATDcfXqVRw8eNCrI15VVRV0Oh2Gh4fJjljwdAh6XABw6NAhnDhxYtrOori4mPwtPa+7FKGGghIwjh07BmAyI4VhGNI0xxdzLSSbL8IXuKSkBHK5HJ9++mlQXidQeK7yhVTY2drIeuJpcKfGNIQAdkdHB1iW9Sv7vpRgGAZ5eXkkW3JqzUliYiKeeOIJlJeXY+PGjTAYDDAYDBgZGZmWIMDzvJcLC4CXBpbgznO5XFi/fv20z61MJkN+fj4OHz7slX0ljPORRx4B8Jm0zVIlLFxPlOWB0JN4dHQUEolk2mTnqcgZLEMhIBKJkJOTg/r6eoyNjYWtNpRcLodOpyMqAw6HAwMDA9P84zMhrFhZlp32HnU6HWQyGQwGAyIjI+fU22KpkJGRQZRhHQ6HV+EiMDmB33777QCA2tpaWK1WUljHMAxZ/TscDnR3dyM1NRXf+c53yPF169ahrq4OHMeR3cDExARRFvCkoKAAPM+jsrIS5eXlXn+Hs2fPAsC0dN2lBt1RUALC1ODhVO0mt9tNdhxzqQ8IBKmpqWBZFufPnw/6a10PFRUVcDqdOHv2LE6ePAkApH3nbAgG17MznieCEu9SLEj0R05ODlQqFRobG2dt8PTNb34T//f//l987nOfA4Bp59bW1gKYlAgRjEBkZCQ2b96MjRs34qmnnkJBQQHq6+tJQeNUcnNzwTDMNPn75aJCSw0FJWAwDEPcJ1OlVa5evYrx8XGsW7cOt99+e0hE1yQSCdLS0nDs2DF89NFHYTtZTnWHiMXiOWU8AZ/JfgjFZ1MR3FGbN29e+ADDEKlUii1btqCzsxMmk8lvXEehUHip8E6V+PCn0CvE1u677z5s374dra2tRLrcE4lEgoSEBDQ1NQGYdIc9++yzJMuvqKgIv/vd75ZsK1ZqKCgBQSwWIyoqClqtFjfddBOKi4u9jre1tSEiIoLkr4eKlStXIi0tDTU1NeRLHG547ga2bt3qJZI5G0Ka8UyV7kJW1HIJZHuyatUqKBQKdHV1zTkBwDPgLASjZ0vVNhqN+NWvfoWCggKsWrUK58+fnyYHAkwG1UdHR3H58mU899xzXgapsLAQg4ODYR8zmwlqKCgBQ6lUwuFwTPOvC5XHarU65GMSiURYvXq1l+pouOE54Rw5cgSffPIJ3n///TmJ2wm7pKmuPgEhE2051E9MRRAJBCbjX2+//fasnekE5eL4+HjccccdSElJQUVFhd/nNDU1YWxsDC0tLdiwYQM4jvO5M0hNTQXP8/jkk0+85GTKy8vJAqmxsXG+bzMsoIaCEjDMZrPPlZ3VagXHcbMK3AUTuVzuJWkRbgi7itzcXFInMBd9IcFtMjVGJCBMWMspkO3Jpk2bkJmZCZ7n0dTUhMOHD8PlcqGhoWFGV+Odd96Jv/3bv0VycjK+9KUvzWpEhSpwqVSK6OhoSKVSIufuSUREBDZs2ACTyUQkywXJfc+YnJCSu5SghoISMNavX4+uri4ipyAguEUWU85AJpPNqCoaDqSkpCAyMhJFRUWksY4wQbW0tMxYD6JUKsEwzIwdIYVYx1zkJpYikZGR4DgOHMdhxYoVqKmpwQsvvIB33nkHf/zjHwMiDy5UVickJBDpGCGLaepnWthplJSUYMOGDXjooYfI30hoJvWf//mfMxr2cIUaCkrAWL16NeRyOal2Fejq6gLLsosqby2Xy6cZsHAiIyODCCcqFAqwLIvR0VGcOHEC9fX1OHr0KLq7u6c9TyQSISEhYUZDotFooNPplpxg4nwQVu9KpZK4f+RyOYxGIz755JPrvv7OnTuxdu1aUtyoUqlmjAkJi5HNmzdj+/btXirYW7ZsIS7C/fv3X7eCciihhoISMCQSCXJzc6dNWmNjYxCJRIsqby0Wi2f1Xy8mnm0+GYZBVFQUTCaT1728cOGCz+fq9Xo4nc4ZZdZdLpdX97blxn333YfIyEjU1dWB53kUFhaS+EN7ezsuXbp0XbvZhIQE7Nq1CwzDwGKxYHBwcFpMaGBgAFeuXIFKpYJIJPLp9srKysK3v/1tAJMpuS+++OKCxxRqqKGgBBS9Xo+xsbFpfRYWuwex0+mcc8rpYiAo4QoujZiYGNhsNrjdbhQVFSEuLm5GQyDUUszk+7bb7WFbcBgIGIbBl770JaSmpqKrqwuVlZW4fPky0tLSoFAo8Ne//hWVlZVwOp2oqamB2+2G1WqF2+3GuXPnSGYYz/OzplB3dHTAarVCIpGQZAODwYBTp07h0qVLGB4eBsMwXu1/PVGpVPjud78LYNK1uFQar9HKbEpASUtLw+HDhzEyMkICtJGRkTP60EOF3W4P6xRRYSIXdj0pKSkwGAxgGAZpaWmYmJjw6V46d+4c2tvbwTAMrl69esP2cdFoNPjCF74At9uNEydO4NixY2hpaYFMJoNcLsfhw4dx+fJl9Pb24qOPPgLLssTwClXdH3/8MUQiEZ588skZs8iEz7HQGEoqleLKlSuIjY1FcXExPv30U1JPccstt/i8hkKhwEMPPYTXX38dr7zyCjZv3jzjueEC3VFQAkpycjLxrwtER0eD47gZ+6CHArvdHtbuF6GZk7CiFSqDN23aBLlc7lM6Apjs+aHT6SCRSNDX1+fVxEdAJBKFtdstkIhEImzZsgVf//rXsWnTJuj1ethsNuj1ei8pd8/dmcvlwl/+8heMjY3BaDT63f1mZ2dj9erVRA9K2FVoNBqShMAwDAYGBvzKdmRlZSEnJwfApHx5uEMNBSWgsCxLtIsEYmNjAUwGtW02W8hblnIcB4vFEtZtc4eHh8Fx3Iypmi6Xa5qhEJocJScnY/v27VCr1Th9+vS0yuHIyMhFNdKLQVxcHDZt2oSHH34Y9913H+666y4Ak5N4aWkpEhISkJCQgM997nPYt28fed4jjzzi11AkJSVh9+7d2LlzJ3msv78fMpkM0dHRUKlUJKPpr3/9q98xzqUxVbhADQUl4MTGxnqlogqr5O7ubuzbt4+0vuU4Do2NjUEvQhoZGYHT6ZxR5iIcEOIMMxXZicXiaf5zlmXBMAzsdjsUCgXy8vLA8zxqa2u9jHFkZGTYFhsGG5ZlUVRUhKSkJDz11FN49NFHUVdXh76+Ptx///1EohyYzEqaS/tZga985SvYsGEDMjMzceutt4JhGBQVFcFsNpPsP3/puZ5V2uEuGkgNBSXgxMTEeAW05XI58vPzyRdScIMcOnQIly9fJk1kgkVPTw9UKlXI5UPmg0ajgUgkmjGFNzo6Gm63e5oLyVMJ1VNfyzMmpFarMTY2dsO4n2YiIiKC7G4BoL6+nqQcq9XqeethJSUlYfv27Xj44YeJ6kBZWRlsNhspcBQEB31RVFQEYPL7Ee5NjaihoAScmJgY2O12rzzxrKwsslpTq9W4du0acU/5E2W7XjiOQ3d3N4qKihY988ofLMsiKipqxhauwsQz1W3H8zwJvLIsS96jZ1W3sFs5ePBgwMe91FAoFHjwwQchkUigUChIL4ubbrppQZP11Ar6mJgYrFmzhuyoBTVgX9x7770oLy+HzWbzWekdToTvN4eyZBG6gHl++GUyGVavXg2JRIKRkRGcP38eWq0Wubm5Qa3YHhoags1mm7Ns92KSmpo6Y+Gc4Pc+cOAATp06BWDSaPA871Oew3P3cPHiRa9r3Ojk5ubiu9/9LtauXYuNGzfiq1/9KjZs2ODz3PHxcb+fz7179+K3v/0tMTgAcMcdd+DrX/86ZDKZ3yJThmGIVtW77767wHcTGmh6LCXgREdHQyKRwGg0EqMhEBUVRdwi+fn5QV9J9ff3Q6PRLInubp6B0KkIuwIhe6yqqgplZWUAPhMEFKQsgEnZieHhYZw8eZLENpZzLcV8Ee6ZRCKZ0SV57do1/Pd//zdWrlyJe+65x+c5giLx8PCw12csLi4O//iP/zjrLiU1NRV33HFHWKduA3RHQQkCDMMgLi7OpxHYsGEDVCoVlEolEhMTwfM8eJ4P2mp3dHQUycnJYe8DBiYn+pnGGR8fj3vuuYcUDfb29uKDDz4A8JnrTgiIsiwLp9OJY8eOwe12o6SkBCqVakncg3BCiDtcuHABly9fxuDgIDo6OrzOEXYbQtGeJ3O53wzDYM2aNWGdaAFQQ0EJEvHx8T4NBcuyiIuLI/GLhIQE8DwflMwnnudhMpnCOojtiWcQ1Bcsy0IkEkGhUHidV11dDavVSvpncxyHzMxM5OTkYNu2bcjOzgbDMDOmJZ87dw7/8R//saiijeEGz/NeSRZvvfUWfve73+FPf/oTcTN5VnJ71mgsR6ihoASFhIQEjI2NefluBTQaDdxuNxwOB6KiohAVFYWWlhZcunQpoGMYGRmBy+Wa1m0vXOnu7p611kMwFnfeeScyMzPJ4z09PV7B+piYGKxcuZJoSInF4hlTbw8cOACj0TgnWfMbhcuXL+PYsWMQiUTYvHmzV7aU0N7UYrEQ4xvOysSBgBoKSlBISUkBz/M+G7wIXy5hYisvL0dUVBRplxoorl27BoVCMa2RUjhiMpkwMDDgpTbqSUdHBz788EOYTCaIRCKwLIuSkhLidhKLxUQOG8A0Ay0SiWZ07wn+8c7OzkC8lWXBpUuXoNPpsGfPHsTExGDTpk2kwZFgfAXXEsMwS0azaaFQQ0EJCnq9HnK53KehcDgcYFmWBBQjIiJQVlYGkUiETz75JCC6UDzPo6+vD9nZ2WGdFisgSLNPDf4LGI1GOBwO6HQ65OfnA/jMjSfgKZsyVSDQs97CE57niX99poyrG5GBgQFERER4xRkuX76MqKgoErsQUpn1en3YF8xdL+H/DaIsSRiGgVar9dlVzpevPCIiAmvWrAHP86isrLxumQ+HwwGn04m8vLzruk6oECYmf1LsLMtiy5YtXjuk0tJSVFRUIDk5mUz4DMOgvb3dZ83FVD799FNSPbzc3SezceXKFZw4cQJmsxkjIyNk5yDgcDiQmppKfhfibFKpNOSyNKGGpsdSgoa/rA9fxxITE1FWVkYkKK5nJyC4WYS00nBndHTUr2jhTKKACoUCycnJcLlcRKZDMAhGo5G0n50pmC3ELTwTDG5ETp48SaRlhCQMT4PscrmmGQohoUAsFmNsbAwnTpzApk2bQjjq0EF3FJSgERsb67PS2F8qrLCivt76CmFSXSorPZPJBIVCsaDnGo1GfPTRR7DZbDP2ZpZIJD5TOCcmJqDX6yGTyW5YQ8FxHDESERERqK2thUQi8VpkGAwG8DxP2pkCn33GBAN/+PDhgHzeDhw44BVvCgeooaAEjYyMDIyOjk5zaQwPD5NUzqkIX76ZpCzmirAbWSopnzabza/byd/7OH/+PDiOw80334zt27eTxz0nfk8JcwGz2YympiYkJCRAKpWGdavYYCJMyuvXryf1DFM7BgpG1tMdJewodDodsrOzASAgLWerq6vx0ksvXfd1Agk1FJSgUVhYCJVKhStXrng97s+lJLhCrlcSfCntKDiOw9jY2IJ3FA6HAxKJhDSK8vXex8fHiRtKoLa2FiKRCBkZGWhpacHo6OiSMayB5PLly5BKpYiLi0N2djY2btyItWvXTks3ZhjGS+RPMLwikYhIcSzXXdkNbSjsdvsN+cUIFWKxGFu2bEFnZ6dX9pO/1bMwWQaqUnsp/H3NZjM4jps1RuGLoaEhjI+Pw2azoa2tDW63m5wrGAqO42A2m70ypDo6OnD8+HEkJiZ6TYg3YvX21atXER8fT0QV4+LiptXeqNVqZGRk4NChQ6S3h+Da86x6XwoLk4VwQxuKF198ET/+8Y8XexjLmtWrVyM2NhYXLlwgE5harZ5R8lqQqKiurr6uzl9CHcFSCGYLqZUzueOAyV2YL2PR2tpKjp87d86r/4FGowEwGcPgOI5oETU1NeG1116DVqtFQUHBkkgfDhYnT57E8PCwz8LQqaxcuRJKpZLEM8bGxsAwDGQyGUQiESQSic8sv/kixEF8pZZ7YrPZ8Mwzz+D999+/7tecjRv3E4Lrd29QZodlWezatQsGg4FMav7E71QqFXJzc6FQKK4rr38pGQrBXSHoXvlCr9fD7XZ7NSCyWq3o6emBVqvFzp07IRKJUFNTQ44L0iXt7e1QqVRkAurs7ATP89i8eTOUSiWZ7LZu3RqstxiW2O12Mun7U3kVEIlEyMvLQ0tLC5HJ9+wlIZfLrzu2BgBr1qwBAJ9tbT0ROugJ36tgckOnx95///0zyhpQAkd6ejrWrl2L2tpakgk1k6YRwzAoLi6G2+2e1tJzPiwlQyEYhyNHjiAhIQFFRUWkzalarYZMJkNcXBwYhkFjYyNWr14NlUpFKqnXrVsHpVKJrKwsXL16FcXFxejv74dEIkFPTw/a2tqwbds2snMwmUzQ6/Xkb2C32+FwOEgh2Y2CUOQIYFrNxEwkJyfj0qVLeOedd5CYmOh1zyIjI72uuVBWrlwJhUJBAuS+EApKAeDzn//8db/mbNzQOwqVSjVjj2JKYNm+fTs0Gg0uXrwIo9FI3CIzoVKp4Ha7F9zrWTAU/tw54YLg12YYBn19fTh48CAOHTqEo0eP4tixY6Q5kVarxdDQEPbv34+BgQF0dnZCoVAQd52wsk1LS8PmzZthNptx9uxZFBQUePVb6Ovr87r/Qs+FpSKeGCgEIT+JROJXjNETkUiEdevWYWJiAs3NzV6GIjo6Gkaj8brjYgzDIDc3169LcO/evbBYLNi8eXNItMxu6B0FJXRIJBJkZmbi7NmzAD6LRcxEZmYmGhoa0N7ePqP+kT+EneJSMBRC7cOmTZvQ29sLpVIJqVQKk8mE5uZm7N27F1Kp1KsOQuic5s9lcvXqVajVatx9991eQWq3203kU4DPDJXnYzcCLpcLERER2LFjx7yC+FqtFllZWejo6PBa9cvlcjidTjidTr+pzoGgrq4OAPz25A4kN9Yng7KolJeXE0Phq/jLE5FIBLlcPut5MzEyMgK9Xh/UNquBQjCaNpsNJSUlXsdUKhWuXr3q8z6o1WqsWLGC/C7sogQBwJ6eHmzatGnaalksFnvVVAhGdSm46QLJxMQExGLxvDO9GIZBaWkpiouLvT5fwj0NhcHV6XQwGAxeqrbB5IZ2PVFCS2xsLPlgzyXf3OVyzdklMBWbzTatbiBcUavViImJ8elmy8rKQk5ODgBg48aNSElJQXFxMYDJAjHPyd1isUAkEkEsFqO9vR0ul8tnC1iFQuEVm7NYLBCLxbPu8pYTTqcTV65cWdBuVWDqIkTYvYaicPH+++/H7bffThRtgw01FJSQIkhaT0xM+Mw55zgOLS0taGlpgdPpXPAq1+12B337H0hyc3NnVc2Ni4vD2rVriQbRVGlrt9sNkUgEnufR3NyM4uJin0FajUbjtUOxWCyIjIy8oWoohoaG4HQ6r8tQTEW41xcuXAjYNWciNjYW5eXlIXMXUkNBCSnC5O1wOKbliff19WHv3r2or69HfX09AJBq4/my1AxFbGwsbDbbnAoNhRiGr65qPM9jeHgYFosFq1ev9vn86Ohor3x/i8VywyV1XLx4ERKJJKAp8kqlErm5uThy5MiyawJFDQUlpHhO3lPdSpcuXSIdxYQ+1wvJIBEqkZfS5CeMdS5uC4ZhkJKSgrGxMS/DIgRT29raoNPpkJaW5vcaAhaLZc7poUsdk8mEl156CVVVVcjOzg74irygoAByuRyHDx+e1/M4jkNtbe11i2EGC2ooKCHF0687VdvIYrEgJiYGMTExSExMBM/zC5rsDQYDXC7XnIqowgVh5+TLUPiSGE9LSwPHcV5uDqvVSlqeCtpEvjAajV73/kYxFMPDw/iv//ov9PX1oaysjDSACiQikQj5+fm4cuXKvFK7TSYTPvzwQ/zqV78KS9kZaigoIcUzN3xqsaNQYAZ8Jt28kMDgwMAAFApFQP3PwUapVEKhUMy5eZBWq4VGo/Gq3h0fH0dUVBTEYrHfjmtdXV3EADudTjgcjlnrWpY6jY2NeOGFFzAyMoKbb74Z6enpQYvJxMTEAJhdgsMTTxdYc3NzwMd0vVBDQQkpnobCl9yBZw9oYGHigGazGUlJSUsuOBsbGzvnvHiGYaDT6bzSXJ1OJ9RqNaKiotDb2+szWcBiscBoNJIMJ8GgLGdD4XK58OGHH0KlUmHLli0koSJYKJVKqFQqtLW1zfk5IpGIZKhVV1cHa2gLhhoKSshRKBRgGAZjY2NE2trhcIDjOOISESa5hQjWuVyuBUt2LybJycnTpL6F4LQvd4RWq4Xb7caZM2cwODgIt9uN2NhYaDQaOJ1On7sTYbUqVGEL2U/LVfdsYmICr732GiwWCzZs2LDg5Ij5wDAM9Hq9z2QDf5SWlgIA2traFqxIECyooaCEFIfDAalUCpZl0dLSgsOHD+Odd97BBx98AOCzuIUwMZ4/f35eKzO3242JiYklWTyWnp4Oq9XqFdAcHh5Gb2+vz91RWloa4uPj0dXVhRMnToBlWcTHx5N72NHRMe054+PjkEgkxLUnGArPznjLid///vfo7u5GXl5eSN+jUqlEb2/vvILT6enpRAreU9wxHKCGghJSHA4HRCIRRCIRbDbbtB2DYCAiIiKg0WjAcRzOnTs3ZxdUW1sbbDYbysrKAj72YCN0V/N0PwmupY0bN047n2VZcBxHjEh0dLRX4ZwvwcupvcitVivUavWSqGBfCMKuyl8GWDAQFiq/+tWv5vwchmFw++23A8CsNTWhhhoKSkhxOBwQi8VkYvJs1iMSiYgiqlgsxrZt27B27VoA8JLXnon+/n7U19cjLi7Oq0nPUkEsFkMikfjsjeBrIu/t7cXg4CAyMzOhUqmIYRAMga+qdplMBqfTSQzy1D7byw3h8xVqZVzB6APza56VmpqKhx56CPfff38QRrVwqKGghBS73Q6xWIyCggIAkxPXhg0bcNNNN0Gv16O7u5tMeAzDkC+4v8YyPM+jrq4Op06dQmRkJGlLuRSZT+3I1atXIZFIUFpaCrVaTdxIQnzHl3HRarXgOI4EsZe7oYiLi1uUxAaWZVFeXg4A03qVz0ZWVlbY/U2CYija29vx5S9/GRkZGVAoFMjKysKPfvQjr61we3s7GIaZ9hOOEX9K4BAMhSCNrFarER8fj6SkJBQXF4Pnea8+FMJk569pfU9PD1pbW7Fz5058+9vf9pLUXmrM1VCMj4/DYDAgNTUVwOR9dLlcJN0V8J0IMLVew2azLes+FEajcdEUhAX3U7i5kRZCUAzFlStXwHEcfv/73+PSpUv45S9/iRdffBE/+MEPpp376aefoq+vj/wsRd8yZe4IhkLIMffMttFoNFCpVGhoaCAuKCEwOzIyMk3bCJisCThz5gxyc3NRUVGx5FJipyISiebUd1mIY2RkZAD47D5aLBZS/e4rriNMmsIq12q1LtuMJ47jMDIysmjFhHq9HkqlkigmL2WCYihuu+02vPrqq7j11luRmZmJu+66C3//93+Pd955Z9q5Op0O8fHx5GehaqGUpYEQzD5z5gzEYjGZ6AS2b98OhUKB+vp6OJ1OSCQS3HTTTQAwrR+x2+1GQ0MDcnNz8cADDyx5IwFMV3adiZ6eHrAsS+ofhH+tVivpsibsNjwRdmhutxtOpxN2u33JqOzOF0/Z9cWAZVmkp6ejoaFhxh7xS4WQxShMJpPPD+Rdd92F2NhYbNy4EXv37p31Ona7HWaz2euHsnSw2+3geR42mw2ZmZnTtHbEYjHWrVsHp9OJs2fPguM44q+duohob2+HzWbDjh07FlRvEY4olUqfhsJT7dVkMqG7u9urSE7YPRgMBly6dAk33XSTz5W0XC6HTCaD2WwmCQJLSRNrPshkMkRERCyqflJaWhpcLheampoWbQyBICTfrpaWFvz617/G3/7t35LH1Go1fv7zn+Ott97Cvn37sHHjRtx9992zGotnn30WGo2G/ISiDSAlcAh1FP6IiopCbm4uent70d/fT3pXTO2X0NPTg8zMzJAUUYUKpVLps1fHyMgI2tvb8fHHH5NCLk83rbBivXLlCtLT07Fjxw6f12cYBvn5+WhsbERlZSVSUlKQkJAQhHcSHkRFRS3qYlKpVEKn06GxsXHRxhAI5mUovve97/kMQHv+XLlyxes5PT09uO222/D5z38eX/3qV8njer0eTz31FCoqKlBeXo7nnnsODz30EJ5//nm/Y/j+978Pk8lEfnz5rSnhicvlmtaGcyaEzm02m42spj2Dgk6nE8PDw8jLywvOYBcJtVrt01AYjUY0NjbCYrHg8uXLYFnWKzOmrq6OuN7uvfdevzusXbt2QaPRQK1W46GHHlq2NRQ8z6OzsxP9/f2LKrSn1WrnlN4dzsxLY/fpp5/GY4895veczMxM8v/e3l7ccsstWL9+PV566aVZr19RUYGDBw/6PUcmky2JPsiU6Qg+Y8FQ+Ava9vX1AZgM0o6MjIBhGC+RNZPJBJ7nQ15IFWymNhUSECaa2NhYiMViZGdnE2PAcZxX4Hq2TnVSqRRPPvkkOI5bUj075stCdMKCgVKpJMkZS5V5GQpBAnou9PT04JZbbkFZWRleffXVOfmQ6+rqlvU2+EZH+OLO5ErypKenBwzDICoqiujeeNZSCH785da+U61WE92rqd8ZlmVRUVExbXI3GAxev4+Njc0q8ncjJI3Mt34hWIjF4rAxWgslKH30enp6sGXLFqSlpeFnP/uZV7cnQfr5tddeg1QqxapVqwAA77zzDl555RX84Q9/CMaQKGGA8GURJvepWUyejI6OQqPRgGVZ9PX1TevJIEyi4TIZBApP+Y2pelXx8fE+dwBTz1uKOlfBQLgPer1+UTPifPUTWWoExVAcPHiQ9D1OTk72OubpK/zJT36Cjo4OiMVirFixAm+++SY+97nPBWNIlDBAMBSCG0VQMPUFy7IwGo2oqqoiwUjPz5IwYdpstmUlkS28l6nChmvXrp0xcSMiIgJSqZTssqhr9jNWrVpF0oUXC0GPaykbjKBkPT322GPged7nj8Cjjz6Ky5cvY2JiAiaTCadPn6ZGYpkjuJwGBgYgkUgQGxs747nbtm1DXFwcCWBLpVLk5OSQ44IbarlNijExMWBZFoODg14xnNlcbFu2bEFsbOyyygALBFqt1mdyQCiJiIiA2+3G6Ojooo7jelgeyeeUJYHggpzLLkAsFmPjxo1ENbWwsNArW0pYPS83N4tIJEJycjIuX76M06dPz/l5ERERUCqVy85wXi9yuRwOh2NRYwTCZ30pS3lQQ0EJGYKh4DhuzuquFy9ehEgkmlZlPD4+TorHlhuCS663t5esQn29T5vNho8//pg0I5qYmFi2chwLJTs7GxzHLeokLcTTwrEX9lyhhoISMjz7LMwle47jOIyOjiI1NdVrNyHkx2dmZi5Zn68/hAQPALh8+TIiIyN9CvedOXMGFosFFy9exPj4OIaHh6dJotzoaLVaiEQiv4kTwcafmu9SISjBbArFF55flLnIRly7dg0cx03bTRiNRoyPjxMZ5+VGTEwMJBIJaUS0evXqaedwHAeDwQCGYcBxHK5cuQKZTEbaaVImYVkWcXFxc+5FHgwESfdwkw6fD3RHQQkZnruCudTVCNLiUwO0BoOB+PKXIwzDEIHMm266yWdKbH9/PziOg1qtBsuyMBgMKCwsXNYFdAtFqVT67WcSbARDsZSz86ihoCwKcwkuCu6CqZXKIyMjiIuLm5MUyFIlMTHR7ypYyIIaGxuDTCbD+Pi4V1c1ymfMpxlUMLBarRCJREQyfylCDQUlZAgqngzDzLqj8JRlrq6u9koVHRkZWfZikImJiRgfH58xtVOr1ZJ7mJWVBQBISkoK2fiWEhEREYsq8+1yuSCVSpd0PI0aCkrIELqqSSSSWQ2FsJpWqVQwGo1oa2sDMLnLmJiYWPaGQnh/U+U5PNm4cSPWrFmDiYkJREVFLVu58OslJiYGZrN5Tg2hKL6hhoISMgR9oblswQWjsn79eqjValy6dAlOpxMdHR2QSCRexXfLEa1Wi4iICL+qozExMUhOTkZvby9R26VMJz4+HhzHkc/UbAwMDODEiRM4cOBAQKq6bTYbVCrVdV9nMaGGghIyhOK4uegzCfEJuVyONWvWwOl04urVq2hvb0dxcfGyD9oKAe2xsTG/5/X19cFut3ul1FK8ERqm+VLl9cTpdKKpqQknT56EVCpFfHw8zp8/j4aGhuuKcUxMTCxaO9ZAsXyjgZSwQygam0sGinCORCKBTqeDSqUivU42bNgQvEEuMdra2pCcnDxnVecbEX89xAVaW1tRV1cHYNKlt3XrVrjdbuzbtw91dXWQy+UL3sWOjY0t+foWuqOghAzhi7oQxVdBfl4kEi3bHs9T6evr8ytRYjabMTg4iDVr1oRwVEsPQe5lpiy5np4eXLhwAWlpafjSl76Ebdu2gWEYiMVi7NmzB/n5+WSRYrPZ5tVbwmg0YmJiYsknGtAdBSVkCG4Ut9sNl8vlN711at9oQUF2uTUq8kdkZOSMAViO41BfXw+tVovCwsIQj2xpISxQfCVQ8DyPc+fOISsrC/fff7/Pz2ROTg4aGxsxNjaGyspKjI+PIyUlZU5ZTC0tLdBqtcjPz7/+N7KI0B0FJWSMjY0hKioKPM/PWik7MTGBiIgI8mUUXFHLrfWpPzQajVd67MTEBPr7+zEwMIBPPvkEw8PDuPPOO5d1PUkgEPpVe+7OHA4HqfB3OBwoLS2d8T4WFxdDIpGgu7ubBMTnuis2m83IyMiYU4FpOEM/YZSQ4Ha7YbFYoNVq5yS3LGj4C8TExMBoNKKoqCiYwwwrrly5QoKo/f39qKys9Aqq7tmzh9RQUGamq6sLUVFRRDCxtbUV9fX15F6yLOu3WFEsFiMrKwuXL18mj81Ft4njOJjNZr9y+ksFaigoIcFoNILneRJYnC1rSSqVYmRkBKdPn0Z5eTlMJhOSkpKWXetTf2RnZ6O5uRnHjx/H0NAQkpKScMstt6C/vx/x8fHUSMyRiIgINDc3Y3x8HBzHoa6uDmlpaSgpKQHHcUhJSZn1czX1+MjIyKy9P0wmE9xud0CkZiorK+F0OnHzzTdf97UWAjUUlJAgFI65XC6wLDurHHZiYiJGRkbQ3d2N7u5uALjhGlvdf//9ePnllzE4OIjy8nLs3LkTIpGIGoh5smPHDjQ1NeH06dOkQvuuu+6aV1JESkoKzp07R37v7Oyc1VAIKd6BaCZ18OBBAEB5efmiLJaWtuOMsmQYHh6GWCyG3W4nhXf+yM7OhkKhQGpqKjIzM7Fhw4YbLmgrFotx//33Y9euXbj11luXtEz1YiKVSnH77bdjbGwMNpsNDz/88Lwz50pKSlBSUkJ+n0sflPHxcUil0oA01xIWB2+//fZ1X2sh0B0FJSQYDAao1Wq43e45TXgikQg6nQ4Mw+Dhhx8OwQjDE51OR9ubBoAVK1bgn/7pn+BwOBbU7IphGNx+++1QKpWoqqpCe3s7VqxY4TdIPTw8jOTk5IBoPBUXF6O1tZVI74c6OE53FJSQMDo6CpVKNS+9HbfbvaS7glHCC4ZhrqsjolQqxY4dO3DrrbfCarWit7fX7/nj4+Ok/ud68Sz2m6sUSSChhoISEoRMp9HR0TlXESclJaGzs3NJN6WnLC8YhsG6deug0+n86nDxPA+LxRKwHhRKpZK4y958882AXHM+UENBCTpOpxNGo5E0cJlriqsgpLaYTWcoFF/odDq/K3un0wme5wMqBijoeXn2Ug8V1FBQgs7Zs2cBfNbha64FYkajESKRiMpnU8IOtVo9TT3AE6Egby6JG3MlPj6e/N9kMhG1glBADQUlJDAMQ4Kyc41TDA4OIjk5OaBfNgolEMTGxsJkMhFj4XQ60dPTA2AyiF1TUwMgsO1PPTO1XnvtNfzyl79Ec3NzwK7vD2ooKEFH2EEIaYJCpzt/OBwODA8PIzMzM6hjo1AWguA+ra2thcViwf79+1FdXQ2TyYSqqioAwO233x7Qqmwhe8pTZ2ou36VAQA0FJehIpVLwPE8MxkxbZofDAafTCYPBgJMnT0IsFmPlypWhHCqFMidUKhU+//nPw2Aw4OOPPyY7i6qqKrAsi8cffxzl5eUBfU1B9ys7Oxu33XYbgEkXWCigdRSUoBMREQEAaG5uBsMwiIuL83ne4cOHSTWrWq3GI488suQbvlCWLytWrMD/+T//B6+//jpGRkYQHx+P9vZ2rF+/fk5dHOeL4GZSKBTk/6GS3KeGghJ0BJfT0NAQpFLpjKsgjuMgEonwyCOPIDk5eckrblKWPwqFAl/5ylfgdDrhdDpx4sQJbNy4MSivVVtbi/T0dHAch+bmZrAsG7JiTGooKEGnr6+PNILxl/Ekk8lQWFiI1NTUEI6OQrk+GIaBVCqFVColLqFgoNfr0d3dTeqQvvrVr4ZM1oUu2ShBZ2hoCBEREXC5XH4rY5dDE3oKJRg4HA7s2bMHDMPg6tWrABAU99ZM0B0FJejYbDZIJBKMjY35NBRDQ0OIjIyERCIh6p4UylKir68Ply5dQkVFBZxOJxiGCVj9D8dxePbZZ5GdnY2oqCj09fVBo9EENPV2NqihoAQdq9UKlmXB8/y0moixsTEcP34cIpEIbrcber1+kUZJoSycixcvorKyEqdOnQIwWbn9jW98IyDXbmlpIf8KabEZGRkBufZcoYaCEnRsNhsJaAv9iwUsFguAyfhEWVkZVq9eHfLxUSjXi/D5jo+Ph91u91u1PV88NaUEkcxQ1xfRGAUl6FitVjidTohEomm6TcIOo6KiAlu2bKGZTpQlidDFrqioCAkJCXPuqT0XGhsbodfrER8fT7IGQ92bhX4rKUFnaGgI/f39cLvd01xPQkDuyJEjuHLlymIMj0K5bhITEwFMFpPOtTnXXHC5XOjt7UVycjJsNhtyc3Px7W9/m/ajoCwvpvaTmCppoFAokJ2dDWBxdPYplEAglUohEolgt9vR09ODtLS0gFy3o6MDHMdBLpfDaDRixYoVi9LpkBoKSlCZ6moSZAgEeJ7H0NAQEhMTvVpNUihLCYZhoNfr0dbWBpvNhra2toBct7q6GpGRkRgfH4dIJCKLqlBDDQUlqIhEIq9t8lSdp+HhYZhMJuzYseO6uo9RKItNRkYG+Xzv2rXruq/X3NyMlpYW5Ofno7e3F1lZWYv2HaGGghJURCIR7rvvPvL70NCQ13HB3USrsSlLnbKyMqxYsQK33XYb8vPzr+tao6Oj+PDDDxEbGwuZTIaRkRGMjY0FaKTzh6bHUoKK0WjEW2+9RX6fmg3icrkgFotpthNlyaPX6/HAAw8E5Fr79u2Dy+VCWVkZTpw4gfj4eOzevTsg114I9NtJCSpCnYRKpUJCQoJXHQXP8xgZGQmpFAGFEu4MDg6itbUVhYWFkEqlGB8fx0033YSEhIRFGxM1FJSgIhiKzZs3w2q1eokCXrp0Cd3d3TPKjlMoNyI1NTVQKBRITk4m7qZQqcTOBHU9UYKK1WoFMJk+yLIsyS+32+1obm5GSUkJdu7cuZhDpFDCipaWFiQmJoJlWYyOjvrt4RIq6I6CElT6+/tJjrnL5SI54GNjY+A4Dhs2bKCuJwrl/8dut8NoNEKpVAIABgYGEBMTs+h94+mOghI0OI7DhQsXkJycDIZhYLVaScc6QSVWKpUu4ggplPBCKpUiMjISDQ0N6O/vx9DQEO6+++7FHhbdUVCCx9jYGMbHx2EwGGA2m+F0OsnuITY2FmKxGDU1NYs8SgolfGAYBk8++SQ2bNiAoaEhZGVlhUXfeLqjoAQNjUaDu+66C3v37kVXVxcAkB2FVCpFVlYWTp06BaVSifXr1y/iSCmU8EEqlWL79u3YuHEjZDIZkRZfTOiOghJUrl27BpVKRWSYU1JSyLHCwkKo1WoYjcZFGh2FEr7I5fKwMBIANRSUINPW1oaUlBS4XC4wDEMMBjBZR2G1WgPWCYxCoQQHaigoQcNms2FiYgKRkZE+j1+8eBE8zyMrKyvEI6MEg0A266GEF0EzFOnp6WAYxuvnueee8zrnwoUL2LRpE+RyOVJSUvDv//7vwRoOZREQBNIUCgVGR0e95JEdDgeam5uxZcuWadLjlKXHT37yEzz77LO4cOHCYg+FEgSCGsz+8Y9/jK9+9avk94iICPJ/s9mMW2+9Fdu3b8eLL76IhoYGfOlLX4JWq8XXvva1YA6LEiIEw2AymdDT04OkpCRyTIhLrFixYjGGRgkwgi/93XffRVFREdXuWmYE1VBEREQgPj7e57H/+Z//gcPhwCuvvAKpVIrCwkLU1dXhF7/4BTUUywTP4jrA2ygYjUaIxeJFlyagBAaZTAar1YqIiAhqJJYhQf2LPvfcc9DpdFi1ahWef/55L0G4qqoqbN682avgaufOnWhqasLo6OiM17Tb7TCbzV4/lPDEU9cJ+Ew51mazobm5GRkZGXRSWSasX78eq1atwh133LHYQ6EEgaDtKL71rW9h9erViI6ORmVlJb7//e+jr68Pv/jFLwBMSjtkZGR4PUfQM+nv758xE+bZZ5/FM888E6xhUwKIsAjgOA4AcO7cOezYsQNtbW1wu9246667FnN4lACyYcOGxR4CJYjMazn3ve99b1qAeurPlStXAABPPfUUtmzZgpUrV+LrX/86fv7zn+PXv/71tFaY8+X73/8+TCYT+REKuSjhh1QqRWxsLNlJms1mcBwHk8mExMREqNVqn89zOBzo6upCX19fKIdLoVBmYF47iqeffhqPPfaY33MyMzN9Pl5RUQGXy4X29nbk5eUhPj4eAwMDXucIv88U1wAmfaG0ZebSQaVSwW63Y9WqVTh//jyAyUIik8nk8/zR0VH87ne/I722v/vd71LRQAplkZmXoYiJiUFMTMyCXqiurg4sy5JUyHXr1uGf/umf4HQ6iTLiwYMHkZeXRwuwlhEmkwnR0dFksm9uboZEIiG7i6kxiqNHjxIjAfh2UVIolNASlEhiVVUVfvWrX6G+vh7Xrl3D//zP/+A73/kOHnroIWIEvvCFL0AqleLLX/4yLl26hDfffBP/8R//gaeeeioYQ6IsElFRUTCbzdDr9RCJRLh48SKuXLkCh8NB3JSetLS0kP/r9XokJyeHcrgUCsUHQQlmy2Qy/PnPf8a//Mu/wG63IyMjA9/5zne8jIBGo8Enn3yCJ598EmVlZdDr9fjhD39IU2OXGStWrMC+fftw7do13HHHHaipqSGxh/Hx8Wnn79mzB/X19UhLS8Pq1aunZU5RKJTQE5Rv4erVq1FdXT3reStXrsSJEyeCMQRKmCDId1y8eBHx8fFeAWpfhiI3Nxe5ubkhGx+FQpkdmsROCSqe8YUzZ84AABEG7O7uXpQxUSiU+UENBSWoSCQSkmMvFEdqNBoAQEdHBynCo1Ao4Qs1FJSgs3btWqIFJBKJkJaWBmCyEO/AgQOkII9CoYQn1FBQgk5kZCRuu+02AMCaNWtIxbZIJEJNTQ1++9vfXnchJoVCCR40pYQSEsrLy9He3o7a2lpSiyO4nUwmE9V8olDCGPrtpIQEhmFw9913o6KiAv39/SSgrVQqsWnTJlJ0SaFQwg+6o6CEDKFpfFJSEmpra1FYWIhVq1Yt9rAoFMosUENBCTn5+fnIz89f7GFQKJQ5Ql1PFAqFQvELNRQUCoVC8Qs1FBQKhULxCzUUFAqFQvELNRQUCoVC8Qs1FBQKhULxCzUUFAqFQvELNRQUCoVC8Qs1FBQKhULxCzUUFAqFQvELNRQUCoVC8Qs1FBQKhULxCzUUFAqFQvELNRQUCoVC8Qs1FBQKhULxCzUUlLCF47jFHgKFQgE1FJQw5eDBg/jpT3+K+vr6xR4KhXLDQw0FJaxwu904c+YMKisrwXEcmpqaFntIFMoND22FSgkb7HY7fvazn8HlcgEARCIRysvLF3lUFAqFGgpKWHDlyhW8+eab5PeIiAjcfffdyMjIWMRRUSgUgBoKShgwODiIt956i/z+j//4j5DL5Ys4IgrFG5fLBYZhIBKJFnsoiwKNUVAWnaqqKpLh9NBDD1EjQZkVnudx7tw5DA0NheT1/vznP+Nf//Vf4Xa7Q/J64QbdUVAWlStXrqC+vh4pKSno6uqCWEw/kouJ2WzGqVOn0NLSAoVCgfz8fKxfvx4Mwyz20Ly4fPkyPvjgAwDAl7/8ZSQnJ3sd53keAwMDOH36NJKSklBWVnZd76G1tRUA0NXVhfT09AVfZ6lCv5WURcNsNuPdd99FQkICMjIy0NXVhaamJqSlpS320G5IWltb8Ze//AUMwyApKQl2ux2HDh2Cw+HALbfcEtTXPnnyJDo7O/GFL3xh1nOtVis++eQTxMbGwu12469//SueeOIJyGQyAJNG4t1330VDQwMAoK6uDiqVCvn5+V7X4XkefX19UCqV0Gg0mJiYgFQqhVQqxfDwMJqammC1WjE6Okqe09/fTw0FhRJKPvroI7Asi9TUVBw/fhxqtRolJSWLPawbErfbjTfffBPR0dFYu3YtpFIpgEm3YHNzM26++WawbPA81YcOHQIADAwMIC4uzu+577//Pux2O9avXw+e53H48GF88MEHuPnmm2EwGFBbW4uWlhasWrUKycnJOHv2LN59912cOnUKd999N/R6PXiex969e1FXVweGYaDRaGA0GiESiRAXF4fe3l6IxWLI5XLIZDLk5+ejv78f9fX1iI+Ph8Vigdlsht1uh8vlglQqhU6nQ05ODiQSSdDu02LB8DzPL/Ygrgez2QyNRgOTyYTIyMjFHg5ljvT29uLll19GWVkZmpqaEB0djcceeyzsXBw3AidPnsS5c+cwOjqKbdu2QavVkmN9fX2oqqpCWVkZtm7dCoVCAWCyan6hhsNut+P8+fMQiUTo6OiAwWBAf38/AECv1yMpKQkTExOIjIyE0WhEVlYWxGIxDAYDDAYDWltbUV5ejtTUVABAZ2cnampqyPU1Gg3y8/ORlJQEAHA4HGhqakJfXx9sNhtWr14Nl8uF2tpalJaWQiQSwWAwICYmBna7HcPDw4iLi0NaWppX8Hp4eBinTp3ySt+WSqVgWRZOpxMOhwNZWVl46KGHFnRfQs185k5qKCiLwokTJ3DixAkUFBTgwoULeOKJJxATE7PYw7ph4HkeDQ0N6OzsRG1tLRITE5GRkYH4+Php57a0tKC+vh5SqRSPPfYYtFotXnrpJURGRmLjxo3IzMycczaQ3W7HH/7wBwwPDwMAtFotIiIiEBUVhZiYGFy6dAkWiwUKhQI2mw0SiQTDw8NgWRYymQxyuRwRERFYs2aN16JifHwcNpsNcrkcarXa52s7nU40Njaip6cHHMchOzsbeXl587pvdrsddrsdcrkcEonEawxXr15FQ0MDfvCDHyyJXQU1FJSwp7a2Fvv27UNsbCxUKhUefvjhxR7SDYPT6cSHH36ICxcugGVZZGRkoKSkxO9uzmKxoLq6GlarFRERERgaGoJMJoPdbodMJkN0dDQqKir8ug4tFgvef/99tLa2YuvWrVCpVHMyMOPj45DL5WGf6DAwMICTJ09izZo12LFjB3HfhSvzmTvD+85Tli0RERHgeR48z8NoNILneep2CgAWiwUdHR3IycmZNrE6nU5cuHABp06dgtlsRnl5OZKSksCy7Kz3XqlUYuPGjWhoaIDNZsPWrVuh1WphMpnQ19eHpqYmVFdXz2goxsfH8fLLL8Nms6G8vHxei7qZdgjhRlxcHEpKSlBXV4erV69i48aNKCwshFKphNvthslkQnR09GIPc0FQQ0EJGTzP4+rVq5DJZBgcHIRIJEJeXh5OnDiBgwcPYseOHdRYXCd79+5FU1MTkpOT8aUvfYncT5PJhP/93//F4OAgEhMTUVZWBo1GM69rS6VSlJWVeT2m1Wqh1WqhVCpx9uxZjI+P+5zYDx06BLvdjm3btkGpVC78DYY52dnZSEhIwIULF/Dxxx/j448/Rm5uLmw2Gzo6OnDXXXdh1apViz3MeUMNBSVknDlzBvv37wcA6HQ6xMfHIzY2FitXrkRVVRVUKhU2bNiwyKNcuphMJmIkuru78eqrryI5ORllZWX4/e9/D7FYjO3bt8/bQMwFvV4PYDL4nZOT43XM5XLhypUryMjIWNZGQkClUmHdunWw2Wzo6elBR0cHbDYbpFIpPvjgA7jdbhQXF5N03qUANRSUkHH27FlER0djZGQEBoMB69atAwDk5ORgfHwcp06dwk033XRDyCQIocGZdlA8z8PhcIDjOMjlcr87LZ7n0dLSgpMnT0IsFmP16tWIiYlBd3c3qqqqSEbQjh07ghZkdTgcAEAmP47jcO3aNQwODhJ3lZCldKMgl8uRlZWFrKwsAJ9Vk+/btw8fffQRMjMz8cADDyyJwDc1FJSQYbPZkJKSAqvVCqvV6rWiSklJwbVr1zAwMIDExMRFHGVoOHDgAFpaWqDX67F161ZERERg3759GBkZgVQqxejoKMxmM4BJH31qaiq2bt0KnU7ndZ2xsTHs3bsXLS0tiIiIwPr16yGRSJCZmYnMzEw0NDSgra0NpaWlQZuQrFYrqqqqoFarERsbCwD49NNPUVVVBZZlERsbi02bNiEiIiIor79UYBgGZWVlyM3NxeDgIOrr63HgwAHs3Lkz7I0FNRSUkJOQkIBr165hYmKCTHxRUVEQiUS4du3asjYUQi5+XV0dgEl3kcPhgEwmw7Vr16BWq9HX14fExESsWLECDMNgZGQEbW1teP/995GVlQWj0QiO42AymdDR0QGJRIL169cjISFh2usVFxejqKgoqLGfy5cvw2q14lvf+hbkcjk4jsP58+eRlZU1azbVjUhERAQiIiLIfRobG8OePXsgkUjC1mBQQ0EJCTzPw263QywWIzo6Gm1tbRgcHCTuCJFIhKSkJNTU1GDDhg1LbnIRCsiKi4unjZ3neXR3d+PChQs4d+4cpFIpSkpKkJWVRQraAJBK4s7OTmRmZpKCtuTkZMTFxeHkyZPo7+9HREQEWJaFRCLB6tWrkZSU5DcVM9j3UnAVfvLJJ3jggQdw5coV4mpaan/HUJKTkwOVSoXq6mo8//zzACZddyzLIiEhASUlJT4/T4sBNRSUoMLzPN577z1cuXIFTqcTkZGR0Gg0RGfHMy1WmCSNRiOioqIWeeT+4TgOhw8fhslkQnZ2Nvbu3QtgMpee53k0NTXBZrMhMzMTg4ODGBwchEKhQF5eHvLy8sjkmpCQgKKiIqjVaiQmJoJhGGRnZ097vbi4OGzfvh0qlSrs6gkKCgrQ2toKiUQCm82Gffv2ISEhIez/huFAYmIidu3ahaGhIfA8D5vNBo7jMDQ0hHfffRc1NTW44447fBZChpLw+sRRFoXh4WFSnZuQkACdTgee5wOi7VNdXY0LFy5g5cqVYBgGsbGxRALB4XBgdHSU5JYL8hBWqzXsJ5nTp0+jsrISCoUCFy9eBADExsaisrISMpkMiYmJkMlkuHjxIqKiorBx40bExsZOWx0yDDPn6uBgZCsFAkE0r6ysDJcvX4bFYsHNN98cFivhpYBCoZgW6M/PzydxjNdeew1PPvnkotaTUENBwYkTJ3DhwgXyu1KphNVqxaOPPnrdSq59fX2IjIyEWCxGb28vYmNjMTg4SI6Pj48TQyGslK1W63W9ZrBxuVyoqalBcnIyCgoKcOXKFchkMhQVFcHhcEAikYBlWTgcDnR0dMxL4mIpYjKZAEzqd9XU1CAuLu6GSIMNNrGxsVizZg0OHz6MkZERaigoi8e1a9dIlaxUKoXD4YDFYgEwuWqeaihaW1vBMAwyMzPndP2CggI0NDTg3LlzAEDE3xITE9Hb2+vlW1cqlZBIJOjt7SUpheGGy+XCe++9B5PJhLKyMqjVaqxZs4Yc98zkkkql02oKliOZmZkYGhrCwYMHodFosHLlysUe0rKho6MDcrl8VkXdYEMNxQ3Of//3f5P/OxwOKJVKpKSkQKFQEGPAcRxcLhdEIhFef/11AMCjjz4KjuOQkpLilakxNjYGtVpN3A4rVqzAV7/6VbhcLmIs9Ho96urqoFQqSaEWALAsC5VK5aX/H040NzfjwIEDGB0dRXl5edi6gkKNWCzGhg0bwHEcGIahLqcAwXEcuru7sWbNmkUvzqOGYolRU1ODTz75BPfeey/y8/Nx8uRJTExMoKysDHa7HUqlcl7+/aSkJAwNDaG4uBgikQitra1oaWnBl770JTidTrz//vtobGyEy+Xy2l289tprAIDc3FysXbsWycnJMBgMePnll7Fy5UrExsaiqKgIGo0GCQkJqKmpwcDAgJec9IYNG6YFZrVaLXp6egJwpwJLXV0d3n//fcTExGDr1q3USPggmP0qbkT6+/tht9tRVFS02EMJjqE4evTojB2xzpw5g/LycrS3tyMjI2Pa8aqqKtx0003BGNayoLW1FS6XC3/5y18QHR2N0dFR8DyP6upqAJN58/feey94nsfRo0fBcRy2bds24/USExNhMpmQlpYGhmGQmJiIAwcO4OWXXwYw6Q7KzMyEy+XC6OgoioqKkJubC4PBgLGxMSKAxrIs8aEKqqTHjx/Hzp07UVdXh66uLiQlJWHNmjWIiYmZ0YctNIEJJ3iex5EjR5CcnIy1a9fSFTMl6LS3t6OxsRFxcXGL7nYCgmQo1q9fj76+Pq/H/vmf/xmHDh3y8ucCkxWchYWF5Peplac3In19fRgbG4NGo4HBYEBqaiqUSiW6u7tRXl6O2NhYnDhxAiMjI1i/fj0qKyvJc9va2vDLX/4SkZGR6O7uBgBkZGQgNTXVZ1rlihUrUFNTg+PHj2PlypWIiorC1q1bMTo6CplMhqioKJ8To16vh16vR2pqKiwWC3p7e9HZ2YktW7ZAq9WC4zgcO3YMH3zwATQaDTZv3jxrvwmr1Yq+vj5s3LjxOu9gYBFcb0NDQ6QXAYUSDDiOQ3t7O86fP4/c3Fxs27YtLBYmQTEUUqnUK+9XcGF885vfnPamBXE4CmAwGHDw4EE0NTXNeq5KpYLD4cD58+ehVCrhcrngcDhIBpHNZsP69etx8eJF/Pd//zckEgnuueceUu0rkJmZidtvvx3V1dU4d+4cbrnlFsjlcp9Vvr4QiUSIiIgg9QGej998881wuVwk7dUfLS0taGpqgkwmQ0VFxZxeO1SwLIuVK1eiurqaulcoQeXq1au4dOkSCgsLcc8994RNtlxIYhR79+6FwWDA448/Pu3YXXfdBZvNhtzcXHz3u9/FXXfd5fdaQocpAUEPZylhNpuJRr1Qwj84OIjW1lYoFAqsWbMG0dHRsFgsUKvVGB4eBsdx0Gg0YFkWRqMRFosFYrEYPM/D5XKBZVlERUVNM7osy6K2thYqlQp/+ctfoFQqcfPNNwOYlF5wu93Q6/XIz8/HqVOn0Nvbi+Tk5IC8z7lKElitVjQ0NGDFihXYsmXLnAxLqOB5HseOHUN1dTUKCgrCzi1GWT7Y7Xa0tLRg9erV2L1792IPx4uQGIo//vGP2Llzp9cEpFar8fOf/xwbNmwAy7J4++23cffdd+O9997zayyeffZZPPPMM6EYdsDheR5vvfUWGhsbkZiYCLPZDIvFAqVSCZVKhZKSEqSnp5NVhCCiplKpvK7j2dN4NuLi4nD77beD53kMDw+jra0NH3/8MSl+EzSGBIMb6i6BZrMZNTU1UCgU2L17d1i5dQwGAz788EO0t7ejsLAQK1asWOwhUZYpPM/j7NmzYBhmxvjuYjKvVqjf+9738G//9m9+z2lsbPT6QnV3dyMtLQ1/+ctfcN999/l97iOPPIK2tjacOHFixnN87ShSUlKWRCtUg8GA3/zmN0hKSsLw8DASEhKwYsWKaYYg2Ai9iD23tSaTCVarNSRuQEG+o7m5GcPDw9DpdPjc5z4XNi7IsbExnDp1ihiwVatWhUVAkbJ8GR0dxeHDh/H5z38eBQUFIXnNoLVCffrpp/HYY4/5PWdqIdarr74KnU43q0sJACoqKnDw4EG/58hkskXPKV4oQlZQTEzMomZ2+Vq1azSakKR8jo+Po6qqihj4e+65B/n5+YummsnzPAYHB3H16lUMDQ1hZGQEvb29EIvFWLFiBXJzc8PGT0xZvgwMDEAqlYbtrnVehiImJmbWzBVPeJ7Hq6++ikceeWROE0FdXd2cg6jhhtvt9juhCDLRAIjW0XLGbDajra0NPM/D1usnjQAAFwhJREFUYrGA4ziIxWIYjUaIxWI89thji64u2tTUhE8++QQjIyMQi8XQarWQy+VExTVcJZ8py4/x8XHExMSEbbJEUGMUhw8fRltbG77yla9MO/baa69BKpWS/rHvvPMOXnnlFfzhD38I5pCCwuDgIH73u99hzZo1yM7ORnd3N6xWK3bt2gW73Y4TJ07g9OnTiImJQUVFRdi4WIJJX18fWlpaAABZWVkQi8VwOp1IT0/Hhg0bFn1B0NzcjLfeegs6nQ4bNmxATEwM3TlQFg232x12qsCeBHVkf/zjH7F+/foZt1M/+clP0NHRQbb5b775Jj73uc8Fc0hBgeM4AJOtPs+ePQuZTAaHw4H29naYTCbwPI+CggLk5uaG7Yoh0CQnJ6OjowNjY2NwOBy45557Qh6L8YXNZsOhQ4dw9uxZxMfH3zCtVynhjVarRWNjI8bGxsKyE+C8gtnhyHwCMsFifHwcP//5z1FUVER0ktrb2zE4OAitVov09PQlG1e5HhwOBwwGA86ePYu8vDzce++9Abu22+3GmTNn0NnZCbfbjfLycr8CfEJnuYsXL4LneRQXFyMzMzMsipkoFLvdjg8//BB79uxBaWlpSF4zaMFsyiTd3d149913ER8fj9WrVyMjIwMKhQJDQ0PIysoCwzDIyMjwKVFyI8DzPC5cuIBr166R3VagDeWxY8dw4sQJUlvyv//7v9i5c6fPJIH+/n784Q9/gFQqRV5eHtLT08MqDZdCkclkiImJwUcffYSLFy/izjvvnFcafLChhmIBXLhwASMjI+A4Do2Njbjnnntw77334s0338Thw4dx880335A7CIHx8XG0tLRg3bp1iI2NhVgs9pJpuV5GR0dRWVmJnJwcFBcXA5j8mxw4cACFhYXTtu4tLS1gGAY7d+6kbiZK2LJmzRrU1NSgtbUV1dXVuO222xZ7SIQbw2EeYITCwYKCAqSkpGDv3r2Ij4/H1772NTgcDhw9ehSnT59GU1MT+vv7YTQa4Xa7F3nUoUPI6iooKEBpaSmKiooC6uI5deoUJBIJCgoKiKy1IB/S0dEx7XybzQaZTAaRSASn04mhoSF0dXWht7c3YGOiUBaC2+1GQ0MDKisrcfToUQwPD0+T3w8H6I5iARQXF+P8+fM4c+YM4uLi4HK50NnZiYKCAjz44IO4cOEChoeH0dTUBKfTCWBShbWoqAjJycnL3i+uVCohk8nw17/+FV//+tfn5eYxm83o7u6esejIZDKhrq4OK1as8MoSkcvlkMlkGBkZmfYcjUaDiYkJfPjhh3A4HPAMy91+++1hJRlCubFoa2tDc3MzsrKykJycjNLSUiQkJITdHEENxQJgGAYPPvgg9u/fj+7ubpSUlJBdRlpaGunbwHEczGYzqfQ9c+YMenp6lr2Mukwmw+bNm3Hw4EGcO3cO69evn9PzeJ7Hm2++id7eXtxxxx1eSsMOhwNXrlzB8ePHIZPJpnXA4zgOIpHIq2pfYOXKlXC5XHC73VCpVEhKSoLNZsOrr76KkZERJCUlXd8bplAWiCAPM5tqxWJDDcUCkUqls1absywLrVYLrVaLv/mbv0F1dTUOHDiAiYmJsEgVDSYRERHIzMzEwYMHcf78eSQnJ2PVqlVISUkhqyWe5/Gzn/0MFosFGo0GarWauIMaGxu9DMXrr7+Orq4u0vBIKIZzu93o6urC1atXYbVafU76MpkM69at83pM6MtdX1+PxMTEsFvBUZY/TqcTY2NjARPhDCbUUAQJnudhNpsREREBlmXR3t6O06dPQ6VS3RCBboZhUFpaitjYWAwMDKC1tRV1dXVITk7GnXfeibi4OLjdbtKfe3x8HCaTCVKpFCKRyEtbSZDZiImJIUHx7u5u9Pf3o7e3F06nEzk5Odi2bduMmkwGgwHNzc3o6+tDT08PDAYDACx64R/lxqWjowM8z4etbIcntI4igPzud7/D4OAg6RXhdDqRkJAAtVqN5uZm6HQ6rFmzhmg+3UjwPI/+/n40NDRgfHwchYWFKCoqgkQiwYEDB2AwGCCTyWC1WsHzPB588EHk5uaS51+6dAl79+6Fw+Egj+l0OhQWFqKkpIT04QAms6J6e3vhdrthMBjQ2NiIoaEhssPTaDTQ6XSIjY2l8QnKolFdXY2BgQF87nOf8+rlEirmM3dSQxFAjhw5guPHjwOY7CWt1Wpx9epV8DyPnJycRdc2Cgfcbjfa29tx9epVspuIiIhAfn4+SktLERMTA5PJhOjo6Gn3ym63w2QyYXh4GAaDgaS6arVaxMbGQqfTobKyEocPHyb1G0ITrcTERMTFxYW1TALlxsLhcODMmTMYGxvDt7/97ZBri1FDsYgMDw/j5ZdfBsdxWLly5Q1bdDcbPM/DZrPBaDRiYGAAvb29sFqtyM7OxpYtW6bFGtxuN5qbm3HhwgU0NTWB53mvxk3AZC8Ns9mMrKws5OfnQywWg2XZG944U8KXsbExHDp0CPn5+bj77rtDWudDDcUiMz4+jr1796Kvrw87d+5c7OEsCXieR3d3N9G7qaiowG233Qa32436+nocO3YMZrMZWq0WqampSE9Ph0QiAc/zZKfR09MDu92OioqKG0ZTi7L06e7uRk1NDRISEnD33XeHrIaCSngsMmq1GlKplLo55gHDMEhJSUFycjKam5tx+vRpuN1utLS0wGg0IikpCWvXrp3WM4NhGMjlcsjlctpciLIkSU5OhkKhwNmzZ/Hiiy9i3bp1WL9+fVjFz+hMFgRcLheuXr3qFYylzA2GYZCTk4OBgQGcPXsWMTEx2LZtW1jp3lAogUan02H79u24cuUKKisrUVVVhYKCAuzatSssDAY1FH5wOBwwm83Q6XTz8nOPjo7C6XTCYrGQVp/UTz53GIbB6tWr0dfXh8zMTOpGotwQiEQiFBYWIisrCx0dHWhsbIRCocCWLVsW3Vjc8IaioaEBHMchNjYWNTU1qKioQHNzM2pra2E0GgEAGRkZuPvuu+ccA1Gr1cjOzkZHRwfa2tqQkZGBkpISKkg3D1QqFbKzsxd7GBRKyJHL5cjLy4PNZsOZM2dw5swZxMTEYM+ePbDZbOju7iZxulAtQG/oYLbQmc4TlmXBcRzS0tKg1+shEonQ0NAAt9uN9evXIzs7GwkJCXNa5XIch5qaGuzfvx8Mw0Cj0SAiIgIikQgsy5IeudSAUCiUqfA8j/HxcYyMjKCpqQljY2MAJncebrcbWq0Wq1evRnl5+YJk82kwe46cPXsWALBlyxYMDQ0hPT0djY2NiIqKQnp6OjkvLi4OFy9exMmTJ3H06FHIZDIUFxejtLQU8fHxXhP96OgoxsfHERUVBZVKhYqKCqSnp6Orqws9PT0YGRmB3W7HwMAAOI5DSkpK2GRrUSiU8IFhGERERCAiIgLx8fHo7+9HVFQUIiIiYDAY0NbWhsOHD0MsFk+TqAk0N7ShcDqdUKlU0Ol00Ol0AEB6eHsilUqxevVqlJaWYnR0FP39/bh06RLOnj0LlmXJ8wVJcQGxWAytVovs7GwUFxdDrVajsbERzc3N4DgOCoVi2Ws+USiU60cmkxGxUQDQ6/XQ6/VwOp1obm6mhiKYsCw7L90lT6OQn5+PkZERmEwmmEwmGAwGREdHIz8/H0qlEhaLBRMTExgbG8P58+dRXV0NYLIoLDU1FXFxcdDpdDRQS6FQFkyo3NY3tKG4HliWJVbdF57pnKWlpRgaGoJSqQzLxukUCoXiD2ooQgDLsrQYjEKhLFmo34NCoVAofqGGgkKhUCh+oYaCQqFQKH6hhoJCoVAofqGGgkKhUCh+oYaCQqFQKH6hhoJCoVAofrnh6yhsNhtaW1sXexgUCoUybwRduWBzQxsKnU4Hu92OhoaGxR4KhUKhLIhQNEi7oQ3F+vXrsX79+sUeBoVCoYQ1NEZBoVAoFL9QQ0GhUCgUv1BDQaFQKBS/UENBoVAoFL9QQ0GhUCgUv1BDQaFQKBS/UENBoVAoFL9QQ0GhUCgUv1BDQaFQKBS/UENBoVAoFL9QQ0GhUCgUv1BDQaFQKBS/UENBoVAoFL9QQ0GhUCgUv1BDQaFQKBS/UENBoVAoFL9QQ0GhUCgUv1BDQaFQKBS/LPlWqDzPAwDMZvMij4RCoVCWDsKcKcyh/ljyhmJsbAwAkJKSssgjoVAolKXH2NgYNBqN33MYfi7mJIzhOA69vb2IiIgAwzCLPRyfmM1mpKSkoKurC5GRkYs9nBmh4ww8S2WsdJyBJ9zHyvM8xsbGkJiYCJb1H4VY8jsKlmWRnJy82MOYE5GRkWH5gZkKHWfgWSpjpeMMPOE81tl2EgI0mE2hUCgUv1BDQaFQKBS/UEMRAmQyGX70ox9BJpMt9lD8QscZeJbKWOk4A89SGutsLPlgNoVCoVCCC91RUCgUCsUv1FBQKBQKxS/UUFAoFArFL9RQUCgUCsUv1FBQKBQKxS/UUASQn/70p1i/fj2USiW0Wq3PcxiGmfbz5z//2euco0ePYvXq1ZDJZMjOzsaf/vSnkI+zs7MTd9xxB5RKJWJjY/EP//APcLlcIR2nL9LT06fdv+eee87rnAsXLmDTpk2Qy+VISUnBv//7vwd9XL544YUXkJ6eDrlcjoqKCpw5c2ZRxiHwL//yL9Pu3YoVK8hxm82GJ598EjqdDmq1Gvfddx8GBgZCMrbjx49j9+7dSExMBMMweO+997yO8zyPH/7wh0hISIBCocD27dvR3Nzsdc7IyAi++MUvIjIyElqtFl/+8pcxPj4e0nE+9thj0+7xbbfdFvJxBhpqKAKIw+HA5z//eTzxxBN+z3v11VfR19dHfu6++25yrK2tDXfccQduueUW1NXV4dvf/ja+8pWv4MCBAyEbp9vtxh133AGHw4HKykq89tpr+NOf/oQf/vCHIR3nTPz4xz/2un/f/OY3yTGz2Yxbb70VaWlpqK2txfPPP49/+Zd/wUsvvRT0cXny5ptv4qmnnsKPfvQjnDt3DiUlJdi5cycGBwdDOo6pFBYWet27kydPkmPf+c538MEHH+Ctt97CsWPH0Nvbi3vvvTck45qYmEBJSQleeOEFn8f//d//Hf/5n/+JF198EadPn4ZKpcLOnTths9nIOV/84hdx6dIlHDx4EB9++CGOHz+Or33tayEdJwDcdtttXvf4jTfe8DoeinEGHJ4ScF599VVeo9H4PAaAf/fdd2d87ne/+12+sLDQ67EHHniA37lzZwBHOMlM4/zoo494lmX5/v5+8tjvfvc7PjIykrfb7SEfpydpaWn8L3/5yxmP//a3v+WjoqLIOHme5//xH/+Rz8vLC+q4prJ27Vr+ySefJL+73W4+MTGRf/bZZ0M6Dk9+9KMf8SUlJT6PGY1GXiKR8G+99RZ5rLGxkQfAV1VVhWiEk0z9jnAcx8fHx/PPP/88ecxoNPIymYx/4403eJ7n+cuXL/MA+JqaGnLOxx9/zDMMw/f09IRknDzP848++ii/Z8+eGZ+zGOMMBHRHsQg8+eST0Ov1WLt2LV555RUvPfiqqips377d6/ydO3eiqqoqZOOrqqpCcXEx4uLivMZgNptx6dKlRR/nc889B51Oh1WrVuH555/3colVVVVh8+bNkEqlXuNqamrC6Oho0McGTO7Yamtrve4Py7LYvn17SP+OvmhubkZiYiIyMzPxxS9+EZ2dnQCA2tpaOJ1OrzGvWLECqampiz7mtrY29Pf3e41No9GgoqKCjK2qqgparRZr1qwh52zfvh0sy+L06dMhHe/Ro0cRGxuLvLw8PPHEEzAYDORYOI1zPix59dilxo9//GNs3boVSqUSn3zyCf7u7/4O4+Pj+Na3vgUA6O/v95qgASAuLg5msxlWqxUKhSLoY5xpDMKxxRznt771LaxevRrR0dGorKzE97//ffT19eEXv/gFGVdGRsaMY4+KigrKuDwZHh6G2+32eX+uXLkS9NefiYqKCvzpT39CXl4e+vr68Mwzz2DTpk24ePEi+vv7IZVKp8Ws4uLiyN98sRBe39f99Pw8xsbGeh0Xi8WIjo4O6fhvu+023HvvvcjIyEBrayt+8IMfYNeuXaiqqoJIJAqbcc4Xaihm4Xvf+x7+7d/+ze85jY2NXkFBf/zzP/8z+f+qVaswMTGB559/nhiKcBlnKJnP2J966iny2MqVKyGVSvG3f/u3ePbZZ5eFpk4w2bVrF/n/ypUrUVFRgbS0NPzlL38JyQLkRuBv/uZvyP+Li4uxcuVKZGVl4ejRo9i2bdsijuz6oIZiFp5++mk89thjfs/JzMxc8PUrKirwk5/8BHa7HTKZDPHx8dMyTQYGBhAZGen3yxzIccbHx0/L0BHGFB8fT/5dyDh9cT1jr6iogMvlQnt7O/Ly8mYcl+fYg41er4dIJPI5jlCNYS5otVrk5uaipaUFO3bsgMPhgNFo9NpVhMOYhdcfGBhAQkICeXxgYAClpaXknKmJAi6XCyMjI4s6/szMTOj1erS0tGDbtm1hO87ZoIZiFmJiYhATExO069fV1SEqKoqshtetW4ePPvrI65yDBw9i3bp1IRvnunXr8NOf/hSDg4Nkm3zw4EFERkaioKDgusbpi+sZe11dHViWJeNct24d/umf/glOpxMSiYSMKy8vLyRuJwCQSqUoKyvDoUOHSEYbx3E4dOgQvvGNb4RkDHNhfHwcra2tePjhh1FWVgaJRIJDhw7hvvvuAwA0NTWhs7NzQX/TQJKRkYH4+HgcOnSIGAaz2YzTp0+TzL1169bBaDSitrYWZWVlAIDDhw+D4zhUVFQs1tDR3d0Ng8FADFy4jnNWFjuavpzo6Ojgz58/zz/zzDO8Wq3mz58/z58/f54fGxvjeZ7n9+7dy7/88st8Q0MD39zczP/2t7/llUol/8Mf/pBc49q1a7xSqeT/4R/+gW9sbORfeOEFXiQS8fv37w/ZOF0uF19UVMTfeuutfF1dHb9//34+JiaG//73vx/ScU6lsrKS/+Uvf8nX1dXxra2t/Ouvv87HxMTwjzzyCDnHaDTycXFx/MMPP8xfvHiR//Of/8wrlUr+97//fdDG5Ys///nPvEwm4//0pz/xly9f5r/2ta/xWq3WK5Ms1Dz99NP80aNH+ba2Nv7UqVP89u3beb1ezw8ODvI8z/Nf//rX+dTUVP7w4cP82bNn+XXr1vHr1q0LydjGxsbI5xAA/4tf/II/f/4839HRwfM8zz/33HO8Vqvl33//ff7ChQv8nj17+IyMDN5qtZJr3HbbbfyqVav406dP8ydPnuRzcnL4Bx98MGTjHBsb4//+7/+er6qq4tva2vhPP/2UX716NZ+Tk8PbbLaQjjPQUEMRQB599FEewLSfI0eO8Dw/mQZXWlrKq9VqXqVS8SUlJfyLL77Iu91ur+scOXKELy0t5aVSKZ+Zmcm/+uqrIR0nz/N8e3s7v2vXLl6hUPB6vZ5/+umneafTGdJxTqW2tpavqKjgNRoNL5fL+fz8fP7//b//5/Ul5Hmer6+v5zdu3MjLZDI+KSmJf+6554I6rpn49a9/zaempvJSqZRfu3YtX11dvSjjEHjggQf4hIQEXiqV8klJSfwDDzzAt7S0kONWq5X/u7/7Oz4qKopXKpX8Pffcw/f19YVkbEeOHPH5mXz00Ud5np9Mkf3nf/5nPi4ujpfJZPy2bdv4pqYmr2sYDAb+wQcf5NVqNR8ZGck//vjjZPETinFaLBb+1ltv5WNiYniJRMKnpaXxX/3qV6ctDkIxzkBD+1FQKBQKxS+0joJCoVAofqGGgkKhUCh+oYaCQqFQKH6hhoJCoVAofqGGgkKhUCh+oYaCQqFQKH6hhoJCoVAofqGGgkKhUCh+oYaCQqFQKH6hhoJCoVAofqGGgkKhUCh++f8Af6f7+77Vxc0AAAAASUVORK5CYII=", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# print(region_a.spatial_extent)\n", "region_a.visualize_spatial_extent()" @@ -958,41 +273,11 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ATL06\n", - "['No temporal parameters set']\n", - "['03', '04', '05', '06', '07']\n", - "['0849', '0902']\n", - "006\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jovyan/icepyx/icepyx/core/query.py:1165: FutureWarning: The geopandas.dataset module is deprecated and will be removed in GeoPandas 1.0. You can get the original 'naturalearth_lowres' data from https://www.naturalearthdata.com/downloads/110m-cultural-vectors/.\n", - " world = gpd.read_file(gpd.datasets.get_path(\"naturalearth_lowres\"))\n" - ] - }, - { - "data": { - "image/png": "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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "print(region_a.product)\n", "print(region_a.temporal) # .dates, .start_time, .end_time can also be used for a piece of this information\n", @@ -1026,34 +311,11 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "ATL06\n", - "['2019-10-01', '2019-10-05']\n", - "002\n", - "Extent type: polygon\n", - "Source file: ./supporting_files/simple_test_poly.gpkg\n", - "Coordinates: [-55.0, 68.0, -55.0, 71.0, -48.0, 71.0, -48.0, 68.0, -55.0, 68.0]\n", - "Start date and time: 2019-10-01 03:30:00\n", - "End date and time: 2019-10-05 21:30:00\n" - ] - }, - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jovyan/icepyx/icepyx/core/validate_inputs.py:25: UserWarning: You are using an old version of this product\n", - " warnings.warn(\"You are using an old version of this product\")\n" - ] - } - ], + "outputs": [], "source": [ "region_a = ipx.Query(short_name, spatial_extent, date_range, \\\n", " start_time='03:30:00', end_time='21:30:00', version='002')\n", @@ -1076,7 +338,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "metadata": { "tags": [] }, @@ -1098,26 +360,11 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "title : ATLAS/ICESat-2 L3A Land Ice Height V006\n", - "short_name : ATL06\n", - "version_id : 006\n", - "time_start : 2018-10-14T00:00:00.000Z\n", - "coordinate_system : CARTESIAN\n", - "summary : This data set (ATL06) provides geolocated, land-ice surface heights (above the WGS 84 ellipsoid, ITRF2014 reference frame), plus ancillary parameters that can be used to interpret and assess the quality of the height estimates. The data were acquired by the Advanced Topographic Laser Altimeter System (ATLAS) instrument on board the Ice, Cloud and land Elevation Satellite-2 (ICESat-2) observatory.\n", - "orbit_parameters : {}\n", - "006\n" - ] - } - ], + "outputs": [], "source": [ "region_a.product_summary_info()\n", "print(region_a.latest_version())" @@ -1134,360 +381,12 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "metadata": { "scrolled": true, "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'feed': {'entry': [{'archive_center': 'NASA NSIDC DAAC',\n", - " 'association_details': {'services': [{'concept_id': 'S2472217299-NSIDC_CPRD'}],\n", - " 'tools': [{'concept_id': 'TL1977971361-NSIDC_ECS'},\n", - " {'concept_id': 'TL2682629857-NSIDC_CPRD'},\n", - " {'concept_id': 'TL2746943302-NSIDC_CPRD'}]},\n", - " 'associations': {'services': ['S2472217299-NSIDC_CPRD'],\n", - " 'tools': ['TL1977971361-NSIDC_ECS',\n", - " 'TL2682629857-NSIDC_CPRD',\n", - " 'TL2746943302-NSIDC_CPRD']},\n", - " 'boxes': ['-90 -180 90 180'],\n", - " 'browse_flag': False,\n", - " 'cloud_hosted': True,\n", - " 'consortiums': ['GEOSS', 'EOSDIS'],\n", - " 'coordinate_system': 'CARTESIAN',\n", - " 'data_center': 'NSIDC_CPRD',\n", - " 'dataset_id': 'ATLAS/ICESat-2 L3A Land Ice Height V005',\n", - " 'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False,\n", - " 'id': 'C2153572614-NSIDC_CPRD',\n", - " 'links': [{'href': 'https://search.earthdata.nasa.gov/search?q=ATL06+V005',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.005',\n", - " 'hreflang': 'en-US',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#'},\n", - " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.005',\n", - " 'hreflang': 'en-US',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#'}],\n", - " 'online_access_flag': True,\n", - " 'orbit_parameters': {'inclination_angle': '92.0',\n", - " 'number_of_orbits': '0.071428571',\n", - " 'period': '96.8',\n", - " 'start_circular_latitude': '0.0',\n", - " 'swath_width': '36.0'},\n", - " 'organizations': ['NASA NSIDC DAAC',\n", - " 'NASA/GSFC/EOS/ESDIS'],\n", - " 'original_format': 'ISO19115',\n", - " 'platforms': ['ICESat-2'],\n", - " 'processing_level_id': 'Level 3',\n", - " 'service_features': {'esi': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False},\n", - " 'harmony': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False},\n", - " 'opendap': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False}},\n", - " 'short_name': 'ATL06',\n", - " 'summary': 'This data set (ATL06) provides geolocated, '\n", - " 'land-ice surface heights (above the WGS 84 '\n", - " 'ellipsoid, ITRF2014 reference frame), plus '\n", - " 'ancillary parameters that can be used to '\n", - " 'interpret and assess the quality of the '\n", - " 'height estimates. The data were acquired by '\n", - " 'the Advanced Topographic Laser Altimeter '\n", - " 'System (ATLAS) instrument on board the Ice, '\n", - " 'Cloud and land Elevation Satellite-2 '\n", - " '(ICESat-2) observatory.',\n", - " 'time_start': '2018-10-14T00:00:00.000Z',\n", - " 'title': 'ATLAS/ICESat-2 L3A Land Ice Height V005',\n", - " 'version_id': '005'},\n", - " {'archive_center': 'NASA NSIDC DAAC',\n", - " 'association_details': {'services': [{'concept_id': 'S1977894169-NSIDC_ECS'},\n", - " {'concept_id': 'S1568899363-NSIDC_ECS',\n", - " 'data': {'order_option': 'OO2700493442-NSIDC_ECS'}},\n", - " {'concept_id': 'S2013515292-NSIDC_ECS',\n", - " 'data': {'order_option': 'OO2700528732-NSIDC_ECS'}},\n", - " {'concept_id': 'S2008499525-NSIDC_ECS'}],\n", - " 'tools': [{'concept_id': 'TL2000645101-NSIDC_ECS'},\n", - " {'concept_id': 'TL1977971361-NSIDC_ECS'},\n", - " {'concept_id': 'TL2012682515-NSIDC_ECS'},\n", - " {'concept_id': 'TL1977912846-NSIDC_ECS'},\n", - " {'concept_id': 'TL1956547654-NSIDC_ECS'},\n", - " {'concept_id': 'TL2011654705-NSIDC_ECS'},\n", - " {'concept_id': 'TL1956087574-NSIDC_ECS'},\n", - " {'concept_id': 'TL1952642907-NSIDC_ECS'},\n", - " {'concept_id': 'TL1994100033-NSIDC_ECS'}]},\n", - " 'associations': {'services': ['S1977894169-NSIDC_ECS',\n", - " 'S1568899363-NSIDC_ECS',\n", - " 'S2013515292-NSIDC_ECS',\n", - " 'S2008499525-NSIDC_ECS'],\n", - " 'tools': ['TL2000645101-NSIDC_ECS',\n", - " 'TL1977971361-NSIDC_ECS',\n", - " 'TL2012682515-NSIDC_ECS',\n", - " 'TL1977912846-NSIDC_ECS',\n", - " 'TL1956547654-NSIDC_ECS',\n", - " 'TL2011654705-NSIDC_ECS',\n", - " 'TL1956087574-NSIDC_ECS',\n", - " 'TL1952642907-NSIDC_ECS',\n", - " 'TL1994100033-NSIDC_ECS']},\n", - " 'boxes': ['-90 -180 90 180'],\n", - " 'browse_flag': False,\n", - " 'cloud_hosted': False,\n", - " 'consortiums': ['GEOSS', 'EOSDIS'],\n", - " 'coordinate_system': 'CARTESIAN',\n", - " 'data_center': 'NSIDC_ECS',\n", - " 'dataset_id': 'ATLAS/ICESat-2 L3A Land Ice Height V005',\n", - " 'has_formats': True,\n", - " 'has_spatial_subsetting': True,\n", - " 'has_temporal_subsetting': True,\n", - " 'has_transforms': False,\n", - " 'has_variables': True,\n", - " 'id': 'C2144439155-NSIDC_ECS',\n", - " 'links': [{'href': 'https://n5eil01u.ecs.nsidc.org/ATLAS/ATL06.005/',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://search.earthdata.nasa.gov/search?q=ATL06+V005',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://openaltimetry.org/',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://nsidc.org/data/data-access-tool/ATL06/versions/5/',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.005',\n", - " 'hreflang': 'en-US',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#'},\n", - " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.005',\n", - " 'hreflang': 'en-US',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#'}],\n", - " 'online_access_flag': True,\n", - " 'orbit_parameters': {'inclination_angle': '92.0',\n", - " 'number_of_orbits': '0.071428571',\n", - " 'period': '96.8',\n", - " 'start_circular_latitude': '0.0',\n", - " 'swath_width': '36.0'},\n", - " 'organizations': ['NASA NSIDC DAAC',\n", - " 'NASA/GSFC/EOS/ESDIS'],\n", - " 'original_format': 'ISO19115',\n", - " 'platforms': ['ICESat-2'],\n", - " 'processing_level_id': 'Level 3',\n", - " 'service_features': {'esi': {'has_formats': True,\n", - " 'has_spatial_subsetting': True,\n", - " 'has_temporal_subsetting': True,\n", - " 'has_transforms': False,\n", - " 'has_variables': True},\n", - " 'harmony': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False},\n", - " 'opendap': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False}},\n", - " 'short_name': 'ATL06',\n", - " 'summary': 'This data set (ATL06) provides geolocated, '\n", - " 'land-ice surface heights (above the WGS 84 '\n", - " 'ellipsoid, ITRF2014 reference frame), plus '\n", - " 'ancillary parameters that can be used to '\n", - " 'interpret and assess the quality of the '\n", - " 'height estimates. The data were acquired by '\n", - " 'the Advanced Topographic Laser Altimeter '\n", - " 'System (ATLAS) instrument on board the Ice, '\n", - " 'Cloud and land Elevation Satellite-2 '\n", - " '(ICESat-2) observatory.',\n", - " 'time_start': '2018-10-14T00:00:00.000Z',\n", - " 'title': 'ATLAS/ICESat-2 L3A Land Ice Height V005',\n", - " 'version_id': '005'},\n", - " {'archive_center': 'NASA NSIDC DAAC',\n", - " 'association_details': {'services': [{'concept_id': 'S2472217299-NSIDC_CPRD'}],\n", - " 'tools': [{'concept_id': 'TL1977971361-NSIDC_ECS'},\n", - " {'concept_id': 'TL2682629857-NSIDC_CPRD'},\n", - " {'concept_id': 'TL2746943302-NSIDC_CPRD'}]},\n", - " 'associations': {'services': ['S2472217299-NSIDC_CPRD'],\n", - " 'tools': ['TL1977971361-NSIDC_ECS',\n", - " 'TL2682629857-NSIDC_CPRD',\n", - " 'TL2746943302-NSIDC_CPRD']},\n", - " 'boxes': ['-90 -180 90 180'],\n", - " 'browse_flag': False,\n", - " 'cloud_hosted': True,\n", - " 'consortiums': ['GEOSS', 'EOSDIS'],\n", - " 'coordinate_system': 'CARTESIAN',\n", - " 'data_center': 'NSIDC_CPRD',\n", - " 'dataset_id': 'ATLAS/ICESat-2 L3A Land Ice Height V006',\n", - " 'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False,\n", - " 'id': 'C2670138092-NSIDC_CPRD',\n", - " 'links': [{'href': 'https://search.earthdata.nasa.gov/search?q=ATL06+V006',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.006',\n", - " 'hreflang': 'en-US',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#'},\n", - " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.006',\n", - " 'hreflang': 'en-US',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#'}],\n", - " 'online_access_flag': True,\n", - " 'orbit_parameters': {},\n", - " 'organizations': ['NASA NSIDC DAAC',\n", - " 'NASA/GSFC/EOS/ESDIS'],\n", - " 'original_format': 'ISO19115',\n", - " 'platforms': ['ICESat-2'],\n", - " 'processing_level_id': 'Level 3',\n", - " 'service_features': {'esi': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False},\n", - " 'harmony': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False},\n", - " 'opendap': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False}},\n", - " 'short_name': 'ATL06',\n", - " 'summary': 'This data set (ATL06) provides geolocated, '\n", - " 'land-ice surface heights (above the WGS 84 '\n", - " 'ellipsoid, ITRF2014 reference frame), plus '\n", - " 'ancillary parameters that can be used to '\n", - " 'interpret and assess the quality of the '\n", - " 'height estimates. The data were acquired by '\n", - " 'the Advanced Topographic Laser Altimeter '\n", - " 'System (ATLAS) instrument on board the Ice, '\n", - " 'Cloud and land Elevation Satellite-2 '\n", - " '(ICESat-2) observatory.',\n", - " 'time_start': '2018-10-14T00:00:00.000Z',\n", - " 'title': 'ATLAS/ICESat-2 L3A Land Ice Height V006',\n", - " 'version_id': '006'},\n", - " {'archive_center': 'NASA NSIDC DAAC',\n", - " 'association_details': {'services': [{'concept_id': 'S1977894169-NSIDC_ECS'},\n", - " {'concept_id': 'S1568899363-NSIDC_ECS',\n", - " 'data': {'order_option': 'OO2700493442-NSIDC_ECS'}},\n", - " {'concept_id': 'S2013515292-NSIDC_ECS',\n", - " 'data': {'order_option': 'OO2700528970-NSIDC_ECS'}}],\n", - " 'tools': [{'concept_id': 'TL1977971361-NSIDC_ECS'},\n", - " {'concept_id': 'TL1952642907-NSIDC_ECS'},\n", - " {'concept_id': 'TL2011654705-NSIDC_ECS'},\n", - " {'concept_id': 'TL2012682515-NSIDC_ECS'},\n", - " {'concept_id': 'TL1977912846-NSIDC_ECS'},\n", - " {'concept_id': 'TL2000645101-NSIDC_ECS'},\n", - " {'concept_id': 'TL1956087574-NSIDC_ECS'}]},\n", - " 'associations': {'services': ['S1977894169-NSIDC_ECS',\n", - " 'S1568899363-NSIDC_ECS',\n", - " 'S2013515292-NSIDC_ECS'],\n", - " 'tools': ['TL1977971361-NSIDC_ECS',\n", - " 'TL1952642907-NSIDC_ECS',\n", - " 'TL2011654705-NSIDC_ECS',\n", - " 'TL2012682515-NSIDC_ECS',\n", - " 'TL1977912846-NSIDC_ECS',\n", - " 'TL2000645101-NSIDC_ECS',\n", - " 'TL1956087574-NSIDC_ECS']},\n", - " 'boxes': ['-90 -180 90 180'],\n", - " 'browse_flag': False,\n", - " 'cloud_hosted': False,\n", - " 'consortiums': ['GEOSS', 'EOSDIS'],\n", - " 'coordinate_system': 'CARTESIAN',\n", - " 'data_center': 'NSIDC_ECS',\n", - " 'dataset_id': 'ATLAS/ICESat-2 L3A Land Ice Height V006',\n", - " 'has_formats': True,\n", - " 'has_spatial_subsetting': True,\n", - " 'has_temporal_subsetting': True,\n", - " 'has_transforms': False,\n", - " 'has_variables': True,\n", - " 'id': 'C2564427300-NSIDC_ECS',\n", - " 'links': [{'href': 'https://n5eil01u.ecs.nsidc.org/ATLAS/ATL06.006/',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://search.earthdata.nasa.gov/search?q=ATL06+V006',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://openaltimetry.org/',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://nsidc.org/data/data-access-tool/ATL06/versions/6/',\n", - " 'hreflang': 'en-US',\n", - " 'length': '0.0KB',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/data#'},\n", - " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.006',\n", - " 'hreflang': 'en-US',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/metadata#'},\n", - " {'href': 'https://doi.org/10.5067/ATLAS/ATL06.006',\n", - " 'hreflang': 'en-US',\n", - " 'rel': 'http://esipfed.org/ns/fedsearch/1.1/documentation#'}],\n", - " 'online_access_flag': True,\n", - " 'orbit_parameters': {},\n", - " 'organizations': ['NASA NSIDC DAAC',\n", - " 'NASA/GSFC/EOS/ESDIS'],\n", - " 'original_format': 'ISO19115',\n", - " 'platforms': ['ICESat-2'],\n", - " 'processing_level_id': 'Level 3',\n", - " 'service_features': {'esi': {'has_formats': True,\n", - " 'has_spatial_subsetting': True,\n", - " 'has_temporal_subsetting': True,\n", - " 'has_transforms': False,\n", - " 'has_variables': True},\n", - " 'harmony': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False},\n", - " 'opendap': {'has_formats': False,\n", - " 'has_spatial_subsetting': False,\n", - " 'has_temporal_subsetting': False,\n", - " 'has_transforms': False,\n", - " 'has_variables': False}},\n", - " 'short_name': 'ATL06',\n", - " 'summary': 'This data set (ATL06) provides geolocated, '\n", - " 'land-ice surface heights (above the WGS 84 '\n", - " 'ellipsoid, ITRF2014 reference frame), plus '\n", - " 'ancillary parameters that can be used to '\n", - " 'interpret and assess the quality of the '\n", - " 'height estimates. The data were acquired by '\n", - " 'the Advanced Topographic Laser Altimeter '\n", - " 'System (ATLAS) instrument on board the Ice, '\n", - " 'Cloud and land Elevation Satellite-2 '\n", - " '(ICESat-2) observatory.',\n", - " 'time_start': '2018-10-14T00:00:00.000Z',\n", - " 'title': 'ATLAS/ICESat-2 L3A Land Ice Height V006',\n", - " 'version_id': '006'}],\n", - " 'id': 'https://cmr.earthdata.nasa.gov:443/search/collections.json?short_name=ATL06',\n", - " 'title': 'ECHO dataset metadata',\n", - " 'updated': '2023-08-23T16:10:59.279Z'}}\n" - ] - } - ], + "outputs": [], "source": [ "region_a.product_all_info()" ] @@ -1504,25 +403,11 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'short_name': 'ATL06',\n", - " 'version': '002',\n", - " 'temporal': '2019-10-01T03:30:00Z,2019-10-05T21:30:00Z',\n", - " 'polygon': '-55.0,68.0,-48.0,68.0,-48.0,71.0,-55.0,71.0,-55.0,68.0'}" - ] - }, - "execution_count": 16, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "#build and view the parameters that will be submitted in our query\n", "region_a.CMRparams" @@ -1543,29 +428,11 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "ename": "AssertionError", - "evalue": "Your search returned no results; try different search parameters", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "File \u001b[0;32m~/icepyx/icepyx/core/query.py:951\u001b[0m, in \u001b[0;36mQuery.avail_granules\u001b[0;34m(self, ids, cycles, tracks, cloud)\u001b[0m\n\u001b[1;32m 950\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 951\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgranules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mavail\u001b[49m\n\u001b[1;32m 952\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mAttributeError\u001b[39;00m:\n", - "\u001b[0;31mAttributeError\u001b[0m: 'Granules' object has no attribute 'avail'", - "\nDuring handling of the above exception, another exception occurred:\n", - "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[17], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m#search for available granules and provide basic summary info about them\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mregion_a\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mavail_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/icepyx/icepyx/core/query.py:953\u001b[0m, in \u001b[0;36mQuery.avail_granules\u001b[0;34m(self, ids, cycles, tracks, cloud)\u001b[0m\n\u001b[1;32m 951\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgranules\u001b[38;5;241m.\u001b[39mavail\n\u001b[1;32m 952\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mAttributeError\u001b[39;00m:\n\u001b[0;32m--> 953\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgranules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_avail\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mCMRparams\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreqparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 955\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ids \u001b[38;5;129;01mor\u001b[39;00m cycles \u001b[38;5;129;01mor\u001b[39;00m tracks \u001b[38;5;129;01mor\u001b[39;00m cloud:\n\u001b[1;32m 956\u001b[0m \u001b[38;5;66;03m# list of outputs in order of ids, cycles, tracks, cloud\u001b[39;00m\n\u001b[1;32m 957\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m granules\u001b[38;5;241m.\u001b[39mgran_IDs(\n\u001b[1;32m 958\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgranules\u001b[38;5;241m.\u001b[39mavail,\n\u001b[1;32m 959\u001b[0m ids\u001b[38;5;241m=\u001b[39mids,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 962\u001b[0m cloud\u001b[38;5;241m=\u001b[39mcloud,\n\u001b[1;32m 963\u001b[0m )\n", - "File \u001b[0;32m~/icepyx/icepyx/core/granules.py:251\u001b[0m, in \u001b[0;36mGranules.get_avail\u001b[0;34m(self, CMRparams, reqparams, cloud)\u001b[0m\n\u001b[1;32m 247\u001b[0m \u001b[38;5;66;03m# Collect results\u001b[39;00m\n\u001b[1;32m 248\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mavail\u001b[38;5;241m.\u001b[39mextend(results[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfeed\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mentry\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m 250\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m (\n\u001b[0;32m--> 251\u001b[0m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mavail) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m 252\u001b[0m ), \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mYour search returned no results; try different search parameters\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", - "\u001b[0;31mAssertionError\u001b[0m: Your search returned no results; try different search parameters" - ] - } - ], + "outputs": [], "source": [ "#search for available granules and provide basic summary info about them\n", "region_a.avail_granules()" @@ -1573,25 +440,11 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "ename": "AssertionError", - "evalue": "Your data object has no granules associated with it", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[18], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m#get a list of granule IDs for the available granules\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mregion_a\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mavail_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43mids\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43;01mTrue\u001b[39;49;00m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/icepyx/icepyx/core/query.py:957\u001b[0m, in \u001b[0;36mQuery.avail_granules\u001b[0;34m(self, ids, cycles, tracks, cloud)\u001b[0m\n\u001b[1;32m 953\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgranules\u001b[38;5;241m.\u001b[39mget_avail(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mCMRparams, \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreqparams)\n\u001b[1;32m 955\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m ids \u001b[38;5;129;01mor\u001b[39;00m cycles \u001b[38;5;129;01mor\u001b[39;00m tracks \u001b[38;5;129;01mor\u001b[39;00m cloud:\n\u001b[1;32m 956\u001b[0m \u001b[38;5;66;03m# list of outputs in order of ids, cycles, tracks, cloud\u001b[39;00m\n\u001b[0;32m--> 957\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mgranules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgran_IDs\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 958\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mgranules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mavail\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 959\u001b[0m \u001b[43m \u001b[49m\u001b[43mids\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mids\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 960\u001b[0m \u001b[43m \u001b[49m\u001b[43mcycles\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcycles\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 961\u001b[0m \u001b[43m \u001b[49m\u001b[43mtracks\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mtracks\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 962\u001b[0m \u001b[43m \u001b[49m\u001b[43mcloud\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mcloud\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 963\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 964\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 965\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m granules\u001b[38;5;241m.\u001b[39minfo(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mgranules\u001b[38;5;241m.\u001b[39mavail)\n", - "File \u001b[0;32m~/icepyx/icepyx/core/granules.py:59\u001b[0m, in \u001b[0;36mgran_IDs\u001b[0;34m(grans, ids, cycles, tracks, dates, cloud)\u001b[0m\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mgran_IDs\u001b[39m(grans, ids\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, cycles\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, tracks\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, dates\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m, cloud\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m):\n\u001b[1;32m 39\u001b[0m \u001b[38;5;250m \u001b[39m\u001b[38;5;124;03m\"\"\"\u001b[39;00m\n\u001b[1;32m 40\u001b[0m \u001b[38;5;124;03m Returns a list of granule information for each granule dictionary in the input list of granule dictionaries.\u001b[39;00m\n\u001b[1;32m 41\u001b[0m \u001b[38;5;124;03m Granule info may be from a list of those available from NSIDC (for ordering/download)\u001b[39;00m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 57\u001b[0m \u001b[38;5;124;03m Return a a list of AWS s3 urls for the available granules in the granule dictionary.\u001b[39;00m\n\u001b[1;32m 58\u001b[0m \u001b[38;5;124;03m \"\"\"\u001b[39;00m\n\u001b[0;32m---> 59\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(grans) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mYour data object has no granules associated with it\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 60\u001b[0m \u001b[38;5;66;03m# regular expression for extracting parameters from file names\u001b[39;00m\n\u001b[1;32m 61\u001b[0m rx \u001b[38;5;241m=\u001b[39m re\u001b[38;5;241m.\u001b[39mcompile(\n\u001b[1;32m 62\u001b[0m \u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m(ATL\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(-\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)?_(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{4}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 63\u001b[0m \u001b[38;5;124mr\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)_(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{4}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)_(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{3}\u001b[39;00m\u001b[38;5;124m)_(\u001b[39m\u001b[38;5;124m\\\u001b[39m\u001b[38;5;124md\u001b[39m\u001b[38;5;132;01m{2}\u001b[39;00m\u001b[38;5;124m)(.*?).(.*?)$\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 64\u001b[0m )\n", - "\u001b[0;31mAssertionError\u001b[0m: Your data object has no granules associated with it" - ] - } - ], + "outputs": [], "source": [ "#get a list of granule IDs for the available granules\n", "region_a.avail_granules(ids=True)" @@ -1599,23 +452,12 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "metadata": { "scrolled": true, "tags": [] }, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 19, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "#print detailed information about the returned search results\n", "region_a.granules.avail" @@ -1628,7 +470,7 @@ }, "source": [ "### Log in to NASA Earthdata\n", - "When downloading data from NSIDC, all users must login using a valid (free) Earthdata account. The process of authenticating is handled by icepyx by creating and handling the required authentication to interface with the data at the DAAC (including ordering and download). Authentication is completed as login-protected features are accessed. In order to allow icepyx to login for us we still have to make sure that we have made our Earthdata credentials available for icepyx to find.\n", + "When downloading data from NSIDC, all users must login using a valid (free) Earthdata account. The process of authenticating is handled by icepyx by creating and handling the required authentication to interface with the data at the DAAC (including ordering and download). Authentication is completed as login-protected featuers are accessed. In order to allow icepyx to login for us we still have to make sure that we have made our Earthdata credentials available for icepyx to find.\n", "\n", "There are multiple ways to provide your Earthdata credentials via icepyx. Behind the scenes, icepyx is using the [earthaccess library](https://nsidc.github.io/earthaccess/). The [earthaccess documentation](https://nsidc.github.io/earthaccess/tutorials/restricted-datasets/#auth) automatically tries three primary mechanisms for logging in, all of which are supported by icepyx:\n", "- with `EARTHDATA_USERNAME` and `EARTHDATA_PASSWORD` environment variables (these are the same as the ones you might have set for icepyx previously)\n", @@ -1643,13 +485,9 @@ }, "source": [ "```{admonition} Important Authentication Update\n", -<<<<<<< Updated upstream - "Previously, icepyx required you to explicitly use the `earthdata_login()` function to login. Running this function is no longer required, but it is still available for backwards compatibility. Note that the function no longer requires any (e.g. email, user ID) inputs.\n", -======= - "Previously, icepyx required you to explicitly use the `earthdata_login()` function to login. Running this function is no longer required, but it is still available for backwards compatibility. \n", + "Previously, icepyx required you to explicitly use the `.earthdata_login()` function to login. Running this function is no longer required, as icepyx will call the login function as needed. The user will still need to provide their credentials using one of the three methods decribed above. The `.earthdata_login()` function is still available for backwards compatibility.\n", "\n", "If you do choose to use the `earthdata_login()`, you will also note that certain inputs, such as `earthdata_uid` and `email`, are no longer required. e.g. `region_a.earthdata_login(earthdata_uid, email)` becomes `region_a.earthdata_login()`\n", ->>>>>>> Stashed changes "```" ] }, @@ -1679,19 +517,11 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "{'page_size': 2000}\n" - ] - } - ], + "outputs": [], "source": [ "print(region_a.reqparams)\n", "# region_a.reqparams['page_size'] = 9\n", @@ -1700,9 +530,7 @@ }, { "cell_type": "markdown", - "metadata": { - "user_expressions": [] - }, + "metadata": {}, "source": [ "#### Subsetting\n", "\n", @@ -1724,32 +552,18 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "data": { - "text/plain": [ - "{'time': '2019-10-01T03:30:00,2019-10-05T21:30:00',\n", - " 'Boundingshape': '{\"type\":\"FeatureCollection\",\"features\":[{\"id\":\"0\",\"type\":\"Feature\",\"properties\":{},\"geometry\":{\"type\":\"Polygon\",\"coordinates\":[[[-55.0,68.0],[-48.0,68.0],[-48.0,71.0],[-55.0,71.0],[-55.0,68.0]]]},\"bbox\":[-55.0,68.0,-48.0,71.0]}],\"bbox\":[-55.0,68.0,-48.0,71.0]}'}" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "region_a.subsetparams()" ] }, { "cell_type": "markdown", - "metadata": { - "user_expressions": [] - }, + "metadata": {}, "source": [ "### Place the order\n", "Then, we can send the order to NSIDC using the order_granules function. Information about the granules ordered and their status will be printed automatically. Status information can also be emailed to the address associated with your EarthData account when the `email` kwarg is set to `True`. Additional information on the order, including request URLs, can be viewed by setting the optional keyword input 'verbose' to True." @@ -1757,36 +571,11 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": null, "metadata": { "tags": [] }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "EARTHDATA_USERNAME and EARTHDATA_PASSWORD are not set in the current environment, try setting them or use a different strategy (netrc, interactive)\n", - "You're now authenticated with NASA Earthdata Login\n", - "Using token with expiration date: 10/13/2023\n", - "Using .netrc file for EDL\n" - ] - }, - { - "ename": "AssertionError", - "evalue": "Your search returned no results; try different search parameters", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAssertionError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[22], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mregion_a\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43morder_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;66;03m# region_a.order_granules(verbose=True, subset=False, email=False)\u001b[39;00m\n", - "File \u001b[0;32m~/icepyx/icepyx/core/query.py:1062\u001b[0m, in \u001b[0;36mQuery.order_granules\u001b[0;34m(self, verbose, subset, email, **kwargs)\u001b[0m\n\u001b[1;32m 1051\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39mplace_order(\n\u001b[1;32m 1052\u001b[0m tempCMRparams,\n\u001b[1;32m 1053\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreqparams,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1058\u001b[0m geom_filepath\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_spatial\u001b[38;5;241m.\u001b[39m_geom_file,\n\u001b[1;32m 1059\u001b[0m )\n\u001b[1;32m 1061\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[0;32m-> 1062\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_granules\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mplace_order\u001b[49m\u001b[43m(\u001b[49m\n\u001b[1;32m 1063\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mCMRparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1064\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mreqparams\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1065\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msubsetparams\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1066\u001b[0m \u001b[43m \u001b[49m\u001b[43mverbose\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1067\u001b[0m \u001b[43m \u001b[49m\u001b[43msubset\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1068\u001b[0m \u001b[43m \u001b[49m\u001b[43msession\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43msession\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1069\u001b[0m \u001b[43m \u001b[49m\u001b[43mgeom_filepath\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_spatial\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_geom_file\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 1070\u001b[0m \u001b[43m \u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/icepyx/icepyx/core/granules.py:315\u001b[0m, in \u001b[0;36mGranules.place_order\u001b[0;34m(self, CMRparams, reqparams, subsetparams, verbose, subset, session, geom_filepath)\u001b[0m\n\u001b[1;32m 309\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 310\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mDon\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt forget to log in to Earthdata using query.earthdata_login()\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 311\u001b[0m )\n\u001b[1;32m 313\u001b[0m base_url \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mhttps://n5eil02u.ecs.nsidc.org/egi/request\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[0;32m--> 315\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mget_avail\u001b[49m\u001b[43m(\u001b[49m\u001b[43mCMRparams\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mreqparams\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 317\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m subset \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mFalse\u001b[39;00m:\n\u001b[1;32m 318\u001b[0m request_params \u001b[38;5;241m=\u001b[39m apifmt\u001b[38;5;241m.\u001b[39mcombine_params(\n\u001b[1;32m 319\u001b[0m CMRparams, reqparams, {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124magent\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mNO\u001b[39m\u001b[38;5;124m\"\u001b[39m}\n\u001b[1;32m 320\u001b[0m )\n", - "File \u001b[0;32m~/icepyx/icepyx/core/granules.py:251\u001b[0m, in \u001b[0;36mGranules.get_avail\u001b[0;34m(self, CMRparams, reqparams, cloud)\u001b[0m\n\u001b[1;32m 247\u001b[0m \u001b[38;5;66;03m# Collect results\u001b[39;00m\n\u001b[1;32m 248\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mavail\u001b[38;5;241m.\u001b[39mextend(results[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mfeed\u001b[39m\u001b[38;5;124m\"\u001b[39m][\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mentry\u001b[39m\u001b[38;5;124m\"\u001b[39m])\n\u001b[1;32m 250\u001b[0m \u001b[38;5;28;01massert\u001b[39;00m (\n\u001b[0;32m--> 251\u001b[0m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mavail) \u001b[38;5;241m>\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m 252\u001b[0m ), \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mYour search returned no results; try different search parameters\u001b[39m\u001b[38;5;124m\"\u001b[39m\n", - "\u001b[0;31mAssertionError\u001b[0m: Your search returned no results; try different search parameters" - ] - } - ], + "outputs": [], "source": [ "region_a.order_granules()\n", "# region_a.order_granules(verbose=True, subset=False, email=False)" @@ -1833,27 +622,13 @@ "* notebook contributors: Amy Steiker and Tyler Sutterley\n", "* source material: [NSIDC Data Access Notebook](https://github.com/ICESAT-2HackWeek/ICESat2_hackweek_tutorials/tree/master/03_NSIDCDataAccess_Steiker) by Amy Steiker and Bruce Wallin and [2020 Hackweek Data Access Notebook](https://github.com/ICESAT-2HackWeek/2020_ICESat-2_Hackweek_Tutorials/blob/main/06-07.Data_Access/02-Data_Access_rendered.ipynb) by Jessica Scheick and Amy Steiker" ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "icepyx-dev", "language": "python", - "name": "python3" + "name": "icepyx-dev" }, "language_info": { "codemirror_mode": { @@ -1865,7 +640,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.10" + "version": "3.11.4" } }, "nbformat": 4, From 24f6a42df3b06bf93e2f16e90434a70aef5d4b1c Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 29 Aug 2023 15:58:03 +0000 Subject: [PATCH 41/63] delete is2cat and references --- icepyx/core/is2cat.py | 178 ------------------------------------------ icepyx/core/read.py | 78 +++++++++++------- 2 files changed, 51 insertions(+), 205 deletions(-) delete mode 100644 icepyx/core/is2cat.py diff --git a/icepyx/core/is2cat.py b/icepyx/core/is2cat.py deleted file mode 100644 index f4e66a7bf..000000000 --- a/icepyx/core/is2cat.py +++ /dev/null @@ -1,178 +0,0 @@ -from intake.catalog import Catalog - -# Need to post on intake's page to see if this would be a useful contribution... -# https://github.com/intake/intake/blob/0.6.4/intake/source/utils.py#L216 -def _pattern_to_glob(pattern): - """ - Adapted from intake.source.utils.path_to_glob to convert a path as pattern into a glob style path - that uses the pattern's indicated number of '?' instead of '*' where an int was specified. - - Returns pattern if pattern is not a string. - - Parameters - ---------- - pattern : str - Path as pattern optionally containing format_strings - - Returns - ------- - glob_path : str - Path with int format strings replaced with the proper number of '?' and '*' otherwise. - - Examples - -------- - >>> _pattern_to_glob('{year}/{month}/{day}.csv') - '*/*/*.csv' - >>> _pattern_to_glob('{year:4}/{month:2}/{day:2}.csv') - '????/??/??.csv' - >>> _pattern_to_glob('data/{year:4}{month:02}{day:02}.csv') - 'data/????????.csv' - >>> _pattern_to_glob('data/*.csv') - 'data/*.csv' - """ - from string import Formatter - - if not isinstance(pattern, str): - return pattern - - fmt = Formatter() - glob_path = "" - # prev_field_name = None - for literal_text, field_name, format_specs, _ in fmt.parse(format_string=pattern): - glob_path += literal_text - if field_name and (glob_path != "*"): - try: - glob_path += "?" * int(format_specs) - except ValueError: - glob_path += "*" - # alternatively, you could use bits=utils._get_parts_of_format_string(resolved_string, literal_texts, format_specs) - # and then use len(bits[i]) to get the length of each format_spec - # print(glob_path) - return glob_path - - -def build_catalog( - data_source, - path_pattern, - source_type, - grp_paths=None, - grp_path_params=None, - extra_engine_kwargs=None, - **kwargs -): - """ - Build a general Intake catalog for reading in ICESat-2 data. - This function is used by the read class object to create catalogs from lists of ICESat-2 variables. - - Parameters - ---------- - data_source : string - A string with a full file path or full directory path to ICESat-2 hdf5 (.h5) format files. - Files within a directory must have a consistent filename pattern that includes the "ATL??" data product name. - Files must all be within a single directory. - - path_pattern : string - String that shows the filename pattern as required for Intake's path_as_pattern argument. - - source_type : string - String to use as the Local Catalog Entry name. - - grp_paths : str, default None - Variable paths to load. - Can include general parameter names, which must be contained within double curly brackets and further - described in `grp_path_params`. - Default list based on data product of provided files. - If multiple data products are included in the files, the default list will be for the product of the first file. - This may result in errors during read-in if all files do not have the same variable paths. - - grp_path_params : [dict], default None - List of dictionaries with a keyword for each parameter name specified in the `grp_paths` string. - Each parameter keyword should contain a dictionary with the acceptable keyword-value pairs for the driver being used. - - **kwargs : - Keyword arguments to be passed through to `intake.catalog.Catalog.from_dict()`. - Keywords needed to override default inputs include: - - `source_args_dict` # highest level source information; keys include: "urlpath", "path_as_pattern", driver-specific ("xarray_kwargs" is default) - - `metadata_dict` - - `source_dict` # individual source entry information (default is supplied by data object; "name", "description", "driver", "args") - - `defaults_dict` # catalog "name", "description", "metadata", "entries", etc. - - Returns - ------- - intake.catalog.Catalog object - - See Also - -------- - read.Read - - """ - from intake.catalog.local import LocalCatalogEntry, UserParameter - import intake_xarray - - import icepyx.core.APIformatting as apifmt - - assert ( - grp_paths - ), "You must enter a variable path or you will not be able to read in any data." - - # generalize this/make it so the [engine] values can be entered as kwargs... - engine_key = "xarray_kwargs" - xarray_kwargs_dict = {"engine": "h5netcdf", "group": grp_paths} - if extra_engine_kwargs: - for key in extra_engine_kwargs.keys(): - xarray_kwargs_dict[key] = extra_engine_kwargs[key] - - source_args_dict = { - "urlpath": data_source, - "path_as_pattern": path_pattern, - engine_key: xarray_kwargs_dict, - } - - metadata_dict = {"version": 1} - - source_dict = { - "name": source_type, - "description": "", - "driver": "intake_xarray.netcdf.NetCDFSource", # NOTE: this must be a string or the catalog cannot be imported after saving - "args": source_args_dict, - } - - if grp_path_params: - source_dict = apifmt.combine_params( - source_dict, - {"parameters": [UserParameter(**params) for params in grp_path_params]}, - ) - - # NOTE: LocalCatalogEntry has some required positional args (name, description, driver) - # I tried doing this generally with *source_dict after the positional args (instead of as part of the if) - # but apparently I don't quite get something about passing dicts with * and ** and couldn't make it work - local_cat_source = { - source_type: LocalCatalogEntry( - name=source_dict.pop("name"), - description=source_dict.pop("description"), - driver=source_dict.pop("driver"), - parameters=source_dict.pop("parameters"), - args=source_dict.pop("args"), - ) - } - - else: - local_cat_source = { - source_type: LocalCatalogEntry( - name=source_dict.pop("name"), - description=source_dict.pop("description"), - driver=source_dict.pop("driver"), - args=source_dict.pop("args"), - ) - } - - defaults_dict = { - "name": "IS2-hdf5-icepyx-intake-catalog", - "description": "an icepyx-generated catalog for creating local ICESat-2 intake entries", - "metadata": metadata_dict, - "entries": local_cat_source, - } - - build_cat_dict = apifmt.combine_params(defaults_dict, kwargs) - - return Catalog.from_dict(**build_cat_dict) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index 5860e32dc..c4c10b296 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -6,7 +6,6 @@ import xarray as xr import h5py -import icepyx.core.is2cat as is2cat import icepyx.core.is2ref as is2ref from icepyx.core.variables import Variables as Variables from icepyx.core.variables import list_of_dict_vals @@ -207,6 +206,56 @@ def _run_fast_scandir(dir, fn_glob): return subfolders, files +# Need to post on intake's page to see if this would be a useful contribution... +# https://github.com/intake/intake/blob/0.6.4/intake/source/utils.py#L216 +def _pattern_to_glob(pattern): + """ + Adapted from intake.source.utils.path_to_glob to convert a path as pattern into a glob style path + that uses the pattern's indicated number of '?' instead of '*' where an int was specified. + + Returns pattern if pattern is not a string. + + Parameters + ---------- + pattern : str + Path as pattern optionally containing format_strings + + Returns + ------- + glob_path : str + Path with int format strings replaced with the proper number of '?' and '*' otherwise. + + Examples + -------- + >>> _pattern_to_glob('{year}/{month}/{day}.csv') + '*/*/*.csv' + >>> _pattern_to_glob('{year:4}/{month:2}/{day:2}.csv') + '????/??/??.csv' + >>> _pattern_to_glob('data/{year:4}{month:02}{day:02}.csv') + 'data/????????.csv' + >>> _pattern_to_glob('data/*.csv') + 'data/*.csv' + """ + from string import Formatter + + if not isinstance(pattern, str): + return pattern + + fmt = Formatter() + glob_path = "" + # prev_field_name = None + for literal_text, field_name, format_specs, _ in fmt.parse(format_string=pattern): + glob_path += literal_text + if field_name and (glob_path != "*"): + try: + glob_path += "?" * int(format_specs) + except ValueError: + glob_path += "*" + # alternatively, you could use bits=utils._get_parts_of_format_string(resolved_string, literal_texts, format_specs) + # and then use len(bits[i]) to get the length of each format_spec + # print(glob_path) + return glob_path + # To do: test this class and functions therein class Read: @@ -322,28 +371,6 @@ def __init__( # ---------------------------------------------------------------------- # Properties - @property - def is2catalog(self): - """ - Print a generic ICESat-2 Intake catalog. - This catalog does not specify groups, so it cannot be used to read in data. - - """ - if not hasattr(self, "_is2catalog") and hasattr(self, "_catalog_path"): - from intake import open_catalog - - self._is2catalog = open_catalog(self._catalog_path) - - else: - self._is2catalog = is2cat.build_catalog( - self.data_source, - self._pattern, - self._source_type, - grp_paths="/paths/to/variables", - ) - - return self._is2catalog - # I cut and pasted this directly out of the Query class - going to need to reconcile the _source/file stuff there @property @@ -378,7 +405,7 @@ def _check_source_for_pattern(source, filename_pattern): """ Check that the entered data source contains files that match the input filename_pattern """ - glob_pattern = is2cat._pattern_to_glob(filename_pattern) + glob_pattern = _pattern_to_glob(filename_pattern) if os.path.isdir(source): _, filelist = _run_fast_scandir(source, glob_pattern) @@ -609,9 +636,6 @@ def load(self): All items in the wanted variables list will be loaded from the files into memory. If you do not provide a wanted variables list, a default one will be created for you. - - If you would like to use the Intake catalog you provided to read in a single data variable, - simply call Intake's `read()` function on the is2catalog property (e.g. `reader.is2catalog.read()`). """ # todo: From b13b8473644589445c79144f6e53a21b7447c383 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Wed, 30 Aug 2023 20:06:14 +0000 Subject: [PATCH 42/63] remove extra comments --- icepyx/core/read.py | 33 ++++++--------------------------- 1 file changed, 6 insertions(+), 27 deletions(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index c4c10b296..f272a3aa4 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -305,7 +305,6 @@ def __init__( data_source=None, product=None, filename_pattern="ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5", - catalog=None, out_obj_type=None, # xr.Dataset, ): # Note: maybe just don't add default values, so that Python enforces their existence? @@ -322,15 +321,9 @@ def __init__( else: self._prod = is2ref._validate_product(product) - # TODO delete? seems like it just validates the pattern - # Does Read accept a directory right now? Why would there be multiple files in the list? - # seems like yes, it does accept a directory - # does it check, then, that all the files have the same version and product? pattern_ck, filelist = Read._check_source_for_pattern( data_source, filename_pattern ) - print('pattern_ck', pattern_ck) - print('filelist', filelist) assert pattern_ck # Note: need to check if this works for subset and non-subset NSIDC files (processed_ prepends the former) self._pattern = filename_pattern @@ -338,8 +331,7 @@ def __init__( # this is a first pass at getting rid of mixed product types and warning the user. # it takes an approach assuming the product name is in the filename, but needs reworking if we let multiple products be loaded # one way to handle this would be bring in the product info during the loading step and fill in product there instead of requiring it from the user - filtered_filelist = [file for file in filelist if self._prod in Read._get_product_and_version(file)] - print('filtered', filtered_filelist) + filtered_filelist = [file for file in filelist if self._prod in file] if len(filtered_filelist) == 0: warnings.warn( "Your filenames do not contain a product identifier (e.g. ATL06). " @@ -355,11 +347,6 @@ def __init__( self._filelist = filelist # after validation, use the notebook code and code outline to start implementing the rest of the class - if catalog is not None: - assert os.path.isfile( - catalog - ), f"Your catalog path '{catalog}' does not point to a valid file." - self._catalog_path = catalog if out_obj_type is not None: print( @@ -697,17 +684,10 @@ def _build_dataset_template(self, file): attrs=dict(data_product=self._prod), ) return is2ds - - def _get_product_and_version(filepath): - # TODO either persist this info or remove 'version', since it isn't necessary right now - with h5py.File(filepath, 'r') as f: - product = f['METADATA']['DatasetIdentification'].attrs['shortName'].decode() - version = f['METADATA']['DatasetIdentification'].attrs['VersionID'].decode() - return product, version def _read_single_grp(self, file, grp_path): """ - For a given file and variable group path, construct an Intake catalog and use it to read in the data. + For a given file and variable group path, construct an an xarray Dataset. Parameters ---------- @@ -723,10 +703,9 @@ def _read_single_grp(self, file, grp_path): Xarray dataset with the specified group. """ - # I think this would fail if a group that has too high of a level of nesting - # is given. Consider this. - # TODO: update docstring - return xr.open_dataset(file, group=grp_path) + + return xr.open_dataset(file, group=grp_path, engine='h5netcdf', + backend_kwargs={'phony_dims': 'access'}) def _build_single_file_dataset(self, file, groups_list): """ @@ -750,7 +729,7 @@ def _build_single_file_dataset(self, file, groups_list): # correctly their product? Do we trust the metadata or the filename more? # Also revisit the semantics of this. Not sure if it makes semantic sense for this # to be a class method - file_product, _ = Read._get_product_and_version(file) + file_product = self._read_single_grp(file, "/").attrs["identifier_product_type"] assert ( file_product == self._prod ), "Your product specification does not match the product specification within your files." From 0779b8017a98ac3f2e683fddcaaebc0ca413ceac Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Wed, 30 Aug 2023 20:23:45 +0000 Subject: [PATCH 43/63] update doc strings --- icepyx/core/read.py | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index f272a3aa4..d3ca0d82a 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -4,7 +4,6 @@ import numpy as np import xarray as xr -import h5py import icepyx.core.is2ref as is2ref from icepyx.core.variables import Variables as Variables @@ -260,7 +259,7 @@ def _pattern_to_glob(pattern): # To do: test this class and functions therein class Read: """ - Data object to create and use Intake catalogs to read ICESat-2 data into the specified formats. + Data object to read ICESat-2 data into the specified formats. Provides flexiblity for reading nested hdf5 files into common analysis formats. Parameters @@ -279,10 +278,6 @@ class Read: The default describes files downloaded directly from NSIDC (subsetted and non-subsetted) for most products (e.g. ATL06). The ATL11 filename pattern from NSIDC is: 'ATL{product:2}_{rgt:4}{orbitsegment:2}_{cycles:4}_{version:3}_{revision:2}.h5'. - catalog : string, default None - Full path to an Intake catalog for reading in data. - If you still need to create a catalog, leave as default. - out_obj_type : object, default xarray.Dataset The desired format for the data to be read in. Currently, only xarray.Dataset objects (default) are available. @@ -307,7 +302,6 @@ def __init__( filename_pattern="ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5", out_obj_type=None, # xr.Dataset, ): - # Note: maybe just don't add default values, so that Python enforces their existence? if data_source is None: raise ValueError("Please provide a data source.") else: @@ -320,7 +314,6 @@ def __init__( ) else: self._prod = is2ref._validate_product(product) - pattern_ck, filelist = Read._check_source_for_pattern( data_source, filename_pattern ) @@ -725,10 +718,6 @@ def _build_single_file_dataset(self, file, groups_list): ------- Xarray Dataset """ - # why do we do get the product twice? is it important to us that the user tells us - # correctly their product? Do we trust the metadata or the filename more? - # Also revisit the semantics of this. Not sure if it makes semantic sense for this - # to be a class method file_product = self._read_single_grp(file, "/").attrs["identifier_product_type"] assert ( file_product == self._prod From 1cfbf7208a8de80a1539d25e0c536f6831330c25 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Wed, 30 Aug 2023 20:24:00 +0000 Subject: [PATCH 44/63] update tests --- icepyx/tests/test_read.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/icepyx/tests/test_read.py b/icepyx/tests/test_read.py index 9748ae992..018435968 100644 --- a/icepyx/tests/test_read.py +++ b/icepyx/tests/test_read.py @@ -63,7 +63,6 @@ def test_validate_source_str_not_a_dir_or_file(): ), sorted( [ - "./icepyx/core/is2cat.py", "./icepyx/core/is2ref.py", "./icepyx/tests/is2class_query.py", ] @@ -73,7 +72,7 @@ def test_validate_source_str_not_a_dir_or_file(): ( "./icepyx/core", "is2*.py", - ([], ["./icepyx/core/is2cat.py", "./icepyx/core/is2ref.py"]), + ([], ["./icepyx/core/is2ref.py"]), ), ( "./icepyx", From de61d87e21ccb4e1feb0e289b83a66ffc1690566 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Wed, 30 Aug 2023 20:43:07 +0000 Subject: [PATCH 45/63] update documentation for removing intake --- .../example_notebooks/IS2_data_read-in.ipynb | 2268 +++++++++++++++-- doc/source/user_guide/documentation/read.rst | 1 - 2 files changed, 2052 insertions(+), 217 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index dc9d8ed31..b8697b1d7 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -3,7 +3,9 @@ { "cell_type": "markdown", "id": "552e9ef9", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "# Reading ICESat-2 Data in for Analysis\n", "This notebook ({nb-download}`download `) illustrates the use of icepyx for reading ICESat-2 data files, loading them into a data object.\n", @@ -36,7 +38,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "id": "2b74b672", "metadata": {}, "outputs": [], @@ -47,7 +49,9 @@ { "cell_type": "markdown", "id": "1ffb9a0c", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "---------------------------------\n", "\n", @@ -57,10 +61,18 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "id": "c4390195", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "You have 6 files matching the filename pattern to be read in.\n" + ] + } + ], "source": [ "path_root = '/full/path/to/your/data/'\n", "pattern = \"processed_ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5\"\n", @@ -69,7 +81,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 6, "id": "2f46029d", "metadata": {}, "outputs": [], @@ -79,10 +91,603 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "id": "c0439388", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n" + ] + }, + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset>\n",
+       "Dimensions:              (photon_idx: 29027, spot: 2, gran_idx: 6)\n",
+       "Coordinates:\n",
+       "  * photon_idx           (photon_idx) int64 0 1 2 3 ... 29023 29024 29025 29026\n",
+       "  * spot                 (spot) uint8 2 5\n",
+       "  * gran_idx             (gran_idx) float64 8.49e+04 9.02e+04 ... 1.016e+05\n",
+       "    source_file          (gran_idx) <U72 '../../../../data/ATL06/processed_AT...\n",
+       "    delta_time           (gran_idx, photon_idx) datetime64[ns] 2019-02-22T01:...\n",
+       "Data variables:\n",
+       "    sc_orient            (gran_idx) int8 0 0 0 1 1 1\n",
+       "    cycle_number         (gran_idx) int8 2 2 2 5 5 5\n",
+       "    rgt                  (gran_idx) int16 849 902 910 986 1001 1016\n",
+       "    atlas_sdp_gps_epoch  (gran_idx) datetime64[ns] 2018-01-01T00:00:18 ... 20...\n",
+       "    data_start_utc       (gran_idx) datetime64[ns] 2019-02-22T01:03:44.199777...\n",
+       "    data_end_utc         (gran_idx) datetime64[ns] 2019-02-22T01:07:38.112326...\n",
+       "    h_li                 (spot, gran_idx, photon_idx) float32 nan nan ... nan\n",
+       "    latitude             (spot, gran_idx, photon_idx) float64 nan nan ... nan\n",
+       "    longitude            (spot, gran_idx, photon_idx) float64 nan nan ... nan\n",
+       "    gt                   (gran_idx, spot) <U4 'gt3r' 'gt1l' ... 'gt1l' 'gt3r'\n",
+       "Attributes:\n",
+       "    data_product:  ATL06\n",
+       "    Description:   The land_ice_height group contains the primary set of deri...\n",
+       "    data_rate:     Data within this group are sparse.  Data values are provid...
" + ], + "text/plain": [ + "\n", + "Dimensions: (photon_idx: 29027, spot: 2, gran_idx: 6)\n", + "Coordinates:\n", + " * photon_idx (photon_idx) int64 0 1 2 3 ... 29023 29024 29025 29026\n", + " * spot (spot) uint8 2 5\n", + " * gran_idx (gran_idx) float64 8.49e+04 9.02e+04 ... 1.016e+05\n", + " source_file (gran_idx) " + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjwAAAGxCAYAAABmyWwBAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8pXeV/AAAACXBIWXMAAA9hAAAPYQGoP6dpAACLhUlEQVR4nOzdd3xTVf/A8c9NugsNlNIlZcoUZMpUhjIFQVFQQYYD8UFEtvI4wAWOh+H4qaAIoig+jwoiylRAkF1AhsqyUCiUMkoHlI7c8/sjbSB0ZrRp0+/b133Znntycm5Dbr45U1NKKYQQQgghPJjB3RUQQgghhChuEvAIIYQQwuNJwCOEEEIIjycBjxBCCCE8ngQ8QgghhPB4EvAIIYQQwuNJwCOEEEIIjycBjxBCCCE8npe7K1DcdF3n9OnTVKxYEU3T3F0dIYQQpZhSipSUFCIjIzEY3NcmcPC3miilaNzphNvq4Gk0T19p+dSpU0RFRbm7GkIIIcqQkydPUq1aNbc8d1paGvVvDkJXcPhoEgEBAW6ph6fx+BaeihUrApZ/vEFBQW6ujRBCiNIsOTmZqKgo62eHO7w3PYqqVYwYjTD7teq8MOO82+riSTy+hSc5ORmTyURSUpIEPEIIIQrk7s+MCxcuUKd2KN99FoFBg37DznD02BlCQ0NLvC6eRgYtCyGEEKXEq8/fTPvb/OjSIYBO7QPo1N6fV56v5+5qeQQJeIQQQohS4NixY8z7Mom3Xgqxpr35QgiffZ3M4cOH3VgzzyABjxBCCFEKPD+uGYP7V+SW+r7WtIb1fBg6oCLPj2vhxpp5Bgl4hBBCCDfbtm0bK3+5zLRJVXKdmzqxCms3XuH33393Q808hwQ8QgghhBsppZj0bBfGjaxMZHjuydPhoV5M+FdlJo3tiofPMypWEvAIIYQQbvTDDz9w+J9MJo6qnG+e8U9VJiY2k++++64Ea+ZZJOARQggh3CQzM5PnJg5k6sRgKlbI/yO5QqCBaZOq8PykQWRkZJRgDT2HBDxCCCGEm8ybeRMa8MRgU6F5H30oCF8fjY/fcc8K0GWdBDxCCCGEGyQnJ/PKfy4y48UQvLwK3+vRy0tjxotVeHXmBZKSkkqghp5FAh4hygCllM2RX5ooW+R1Ld/eerkmDW72pm+PwCI/pnfXQJo09GXGi7Xsfr4ZM2Zw2223UbFiRUJDQ7n33ns5dOiQTR6lFNOmTSMyMhJ/f386d+7MwYMHbfKkp6fzzDPPEBISQmBgIH379uXUqVM2eRITExkyZAgmkwmTycSQIUO4dOmS3XV2JQl4hCjl8vrQK2qaKJ3yC2bkdS0/4uLimDPvEm9PrYqmFd66k0PTNN5+OYT3Pr3EyZMn7XrOjRs38vTTT7Nt2zbWrl1LVlYW3bt35/Lly9Y8b7/9NrNmzeKDDz5g586dhIeH061bN1JSUqx5xo4dy9KlS1myZAmbN28mNTWVPn36YDabrXkGDRrE3r17WbVqFatWrWLv3r0MGTLErvq6muylJUQp5sjb056bp3APeV1Lr5L6zHhskInLV3S+/jjCocc/MioeLy9Y9N9kh+tw7tw5QkND2bhxIx07dkQpRWRkJGPHjuW5554DLK05YWFhvPXWW4wcOZKkpCSqVq3KF198wYMPPgjA6dOniYqK4ueff6ZHjx789ddfNGrUiG3bttGmTRvAss5Qu3bt+Pvvv6lfv77DdXaGtPAIUUp5+HeRckteV7F//36+XprCG1NCCs+cj9enVOF/P6ayd+9eh8vIGQcUHBwMQExMDPHx8XTv3t2ax9fXl06dOrFlyxYAoqOjyczMtMkTGRlJ48aNrXm2bt2KyWSyBjsAbdu2xWQyWfO4gwQ8QngY+UAVonR7+bl2PPmIido1vB0uo2aUN6OGm3hxUgeSk5NtjvT09EIfr5Ri/Pjx3H777TRu3BiA+Ph4AMLCwmzyhoWFWc/Fx8fj4+ND5cqVC8yT1+7uoaGh1jzuIAGPEKWQM0GLdH2UXhKMCoC48424vY2f0+Xc3saf6ANB1oHBOceMGTMKfezo0aPZt28fX3/9da5zN95DlFKF3lduzJNX/qKUU5xyr2EthBBCiGKlUOjoTpcRHh6ea6aVr69vPo+weOaZZ1i+fDm//fYb1apdW9MnPDwcsLTQRERcG1uUkJBgbfUJDw8nIyODxMREm1aehIQE2rdvb81z9uzZXM977ty5XK1HJUlaeIQoZaQVwDPJ6yqup6MwK92pQ1c6mqYRFBRkc+QX8CilGD16NN9//z2//vortWrZTm2vVasW4eHhrF271pqWkZHBxo0brcFMy5Yt8fb2tslz5swZDhw4YM3Trl07kpKS2LFjhzXP9u3bSUpKsuZxB2nhEcKDSHeWJ8gJjAruHhDCXk8//TRfffUVP/zwAxUrVrSOpzGZTPj7+6NpGmPHjmX69OnUrVuXunXrMn36dAICAhg0aJA17+OPP86ECROoUqUKwcHBTJw4kSZNmtC1a1cAGjZsSM+ePRkxYgRz584F4Mknn6RPnz5um6EFEvAIUapIK4BnsryuOteCGEV+Dewq+R8Mppvl34KHs3RpOfca29sh9tFHHwHQuXNnm/QFCxYwfPhwACZPnkxaWhqjRo0iMTGRNm3asGbNGipWrGjNP3v2bLy8vBg4cCBpaWncddddLFy4EKPRaM2zePFixowZY53N1bdvXz744AO7r9GVZB0eIUoRGazsea4FO4CeCGSAIQTI+XAw2OZNaIgW8gsYIwFNXtcSVhKfGa1bt+bZJ2O4t3eAU+WsWHWFt96PYvfu3S6qmWeTFh4hSgkP/+5RjulomhGVeQTMR8GrPprmgzKfzQ58rpPwH0BBZjQYw9A0x6cti9JNVwqzk+9554Y8lz8S8AhRquQsza6w5+0prQClkyWIzUJPHA3pv1xL9+2JVuk/QBaW19mA0nXgU0sGYxQyp0QI15KAR4hSQCmzpRUgYw8qfQOaZgL/+8BQhesHr4qyRqFS37UJdgBIX4VKvRmtwlNYvqcb4FxDyzmvxmg+LUq6oqKEuWIMj3Ly8eWNBDxClAKaZkS/NAGu/ghkz9NJfRet0vvg24mCvu1L607ppWkGVNrSvE9eXYZWcQxKZaLMZsAIvnehmV5FqSw0TW7PnkwHzE4GLM4+vryRd5QQbqZUJqRvsgY712Sikl9Eq7rJLfUSLqLS8k7Xc3aoNqIZrkDYbjTNX4KdckKXFp4SJ53EQriZpnmj0tfmfVI/D5l7C3istO6Uer535p3u1zV7qX0DmqECmuYPIMGOEMVE3llCuJllYGsBS8Free+5I8FO6aeUGa3iZFRGNOhnrp0wRqFVGIel81Jex/LIJbO0pIHHLhLwCOF2ZjT/+1BpX+U+ZayN5n2LTFkvozTNiDKEoFVdBWnLUFlH0bzqg38/wIimSSN7eXXd6kxOlSGKTgIeIdxM07zApylUmIRKnQNkWk4YItEqvYdSWVxbpC7nMdIqUFZYuqi8UP4PoGEEzLK+jnDJoGVnxwCVNxLwCFFaBD6BFjAA0jeDwQQ+7bF8hzMW9khRBlwLcqRVRwh3kIBHiNJEM4FfTyzjOjTy+nCU1h0hyj4dMDvZQOPs48sbCXiEKAWsCw+mb7csPGgwgX//7K0HJMARwtPIGJ6S59a21Zo1a6JpWq7j6aefzpV35MiRaJrGnDlzSr6iQhQ7A/qlcajEIXBlPip1FupcF0hfz/W3RWndEcIzWMbwaE4dunwZsotbW3h27tyJ2Wy2/n7gwAG6devGgAEDbPItW7aM7du3ExkZWdJVFKLYXVt48KcbzmSikl9Cq/qbW+olhCg+unJ+Wrm08NjHrS08VatWJTw83HqsWLGCOnXq0KlTJ2ueuLg4Ro8ezeLFi/H2lpkNwvMUdeFBad0RQgjHlZoxPBkZGXz55ZeMHz/eemPXdZ0hQ4YwadIkbrnlliKVk56eTnp6uvX35OTkYqmvEK6ilMp3cUEAslfgFaWbUpmW4FXpgELTZHadyJ+e3S3lXBnCHqVmfuSyZcu4dOkSw4cPt6a99dZbeHl5MWbMmCKXM2PGDEwmk/WIiooqhtoK4UpmNL/78j5lrIPmfYu07pRiSmVZ1kq6+jP6pcmolLfBfCI78BEib7qT43dkDI/9Sk3AM3/+fHr16mUdpxMdHc27777LwoUL7brZT5kyhaSkJOtx8uTJ4qqyEC6haV5oPreiVXwO8Ll2wlgNrdL72QsPitJLoS4OQyVNgqvL4MpnqPN94OpqlDIX+mhRPikFutKcPkTRlYourRMnTrBu3Tq+//57a9qmTZtISEigevXq1jSz2cyECROYM2cOx48fz7MsX19ffH0L2JdIiNIq4DE0/+sXHmwH6LKZZCmmVCak/QCZO284k4VKeR3Nr7tb6iWEyK1U3EkXLFhAaGgovXv3tqYNGTKErl272uTr0aMHQ4YM4dFHHy3pKgpR7DRNAy0I5dcd0LL3WSo1jbAiD5rmjZ6+Me+T+jnI+hu8izb+UJQvrhnDIy089nB7wKPrOgsWLGDYsGF4eV2rTpUqVahSpYpNXm9vb8LDw6lfv35JV1OIEiMtOmWMwZT/Oa2Ac6JcswQ8zn2hkYDHPm7/+rhu3TpiY2N57LHH3F0VIYSwi1JZlm7IvD54vG9D86pW4nUSZYOO8+N3lIzhsYvbv0p2797dMi23CPIbtyOEEO5g3ek+6BVUyjugUiwnvJujVZpjnaouhHA/twc8QghR5vkPRPO/DzL2gqEKmvfNEuyIAsk6PCVPAh4hhHCSZYC5L/i2uS5Ngh2RP11pmJVzo0qcfXx5IwGPEEIIUcIUGrqTw2iVDFq2i4SHQgghhPB40sIjhBBClDBZh6fkScAjhBBClDBXjOGRgMc+0qUlhBBClDCVvfmnM4cjY3h+++037rnnHiIjI9E0jWXLltmc1zQtz+Odd96x5uncuXOu8w899JBNOYmJiQwZMsS6kfeQIUO4dOmSI38ql5GARwghhCgnLl++TNOmTfnggw/yPH/mzBmb47PPPkPTNO6//36bfCNGjLDJN3fuXJvzgwYNYu/evaxatYpVq1axd+9ehgwZUmzXVRTSpSWEEEKUMB2D01tLODIGqFevXvTq1Svf8+Hh4Ta///DDD3Tp0oXatWvbpAcEBOTKm+Ovv/5i1apVbNu2jTZtLEs1fPLJJ7Rr145Dhw65bXsoaeERQgghSpiOZQyPM4dezOvwnD17lp9++onHH38817nFixcTEhLCLbfcwsSJE0lJSbGe27p1KyaTyRrsALRt2xaTycSWLVuKtc4FkRYeIYQQooTpLlqHRylFcnKyTbqvry++vr5OlQ3w+eefU7FiRfr372+TPnjwYGrVqkV4eDgHDhxgypQp/PHHH6xduxaA+Ph4QkNDc5UXGhpKfHy80/VylAQ8QgghRAmzzNJyclq60oiPj8dkMtmkT506lWnTpjlVNsBnn33G4MGD8fPzs0kfMWKE9efGjRtTt25dWrVqxe7du2nRogVgGfx8I6VUnuklRQIeIYQQoowKDw/n0KFDNmmuaN3ZtGkThw4d4ptvvik0b4sWLfD29ubIkSO0aNGC8PBwzp49myvfuXPnCAsLc7pujpKARwghhChhloUHnV+HR9M0goKCXFSra+bPn0/Lli1p2rRpoXkPHjxIZmYmERERALRr146kpCR27NhB69atAdi+fTtJSUm0b9/e5XUtKgl4hBBCiBKmXDDo2JF1eFJTUzl69Kj195iYGPbu3UtwcDDVq1cHIDk5mf/973/MnDkz1+OPHTvG4sWLufvuuwkJCeHPP/9kwoQJNG/enA4dOgDQsGFDevbsyYgRI6zT1Z988kn69OnjthlaIAGPEEIIUeJc0cLjyON37dpFly5drL+PHz8egGHDhrFw4UIAlixZglKKhx9+ONfjfXx8+OWXX3j33XdJTU0lKiqK3r17M3XqVIxGozXf4sWLGTNmDN27dwegb9+++a79U1I0pZRyaw2KWXJyMiaTiaSkpGJp9hNCeC6lstA0r+yfzWiasZBHiLKuJD4zWrduTfuhibTuGexUObvWJbJhXgV2797topp5NmnhEUKIG1i+BypI+xY97QdQV9H87kIFPg74SOAjnGZZh8fZWVouqkw5IQGPEELcQNM09KSXIO2/1jSVehDSN6AFFz5rRYjCuGYdHlk72B4S8AghxHWUUqCfgbT/5T6ZuQ/S16F877J2dQnhCJfslu5kC1F5I+GhEELY0CFjN5B3f4HK2AMOzI4RQriXfEURQggbBjBWz/esZrwJ0AEZxyMcp9DQnQycHZmWXp5JwCOEENfRNA18bkV5N4XMP244WRn8+6Np3u6pnPAYrujScmS39PJMurSEEOIGSmWhVf4E/O4GsoMbnzZowV+C5vyy/ULoGDA7eTg76Lm8kRYeIYS4gaZ5oaiIodIclEoHlYVmCLRZl0cIUbbIO1cIIfKQs9aOpvlaW3Uk2BGuonB+lpVnLxvsevLuFUIIIUpYTpeWs2WIopOARwghhChhutKc3zxU1uGxi4SHQgghhPB40sIjhBBClDDLbunOtdDItHT7SMAjhBBClDDlii4tCXjsIgGPEEIIUcJc0cJjWalZpmoVlQQ8QgghRAlTuGrQsgQ8ReXWQcs1a9ZE07Rcx9NPP01mZibPPfccTZo0ITAwkMjISIYOHcrp06fdWWUhhBBClEFuDXh27tzJmTNnrMfatWsBGDBgAFeuXGH37t289NJL7N69m++//57Dhw/Tt29fd1ZZCCGEcFrOXlrOHM62EJU3bu3Sqlq1qs3vb775JnXq1KFTp05ommYNgHK8//77tG7dmtjYWKpXz383YyGEEKI0012wW7ruorqUF6VmDE9GRgZffvkl48ePt+xWnIekpCQ0TaNSpUolWzkhhBDChVyxW7qstGyfUhPwLFu2jEuXLjF8+PA8z1+9epXnn3+eQYMGERQUlG856enppKenW39PTk52dVWFEEIIUcaUmvBw/vz59OrVi8jIyFznMjMzeeihh9B1nQ8//LDAcmbMmIHJZLIeUVFRxVVlIYQQwiGWWVrOHbJ5qH1KRcBz4sQJ1q1bxxNPPJHrXGZmJgMHDiQmJoa1a9cW2LoDMGXKFJKSkqzHyZMni6vaQgghhENyNg915pAuLfuUii6tBQsWEBoaSu/evW3Sc4KdI0eOsH79eqpUqVJoWb6+vvj6+hZXVYUQQgin6coyjse5MmSlZXu4PeDRdZ0FCxYwbNgwvLyuVScrK4sHHniA3bt3s2LFCsxmM/Hx8QAEBwfj4+PjrioLIYQQooxxe8Czbt06YmNjeeyxx2zST506xfLlywFo1qyZzbn169fTuXPnEqqhEEII4VrKBV1SspeWfdwe8HTv3h2Vx8irmjVr5pkuhBBClHW6ArN0aZUotwc8QgghRHmTM0vLGbLwoH1kiLcQQgghPJ4EPEIIIcospVSeR2lnWUvH4NShHFip+bfffuOee+4hMjISTdNYtmyZzfnhw4fn2tC7bdu2NnnS09N55plnCAkJITAwkL59+3Lq1CmbPImJiQwZMsS6Jt6QIUO4dOmS3fV1JQl4hBBClEmWwCbv4Ka0Bz06GmYnD0e6tC5fvkzTpk354IMP8s3Ts2dPm429f/75Z5vzY8eOZenSpSxZsoTNmzeTmppKnz59MJvN1jyDBg1i7969rFq1ilWrVrF3716GDBniQI1dR8bwCCGEKMPK5sBdpZwfw6MceHyvXr3o1atXgXl8fX0JDw/P81xSUhLz58/niy++oGvXrgB8+eWXREVFsW7dOnr06MFff/3FqlWr2LZtG23atAHgk08+oV27dhw6dIj69evbXW9XkBYeIYQQZU5RWnBKeytPabVhwwZCQ0OpV68eI0aMICEhwXouOjqazMxMunfvbk2LjIykcePGbNmyBYCtW7diMpmswQ5A27ZtMZlM1jzuIC08QgghRAmzzNJydrd0DaVUrk2yndlxoFevXgwYMIAaNWoQExPDSy+9xJ133kl0dDS+vr7Ex8fj4+ND5cqVbR4XFhZmXRw4Pj6e0NDQXGWHhoZa87iDBDxCCI+WM85DkUWWnoy3IRhQaJrR3VUTDvKElhsdDd3J7jiFRnx8PCaTySZ96tSpTJs2zaEyH3zwQevPjRs3plWrVtSoUYOffvqJ/v37518XpdC0a9dz/c/55SlpEvAIITyW5YNRJybxHeJTlmBWqfgaI6hReRxhFfK/eQvP4M4P18K4auHB8PBwDh06ZJPuyv0kIyIiqFGjBkeOHAEgPDycjIwMEhMTbVp5EhISaN++vTXP2bNnc5V17tw5wsLCXFY3e8kYHiGEB1McvzSbuORPMatUANLNZzh8fjKJaZvQVZab6yfKK+XklHTLYZk2HhQUZHO4MuC5cOECJ0+eJCIiAoCWLVvi7e3N2rVrrXnOnDnDgQMHrAFPu3btSEpKYseOHdY827dvJykpyZrHHYrUwlNQM1Z+Pv744zz78IQQouQo/Iw30TJyDSjF+bQ1nElZTIY5nrjkz6nsf4e7KyjsVNTurNLcuuNOqampHD161Pp7TEwMe/fuJTg4mODgYKZNm8b9999PREQEx48f59///jchISHcd999AJhMJh5//HEmTJhAlSpVCA4OZuLEiTRp0sQ6a6thw4b07NmTESNGMHfuXACefPJJ+vTpk+8MrX379tl9LY0aNbLZdLwwRcq5bNkyBg4ciL+/f5EK/eqrr0hNTZWAp5gV9MaXN7sQABrhFR9E0yyN2VE+T1At6En+OjeKq1mxbq6bKM+Ucn4vLEc2D921axddunSx/j5+/HgAhg0bxkcffcT+/ftZtGgRly5dIiIigi5duvDNN99QsWJF62Nmz56Nl5cXAwcOJC0tjbvuuouFCxdiNF4bF7d48WLGjBljnc3Vt2/fAtf+adasGZqmFTmgNRgMHD58mNq1axf52jVVhNINBkO+o67zUrFiRf744w+7KlJckpOTMZlMJCUlERQU5O7quIxSiixdRynLKhRexrx7JyXwEeWVUlmgUlGpH0P6RjBURPN/AC1gIErpnEh8lxqVx8p7pIzJ/ZGlyGstHkdf15L4zGjdujW+9wVR/c5aTpVz6rcTpHx9nt27d7uoZu5jMBjYsWMHVatWLTSvUorGjRuzb98+u+KMIrXwrF+/nuDg4CIXunLlSm666aYi5y9vlFIoXWHIDlLMWWaMXkWfMZJlNuNlNOJlMGSXB2ZdoVCWNKUg+83u7lHxQrhPJurCQDAft/xqBpW5F5V1DEPQFKpVGkl+H5aidMr7+3ler5/Kvg2W3tfWJZuHlv3JaladOnXi5ptvplKlSkXK37FjxyL3OuUoUsDTqVMnuwq9/fbb7cpfnmRlmUlLucp3H61j76ZDVKpakT7DO9LqzluK9HilFEaDweaNr2lg1DSUgixdtwZCQpRXSmXCle+vBTvXu/IlqsJTGDWTtatLeJrSG+iIvK1fv96u/Ddud1EUDk1L13Wdo0ePkpCQgK7b7ubRsWNHR4osN9KvZDCmx5vEx16wpm1fs59/vTGQPo92xOBEsKJpGt7WYCgnIJI3vih/NM0bPTO/QZCZkHkQfDqUaJ1ESbBtsSvNLdxKOb/woCObh5ZFZrOZ/fv3U6NGjVwLHtrD7oBn27ZtDBo0iBMnTuRqXtQ0zWbzMHGNrusoXfHjZxttgp0cX/7nJ3oNuR2Dj7NvgOsCnZwBPkKUM0qZ0byi8tlWEjDWLMHaCFco2mDWsnPD012xl5aL6lLajB07liZNmvD4449jNpvp1KkTW7ZsISAggBUrVtC5c2eHyrX70/Wpp56iVatWHDhwgIsXL5KYmGg9Ll686FAlPJ3SFb//tBejl5E/dx7LM09K4mVOHTtb4JvavtVFzaBplqZ9IcoZTTOC/8OgVcx90vcuNK9qpfabvygfLEtiak4fnujbb7+ladOmAPz444/ExMTw999/M3bsWF544QWHy7U74Dly5AjTp0+nYcOGVKpUCZPJZHMIW0opzp1O5N2JX6GUoupNeQ/+NhgNBIe57u+naTmNd7J8viinDCa04C/Ap7Xld80f/B9CqzTLMoNLlBmObiUhQW3ZdP78eetu7T///DMDBgygXr16PP744+zfv9/hcu0OeNq0aWOzaJEomDlLZ91/t3E56Qq6Weeexzph9Mr9Z+/UryWm4Aoue17LDcKMwSABjyifNM0LvOpiCP4SLWwfWuhutKBXAJ/rvhAIz1J2Onn07FlazhzKyS6x0iosLIw///wTs9nMqlWrrAsaXrlyxWatH3sV6V1//QqIzzzzDBMmTCA+Pp4mTZrg7e1tk/fWW291uDIeSYOrVzKsP1evF85LC0by6Svfc+roWbx9vbjz/tb8a/pAzFlm0CzrEdz4zcSxbzjlY0CbEPnRNO/s//tdlypfAoT7KReM4fGkaenXe/TRRxk4cCARERFomka3bt0Ay/YUDRo0cLjcIgU8ea2A+Nhjj1l/zjkng5Zz04AOdzfjfx+sYXiLl1m093VadWlEm25NuHg2iYCK/vgF+GDOMqMZNHRP/RcshBAOsO/LngboQO4vjaWNS1Za9tAWnmnTptGkSRNiY2MZMGCAdW8wo9HI888/73C5RQp4YmJiHH6C8s7oZaR+i5r0ebQjKxb8ZgkMDRq6rmOqYunCUtkLBWZkZOHn5+Oy55Y1RoQQ5YcZS+ud3PfKsszMTLp3787cuXO5//77bc4NGzbMqbKLFPDUqFHD+vNvv/1G+/btc23YlZWVxZYtW2zyCgvdrPP0jIe48/7WZGWZMRqNmM1mvLy8MBg0MjOySLiYQmhIEGazGaUs3VoGw7XVkoUQQhQkZ004Y6lv3YFrY3ic4cheWqWdt7c3Bw4cKJbX0O5QuEuXLnlOP09KSrLZkExcoxksXX71mtWwDLjSrgU0WVlmjN5GIkIrYcjuEsy8mmkNdoQQory69mVPBzKzD7AMTr7hi6C6Qlkan6VcMCVdL/xpyqShQ4cyf/58l5dr91SF/FauvHDhAoGBgS6plKfJGeNkuG6DT7PBshihMTtNVzrpWVmknEshrFoI4NwqoWXhG44QQhRG0zRUViyk/wpaBfDrA5oftosM6qDMoFnG75QFrhrD44l3+oyMDD799FPWrl1Lq1atcsUWs2bNcqjcIgc8/fv3Byz/+IYPH24dRASWZZ/37dtH+/btHapEuWRWXL2agZevFz4+3iRdTCXu0Gkata3Hnzv/oWEryy660p0lhCivNE1DT34L9JtAPw8Zb0HKm2iVPgSf27AENxoq5W20is/LFz0PceDAAVq0aAHA4cOHbc458xoXOeDJWVRQKUXFihVtdin18fGhbdu2jBgxwuGKeDpNswxUvvZiKXRd4eNjmTYbXNWEr58PPy3aRIfezdF1Jd1aQohyS6ksUAa0ipOvS52M0nXUhU5oVTdm51OQ9g1UHA/45llWaeSKrSV0pZWhTryis3cj0aIqcsCzYMEClFIopXj//fepWDGPJdtFgXKCHaUss7f8A31JupDC3s2HOXvyAr5+3nR7sB0+ft6FlFS05xFCiLLLmN1rldPKrQADmkGDkN8gY5ellSczwzJ+R09EGcLKzP1PyaDlQh09epRjx47RsWNH/P39nd4M1q4xPEopvvrqK1544QUJeJyQ83oZjAYqVg7kjj7NMRgNmLPMGIwGad0RQggr7Yb/W5bxwJC9yG1iEzCEgqFqmQl2wFVjeFxUmVLmwoULDBw4kPXr16NpGkeOHKF27do88cQTVKpUiZkzZzpUrl2juwwGA3Xr1uXChdy7fYuCmc16nuNxNE2zfGOB7GBHdyrYKUtveCGEyIvtvVIHm/lIBkCBl681n1bhmRKsnWuo7K0hnD080bhx4/D29iY2NpaAgABr+oMPPsiqVascLtfu4exvv/02kyZN4sCBAw4/aXlkMGhkZGTkez7njWswlI0ZBkIIUbyyLF8INSOaZsSysGBOIGS5TxoMBrSqW9ECHszOIzzBmjVreOutt6hWrZpNet26dTlx4oTD5dr96frII4+wY8cOmjZtir+/P8HBwTaHyJumaTz8zEJ3V0MIIcoABRnn0c2X0c3J6CkL4cri7NXjr7X+qMsLwGByWy2d4Yp1eDx1DM/ly5dtWnZynD9/3maGuL3sXodnzpw5Dj9Zeefn513goCtnB2RJd5YQoqxTKsvyg0/4tY/zCkNBgUpdAYG9gOy9HS8vwBD4qJtq6hwd58fweOrCgx07dmTRokW89tprwLVZzu+8845TCxzbHfA4u5fF9WrWrJln89SoUaP4v//7P5RSvPLKK8ybN4/ExETatGnD//3f/3HLLbe4rA4lxWzW6dX5FtLS0vKMXEECFiGEsKyWnGVzP1TKDJoRAntey3blCujxKJWJpjk3s9UtXDEGx0PH8Lzzzjt07tyZXbt2kZGRweTJkzl48CAXL17k999/d7hchwaMmM1mvvvuO15//XXeeOMNli5d6tAu6Tt37uTMmTPWY+3atQAMGDAAsIwXmjVrFh988AE7d+4kPDycbt26kZKS4ki13cpoNDD43tb8Z17xrC8ghBCeQUHGAfT0FPS0BPRzfbO7szTAaO3R0gL9wee9shnsiAI1atSIffv20bp1a7p168bly5fp378/e/bsoU6dOg6Xqyk7l/I9evQod999N3FxcdSvXx+lFIcPHyYqKoqffvrJqcqMHTuWFStWcOTIEQAiIyMZO3Yszz33HADp6emEhYXx1ltvMXLkyCKVmZycjMlkIikpiaCgIIfr5go5081tFyB0DWkdEkKUdUplkrvjQaEUaFfmQ+BjWLqzLAOWla6DpqNpdndW5KskPjNat27NpR43UeWO+k6Vc3HLEQKXx7B7924X1ax0iI2NJSoqKs/PtdjYWKpXr+5QuXa38IwZM4Y6depw8uRJdu/ezZ49e4iNjaVWrVqMGTPGoUqAZe+ML7/8ksceewxN04iJiSE+Pp7u3btb8/j6+tKpUye2bNmSbznp6ekkJyfbHKVFznRzmYklhBB5MWIZmaKyZ2hpQPYXxMAnsvNocD4elb4DNLNLg52S5vS0dHdfQDGpVasW586dy5V+4cIFatWq5XC5dv9L2bhxI9u2bbOZkVWlShXefPNNOnTo4HBFli1bxqVLlxg+fDgA8fHxAISFhdnkCwsLK3Ba2owZM3jllVccrocQQgh30cEcj7ryGSrzIHjVRAt4FLzqARooHTQD6J1RGU+h+TR3d4Ud5oqtJTx1HZ78JvCkpqbi5+fncLl2Bzy+vr55jqFJTU3Fx8fH4YrMnz+fXr16ERkZaZN+40UXNpNpypQpjB8/3vp7cnIyUVFRDteruOTsoO6qsoQQoixTKgvMJ1AXBoBKtSRm7kGlrUCr/Bn4tADN69pigwZZBsXT5Hx2a5rGSy+9ZDPBx2w2s337dpo1a+Zw+XYHPH369OHJJ59k/vz5tG7dGoDt27fz1FNP0bdvX4cqceLECdatW8f3339vTQsPDwcsLT0RERHW9ISEhFytPtfz9fV1ap6+EEKIkqdpXuipH1wLdqwyUamzMFT5xhLsXLgAWgD431e2Bywr57eG8LStJfbs2QNYGjb2799v04ji4+ND06ZNmThxosPl2x3wvPfeewwbNox27drh7W35x5aVlUXfvn159913HarEggULCA0NpXfv3ta0WrVqER4eztq1a2ne3NJsmZGRwcaNG3nrrbcceh4hhBClWMauvNMz96CUjmU/rYfQKs0FrUJJ1szlchYPdIanLTyYs0v6o48+yrvvvuvyQeN2j56tVKkSP/zwA4cOHeLbb7/lf//7H4cOHWLp0qWYTPaveKnrOgsWLGDYsGF4eV2LvzRNY+zYsUyfPp2lS5dy4MABhg8fTkBAAIMGDbL7eUojV3RFSXeWEMJjGMPzTjeEWlZZVgotZC34tPSArSRcsZeW/c/622+/cc899xAZGYmmaSxbtsx6LjMzk+eee44mTZoQGBhIZGQkQ4cO5fTp0zZldO7c2TqoPOd46KGHbPIkJiYyZMgQTCYTJpOJIUOGcOnSpSLVccGCBQQFBXH06FFWr15NWloacOMea/ZzeHh73bp1qVu3rlNPDrBu3TpiY2N57LHHcp2bPHkyaWlpjBo1yrrw4Jo1a2SndiGE8DBKZaIFDEUlTch1TgsYglJmNENOkCMzXR11+fJlmjZtyqOPPsr9999vc+7KlSvs3r2bl156iaZNm5KYmMjYsWPp27cvu3bZtr6NGDGCV1991fq7v7+/zflBgwZx6tQp62afTz75JEOGDOHHH38stI4XL15kwIABLt8t3e6Ax2w2s3DhQn755RcSEhLQddvFrX/99Ve7yuvevXu+UZumaUybNo1p06bZW00hhBBliKZ5g/89oF9AXZ4L+gVLt1XAIxA4InsfLc+hK+e3lnCkS6tXr1706tUrz3Mmk8m6AHCO999/n9atW+da/yYgIMA61vZGf/31F6tWrWLbtm20adMGgE8++YR27dpx6NAh6tcveP2hsWPHWndLb9iwoTX9wQcfZNy4cSUX8Dz77LMsXLiQ3r1707hxY+lSyZYTtJmzzNYZWEajEbSCu52cma0lf3shhMcJGIIW8Ajo58EQDHh5XLADlJlBy0lJSWiaRqVKlWzSFy9ezJdffklYWBi9evVi6tSp1t6XrVu3YjKZrMEOQNu2bTGZTGzZsqXQgGfNmjWsXr3a5bul2x3wLFmyhP/+97/cfffdDj+pJ8oJWoxeRpvfdbNuTSvs8RLACCHKO+vYnPzG83gIhWv20lJK5Vpg11Wzla9evcrzzz/PoEGDbAYQDx482Dqx6MCBA0yZMoU//vjD2joUHx9PaGhorvJCQ0Ota+wVpLh2S7c7bPbx8eHmm292+Ak9kVIqO1pX6LpOZmYWBoMBs1m3LH9ehDBcgh0hhBD2io+Ptw4MzjlmzJjhdLmZmZk89NBD6LrOhx9+aHNuxIgRdO3alcaNG/PQQw/x7bffsm7dOpstLvL6TCvqF/uc3dKvL8stu6VPmDCBd999lw8++EA+pLMpZZlt5uVt+XMajUayssygKcxmHU2j0FYePTs4unL5KgEVHF9JUgghROmXM9PKqTLQCA8P59ChQzbpzrbuZGZmMnDgQGJiYvj1118LnR7eokULvL29OXLkCC1atCA8PJyzZ8/mynfu3LkC19HLUVy7pdsd8GzevJn169ezcuVKbrnlFutaPDmuXzywPMjZCHT/1iMs/fgXTh8/T71mNXjo2Z7cVCcMo7cBpVtafvLaQysn4lXZ//kH+hY5CpZuMCGEKJuUKwYtK0vrhyvXq8kJdo4cOcL69eupUqVKoY85ePAgmZmZ1kWC27VrR1JSEjt27LBZoDgpKYn27dsXWl7ObukfffQRRqPRulv6008/bbMQsb3sDngqVarEfffd5/ATehrdrND1LJrd0YBmdzQALAsxTug3k4mzhxFZJxSj0YButsxmuzHoMWfpGL0M17q+FBiMHjhATwghhJXCPYOWU1NTOXr0qPX3mJgY9u7dS3BwMJGRkTzwwAPs3r2bFStWYDabrWNugoOD8fHx4dixYyxevJi7776bkJAQ/vzzTyZMmEDz5s2t+2k2bNiQnj17MmLECObOnQtYpqX36dOn0AHLOcLDw12+L6amXLWh0w1+//13WrVq5fZtHpKTkzGZTCQlJbl81UawtLLk19Kyc8NeWndpbjOG58Z8OS1E5iyzddyP0ctQ5JYbaeERQgjXKe7PDIDWrVsT17kWQe0aOVVOyo6/CV19yGbsTGE2bNiQ5ziYYcOGMW3atHx3I1+/fj2dO3fm5MmTPPLIIxw4cIDU1FSioqLo3bs3U6dOtdlU/OLFi4wZM4bly5cD0LdvXz744INcs73yc/XqVfbt25fn8jeObmPl8MKDhenVqxd79+6ldu3axfUUpUZ+QcdtnZsV+ljdrMhMz2DtN9s4HXOOes1q0LFfSwzGogUz0q0lhBCiqDp37lzgRJrC2kCioqLYuHFjoc8THBzMl19+aXf9AFatWsXQoUM5f/58rnOapmE2mx0qt9gCnmJqOCpV8rrG6wOQ63/Oacm5PjjJyszibOwFJt07m8Rz16YV/u+DNby7ZnKu8VFCCOFJLPdQM5Y9shRgLD9f4FwxaNnZae2l1OjRoxkwYAAvv/xykQY5F5UMFnFSTpdWzrT0nDS4NpUOLGN3bnwje3l78fFL/7MJdgCO/32aL976qQRqL4QQ7qFUVvZPRsCApnkB5uvSPZtyweGpEhISGD9+vEuDHZCAx2nWVhsNmxac64Oe/GRlmole/1ee57au+qPI33TKQ2uaEMJzKHV9q47lsKQZsGyq6fn3NMug5ZLfPLQseOCBB9iwYYPLyy22Li1PV9AbssgDjg0aPn5epKdl5jrnF+Dewd5CCFF8tOzjxjR1w/9FefTBBx8wYMAANm3aRJMmTXIN7xgzZoxD5RZbwFNu+mHtcOPfxGDQ6Hzfbaz+akuuvF0HtCEry4xRpqgLITxSlmXDUCw7pVs+jnKCnXLA0/ulnPDVV1+xevVq/P392bBhg81np6ZppS/gKQ9NkkVR0Cwq3azz5KsPEH/iPH/8fhiwvJh3DWxD3yc6W9fskb+lEMJTKKWjaQZU+k70tG9BpaD5dgL/B7AEPIXvPegRZNByvl588UVeffVVnn/++TwX7HWU3QFPWloaSinrxl4nTpxg6dKlNGrUiO7du1vzpaSkuKySpY29AUh+QY/Ry4ivH7z53Vj+OXiKk0fP0qB5TcKqV0HXdbueR6anCyHKBg11+TNUypvWFJX+K6T9iBa8iPLSneWKhQc9tYUoIyODBx980KXBDjgwaLlfv37WTb0uXbpEmzZtmDlzJv369eOjjz5yaeVKO6XMoDKzB9vldV5ZBzLnF4zk7LFVq9FN3N67GWHVLct4S/AihPBIKg2V+i54dQOv1tfSM3fB1VVYpqmL8mzYsGF88803Li/X7hae3bt3M3v2bAC+/fZbwsLC2LNnD9999x0vv/wy//rXv1xeyVJHmdEMXtnNiUYwX0XzDkTpWaBda461J2jRNK3QDUaFEKLs80ML3WuTovRMONcYlbEFg38f91SrhLlq81BPZDabefvtt1m9ejW33nprrkHLs2bNcqhcuwOeK1euULFiRQDWrFlD//79MRgMtG3blhMnTjhUibJE6TpoxuzWG0sDmeYVkN39lIlSmjW9xOsm3VpCiFJMWXa7zJWuGbwh9G/U5TkoZVm7zF330RKjAGfH4Hhol9b+/ftp3rw5AAcOHLA558xnnN0Bz80338yyZcu47777WL16NePGjQMsCwUV174jpUpBf2zNDy2Pf4GOvECaVj7WohBClGfXjdfRNDT/p7N/NJSLL3Du2Dy0LFi/fn2xlGt3CP3yyy8zceJEatasSevWrWnXrh1gae3JicjKM4//ViKEEA649gUur7WCszeHNPoACmXOQMbyCFez+9P5gQceIDY2ll27drF69Wpr+l133WUd2+OpitLi4u5WGXc/vxBC5E/n2qKDOd3/OSss59y7DGAw4PHT012xt4QH3e779+9PcnJy4RmzDR48mISEBLuew6HmiPDwcCpWrMjatWtJS0sD4LbbbqNBgwaOFOfRnGmS9fTmXCFEeWP7kWP5gmbk2gaiOTx/E1Hnt5XIa7XqsuuHH37g3LlzJCcnF3okJSXx448/kpqaatdz2D2G58KFCwwcOJD169ejaRpHjhyhdu3aPPHEE1SqVImZM2faW2SZ5Gj/sm7W0XVlXVBUM2iymrIQwqNZBiIXdL/M3ZpTHsbwON1C40EtPEop6tWrV6zPYXfAM27cOLy9vYmNjaVhw4bW9AcffJBx48Z5bMCjlELXFQaDQtctb0KDQbtuE7zC35hZWWaUrti4Yg+xR85Sq0Ekd9zdFLMyu3RKerm4UQghypCi3I/MXB/4yD2sfHFkoPJNN91kV367A541a9awevVqqlWrZpNet25dj56WnjM2JitTZ/vWY2RmmmnTvjZ+fr5oWt4rg17/hs3KMpN88TITB37AmRPnrelLPljLO/8dTWBFP4BcgY/M1hJClA/lq6XbJevweNDWEp06dSr257D7X9jly5et20pc7/z58/j6eu4O30qBrpvx8vaiQ8f6dL6rEQDrVu8HZSg0KPHyMjL/zR9tgh2A2KNnWTRrJQaDQYIbIUQ55jkf3kUiA5ZLnN0BT8eOHa1bS4ClBULXdd555x26dOni0sqVJgYNvLyu3yZCx9/fj249b+X8+aQCl+fJsWX1/nzTNYPG2VMXUMrSGiSEEJ6g6F/iruUrP91ZmpOHsIfdXVrvvPMOnTt3ZteuXWRkZDB58mQOHjzIxYsX+f3334ujjm5nXR008zK6IQCUjpa+CAIeBM2fKiFBmM0Ko7Hgf4DePl5cvZKRZzpA9Ia/uK3LLVStVtkldS4/Nw0hRNlXzu5XrmilkVYeu9jdwtOoUSP27dvHbbfdRrdu3bh8+TL9+/dnz5491KlTpzjqWApkL4rlHYRm9ELz8oHAJ1BUAJWWZ2BxY5quK5ZEv8pPx/7DT8f+w5wVz1jP3XlvS8xmnd5D72Dzyt0oXRVYlhBCCCHsY3cLD1jW4Xn11VddXZdSLO+4UNM0UBUAHYOh4KDErHS8jdcGJNduUJ2f/5nJqyM+ZdCY7pixzAK7b8RdErULITyCbXdW9hfHPO6nlvGLhU1d90DSwpOnO++8k++//55KlSrZpCcnJ3Pvvffy66+/OlSuQ8PiN23axCOPPEL79u2Ji4sD4IsvvmDz5s0OVaI0K7T/WdPQtIIXyVJKoSmFyj6uZGSwLuYYmqYx9dMRGIwab/9+7W+n6675VywDoIUQ7qcDZtAvgX7R8rM1+LFQV65Yfy43LdpKc/7w0ABxw4YNZGTkHv5x9epVNm3a5HC5dgc83333HT169MDf35/du3eTnp4OQEpKCtOnT3e4Ip7k+jdsptmMOUvHy8uLK6npXLmcToCPD91q1OHC5ctkms3owAt3dGTfmTOYlcLLO/eaPDllZpn18nNDEEKUcQpNM4L5NGT8BllHAAOoNK4PelRKRyDLXZV0D2WZ/evs4Un27dvHvn37APjzzz+tv+/bt489e/Ywf/58u9feuZ7dXVqvv/46H3/8MUOHDmXJkiXW9Pbt25ezbq5rCmpJ0RRcvJDKufhLGIwGYo6c5eCeWIaNupPgkIp4GY3ouo5ZKZpHRt7wvSc3L2PhU+CFEMLdLBMnDOhJ0yDta6z9L8Y6aMGfgOYDZN/PVDKYz4CxuhtrLNytWbNm1pnQd955Z67z/v7+vP/++w6Xb3cLz6FDh+jYsWOu9KCgIC5dumR3BeLi4njkkUeoUqUKAQEBNGvWjOjoaOv51NRURo8eTbVq1fD396dhw4Z89NFHdj+PMyxdUZZWlixzYSGJLYNBo3LVCtzSrAYNm0TR676WjH/lXmKOnrWO+9E0DXS9WNbhkeBICOEeWai0HyHtK2wGm5iPoZJeRNN8gCzL/c9vKBjDyl/rtazFYyMmJoZjx46hlGLHjh3ExMRYj7i4OJKTk3nsscccLt/uFp6IiAiOHj1KzZo1bdI3b95M7dq17SorMTGRDh060KVLF1auXEloaCjHjh2zGag0btw41q9fz5dffknNmjVZs2YNo0aNIjIykn79+tlbfbsopVBA3OlLrFi1j5SUNFq3qkXHDvVQSmEwWOJFs1m37od1/RtW13UMBgO/xhzj8z/2cCY1hdsib+LpVm1o2aEuZ89comqoCYNRw2g0oitlM7D5RrIwoRCirNA0b/S05VB5KxgrQvrfkPKA5WTGFpT5AhgqWfKa/o2njkfJl3UcjjM8629Wo0YNwPLZWRzsDnhGjhzJs88+y2effYamaZw+fZqtW7cyceJEXn75ZbvKeuutt4iKimLBggXWtBsDqa1btzJs2DA6d+4MwJNPPsncuXPZtWtXiQQ863/7m+nv/IQ5eyDxz2v2c1uLmrz56gPWfJcSr1A5ODDXTC0FfHXgD15Yv86adizxIquPHeXnh4dQNdyEblZEnzxNi2qRBQY7QghR1miV5137JaAJBBxCZSRD4m1YBi/ndDJo5bJ1R3Py+6uzjy/NDh8+zIYNG0hISMgVANkba+Swu0tr8uTJ3HvvvXTp0oXU1FQ6duzIE088wciRIxk9erRdZS1fvpxWrVoxYMAAQkNDad68OZ988olNnttvv53ly5cTFxdnCUDWr+fw4cP06NHD3qrbTdcV7338izXYybFz93HW//Y35uzurc8/3ZjvtPR3d2zNlZZ4NY15u3dhMBgwGg3M3rgFb6NRWm+EEB7DsrFyzows3fqz5hMEwdFoxlBQZsrdYGVRqE8++YRGjRrx8ssv8+2337J06VLrsWzZMofLtSvgMZvNbNy4kQkTJnD+/Hl27NjBtm3bOHfuHK+99prdT/7PP//w0UcfUbduXVavXs1TTz3FmDFjbLaueO+992jUqBHVqlXDx8eHnj178uGHH3L77bfnWWZ6ejrJyck2h6MOHYknKSktz3Pbdv6Dl5clSNmx7Vie304Srlwm4fLlPB//x9l4DNnbcuw+dRpdL9rKyOXuW5AQosxRSrfMzso6jEp5B5XyNmT+aUkDNO8KKJUFmgFN83Zzbd3IDWN4fvvtN+655x4iIyPRNC1XAKGUYtq0aURGRuLv70/nzp05ePCgTZ709HSeeeYZQkJCCAwMpG/fvpw6dcomT2JiIkOGDMFkMmEymRgyZEiRx/m+/vrrvPHGG8THx7N371727NljPXbv3m3/RWezK+AxGo306NGDpKQkAgICaNWqFa1bt6ZChQoOPbmu67Ro0YLp06fTvHlzRo4cyYgRI2wGJb/33nts27aN5cuXEx0dzcyZMxk1ahTr1q3Ls8wZM2ZY/8Amk4moqCiH6gZQIdAv33OBAT6WNXWuXCEw0LJp6o3BSLCfP4Heeb+Zq5tMAPzr2+WEVcjdHVYQe1qCpNVICFHSNM2ASv0QdeFeuPIZXFmAuvgAespM631SZaRZ8qniGa9R6ilcsBaP/U97+fJlmjZtygcffJDn+bfffptZs2bxwQcfsHPnTsLDw+nWrRspKSnWPGPHjmXp0qUsWbKEzZs3k5qaSp8+fTCbr+0DOWjQIPbu3cuqVatYtWoVe/fuZciQIUWqY2JiIgMGDLD/4gphd5dWkyZN+Oeff1zy5BERETRq1MgmrWHDhsTGxgKQlpbGv//9b2bNmsU999zDrbfeyujRo3nwwQf5z3/+k2eZU6ZMISkpyXqcPHnS4frVqF6F+vXCc6VrGvTu2dSyMnLPd+nRu6m1e+t6PkYjDze+NVe6l8HAY81akJ6ZxW8xJ3ikVTPMdgzSKmorj+ynJYQoaUoplDkelToX/N8Gv5ewDq69PBeVdQJL11YgKvM8lq6ucshNM7R69erF66+/Tv/+/XNXSSnmzJnDCy+8QP/+/WncuDGff/45V65c4auvvgIgKSmJ+fPnM3PmTLp27Urz5s358ssv2b9/v7Uh4q+//mLVqlV8+umntGvXjnbt2vHJJ5+wYsUKDh06VGgdBwwYwJo1axy7wALYPWj5jTfeYOLEibz22mu0bNmSwMBAm/NBQUFFLqtDhw65Lv7w4cPWkdqZmZlkZmZaZ0PlMGavXZMXX19ffH19i1yHgmRlmXn1hX688OpSjh5LACwtOyMf60zdOqHouk6ve5ox4OG2+bbQPN++I75GL77c/wdJ6VdpGFKVye1u55aqYcz9fQf/6tCaEe1uw2BHYJLXbC1dKQzZ6xdYuseu5ZOgRwhRcjJBC0UL24M10DENttyzEhpC+loIGAoYwCsYTXNowX9RDGJiYoiPj6d79+7WNF9fXzp16sSWLVsYOXIk0dHRZGZm2uSJjIykcePGbNmyhR49erB161ZMJhNt2rSx5mnbti0mk4ktW7ZQv379XM/93nvvWX+++eabeemll9i2bRtNmjTB+4aekjFjxjh0fXYHPD179gSgb9++Nh+kOR+s1zdpFWbcuHG0b9+e6dOnM3DgQHbs2MG8efOYN88ysj8oKIhOnToxadIk/P39qVGjBhs3bmTRokXMmjXL3qrbzcvLSJXgCnz6wXCOHjvLpaQ0mtxyE97eXiilSLqUxvjneue7FYSmaRiA8W07MK5Ne9LNWQR4+5Clm0nLyOTxtq3wMhrsCnbylb2ju+V1uPZ63BgsCiFE8fICTUfTrn28KJVl+T3sb0jLWbDWgMctJGMvF+ylpZTKNVbV0S/+8fHxAISFhdmkh4WFceLECWseHx8fKleunCtPzuPj4+MJDQ3NVX5oaKg1z41mz55t83uFChXYuHEjGzdutEnXNK3kAp7169c79ER5ue2221i6dClTpkzh1VdfpVatWsyZM4fBgwdb8yxZsoQpU6YwePBgLl68SI0aNXjjjTd46qmnXFaPgnh5WQbZ3Vwn7IYzGsFVLGOXChp/o2ma5TuOphFg8LGUaTDi5evcFPQbW22MN0xpl1YdIYR76MANs06VEc2gWbZC8BuA5aNHx7LSsl4+W3lcsXCgsgQXpuwxoTmmTp3KtGnTHC72xs+PovQU3Jgnr/wFlRMTE+NATe1jd8DTqVMnl1agT58+9OnTJ9/z4eHhNuv0CCGEKJ0sU9GNWIKZ6z7NtZwASIG15SdnsdZyGOyAyxYeDA8PzzU0xNFhHeHhljGr8fHxREREWNMTEhKsrT7h4eFkZGSQmJho08qTkJBA+/btrXnOnj2bq/xz587laj0qSXYHPDkbe91I0zT8/PyoXr26y8bQCCGEKEsM2WMHbYOYa+MOcz7gc37OBHxKtooeRtM0u8bOFqRWrVqEh4ezdu1amjdvDkBGRgYbN27krbfeAqBly5Z4e3uzdu1aBg4cCMCZM2c4cOAAb7/9NgDt2rUjKSmJHTt20Lp1awC2b99OUlKSNSgqyPjx4/NMz4kzbr75Zvr160dwcLBd12d3wJOzuVd+vL29efDBB5k7dy5+fvlP6xZCCOF5LK08Ck3zsqy1gyUAun6yhWU6usKBjyCPoeGelZZTU1M5evSo9feYmBj27t1LcHAw1atXZ+zYsUyfPp26detSt25dpk+fTkBAAIMGDQLAZDLx+OOPM2HCBKpUqUJwcDATJ06kSZMmdO3aFbDMtu7ZsycjRoxg7ty5gGWXhD59+uQ5YPlGOevtmM1m6tevj1KKI0eOYDQaadCgAR9++CETJkxg8+bNuWZ6F8TutsSlS5dSt25d5s2bZ10QaN68edSvX5+vvvqK+fPn8+uvv/Liiy/aW7QQQogyzQwqDa58hZ70Elz5GtRVwJwd4OiWaetXf6Xcr7DsimnpDgQ8u3btonnz5tYWnPHjx9O8eXPrdg2TJ09m7NixjBo1ilatWhEXF8eaNWuoWLGitYzZs2dz7733MnDgQDp06EBAQAA//vijzVjSxYsX06RJE7p370737t259dZb+eKLL4pUx379+tG1a1dOnz5NdHQ0u3fvJi4ujm7duvHwww8TFxdHx44dGTdunF3Xrik7V6Zr3bo1r732Wq6tHVavXs1LL73Ejh07WLZsGRMmTODYsWN2VaY4JCcnYzKZSEpKclmznxBCCFtKZYKegLrwEOjXjd8whKNV+QYMVQEDKjMLrryIodLbbqtrQUriM6N169Ycb9KQwGa512mzx5V9B7gp+g+nVh8ujW666SbWrl2bq/Xm4MGDdO/enbi4OHbv3k337t05f/58kcu1u4Vn//791nVyrlejRg32798PWLq9zpw5Y2/RQgghyihN80alzLQNdgD0eFTK7Oxp6hpcnAHleTuJbJpy/vBUSUlJJCQk5Eo/d+6cdQp+pUqVyMjIsKtcuwOeBg0a8Oabb9o8UWZmJm+++SYNGjQAIC4uzq0jsYUQQrhB+oZ80n+97pfFaH79ssf3CJFbv379eOyxx1i6dCmnTp0iLi6OpUuX8vjjj3PvvfcCsGPHDurVq2dXuXaPGPu///s/+vbtS7Vq1bj11lvRNI19+/ZhNptZsWIFYNkUdNSoUfYWLYQQoizTAkGl5pFuWbNMKQWBo9B8W5dwxUojF0xLd3pae+k0d+5cxo0bx0MPPURWliUw9vLyYtiwYdYFChs0aMCnn35qV7l2j+EByyjvL7/8ksOHD6OUokGDBgwaNMhmUFNpIWN4hBCi+CllRqW+B5c/ynVOq/AMBI4C/SKasaobald0JTWG58QtjQhs6twYnsv7D3DTnr0eN4YnR2pqKv/88w9KKerUqePwRuU5HJoTWKFChRJb6VgIIURZYECrMBpljoWrP2Nda8evNwT+CzCAIcTNdSxFXLHSsoerUKECt97qXFB4PYcCni+++IK5c+fyzz//sHXrVmrUqMHs2bOpXbs2/fr1c1nlhBBClA2WdXaMGCrNRpknQebf4N0AzRiZvX2EZ3a/CNfo378/CxcuJCgoKM+d3K/3/fffO/Qcdg9a/uijjxg/fjy9evUiMTHRullo5cqVmTNnjkOVEEIIUfblbBOhGSPBt4vl/9elC1syU+sak8lkDYpNJlOBh6PsbuF5//33+eSTT7j33nt58803remtWrVi4sSJDldECCGE55AWnUK4aPNQT3H9npnFtX+m3WF3TEyMdYXG6/n6+nL58mWXVEoIIYTwaG5aabmsyMrKYt26dcydO5eUlBQATp8+TWpqHrMAi8juFp5atWqxd+/eXIsPrly50q49LYQQQgghbnTixAl69uxJbGws6enpdOvWjYoVK/L2229z9epVPv74Y4fKtTvgmTRpEk8//TRXr15FKcWOHTv4+uuvmTFjht1z4oUQQojyyCWbh7qkJqXPs88+S6tWrfjjjz+oUqWKNf2+++7jiSeecLhcuwOeRx99lKysLCZPnsyVK1cYNGgQN910E++++y4PPfSQwxURQgghyg2FLDyYj82bN/P777/j4+Njk16jRg3i4uIcLtehaekjRoxgxIgRnD9/Hl3XCQ0NdbgCQgghRLkjg5bzpeu6dQb49U6dOuXUAsdOzRUMCQmRYEcIIYQQLtOtWzebZW40TSM1NZWpU6dy9913O1xukVp4mjdvXuQphp66xLUQQgjhKq4Yw+OpZs+eTZcuXWjUqBFXr15l0KBBHDlyhJCQEL7++muHyy1SwJOzOynA1atX+fDDD2nUqBHt2rUDYNu2bRw8eFA2DBVCCCGKQrq08hUZGcnevXv5+uuv2b17N7qu8/jjjzN48GD8/f0dLrdIAc/UqVOtPz/xxBOMGTOG1157LVeekydPOlwRIYQQotxwwUrJntxC5O/vz2OPPcZjjz3msjLtHrT8v//9j127duVKf+SRR2jVqhWfffaZSyomhBBCiPLp8OHDbNiwgYSEBHRdtzn38ssvO1Sm3QGPv78/mzdvpm7dujbpmzdvxs/Pz6FKCCGEEOWOB7fQOOOTTz7hX//6FyEhIYSHh9uMIdY0reQCnrFjx/Kvf/2L6Oho2rZtC1jG8Hz22WcOV0IIIYQoV2QMT75ef/113njjDZ577jmXlmt3wPP8889Tu3Zt3n33Xb766isAGjZsyMKFCxk4cKBLKyeEEEJ4Ilfsdu6pY3gSExMZMGCAy8t1aOHBgQMHSnAjhBBCCJcbMGAAa9as4amnnnJpuQ4FPEIIIYQQrvLee+9Zf7755pt56aWX2LZtG02aNMHb29sm75gxYxx6jiIFPMHBwRw+fJiQkJAiFVq9enU2bdqUa0d1IYQQQmTz0C4pR8yePdvm9woVKrBx40Y2btxok65pWvEGPJcuXWLlypWYTKYiFXrhwoU898EQQgghhGvG8HhSwBQTE1Psz1HkLq1hw4YVZz2EEEKI8kNmaZW4IgU8Ny76I4QQQghRlsigZSGEEMIdpIWmREnAI4QQQpQ0WYenxBncXQEhhBCi3FEuOuxQs2ZNNE3LdTz99NMADB8+PNe5nB0VcqSnp/PMM88QEhJCYGAgffv25dSpUw7+EUqW2wOeuLg4HnnkEapUqUJAQADNmjUjOjraJs9ff/1F3759MZlMVKxYkbZt2xIbG+umGgshhBBlz86dOzlz5oz1WLt2LYDNqsY9e/a0yfPzzz/blDF27FiWLl3KkiVL2Lx5M6mpqfTp08flM7M3bdrEI488Qrt27YiLiwPgiy++YPPmzQ6X6daAJzExkQ4dOuDt7c3KlSv5888/mTlzJpUqVbLmOXbsGLfffjsNGjRgw4YN/PHHH7z00kuyUakQQogyS+Pa1HRnDntUrVqV8PBw67FixQrq1KlDp06drHl8fX1t8gQHB1vPJSUlMX/+fGbOnEnXrl1p3rw5X375Jfv372fdunUu+svAd999R48ePfD392fPnj2kp6cDkJKSwvTp0x0u16GA59ixY7z44os8/PDDJCQkALBq1SoOHjxoVzlvvfUWUVFRLFiwgNatW1OzZk3uuusu6tSpY83zwgsvcPfdd/P222/TvHlzateuTe/evQkNDXWk6kIIIYT7lXB31o0yMjL48ssveeyxx2x2I9+wYQOhoaHUq1ePESNGWD/jAaKjo8nMzKR79+7WtMjISBo3bsyWLVucq9B1Xn/9dT7++GM++eQTm1WW27dvz+7dux0u1+6AZ+PGjTRp0oTt27fz/fffk5qaCsC+ffuYOnWqXWUtX76cVq1aMWDAAEJDQ2nevDmffPKJ9byu6/z000/Uq1ePHj16EBoaSps2bVi2bFm+Zaanp5OcnGxzCCGEEKWKi8bwKKVyfebltIgUZNmyZVy6dInhw4db03r16sXixYv59ddfmTlzJjt37uTOO++0lhcfH4+Pjw+VK1e2KSssLIz4+Hhn/ho2Dh06RMeOHXOlBwUFcenSJYfLtTvgef7553n99ddZu3YtPj4+1vQuXbqwdetWu8r6559/+Oijj6hbty6rV6/mqaeeYsyYMSxatAiAhIQEUlNTefPNN+nZsydr1qzhvvvuo3///rmWm84xY8YMTCaT9YiKirL3EoUQQogyIT4+3uYzz2QyMWPGjEIfN3/+fHr16kVkZKQ17cEHH6R37940btyYe+65h5UrV3L48GF++umnAstSStm0EjkrIiKCo0eP5krfvHkztWvXdrhcu6el79+/n6+++ipXetWqVblw4YJdZem6TqtWrax9cs2bN+fgwYN89NFHDB061LrgYb9+/Rg3bhwAzZo1Y8uWLXz88cc2/Y45pkyZwvjx462/JycnS9AjhBCiVHHF1hKagvDwcA4dOmST7uvrW+DjTpw4wbp16/j+++8LzBcREUGNGjU4cuQIYHmujIwMEhMTbVp5EhISaN++vYNXkdvIkSN59tln+eyzz9A0jdOnT7N161YmTpzIyy+/7HC5drfwVKpUiTNnzuRK37NnDzfddJNdZUVERNCoUSObtIYNG1pnYIWEhODl5VVgnhv5+voSFBRkcwghhBCljgvG8Gialuszr7CAZ8GCBYSGhtK7d+8C8124cIGTJ08SEREBQMuWLfH29rbO7gI4c+YMBw4ccGnAM3nyZO699166dOlCamoqHTt25IknnmDkyJGMHj3a4XLt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vbs1LTIyksaNG7Nlyxan6lPcpIVHCJGLpnnn+bMQwkVctHmoUork5GSbZF9fX3x9fQt+qFKMHz+e22+/ncaNG1vTe/XqxYABA6hRowYxMTG89NJL3HnnnURHR+Pr60t8fDw+Pj5UrlzZprywsDDi4+OdvKDiJQGPEEIIUUbFx8djMpls0qZOncq0adMKfNzo0aPZt28fmzdvtkl/8MEHrT83btyYVq1aUaNGDX766Sf69++fb3llYY89CXiEEEKIEuaqrSXCw8NzzbQqrHXnmWeeYfny5fz2229Uq1atwLwRERHUqFGDI0eOABAeHk5GRgaJiYk2rTwJCQm0b1/ALM9SQMbwCCGEEO7g9MKDlnF3QUFBNkd+AY9SitGjR/P999/z66+/UqtWrUKreOHCBU6ePElERAQALVu2xNvbm7Vr11rznDlzhgMHDpT6gEdaeIQQQoiSplPiu6U//fTTfPXVV/zwww9UrFjROubGZDLh7+9Pamoq06ZN4/777yciIoLjx4/z73//m5CQEO677z5r3scff5wJEyZQpUoVgoODmThxIk2aNLHO2iqtJOARQgghyoGPPvoIgM6dO9ukL1iwgOHDh2M0Gtm/fz+LFi3i0qVLRERE0KVLF7755hsqVqxozT979my8vLwYOHAgaWlp3HXXXSxcuBCjsXTP5HR7wBMXF8dzzz3HypUrSUtLo169esyfP5+WLVuSmZnJiy++yM8//8w///yDyWSia9euvPnmm0RGRrq76kIIIYRDNFwzhsceqpD8/v7+rF69utBy/Pz8eP/993n//fften53c+sYnsTERDp06IC3tzcrV67kzz//ZObMmVSqVAmAK1eusHv3bl566SV2797N999/z+HDh+nbt687qy2EEEI4xyUbh8pmWvZwawvPW2+9RVRUFAsWLLCm1axZ0/qzyWSyGRgF8P7779O6dWtiY2OpXr16SVVVCCGEcB2F87udS7xjF7e28CxfvpxWrVoxYMAAQkNDad68OZ988kmBj0lKSkLTNGsrkBBCCCFEYdwa8Pzzzz989NFH1K1bl9WrV/PUU08xZswYFi1alGf+q1ev8vzzzzNo0CCCgoLyzJOenk5ycrLNIYQQQpQqimsztRw9pIXHLm7t0tJ1nVatWjF9+nQAmjdvzsGDB/noo48YOnSoTd7MzEweeughdF3nww8/zLfM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rb7++us8y1i8eLHy8fHJld61a1c1cuTIYrmWd999V7Vv397anx4TE1Ngl8mWLVsUoHbt2mVXfZQqmdfG3uvJ8Z///EcFBQXle96Vr01xXo873juuvBZ3v2/suZ4c586dU4cOHVJr1qxRHTp0UHfffbfSdT1Xue547xTXteQo6feNKN08uoVn9OjRhc4cqFmzZp7pbdu2BeDo0aNUqVLFmv7nn39y5513MmLEiHy/NRSkRYsWeHt7c+TIEVq0aGHXY115PeHh4Wzfvt0mT2JiIpmZmbm+weYIDw8nIyODxMREm29ECQkJtG/f3o4rKfq1vP7662zbti3XcvGtWrVi8ODBfP755zbpn376Kc2aNaNly5Z21QdK5rWx93pytG3bluTkZM6ePZvn6+PK16a4rsdd7x1XXou73zf2XE+OkJAQQkJCqFevHg0bNiQqKopt27bRrl07m8e4471TXNeSo6TfN6KUc3fEVVr9+OOPClAnTpywph04cECFhoaqSZMmOVzu/v37FaA2btzoimoW2Y3XkzP48vTp09Y8S5YsKdLgy2+++caadvr06WId4HfixAm1f/9+67F69WoFqG+//VadPHnSJm9KSoqqUKFCobN/8lMSr40913O9999/X/n5+amrV6/med4dr41SRb+esvDeKcq1lJX3TX5iY2MVoNavX2+TXhbeOzfK71quV1rfN8I9JOBRlqbcWbNmqT179qh//vlHffPNNyoyMlL17dvXmienKX7w4ME2Ux4TEhKseU6dOqXq16+vtm/frpRS6ujRo+qVV15RO3fuVDExMeqnn35SDRo0UM2bNy/WKY9FuZ6c6bV33XWX2r17t1q3bp2qVq2azfTaG69HKcsUzmrVqql169ap3bt3qzvvvLNEp3AW1GXy6aefKj8/P3Xx4sVc50rLa3OjvK5n+fLlat68eWr//v3q6NGj6pNPPlFBQUFqzJgx+V6PUu5/bfK7nrL03insWsrS+2b79u3q/fffV3v27FHHjx9Xv/76q7r99ttVnTp1cgUApf29U5RrKcvvG1EyJOBRSkVHR6s2bdook8mk/Pz8VP369dXUqVPV5cuXrXny62uuUaOGNU/ODTLnG0dsbKzq2LGjCg4OVj4+PqpOnTpqzJgx6sKFC26/HqUs32h79+6t/P39VXBwsBo9erTNjfDG61FKqbS0NDV69GgVHBys/P39VZ8+fVRsbGyxXs/1Cgp42rVrpwYNGlTg49z92uRXr+uvZ+XKlapZs2aqQoUKKiAgQDVu3FjNmTNHZWZm5ns9Srn/tbm+XtdfT1l67xR2LUqVnffNvn37VJcuXVRwcLDy9fVVNWvWVE899ZQ6depUrryl/b1TlGspy+8bUTJkt3QhhBBCeDxZh0cIIYQQHk8CHiGEEEJ4PAl4hBBCCOHxJOARQgghhMeTgEcIIYQQHk8CHiGEEEJ4PAl4hBBCCOHxJOARQgghhMeTgEeIQhw/fhxN09i7d2+xlK9pGsuWLXP48Rs2bEDTNDRN49577y0wb+fOnRk7dqzDzyUKlvM6VKpUyd1VEULcQAIeUaoNHz680A/x4hYVFcWZM2do3LgxcC3AuHTpklvrdaNDhw6xcOFCd1ejXMjv3+WZM2eYM2dOiddHCFE4CXiEKITRaCQ8PBwvLy93V6VAoaGhpaJlITMz091VcJvw8HBMJpO7qyGEyIMEPKJM27hxI61bt8bX15eIiAief/55srKyrOc7d+7MmDFjmDx5MsHBwYSHhzNt2jSbMv7++29uv/12/Pz8aNSoEevWrbPpZrq+S+v48eN06dIFgMqVK6NpGsOHDwegZs2aub7dN2vWzOb5jhw5QseOHa3PtXbt2lzXFBcXx4MPPkjlypWpUqUK/fr14/jx43b/bS5fvszQoUOpUKECERERzJw5M1eejIwMJk+ezE033URgYCBt2rRhw4YNNnk++eQToqKiCAgI4L777mPWrFk2gdW0adNo1qwZn332GbVr18bX1xelFElJSTz55JOEhoYSFBTEnXfeyR9//GFT9o8//kjLli3x8/Ojdu3avPLKKzav37Rp06hevTq+vr5ERkYyZsyYIl17Ydd14cIFHn74YapVq0ZAQABNmjTh66+/tinj22+/pUmTJvj7+1OlShW6du3K5cuXmTZtGp9//jk//PCDtQvrxr+ZEKL0Kd1fWYUoQFxcHHfffTfDhw9n0aJF/P3334wYMQI/Pz+bIOPzzz9n/PjxbN++na1btzJ8+HA6dOhAt27d0HWde++9l+rVq7N9+3ZSUlKYMGFCvs8ZFRXFd999x/3338+hQ4cICgrC39+/SPXVdZ3+/fsTEhLCtm3bSE5OzjWe5sqVK3Tp0oU77riD3377DS8vL15//XV69uzJvn378PHxKfLfZ9KkSaxfv56lS5cSHh7Ov//9b6Kjo2nWrJk1z6OPPsrx48dZsmQJkZGRLF26lJ49e7J//37q1q3L77//zlNPPcVbb71F3759WbduHS+99FKu5zp69Cj//e9/+e677zAajQD07t2b4OBgfv75Z0wmE3PnzuWuu+7i8OHDBAcHs3r1ah555BHee+897rjjDo4dO8aTTz4JwNSpU/n222+ZPXs2S5Ys4ZZbbiE+Pj5XwJSfwq7r6tWrtGzZkueee46goCB++uknhgwZQu3atWnTpg1nzpzh4Ycf5u233+a+++4jJSWFTZs2oZRi4sSJ/PXXXyQnJ7NgwQIAgoODi/y6CCHcxL2btQtRsGHDhql+/frlee7f//63ql+/vtJ13Zr2f//3f6pChQrKbDYrpZTq1KmTuv32220ed9ttt6nnnntOKaXUypUrlZeXlzpz5oz1/Nq1axWgli5dqpRSKiYmRgFqz549Siml1q9frwCVmJhoU26NGjXU7NmzbdKaNm2qpk6dqpRSavXq1cpoNKqTJ09az69cudLmuebPn5/rmtLT05W/v79avXp1nn+HvOqTkpKifHx81JIlS6xpFy5cUP7+/urZZ59VSil19OhRpWmaiouLsynvrrvuUlOmTFFKKfXggw+q3r1725wfPHiwMplM1t+nTp2qvL29VUJCgjXtl19+UUFBQerq1as2j61Tp46aO3euUkqpO+64Q02fPt3m/BdffKEiIiKUUkrNnDlT1atXT2VkZOR53fkpynXl5e6771YTJkxQSikVHR2tAHX8+PE88xb073LBggU2fx8hROkgLTyizPrrr79o164dmqZZ0zp06EBqaiqnTp2ievXqANx66602j4uIiCAhIQGwDPSNiooiPDzcer5169bFVt/q1atTrVo1a1q7du1s8kRHR3P06FEqVqxok3716lWOHTtW5Oc6duwYGRkZNuUHBwdTv3596++7d+9GKUW9evVsHpuenk6VKlUAy9/nvvvusznfunVrVqxYYZNWo0YNqlatanMdqamp1nJypKWlWa8jOjqanTt38sYbb1jPm81mrl69ypUrVxgwYABz5syhdu3a9OzZk7vvvpt77rmn0LFURbkus9nMm2++yTfffENcXBzp6emkp6cTGBgIQNOmTbnrrrto0qQJPXr0oHv37jzwwANUrly5wOcWQpReEvCI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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "ds.plot.scatter(x=\"longitude\", y=\"latitude\", hue=\"h_li\", vmin=-100, vmax=2000)" ] @@ -101,7 +727,9 @@ { "cell_type": "markdown", "id": "b8875936", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "---------------------------------------\n", "## Key steps for loading (reading) ICESat-2 data\n", @@ -119,7 +747,9 @@ { "cell_type": "markdown", "id": "9bf6d38c", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Step 0: Get some data if you haven't already\n", "Here are a few lines of code to get you set up with a few data files if you don't already have some on your local system." @@ -127,7 +757,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "id": "63da2b3c", "metadata": {}, "outputs": [], @@ -138,10 +768,24 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 10, "id": "e6f7c047", "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'Query' object has no attribute '_session'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[10], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mregion_a\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdownload_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpath_root\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/envs/general/lib/python3.11/site-packages/icepyx/core/query.py:1129\u001b[0m, in \u001b[0;36mQuery.download_granules\u001b[0;34m(self, path, verbose, subset, restart, **kwargs)\u001b[0m\n\u001b[1;32m 1124\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1125\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[1;32m 1126\u001b[0m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124morderIDs\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 1127\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39morderIDs) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m 1128\u001b[0m ):\n\u001b[0;32m-> 1129\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43morder_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43mverbose\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mverbose\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msubset\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msubset\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1131\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39mdownload(verbose, path, session\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_session, restart\u001b[38;5;241m=\u001b[39mrestart)\n", + "File \u001b[0;32m~/envs/general/lib/python3.11/site-packages/icepyx/core/query.py:1065\u001b[0m, in \u001b[0;36mQuery.order_granules\u001b[0;34m(self, verbose, subset, email, **kwargs)\u001b[0m\n\u001b[1;32m 1048\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39mplace_order(\n\u001b[1;32m 1049\u001b[0m tempCMRparams,\n\u001b[1;32m 1050\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreqparams,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1055\u001b[0m geom_filepath\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_spatial\u001b[38;5;241m.\u001b[39m_geom_file,\n\u001b[1;32m 1056\u001b[0m )\n\u001b[1;32m 1058\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1059\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39mplace_order(\n\u001b[1;32m 1060\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mCMRparams,\n\u001b[1;32m 1061\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreqparams,\n\u001b[1;32m 1062\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msubsetparams(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs),\n\u001b[1;32m 1063\u001b[0m verbose,\n\u001b[1;32m 1064\u001b[0m subset,\n\u001b[0;32m-> 1065\u001b[0m session\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_session\u001b[49m,\n\u001b[1;32m 1066\u001b[0m geom_filepath\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_spatial\u001b[38;5;241m.\u001b[39m_geom_file,\n\u001b[1;32m 1067\u001b[0m )\n", + "\u001b[0;31mAttributeError\u001b[0m: 'Query' object has no attribute '_session'" + ] + } + ], "source": [ "region_a.download_granules(path=path_root)" ] @@ -182,7 +826,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 11, "id": "9cde6679", "metadata": {}, "outputs": [], @@ -192,7 +836,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 13, "id": "8b6edf0c", "metadata": {}, "outputs": [], @@ -202,7 +846,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 14, "id": "e683ebf7", "metadata": {}, "outputs": [], @@ -213,7 +857,9 @@ { "cell_type": "markdown", "id": "92743496", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Step 2: Create a filename pattern for your data files\n", "\n", @@ -227,7 +873,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 15, "id": "7318abd0", "metadata": {}, "outputs": [], @@ -238,7 +884,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 16, "id": "f43e8664", "metadata": {}, "outputs": [], @@ -248,7 +894,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 17, "id": "992a77fb", "metadata": {}, "outputs": [], @@ -258,7 +904,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 18, "id": "6aec1a70", "metadata": {}, "outputs": [], @@ -269,7 +915,9 @@ { "cell_type": "markdown", "id": "4275b04c", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Step 3: Create an icepyx read object\n", "\n", @@ -277,29 +925,52 @@ "- `path` = a string with the full file path or full directory path to your hdf5 (.h5) format files.\n", "- `product` = the data product you're working with, also known as the \"short name\".\n", "\n", - "The `Read` object also accepts two optional keyword inputs:\n", - "- `pattern` = a formatted string indicating the filename pattern required for Intake's path_as_pattern argument.\n", - "- `catalog` = a string with the full path to an Intake catalog, for users who wish to use their own catalog (note this may have unintended consequenses if multiple granules are being combined)." + "The `Read` object also accepts the optional keyword input:\n", + "- `pattern` = a formatted string indicating the filename pattern required for Intake's path_as_pattern argument." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 19, "id": "39bd7eb8", "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "You have 6 files matching the filename pattern to be read in.\n" + ] + } + ], "source": [ "reader = ipx.Read(data_source=path_root, product=\"ATL06\", filename_pattern=pattern) # or ipx.Read(filepath, \"ATLXX\") if your filenames match the default pattern" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 20, "id": "6c9ebc4a", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "['../../../../data/ATL06/processed_ATL06_20190226005526_09100205_006_02.h5',\n", + " '../../../../data/ATL06/processed_ATL06_20191201105502_10010505_006_01.h5',\n", + " '../../../../data/ATL06/processed_ATL06_20190225121032_09020203_006_02.h5',\n", + " '../../../../data/ATL06/processed_ATL06_20190222010344_08490205_006_02.h5',\n", + " '../../../../data/ATL06/processed_ATL06_20191130112041_09860505_006_01.h5',\n", + " '../../../../data/ATL06/processed_ATL06_20191202102922_10160505_006_01.h5']" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "reader._filelist" ] @@ -307,7 +978,9 @@ { "cell_type": "markdown", "id": "da8d8024", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Step 4: Specify variables to be read in\n", "\n", @@ -320,12 +993,616 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "id": "18f65f67", "metadata": { "scrolled": true }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "['ancillary_data/atlas_sdp_gps_epoch',\n", + " 'ancillary_data/control',\n", + " 'ancillary_data/data_end_utc',\n", + " 'ancillary_data/data_start_utc',\n", + " 'ancillary_data/end_cycle',\n", + " 'ancillary_data/end_delta_time',\n", + " 'ancillary_data/end_geoseg',\n", + " 'ancillary_data/end_gpssow',\n", + " 'ancillary_data/end_gpsweek',\n", + " 'ancillary_data/end_orbit',\n", + " 'ancillary_data/end_region',\n", + " 'ancillary_data/end_rgt',\n", + " 'ancillary_data/granule_end_utc',\n", + " 'ancillary_data/granule_start_utc',\n", + " 'ancillary_data/land_ice/dt_hist',\n", + " 'ancillary_data/land_ice/fit_maxiter',\n", + " 'ancillary_data/land_ice/fpb_maxiter',\n", + " 'ancillary_data/land_ice/max_res_ids',\n", + " 'ancillary_data/land_ice/min_dist',\n", + " 'ancillary_data/land_ice/min_gain_th',\n", + " 'ancillary_data/land_ice/min_n_pe',\n", + " 'ancillary_data/land_ice/min_n_sel',\n", + " 'ancillary_data/land_ice/min_signal_conf',\n", + " 'ancillary_data/land_ice/n_hist',\n", + " 'ancillary_data/land_ice/n_sigmas',\n", + " 'ancillary_data/land_ice/nhist_bins',\n", + " 'ancillary_data/land_ice/proc_interval',\n", + " 'ancillary_data/land_ice/qs_lim_bsc',\n", + " 'ancillary_data/land_ice/qs_lim_hrs',\n", + " 'ancillary_data/land_ice/qs_lim_hsigma',\n", + " 'ancillary_data/land_ice/qs_lim_msw',\n", + " 'ancillary_data/land_ice/qs_lim_snr',\n", + " 'ancillary_data/land_ice/qs_lim_sss',\n", + " 'ancillary_data/land_ice/rbin_width',\n", + " 'ancillary_data/land_ice/sigma_beam',\n", + " 'ancillary_data/land_ice/sigma_tx',\n", + " 'ancillary_data/land_ice/t_dead',\n", + " 'ancillary_data/land_ice/txp_maxiter',\n", + " 'ancillary_data/qa_at_interval',\n", + " 'ancillary_data/release',\n", + " 'ancillary_data/start_cycle',\n", + " 'ancillary_data/start_delta_time',\n", + " 'ancillary_data/start_geoseg',\n", + " 'ancillary_data/start_gpssow',\n", + " 'ancillary_data/start_gpsweek',\n", + " 'ancillary_data/start_orbit',\n", + " 'ancillary_data/start_region',\n", + " 'ancillary_data/start_rgt',\n", + " 'ancillary_data/version',\n", + " 'gt1l/land_ice_segments/atl06_quality_summary',\n", + " 'gt1l/land_ice_segments/bias_correction/fpb_mean_corr',\n", + " 'gt1l/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", + " 'gt1l/land_ice_segments/bias_correction/fpb_med_corr',\n", + " 'gt1l/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", + " 'gt1l/land_ice_segments/bias_correction/fpb_n_corr',\n", + " 'gt1l/land_ice_segments/bias_correction/med_r_fit',\n", + " 'gt1l/land_ice_segments/bias_correction/tx_mean_corr',\n", + " 'gt1l/land_ice_segments/bias_correction/tx_med_corr',\n", + " 'gt1l/land_ice_segments/delta_time',\n", + " 'gt1l/land_ice_segments/dem/dem_flag',\n", + " 'gt1l/land_ice_segments/dem/dem_h',\n", + " 'gt1l/land_ice_segments/dem/geoid_free2mean',\n", + " 'gt1l/land_ice_segments/dem/geoid_h',\n", + " 'gt1l/land_ice_segments/fit_statistics/dh_fit_dx',\n", + " 'gt1l/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", + " 'gt1l/land_ice_segments/fit_statistics/dh_fit_dy',\n", + " 'gt1l/land_ice_segments/fit_statistics/h_expected_rms',\n", + " 'gt1l/land_ice_segments/fit_statistics/h_mean',\n", + " 'gt1l/land_ice_segments/fit_statistics/h_rms_misfit',\n", + " 'gt1l/land_ice_segments/fit_statistics/h_robust_sprd',\n", + " 'gt1l/land_ice_segments/fit_statistics/n_fit_photons',\n", + " 'gt1l/land_ice_segments/fit_statistics/n_seg_pulses',\n", + " 'gt1l/land_ice_segments/fit_statistics/sigma_h_mean',\n", + " 'gt1l/land_ice_segments/fit_statistics/signal_selection_source',\n", + " 'gt1l/land_ice_segments/fit_statistics/signal_selection_source_status',\n", + " 'gt1l/land_ice_segments/fit_statistics/snr',\n", + " 'gt1l/land_ice_segments/fit_statistics/snr_significance',\n", + " 'gt1l/land_ice_segments/fit_statistics/w_surface_window_final',\n", + " 'gt1l/land_ice_segments/geophysical/bckgrd',\n", + " 'gt1l/land_ice_segments/geophysical/bsnow_conf',\n", + " 'gt1l/land_ice_segments/geophysical/bsnow_h',\n", + " 'gt1l/land_ice_segments/geophysical/bsnow_od',\n", + " 'gt1l/land_ice_segments/geophysical/cloud_flg_asr',\n", + " 'gt1l/land_ice_segments/geophysical/cloud_flg_atm',\n", + " 'gt1l/land_ice_segments/geophysical/dac',\n", + " 'gt1l/land_ice_segments/geophysical/e_bckgrd',\n", + " 'gt1l/land_ice_segments/geophysical/layer_flag',\n", + " 'gt1l/land_ice_segments/geophysical/msw_flag',\n", + " 'gt1l/land_ice_segments/geophysical/neutat_delay_total',\n", + " 'gt1l/land_ice_segments/geophysical/r_eff',\n", + " 'gt1l/land_ice_segments/geophysical/solar_azimuth',\n", + " 'gt1l/land_ice_segments/geophysical/solar_elevation',\n", + " 'gt1l/land_ice_segments/geophysical/tide_earth',\n", + " 'gt1l/land_ice_segments/geophysical/tide_earth_free2mean',\n", + " 'gt1l/land_ice_segments/geophysical/tide_equilibrium',\n", + " 'gt1l/land_ice_segments/geophysical/tide_load',\n", + " 'gt1l/land_ice_segments/geophysical/tide_ocean',\n", + " 'gt1l/land_ice_segments/geophysical/tide_pole',\n", + " 'gt1l/land_ice_segments/ground_track/ref_azimuth',\n", + " 'gt1l/land_ice_segments/ground_track/ref_coelv',\n", + " 'gt1l/land_ice_segments/ground_track/seg_azimuth',\n", + " 'gt1l/land_ice_segments/ground_track/sigma_geo_at',\n", + " 'gt1l/land_ice_segments/ground_track/sigma_geo_r',\n", + " 'gt1l/land_ice_segments/ground_track/sigma_geo_xt',\n", + " 'gt1l/land_ice_segments/ground_track/x_atc',\n", + " 'gt1l/land_ice_segments/ground_track/y_atc',\n", + " 'gt1l/land_ice_segments/h_li',\n", + " 'gt1l/land_ice_segments/h_li_sigma',\n", + " 'gt1l/land_ice_segments/latitude',\n", + " 'gt1l/land_ice_segments/longitude',\n", + " 'gt1l/land_ice_segments/segment_id',\n", + " 'gt1l/land_ice_segments/sigma_geo_h',\n", + " 'gt1l/residual_histogram/bckgrd_per_m',\n", + " 'gt1l/residual_histogram/bin_top_h',\n", + " 'gt1l/residual_histogram/count',\n", + " 'gt1l/residual_histogram/delta_time',\n", + " 'gt1l/residual_histogram/ds_segment_id',\n", + " 'gt1l/residual_histogram/lat_mean',\n", + " 'gt1l/residual_histogram/lon_mean',\n", + " 'gt1l/residual_histogram/pulse_count',\n", + " 'gt1l/residual_histogram/segment_id_list',\n", + " 'gt1l/residual_histogram/x_atc_mean',\n", + " 'gt1l/segment_quality/delta_time',\n", + " 'gt1l/segment_quality/record_number',\n", + " 'gt1l/segment_quality/reference_pt_lat',\n", + " 'gt1l/segment_quality/reference_pt_lon',\n", + " 'gt1l/segment_quality/segment_id',\n", + " 'gt1l/segment_quality/signal_selection_source',\n", + " 'gt1l/segment_quality/signal_selection_status/signal_selection_status_all',\n", + " 'gt1l/segment_quality/signal_selection_status/signal_selection_status_backup',\n", + " 'gt1l/segment_quality/signal_selection_status/signal_selection_status_confident',\n", + " 'gt1r/land_ice_segments/atl06_quality_summary',\n", + " 'gt1r/land_ice_segments/bias_correction/fpb_mean_corr',\n", + " 'gt1r/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", + " 'gt1r/land_ice_segments/bias_correction/fpb_med_corr',\n", + " 'gt1r/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", + " 'gt1r/land_ice_segments/bias_correction/fpb_n_corr',\n", + " 'gt1r/land_ice_segments/bias_correction/med_r_fit',\n", + " 'gt1r/land_ice_segments/bias_correction/tx_mean_corr',\n", + " 'gt1r/land_ice_segments/bias_correction/tx_med_corr',\n", + " 'gt1r/land_ice_segments/delta_time',\n", + " 'gt1r/land_ice_segments/dem/dem_flag',\n", + " 'gt1r/land_ice_segments/dem/dem_h',\n", + " 'gt1r/land_ice_segments/dem/geoid_free2mean',\n", + " 'gt1r/land_ice_segments/dem/geoid_h',\n", + " 'gt1r/land_ice_segments/fit_statistics/dh_fit_dx',\n", + " 'gt1r/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", + " 'gt1r/land_ice_segments/fit_statistics/dh_fit_dy',\n", + " 'gt1r/land_ice_segments/fit_statistics/h_expected_rms',\n", + " 'gt1r/land_ice_segments/fit_statistics/h_mean',\n", + " 'gt1r/land_ice_segments/fit_statistics/h_rms_misfit',\n", + " 'gt1r/land_ice_segments/fit_statistics/h_robust_sprd',\n", + " 'gt1r/land_ice_segments/fit_statistics/n_fit_photons',\n", + " 'gt1r/land_ice_segments/fit_statistics/n_seg_pulses',\n", + " 'gt1r/land_ice_segments/fit_statistics/sigma_h_mean',\n", + " 'gt1r/land_ice_segments/fit_statistics/signal_selection_source',\n", + " 'gt1r/land_ice_segments/fit_statistics/signal_selection_source_status',\n", + " 'gt1r/land_ice_segments/fit_statistics/snr',\n", + " 'gt1r/land_ice_segments/fit_statistics/snr_significance',\n", + " 'gt1r/land_ice_segments/fit_statistics/w_surface_window_final',\n", + " 'gt1r/land_ice_segments/geophysical/bckgrd',\n", + " 'gt1r/land_ice_segments/geophysical/bsnow_conf',\n", + " 'gt1r/land_ice_segments/geophysical/bsnow_h',\n", + " 'gt1r/land_ice_segments/geophysical/bsnow_od',\n", + " 'gt1r/land_ice_segments/geophysical/cloud_flg_asr',\n", + " 'gt1r/land_ice_segments/geophysical/cloud_flg_atm',\n", + " 'gt1r/land_ice_segments/geophysical/dac',\n", + " 'gt1r/land_ice_segments/geophysical/e_bckgrd',\n", + " 'gt1r/land_ice_segments/geophysical/layer_flag',\n", + " 'gt1r/land_ice_segments/geophysical/msw_flag',\n", + " 'gt1r/land_ice_segments/geophysical/neutat_delay_total',\n", + " 'gt1r/land_ice_segments/geophysical/r_eff',\n", + " 'gt1r/land_ice_segments/geophysical/solar_azimuth',\n", + " 'gt1r/land_ice_segments/geophysical/solar_elevation',\n", + " 'gt1r/land_ice_segments/geophysical/tide_earth',\n", + " 'gt1r/land_ice_segments/geophysical/tide_earth_free2mean',\n", + " 'gt1r/land_ice_segments/geophysical/tide_equilibrium',\n", + " 'gt1r/land_ice_segments/geophysical/tide_load',\n", + " 'gt1r/land_ice_segments/geophysical/tide_ocean',\n", + " 'gt1r/land_ice_segments/geophysical/tide_pole',\n", + " 'gt1r/land_ice_segments/ground_track/ref_azimuth',\n", + " 'gt1r/land_ice_segments/ground_track/ref_coelv',\n", + " 'gt1r/land_ice_segments/ground_track/seg_azimuth',\n", + " 'gt1r/land_ice_segments/ground_track/sigma_geo_at',\n", + " 'gt1r/land_ice_segments/ground_track/sigma_geo_r',\n", + " 'gt1r/land_ice_segments/ground_track/sigma_geo_xt',\n", + " 'gt1r/land_ice_segments/ground_track/x_atc',\n", + " 'gt1r/land_ice_segments/ground_track/y_atc',\n", + " 'gt1r/land_ice_segments/h_li',\n", + " 'gt1r/land_ice_segments/h_li_sigma',\n", + " 'gt1r/land_ice_segments/latitude',\n", + " 'gt1r/land_ice_segments/longitude',\n", + " 'gt1r/land_ice_segments/segment_id',\n", + " 'gt1r/land_ice_segments/sigma_geo_h',\n", + " 'gt1r/residual_histogram/bckgrd_per_m',\n", + " 'gt1r/residual_histogram/bin_top_h',\n", + " 'gt1r/residual_histogram/count',\n", + " 'gt1r/residual_histogram/delta_time',\n", + " 'gt1r/residual_histogram/ds_segment_id',\n", + " 'gt1r/residual_histogram/lat_mean',\n", + " 'gt1r/residual_histogram/lon_mean',\n", + " 'gt1r/residual_histogram/pulse_count',\n", + " 'gt1r/residual_histogram/segment_id_list',\n", + " 'gt1r/residual_histogram/x_atc_mean',\n", + " 'gt1r/segment_quality/delta_time',\n", + " 'gt1r/segment_quality/record_number',\n", + " 'gt1r/segment_quality/reference_pt_lat',\n", + " 'gt1r/segment_quality/reference_pt_lon',\n", + " 'gt1r/segment_quality/segment_id',\n", + " 'gt1r/segment_quality/signal_selection_source',\n", + " 'gt1r/segment_quality/signal_selection_status/signal_selection_status_all',\n", + " 'gt1r/segment_quality/signal_selection_status/signal_selection_status_backup',\n", + " 'gt1r/segment_quality/signal_selection_status/signal_selection_status_confident',\n", + " 'gt2l/land_ice_segments/atl06_quality_summary',\n", + " 'gt2l/land_ice_segments/bias_correction/fpb_mean_corr',\n", + " 'gt2l/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", + " 'gt2l/land_ice_segments/bias_correction/fpb_med_corr',\n", + " 'gt2l/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", + " 'gt2l/land_ice_segments/bias_correction/fpb_n_corr',\n", + " 'gt2l/land_ice_segments/bias_correction/med_r_fit',\n", + " 'gt2l/land_ice_segments/bias_correction/tx_mean_corr',\n", + " 'gt2l/land_ice_segments/bias_correction/tx_med_corr',\n", + " 'gt2l/land_ice_segments/delta_time',\n", + " 'gt2l/land_ice_segments/dem/dem_flag',\n", + " 'gt2l/land_ice_segments/dem/dem_h',\n", + " 'gt2l/land_ice_segments/dem/geoid_free2mean',\n", + " 'gt2l/land_ice_segments/dem/geoid_h',\n", + " 'gt2l/land_ice_segments/fit_statistics/dh_fit_dx',\n", + " 'gt2l/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", + " 'gt2l/land_ice_segments/fit_statistics/dh_fit_dy',\n", + " 'gt2l/land_ice_segments/fit_statistics/h_expected_rms',\n", + " 'gt2l/land_ice_segments/fit_statistics/h_mean',\n", + " 'gt2l/land_ice_segments/fit_statistics/h_rms_misfit',\n", + " 'gt2l/land_ice_segments/fit_statistics/h_robust_sprd',\n", + " 'gt2l/land_ice_segments/fit_statistics/n_fit_photons',\n", + " 'gt2l/land_ice_segments/fit_statistics/n_seg_pulses',\n", + " 'gt2l/land_ice_segments/fit_statistics/sigma_h_mean',\n", + " 'gt2l/land_ice_segments/fit_statistics/signal_selection_source',\n", + " 'gt2l/land_ice_segments/fit_statistics/signal_selection_source_status',\n", + " 'gt2l/land_ice_segments/fit_statistics/snr',\n", + " 'gt2l/land_ice_segments/fit_statistics/snr_significance',\n", + " 'gt2l/land_ice_segments/fit_statistics/w_surface_window_final',\n", + " 'gt2l/land_ice_segments/geophysical/bckgrd',\n", + " 'gt2l/land_ice_segments/geophysical/bsnow_conf',\n", + " 'gt2l/land_ice_segments/geophysical/bsnow_h',\n", + " 'gt2l/land_ice_segments/geophysical/bsnow_od',\n", + " 'gt2l/land_ice_segments/geophysical/cloud_flg_asr',\n", + " 'gt2l/land_ice_segments/geophysical/cloud_flg_atm',\n", + " 'gt2l/land_ice_segments/geophysical/dac',\n", + " 'gt2l/land_ice_segments/geophysical/e_bckgrd',\n", + " 'gt2l/land_ice_segments/geophysical/layer_flag',\n", + " 'gt2l/land_ice_segments/geophysical/msw_flag',\n", + " 'gt2l/land_ice_segments/geophysical/neutat_delay_total',\n", + " 'gt2l/land_ice_segments/geophysical/r_eff',\n", + " 'gt2l/land_ice_segments/geophysical/solar_azimuth',\n", + " 'gt2l/land_ice_segments/geophysical/solar_elevation',\n", + " 'gt2l/land_ice_segments/geophysical/tide_earth',\n", + " 'gt2l/land_ice_segments/geophysical/tide_earth_free2mean',\n", + " 'gt2l/land_ice_segments/geophysical/tide_equilibrium',\n", + " 'gt2l/land_ice_segments/geophysical/tide_load',\n", + " 'gt2l/land_ice_segments/geophysical/tide_ocean',\n", + " 'gt2l/land_ice_segments/geophysical/tide_pole',\n", + " 'gt2l/land_ice_segments/ground_track/ref_azimuth',\n", + " 'gt2l/land_ice_segments/ground_track/ref_coelv',\n", + " 'gt2l/land_ice_segments/ground_track/seg_azimuth',\n", + " 'gt2l/land_ice_segments/ground_track/sigma_geo_at',\n", + " 'gt2l/land_ice_segments/ground_track/sigma_geo_r',\n", + " 'gt2l/land_ice_segments/ground_track/sigma_geo_xt',\n", + " 'gt2l/land_ice_segments/ground_track/x_atc',\n", + " 'gt2l/land_ice_segments/ground_track/y_atc',\n", + " 'gt2l/land_ice_segments/h_li',\n", + " 'gt2l/land_ice_segments/h_li_sigma',\n", + " 'gt2l/land_ice_segments/latitude',\n", + " 'gt2l/land_ice_segments/longitude',\n", + " 'gt2l/land_ice_segments/segment_id',\n", + " 'gt2l/land_ice_segments/sigma_geo_h',\n", + " 'gt2l/residual_histogram/bckgrd_per_m',\n", + " 'gt2l/residual_histogram/bin_top_h',\n", + " 'gt2l/residual_histogram/count',\n", + " 'gt2l/residual_histogram/delta_time',\n", + " 'gt2l/residual_histogram/ds_segment_id',\n", + " 'gt2l/residual_histogram/lat_mean',\n", + " 'gt2l/residual_histogram/lon_mean',\n", + " 'gt2l/residual_histogram/pulse_count',\n", + " 'gt2l/residual_histogram/segment_id_list',\n", + " 'gt2l/residual_histogram/x_atc_mean',\n", + " 'gt2l/segment_quality/delta_time',\n", + " 'gt2l/segment_quality/record_number',\n", + " 'gt2l/segment_quality/reference_pt_lat',\n", + " 'gt2l/segment_quality/reference_pt_lon',\n", + " 'gt2l/segment_quality/segment_id',\n", + " 'gt2l/segment_quality/signal_selection_source',\n", + " 'gt2l/segment_quality/signal_selection_status/signal_selection_status_all',\n", + " 'gt2l/segment_quality/signal_selection_status/signal_selection_status_backup',\n", + " 'gt2l/segment_quality/signal_selection_status/signal_selection_status_confident',\n", + " 'gt2r/land_ice_segments/atl06_quality_summary',\n", + " 'gt2r/land_ice_segments/bias_correction/fpb_mean_corr',\n", + " 'gt2r/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", + " 'gt2r/land_ice_segments/bias_correction/fpb_med_corr',\n", + " 'gt2r/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", + " 'gt2r/land_ice_segments/bias_correction/fpb_n_corr',\n", + " 'gt2r/land_ice_segments/bias_correction/med_r_fit',\n", + " 'gt2r/land_ice_segments/bias_correction/tx_mean_corr',\n", + " 'gt2r/land_ice_segments/bias_correction/tx_med_corr',\n", + " 'gt2r/land_ice_segments/delta_time',\n", + " 'gt2r/land_ice_segments/dem/dem_flag',\n", + " 'gt2r/land_ice_segments/dem/dem_h',\n", + " 'gt2r/land_ice_segments/dem/geoid_free2mean',\n", + " 'gt2r/land_ice_segments/dem/geoid_h',\n", + " 'gt2r/land_ice_segments/fit_statistics/dh_fit_dx',\n", + " 'gt2r/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", + " 'gt2r/land_ice_segments/fit_statistics/dh_fit_dy',\n", + " 'gt2r/land_ice_segments/fit_statistics/h_expected_rms',\n", + " 'gt2r/land_ice_segments/fit_statistics/h_mean',\n", + " 'gt2r/land_ice_segments/fit_statistics/h_rms_misfit',\n", + " 'gt2r/land_ice_segments/fit_statistics/h_robust_sprd',\n", + " 'gt2r/land_ice_segments/fit_statistics/n_fit_photons',\n", + " 'gt2r/land_ice_segments/fit_statistics/n_seg_pulses',\n", + " 'gt2r/land_ice_segments/fit_statistics/sigma_h_mean',\n", + " 'gt2r/land_ice_segments/fit_statistics/signal_selection_source',\n", + " 'gt2r/land_ice_segments/fit_statistics/signal_selection_source_status',\n", + " 'gt2r/land_ice_segments/fit_statistics/snr',\n", + " 'gt2r/land_ice_segments/fit_statistics/snr_significance',\n", + " 'gt2r/land_ice_segments/fit_statistics/w_surface_window_final',\n", + " 'gt2r/land_ice_segments/geophysical/bckgrd',\n", + " 'gt2r/land_ice_segments/geophysical/bsnow_conf',\n", + " 'gt2r/land_ice_segments/geophysical/bsnow_h',\n", + " 'gt2r/land_ice_segments/geophysical/bsnow_od',\n", + " 'gt2r/land_ice_segments/geophysical/cloud_flg_asr',\n", + " 'gt2r/land_ice_segments/geophysical/cloud_flg_atm',\n", + " 'gt2r/land_ice_segments/geophysical/dac',\n", + " 'gt2r/land_ice_segments/geophysical/e_bckgrd',\n", + " 'gt2r/land_ice_segments/geophysical/layer_flag',\n", + " 'gt2r/land_ice_segments/geophysical/msw_flag',\n", + " 'gt2r/land_ice_segments/geophysical/neutat_delay_total',\n", + " 'gt2r/land_ice_segments/geophysical/r_eff',\n", + " 'gt2r/land_ice_segments/geophysical/solar_azimuth',\n", + " 'gt2r/land_ice_segments/geophysical/solar_elevation',\n", + " 'gt2r/land_ice_segments/geophysical/tide_earth',\n", + " 'gt2r/land_ice_segments/geophysical/tide_earth_free2mean',\n", + " 'gt2r/land_ice_segments/geophysical/tide_equilibrium',\n", + " 'gt2r/land_ice_segments/geophysical/tide_load',\n", + " 'gt2r/land_ice_segments/geophysical/tide_ocean',\n", + " 'gt2r/land_ice_segments/geophysical/tide_pole',\n", + " 'gt2r/land_ice_segments/ground_track/ref_azimuth',\n", + " 'gt2r/land_ice_segments/ground_track/ref_coelv',\n", + " 'gt2r/land_ice_segments/ground_track/seg_azimuth',\n", + " 'gt2r/land_ice_segments/ground_track/sigma_geo_at',\n", + " 'gt2r/land_ice_segments/ground_track/sigma_geo_r',\n", + " 'gt2r/land_ice_segments/ground_track/sigma_geo_xt',\n", + " 'gt2r/land_ice_segments/ground_track/x_atc',\n", + " 'gt2r/land_ice_segments/ground_track/y_atc',\n", + " 'gt2r/land_ice_segments/h_li',\n", + " 'gt2r/land_ice_segments/h_li_sigma',\n", + " 'gt2r/land_ice_segments/latitude',\n", + " 'gt2r/land_ice_segments/longitude',\n", + " 'gt2r/land_ice_segments/segment_id',\n", + " 'gt2r/land_ice_segments/sigma_geo_h',\n", + " 'gt2r/residual_histogram/bckgrd_per_m',\n", + " 'gt2r/residual_histogram/bin_top_h',\n", + " 'gt2r/residual_histogram/count',\n", + " 'gt2r/residual_histogram/delta_time',\n", + " 'gt2r/residual_histogram/ds_segment_id',\n", + " 'gt2r/residual_histogram/lat_mean',\n", + " 'gt2r/residual_histogram/lon_mean',\n", + " 'gt2r/residual_histogram/pulse_count',\n", + " 'gt2r/residual_histogram/segment_id_list',\n", + " 'gt2r/residual_histogram/x_atc_mean',\n", + " 'gt2r/segment_quality/delta_time',\n", + " 'gt2r/segment_quality/record_number',\n", + " 'gt2r/segment_quality/reference_pt_lat',\n", + " 'gt2r/segment_quality/reference_pt_lon',\n", + " 'gt2r/segment_quality/segment_id',\n", + " 'gt2r/segment_quality/signal_selection_source',\n", + " 'gt2r/segment_quality/signal_selection_status/signal_selection_status_all',\n", + " 'gt2r/segment_quality/signal_selection_status/signal_selection_status_backup',\n", + " 'gt2r/segment_quality/signal_selection_status/signal_selection_status_confident',\n", + " 'gt3l/land_ice_segments/atl06_quality_summary',\n", + " 'gt3l/land_ice_segments/bias_correction/fpb_mean_corr',\n", + " 'gt3l/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", + " 'gt3l/land_ice_segments/bias_correction/fpb_med_corr',\n", + " 'gt3l/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", + " 'gt3l/land_ice_segments/bias_correction/fpb_n_corr',\n", + " 'gt3l/land_ice_segments/bias_correction/med_r_fit',\n", + " 'gt3l/land_ice_segments/bias_correction/tx_mean_corr',\n", + " 'gt3l/land_ice_segments/bias_correction/tx_med_corr',\n", + " 'gt3l/land_ice_segments/delta_time',\n", + " 'gt3l/land_ice_segments/dem/dem_flag',\n", + " 'gt3l/land_ice_segments/dem/dem_h',\n", + " 'gt3l/land_ice_segments/dem/geoid_free2mean',\n", + " 'gt3l/land_ice_segments/dem/geoid_h',\n", + " 'gt3l/land_ice_segments/fit_statistics/dh_fit_dx',\n", + " 'gt3l/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", + " 'gt3l/land_ice_segments/fit_statistics/dh_fit_dy',\n", + " 'gt3l/land_ice_segments/fit_statistics/h_expected_rms',\n", + " 'gt3l/land_ice_segments/fit_statistics/h_mean',\n", + " 'gt3l/land_ice_segments/fit_statistics/h_rms_misfit',\n", + " 'gt3l/land_ice_segments/fit_statistics/h_robust_sprd',\n", + " 'gt3l/land_ice_segments/fit_statistics/n_fit_photons',\n", + " 'gt3l/land_ice_segments/fit_statistics/n_seg_pulses',\n", + " 'gt3l/land_ice_segments/fit_statistics/sigma_h_mean',\n", + " 'gt3l/land_ice_segments/fit_statistics/signal_selection_source',\n", + " 'gt3l/land_ice_segments/fit_statistics/signal_selection_source_status',\n", + " 'gt3l/land_ice_segments/fit_statistics/snr',\n", + " 'gt3l/land_ice_segments/fit_statistics/snr_significance',\n", + " 'gt3l/land_ice_segments/fit_statistics/w_surface_window_final',\n", + " 'gt3l/land_ice_segments/geophysical/bckgrd',\n", + " 'gt3l/land_ice_segments/geophysical/bsnow_conf',\n", + " 'gt3l/land_ice_segments/geophysical/bsnow_h',\n", + " 'gt3l/land_ice_segments/geophysical/bsnow_od',\n", + " 'gt3l/land_ice_segments/geophysical/cloud_flg_asr',\n", + " 'gt3l/land_ice_segments/geophysical/cloud_flg_atm',\n", + " 'gt3l/land_ice_segments/geophysical/dac',\n", + " 'gt3l/land_ice_segments/geophysical/e_bckgrd',\n", + " 'gt3l/land_ice_segments/geophysical/layer_flag',\n", + " 'gt3l/land_ice_segments/geophysical/msw_flag',\n", + " 'gt3l/land_ice_segments/geophysical/neutat_delay_total',\n", + " 'gt3l/land_ice_segments/geophysical/r_eff',\n", + " 'gt3l/land_ice_segments/geophysical/solar_azimuth',\n", + " 'gt3l/land_ice_segments/geophysical/solar_elevation',\n", + " 'gt3l/land_ice_segments/geophysical/tide_earth',\n", + " 'gt3l/land_ice_segments/geophysical/tide_earth_free2mean',\n", + " 'gt3l/land_ice_segments/geophysical/tide_equilibrium',\n", + " 'gt3l/land_ice_segments/geophysical/tide_load',\n", + " 'gt3l/land_ice_segments/geophysical/tide_ocean',\n", + " 'gt3l/land_ice_segments/geophysical/tide_pole',\n", + " 'gt3l/land_ice_segments/ground_track/ref_azimuth',\n", + " 'gt3l/land_ice_segments/ground_track/ref_coelv',\n", + " 'gt3l/land_ice_segments/ground_track/seg_azimuth',\n", + " 'gt3l/land_ice_segments/ground_track/sigma_geo_at',\n", + " 'gt3l/land_ice_segments/ground_track/sigma_geo_r',\n", + " 'gt3l/land_ice_segments/ground_track/sigma_geo_xt',\n", + " 'gt3l/land_ice_segments/ground_track/x_atc',\n", + " 'gt3l/land_ice_segments/ground_track/y_atc',\n", + " 'gt3l/land_ice_segments/h_li',\n", + " 'gt3l/land_ice_segments/h_li_sigma',\n", + " 'gt3l/land_ice_segments/latitude',\n", + " 'gt3l/land_ice_segments/longitude',\n", + " 'gt3l/land_ice_segments/segment_id',\n", + " 'gt3l/land_ice_segments/sigma_geo_h',\n", + " 'gt3l/residual_histogram/bckgrd_per_m',\n", + " 'gt3l/residual_histogram/bin_top_h',\n", + " 'gt3l/residual_histogram/count',\n", + " 'gt3l/residual_histogram/delta_time',\n", + " 'gt3l/residual_histogram/ds_segment_id',\n", + " 'gt3l/residual_histogram/lat_mean',\n", + " 'gt3l/residual_histogram/lon_mean',\n", + " 'gt3l/residual_histogram/pulse_count',\n", + " 'gt3l/residual_histogram/segment_id_list',\n", + " 'gt3l/residual_histogram/x_atc_mean',\n", + " 'gt3l/segment_quality/delta_time',\n", + " 'gt3l/segment_quality/record_number',\n", + " 'gt3l/segment_quality/reference_pt_lat',\n", + " 'gt3l/segment_quality/reference_pt_lon',\n", + " 'gt3l/segment_quality/segment_id',\n", + " 'gt3l/segment_quality/signal_selection_source',\n", + " 'gt3l/segment_quality/signal_selection_status/signal_selection_status_all',\n", + " 'gt3l/segment_quality/signal_selection_status/signal_selection_status_backup',\n", + " 'gt3l/segment_quality/signal_selection_status/signal_selection_status_confident',\n", + " 'gt3r/land_ice_segments/atl06_quality_summary',\n", + " 'gt3r/land_ice_segments/bias_correction/fpb_mean_corr',\n", + " 'gt3r/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", + " 'gt3r/land_ice_segments/bias_correction/fpb_med_corr',\n", + " 'gt3r/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", + " 'gt3r/land_ice_segments/bias_correction/fpb_n_corr',\n", + " 'gt3r/land_ice_segments/bias_correction/med_r_fit',\n", + " 'gt3r/land_ice_segments/bias_correction/tx_mean_corr',\n", + " 'gt3r/land_ice_segments/bias_correction/tx_med_corr',\n", + " 'gt3r/land_ice_segments/delta_time',\n", + " 'gt3r/land_ice_segments/dem/dem_flag',\n", + " 'gt3r/land_ice_segments/dem/dem_h',\n", + " 'gt3r/land_ice_segments/dem/geoid_free2mean',\n", + " 'gt3r/land_ice_segments/dem/geoid_h',\n", + " 'gt3r/land_ice_segments/fit_statistics/dh_fit_dx',\n", + " 'gt3r/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", + " 'gt3r/land_ice_segments/fit_statistics/dh_fit_dy',\n", + " 'gt3r/land_ice_segments/fit_statistics/h_expected_rms',\n", + " 'gt3r/land_ice_segments/fit_statistics/h_mean',\n", + " 'gt3r/land_ice_segments/fit_statistics/h_rms_misfit',\n", + " 'gt3r/land_ice_segments/fit_statistics/h_robust_sprd',\n", + " 'gt3r/land_ice_segments/fit_statistics/n_fit_photons',\n", + " 'gt3r/land_ice_segments/fit_statistics/n_seg_pulses',\n", + " 'gt3r/land_ice_segments/fit_statistics/sigma_h_mean',\n", + " 'gt3r/land_ice_segments/fit_statistics/signal_selection_source',\n", + " 'gt3r/land_ice_segments/fit_statistics/signal_selection_source_status',\n", + " 'gt3r/land_ice_segments/fit_statistics/snr',\n", + " 'gt3r/land_ice_segments/fit_statistics/snr_significance',\n", + " 'gt3r/land_ice_segments/fit_statistics/w_surface_window_final',\n", + " 'gt3r/land_ice_segments/geophysical/bckgrd',\n", + " 'gt3r/land_ice_segments/geophysical/bsnow_conf',\n", + " 'gt3r/land_ice_segments/geophysical/bsnow_h',\n", + " 'gt3r/land_ice_segments/geophysical/bsnow_od',\n", + " 'gt3r/land_ice_segments/geophysical/cloud_flg_asr',\n", + " 'gt3r/land_ice_segments/geophysical/cloud_flg_atm',\n", + " 'gt3r/land_ice_segments/geophysical/dac',\n", + " 'gt3r/land_ice_segments/geophysical/e_bckgrd',\n", + " 'gt3r/land_ice_segments/geophysical/layer_flag',\n", + " 'gt3r/land_ice_segments/geophysical/msw_flag',\n", + " 'gt3r/land_ice_segments/geophysical/neutat_delay_total',\n", + " 'gt3r/land_ice_segments/geophysical/r_eff',\n", + " 'gt3r/land_ice_segments/geophysical/solar_azimuth',\n", + " 'gt3r/land_ice_segments/geophysical/solar_elevation',\n", + " 'gt3r/land_ice_segments/geophysical/tide_earth',\n", + " 'gt3r/land_ice_segments/geophysical/tide_earth_free2mean',\n", + " 'gt3r/land_ice_segments/geophysical/tide_equilibrium',\n", + " 'gt3r/land_ice_segments/geophysical/tide_load',\n", + " 'gt3r/land_ice_segments/geophysical/tide_ocean',\n", + " 'gt3r/land_ice_segments/geophysical/tide_pole',\n", + " 'gt3r/land_ice_segments/ground_track/ref_azimuth',\n", + " 'gt3r/land_ice_segments/ground_track/ref_coelv',\n", + " 'gt3r/land_ice_segments/ground_track/seg_azimuth',\n", + " 'gt3r/land_ice_segments/ground_track/sigma_geo_at',\n", + " 'gt3r/land_ice_segments/ground_track/sigma_geo_r',\n", + " 'gt3r/land_ice_segments/ground_track/sigma_geo_xt',\n", + " 'gt3r/land_ice_segments/ground_track/x_atc',\n", + " 'gt3r/land_ice_segments/ground_track/y_atc',\n", + " 'gt3r/land_ice_segments/h_li',\n", + " 'gt3r/land_ice_segments/h_li_sigma',\n", + " 'gt3r/land_ice_segments/latitude',\n", + " 'gt3r/land_ice_segments/longitude',\n", + " 'gt3r/land_ice_segments/segment_id',\n", + " 'gt3r/land_ice_segments/sigma_geo_h',\n", + " 'gt3r/residual_histogram/bckgrd_per_m',\n", + " 'gt3r/residual_histogram/bin_top_h',\n", + " 'gt3r/residual_histogram/count',\n", + " 'gt3r/residual_histogram/delta_time',\n", + " 'gt3r/residual_histogram/ds_segment_id',\n", + " 'gt3r/residual_histogram/lat_mean',\n", + " 'gt3r/residual_histogram/lon_mean',\n", + " 'gt3r/residual_histogram/pulse_count',\n", + " 'gt3r/residual_histogram/segment_id_list',\n", + " 'gt3r/residual_histogram/x_atc_mean',\n", + " 'gt3r/segment_quality/delta_time',\n", + " 'gt3r/segment_quality/record_number',\n", + " 'gt3r/segment_quality/reference_pt_lat',\n", + " 'gt3r/segment_quality/reference_pt_lon',\n", + " 'gt3r/segment_quality/segment_id',\n", + " 'gt3r/segment_quality/signal_selection_source',\n", + " 'gt3r/segment_quality/signal_selection_status/signal_selection_status_all',\n", + " 'gt3r/segment_quality/signal_selection_status/signal_selection_status_backup',\n", + " 'gt3r/segment_quality/signal_selection_status/signal_selection_status_confident',\n", + " 'orbit_info/bounding_polygon_lat1',\n", + " 'orbit_info/bounding_polygon_lon1',\n", + " 'orbit_info/crossing_time',\n", + " 'orbit_info/cycle_number',\n", + " 'orbit_info/lan',\n", + " 'orbit_info/orbit_number',\n", + " 'orbit_info/rgt',\n", + " 'orbit_info/sc_orient',\n", + " 'orbit_info/sc_orient_time',\n", + " 'quality_assessment/gt1l/delta_time',\n", + " 'quality_assessment/gt1l/lat_mean',\n", + " 'quality_assessment/gt1l/lon_mean',\n", + " 'quality_assessment/gt1l/signal_selection_source_fraction_0',\n", + " 'quality_assessment/gt1l/signal_selection_source_fraction_1',\n", + " 'quality_assessment/gt1l/signal_selection_source_fraction_2',\n", + " 'quality_assessment/gt1l/signal_selection_source_fraction_3',\n", + " 'quality_assessment/gt1r/delta_time',\n", + " 'quality_assessment/gt1r/lat_mean',\n", + " 'quality_assessment/gt1r/lon_mean',\n", + " 'quality_assessment/gt1r/signal_selection_source_fraction_0',\n", + " 'quality_assessment/gt1r/signal_selection_source_fraction_1',\n", + " 'quality_assessment/gt1r/signal_selection_source_fraction_2',\n", + " 'quality_assessment/gt1r/signal_selection_source_fraction_3',\n", + " 'quality_assessment/gt2l/delta_time',\n", + " 'quality_assessment/gt2l/lat_mean',\n", + " 'quality_assessment/gt2l/lon_mean',\n", + " 'quality_assessment/gt2l/signal_selection_source_fraction_0',\n", + " 'quality_assessment/gt2l/signal_selection_source_fraction_1',\n", + " 'quality_assessment/gt2l/signal_selection_source_fraction_2',\n", + " 'quality_assessment/gt2l/signal_selection_source_fraction_3',\n", + " 'quality_assessment/gt2r/delta_time',\n", + " 'quality_assessment/gt2r/lat_mean',\n", + " 'quality_assessment/gt2r/lon_mean',\n", + " 'quality_assessment/gt2r/signal_selection_source_fraction_0',\n", + " 'quality_assessment/gt2r/signal_selection_source_fraction_1',\n", + " 'quality_assessment/gt2r/signal_selection_source_fraction_2',\n", + " 'quality_assessment/gt2r/signal_selection_source_fraction_3',\n", + " 'quality_assessment/gt3l/delta_time',\n", + " 'quality_assessment/gt3l/lat_mean',\n", + " 'quality_assessment/gt3l/lon_mean',\n", + " 'quality_assessment/gt3l/signal_selection_source_fraction_0',\n", + " 'quality_assessment/gt3l/signal_selection_source_fraction_1',\n", + " 'quality_assessment/gt3l/signal_selection_source_fraction_2',\n", + " 'quality_assessment/gt3l/signal_selection_source_fraction_3',\n", + " 'quality_assessment/gt3r/delta_time',\n", + " 'quality_assessment/gt3r/lat_mean',\n", + " 'quality_assessment/gt3r/lon_mean',\n", + " 'quality_assessment/gt3r/signal_selection_source_fraction_0',\n", + " 'quality_assessment/gt3r/signal_selection_source_fraction_1',\n", + " 'quality_assessment/gt3r/signal_selection_source_fraction_2',\n", + " 'quality_assessment/gt3r/signal_selection_source_fraction_3',\n", + " 'quality_assessment/qa_granule_fail_reason',\n", + " 'quality_assessment/qa_granule_pass_fail']" + ] + }, + "execution_count": 21, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "reader.vars.avail()" ] @@ -333,7 +1610,9 @@ { "cell_type": "markdown", "id": "b2449941", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "To make things easier, you can use icepyx's built-in default list that loads commonly used variables for your non-gridded data product, or create your own list of variables to be read in.\n", "icepyx will determine what variables are available for you to read in by creating a list from one of your source files.\n", @@ -349,7 +1628,9 @@ { "cell_type": "markdown", "id": "55092d1b", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "For a basic case, let's say we want to read in height, latitude, and longitude for all beam pairs.\n", "We create our variables list as" @@ -357,7 +1638,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "id": "e3734e09", "metadata": {}, "outputs": [], @@ -368,17 +1649,53 @@ { "cell_type": "markdown", "id": "fff0bb19", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "Then we can view a dictionary of the variables we'd like to read in." ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 29, "id": "e5456e36", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "{'sc_orient': ['orbit_info/sc_orient'],\n", + " 'atlas_sdp_gps_epoch': ['ancillary_data/atlas_sdp_gps_epoch'],\n", + " 'cycle_number': ['orbit_info/cycle_number'],\n", + " 'rgt': ['orbit_info/rgt'],\n", + " 'data_start_utc': ['ancillary_data/data_start_utc'],\n", + " 'data_end_utc': ['ancillary_data/data_end_utc'],\n", + " 'h_li': ['gt1l/land_ice_segments/h_li',\n", + " 'gt1r/land_ice_segments/h_li',\n", + " 'gt2l/land_ice_segments/h_li',\n", + " 'gt2r/land_ice_segments/h_li',\n", + " 'gt3l/land_ice_segments/h_li',\n", + " 'gt3r/land_ice_segments/h_li'],\n", + " 'latitude': ['gt1l/land_ice_segments/latitude',\n", + " 'gt1r/land_ice_segments/latitude',\n", + " 'gt2l/land_ice_segments/latitude',\n", + " 'gt2r/land_ice_segments/latitude',\n", + " 'gt3l/land_ice_segments/latitude',\n", + " 'gt3r/land_ice_segments/latitude'],\n", + " 'longitude': ['gt1l/land_ice_segments/longitude',\n", + " 'gt1r/land_ice_segments/longitude',\n", + " 'gt2l/land_ice_segments/longitude',\n", + " 'gt2r/land_ice_segments/longitude',\n", + " 'gt3l/land_ice_segments/longitude',\n", + " 'gt3r/land_ice_segments/longitude']}" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "reader.vars.wanted" ] @@ -386,14 +1703,16 @@ { "cell_type": "markdown", "id": "9d5b50b5", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "Don't forget - if you need to start over, and re-generate your wanted variables list, it's easy!" ] }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "id": "69894391", "metadata": {}, "outputs": [], @@ -404,7 +1723,9 @@ { "cell_type": "markdown", "id": "473de4d7", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Step 5: Loading your data\n", "\n", @@ -414,9 +1735,120 @@ { "cell_type": "code", "execution_count": null, - "id": "eaabc976", + "id": "4a66d889-8d2d-4b9a-821a-96a394ff8d66", "metadata": {}, "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "eaabc976", + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", + " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n", + "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", + " .rename({\"delta_time\": \"photon_idx\"})\n" + ] + } + ], "source": [ "ds = reader.load()" ] @@ -424,7 +1856,9 @@ { "cell_type": "markdown", "id": "db6560f1", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "Within a Jupyter Notebook, you can get a summary view of your data object.\n", "\n", @@ -435,10 +1869,549 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "id": "723256f7", "metadata": {}, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "\n", + "
<xarray.Dataset>\n",
+       "Dimensions:              (photon_idx: 29027, spot: 2, gran_idx: 6)\n",
+       "Coordinates:\n",
+       "  * photon_idx           (photon_idx) int64 0 1 2 3 ... 29023 29024 29025 29026\n",
+       "  * spot                 (spot) uint8 2 5\n",
+       "  * gran_idx             (gran_idx) float64 8.49e+04 9.02e+04 ... 1.016e+05\n",
+       "    source_file          (gran_idx) <U72 '../../../../data/ATL06/processed_AT...\n",
+       "    delta_time           (gran_idx, photon_idx) datetime64[ns] 2019-02-22T01:...\n",
+       "Data variables:\n",
+       "    sc_orient            (gran_idx) int8 0 0 0 1 1 1\n",
+       "    cycle_number         (gran_idx) int8 2 2 2 5 5 5\n",
+       "    rgt                  (gran_idx) int16 849 902 910 986 1001 1016\n",
+       "    atlas_sdp_gps_epoch  (gran_idx) datetime64[ns] 2018-01-01T00:00:18 ... 20...\n",
+       "    data_start_utc       (gran_idx) datetime64[ns] 2019-02-22T01:03:44.199777...\n",
+       "    data_end_utc         (gran_idx) datetime64[ns] 2019-02-22T01:07:38.112326...\n",
+       "    h_li                 (spot, gran_idx, photon_idx) float32 nan nan ... nan\n",
+       "    latitude             (spot, gran_idx, photon_idx) float64 nan nan ... nan\n",
+       "    longitude            (spot, gran_idx, photon_idx) float64 nan nan ... nan\n",
+       "    gt                   (gran_idx, spot) <U4 'gt3r' 'gt1l' ... 'gt1l' 'gt3r'\n",
+       "Attributes:\n",
+       "    data_product:  ATL06\n",
+       "    Description:   The land_ice_height group contains the primary set of deri...\n",
+       "    data_rate:     Data within this group are sparse.  Data values are provid...
" + ], + "text/plain": [ + "\n", + "Dimensions: (photon_idx: 29027, spot: 2, gran_idx: 6)\n", + "Coordinates:\n", + " * photon_idx (photon_idx) int64 0 1 2 3 ... 29023 29024 29025 29026\n", + " * spot (spot) uint8 2 5\n", + " * gran_idx (gran_idx) float64 8.49e+04 9.02e+04 ... 1.016e+05\n", + " source_file (gran_idx) " + ] + }, + "execution_count": 27, + "metadata": {}, + "output_type": "execute_result" + } + ], "source": [ "ds.plot.scatter(x=\"longitude\", y=\"latitude\", hue=\"h_li\", vmin=-100, vmax=2000)" ] @@ -469,7 +2455,9 @@ { "cell_type": "markdown", "id": "6421f67c", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "A developer note to users:\n", "our next steps will be to create an xarray extension with ICESat-2 aware functions (like \"get_strong_beams\", etc.).\n", @@ -478,191 +2466,39 @@ }, { "cell_type": "markdown", - "id": "6edfbb25", - "metadata": {}, - "source": [ - "### More on Intake catalogs and the read object\n", - "\n", - "As anyone familiar with ICESat-2 hdf5 files knows, one of the challenges to reading in data is looping through all of the beam pairs for each track.\n", - "The icepyx read module takes advantage of icepyx's variables module, which has some awareness of ICESat-2 data and uses that to save the user the trouble of having to loop through each beam pair.\n", - "The `reader.load()` function does this by automatically creating minimal Intake catalogs for each variable path, reading in the data, and merging each variable into a ready-to-analyze Xarray DataSet.\n", - "The Intake savvy user may wish to view the template catalog or use an existing catalog." - ] - }, - { - "cell_type": "markdown", - "id": "0f0076f9", - "metadata": {}, - "source": [ - "#### Viewing the template catalog\n", - "\n", - "You can access the ICESat-2 catalog template as an attribute of the read object.\n", - "\n", - "***NOTE: accessing `reader.is2catalog` creates a template with a placeholder in the 'group' parameter; thus, it will not work to actually read in data***" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "2de29fd8", + "id": "1b0cb477", "metadata": { - "scrolled": true + "user_expressions": [] }, - "outputs": [], - "source": [ - "reader.is2catalog" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7a5deef8", - "metadata": {}, - "outputs": [], - "source": [ - "reader.is2catalog.gui" - ] - }, - { - "cell_type": "markdown", - "id": "fef43556", - "metadata": {}, - "source": [ - "#### Use an existing catalog\n", - "If you already have a catalog for your data, you can supply that when you create the read object." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "64986a60", - "metadata": {}, - "outputs": [], - "source": [ - "catpath = path_root + 'test_catalog.yml'\n", - "reader = ipx.Read(filepath, pattern, catpath)" - ] - }, - { - "cell_type": "markdown", - "id": "cf930e0a", - "metadata": {}, - "source": [ - "Then, you can use the catalog you supplied by calling intake's `read` directly to read in the specified data variable." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dd0e086a", - "metadata": {}, - "outputs": [], - "source": [ - "ds = reader.is2catalog.read()" - ] - }, - { - "cell_type": "markdown", - "id": "60b1a304", - "metadata": {}, "source": [ - "***NOTE: this means that you will only be able to read in a single data variable!***\n", - "\n", - "To take advantage of icepyx's knowledge of ICESat-2 data nesting of beam pairs and read in multiple related variables at once, you must use the variable approach outlined earlier in this tutorial." + "#### Credits\n", + "* original notebook by: Jessica Scheick\n", + "* notebook contributors: Wei Ji and Tian\n", + "* templates for default ICESat-2 Intake catalogs from: [Wei Ji](https://github.com/icesat2py/icepyx/issues/106) and [Tian](https://github.com/icetianli/ICESat2_xarray)." ] }, { "cell_type": "code", "execution_count": null, - "id": "f5e3a221", - "metadata": {}, - "outputs": [], - "source": [ - "ds = reader.load()\n", - "ds" - ] - }, - { - "cell_type": "markdown", - "id": "d56fc41c", + "id": "aaf6f5a6-355b-456a-99fd-ce0b51045b58", "metadata": {}, - "source": [ - "### More customization options\n", - "\n", - "If you'd like to use the icepyx ICESat-2 Catalog template to create your own customized catalog, we recommend that you access the `build_catalog` function directly, which returns an Intake Catalog instance.\n", - "\n", - "You'll need to supply the required `data_source`, `path_pattern`, and `source_type` arguments. `data_source` and `path_pattern` are described in Steps 2 and 3 of this tutorial. `source_type` is the string you'd like to use for your Local Catalog entry.\n", - "\n", - "This function accepts as keyword input arguments (kwargs) dictionaries with appropriate keys (depending on the Intake driver you are using).\n", - "The simplest version of this is specifying the variable parameters and paths of interest.\n", - "`grp_paths` may contain \"variables\", each of which must then be further defined by `grp_path_params`.\n", - "You cannot use glob-like path syntax to access variables (so `grp_path = '/*/land_ice_segments'` is NOT VALID)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f174f885", - "metadata": { - "scrolled": true - }, "outputs": [], - "source": [ - "import icepyx.core.is2cat as is2cat\n", - "\n", - "# build a custom ICESat-2 catalog with a group and parameter\n", - "cat = is2cat.build_catalog(data_source = path_root,\n", - " path_pattern = pattern,\n", - " source_type = \"manual_catalog\",\n", - " grp_paths = \"/{{gt}}/land_ice_segments\",\n", - " grp_path_params = [{\"name\": \"gt\",\n", - " \"description\": \"Ground track\",\n", - " \"type\": \"str\",\n", - " \"default\": \"gt1l\",\n", - " \"allowed\": [\"gt1l\", \"gt1r\", \"gt2l\", \"gt2r\", \"gt3l\", \"gt3r\"]\n", - " }]\n", - " )" - ] - }, - { - "cell_type": "markdown", - "id": "bab9c949", - "metadata": {}, - "source": [ - "#### Saving your catalog\n", - "If you create a highly customized ICESat-2 catalog, you can use Intake's `save` to export it as a .yml file.\n", - "\n", - "Don't forget you can easily use an existing catalog (such as this highly customized one you just made) to read in your data with `reader = ipx.Read(filepath, pattern, catalog)` (so it's as easy as re-creating your reader object with your modified catalog)." - ] + "source": [] }, { "cell_type": "code", "execution_count": null, - "id": "30f0122a", + "id": "8ea1987f-b6bf-44df-a869-949290f498cb", "metadata": {}, "outputs": [], - "source": [ - "catpath = path_root + 'test_catalog.yml'\n", - "cat.save(catpath)" - ] - }, - { - "cell_type": "markdown", - "id": "1b0cb477", - "metadata": {}, - "source": [ - "#### Credits\n", - "* original notebook by: Jessica Scheick\n", - "* notebook contributors: Wei Ji and Tian\n", - "* templates for default ICESat-2 Intake catalogs from: [Wei Ji](https://github.com/icesat2py/icepyx/issues/106) and [Tian](https://github.com/icetianli/ICESat2_xarray)." - ] + "source": [] } ], "metadata": { "kernelspec": { - "display_name": "Python 3 (ipykernel)", + "display_name": "general", "language": "python", - "name": "python3" + "name": "general" }, "language_info": { "codemirror_mode": { @@ -674,7 +2510,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.10.12" + "version": "3.11.4" } }, "nbformat": 4, diff --git a/doc/source/user_guide/documentation/read.rst b/doc/source/user_guide/documentation/read.rst index b076ef210..a5beedf4e 100644 --- a/doc/source/user_guide/documentation/read.rst +++ b/doc/source/user_guide/documentation/read.rst @@ -19,7 +19,6 @@ Attributes .. autosummary:: :toctree: ../../_icepyx/ - Read.is2catalog Read.vars From 9f066112c8b73200128e18eed8e6242d15329da6 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Wed, 30 Aug 2023 20:52:51 +0000 Subject: [PATCH 46/63] update approach paragraph --- doc/source/example_notebooks/IS2_data_read-in.ipynb | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index b8697b1d7..c459b7c78 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -22,10 +22,7 @@ "Instead of needing to manually iterate through the beam pairs, you can provide a few options to the `Read` object and icepyx will do the heavy lifting for you (as detailed in this notebook).\n", "\n", "### Approach\n", - "If you're interested in what's happening under the hood: icepyx turns your instructions into something called a catalog, then uses the Intake library and the catalog to actually load the data into memory. Specifically, icepyx creates an [Intake](https://intake.readthedocs.io/en/latest/) data [catalog](https://intake.readthedocs.io/en/latest/catalog.html) for each requested variable and then merges the read-in data from each of the variables to create a single data object.\n", - "\n", - "Intake catalogs are powerful (and the tool we selected) because they can be saved, shared, modified, and reused to reproducibly read in a set of data files in a consistent way as part of an analysis workflow.\n", - "This approach streamlines the transition between data sources (local/downloaded files or, ultimately, cloud/bucket access) and data object types (e.g. [Xarray Dataset](http://xarray.pydata.org/en/stable/generated/xarray.Dataset.html) or [GeoPandas GeoDataFrame](https://geopandas.org/docs/reference/api/geopandas.GeoDataFrame.html))." + "If you're interested in what's happening under the hood: icepyx uses the [xarray](https://docs.xarray.dev/en/stable/) library to read in each of the requested variables of the dataset. icepyx formats each requested variable and then merges the read-in data from each of the variables to create a single data object. The use of xarray is powerful, because the returned data object can be used with relevant xarray processing tools." ] }, { From d019b9a2db2391882dbc69c4816f64eb03f389e3 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Wed, 30 Aug 2023 20:59:03 +0000 Subject: [PATCH 47/63] remove one more instance of catalog from the docs --- doc/source/example_notebooks/IS2_data_read-in.ipynb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index c459b7c78..13b49cddb 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -2470,8 +2470,7 @@ "source": [ "#### Credits\n", "* original notebook by: Jessica Scheick\n", - "* notebook contributors: Wei Ji and Tian\n", - "* templates for default ICESat-2 Intake catalogs from: [Wei Ji](https://github.com/icesat2py/icepyx/issues/106) and [Tian](https://github.com/icetianli/ICESat2_xarray)." + "* notebook contributors: Wei Ji and Tian" ] }, { From 156ea89103f44dd4b7be680ac51eecb5e1b85b18 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Wed, 30 Aug 2023 21:01:36 +0000 Subject: [PATCH 48/63] clear jupyter history --- .../example_notebooks/IS2_data_read-in.ipynb | 2019 +---------------- 1 file changed, 34 insertions(+), 1985 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index 13b49cddb..115c63044 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -35,7 +35,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "2b74b672", "metadata": {}, "outputs": [], @@ -58,18 +58,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "c4390195", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "You have 6 files matching the filename pattern to be read in.\n" - ] - } - ], + "outputs": [], "source": [ "path_root = '/full/path/to/your/data/'\n", "pattern = \"processed_ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5\"\n", @@ -78,7 +70,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "2f46029d", "metadata": {}, "outputs": [], @@ -88,603 +80,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "c0439388", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n" - ] - }, - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
<xarray.Dataset>\n",
-       "Dimensions:              (photon_idx: 29027, spot: 2, gran_idx: 6)\n",
-       "Coordinates:\n",
-       "  * photon_idx           (photon_idx) int64 0 1 2 3 ... 29023 29024 29025 29026\n",
-       "  * spot                 (spot) uint8 2 5\n",
-       "  * gran_idx             (gran_idx) float64 8.49e+04 9.02e+04 ... 1.016e+05\n",
-       "    source_file          (gran_idx) <U72 '../../../../data/ATL06/processed_AT...\n",
-       "    delta_time           (gran_idx, photon_idx) datetime64[ns] 2019-02-22T01:...\n",
-       "Data variables:\n",
-       "    sc_orient            (gran_idx) int8 0 0 0 1 1 1\n",
-       "    cycle_number         (gran_idx) int8 2 2 2 5 5 5\n",
-       "    rgt                  (gran_idx) int16 849 902 910 986 1001 1016\n",
-       "    atlas_sdp_gps_epoch  (gran_idx) datetime64[ns] 2018-01-01T00:00:18 ... 20...\n",
-       "    data_start_utc       (gran_idx) datetime64[ns] 2019-02-22T01:03:44.199777...\n",
-       "    data_end_utc         (gran_idx) datetime64[ns] 2019-02-22T01:07:38.112326...\n",
-       "    h_li                 (spot, gran_idx, photon_idx) float32 nan nan ... nan\n",
-       "    latitude             (spot, gran_idx, photon_idx) float64 nan nan ... nan\n",
-       "    longitude            (spot, gran_idx, photon_idx) float64 nan nan ... nan\n",
-       "    gt                   (gran_idx, spot) <U4 'gt3r' 'gt1l' ... 'gt1l' 'gt3r'\n",
-       "Attributes:\n",
-       "    data_product:  ATL06\n",
-       "    Description:   The land_ice_height group contains the primary set of deri...\n",
-       "    data_rate:     Data within this group are sparse.  Data values are provid...
" - ], - "text/plain": [ - "\n", - "Dimensions: (photon_idx: 29027, spot: 2, gran_idx: 6)\n", - "Coordinates:\n", - " * photon_idx (photon_idx) int64 0 1 2 3 ... 29023 29024 29025 29026\n", - " * spot (spot) uint8 2 5\n", - " * gran_idx (gran_idx) float64 8.49e+04 9.02e+04 ... 1.016e+05\n", - " source_file (gran_idx) " - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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p6cDkJKSwvTp0x0u16GA59ixY7z44os8/PDDJCQkALBq1SoOHjxoVzlvvfUWUVFRLFiwgNatW1OzZk3uuusu6tSpY83zwgsvcPfdd/P222/TvHlzateuTe/evQkNDXWk6kIIIYT7lXB31o0yMjL48ssveeyxx2x2I9+wYQOhoaHUq1ePESNGWD/jAaKjo8nMzKR79+7WtMjISBo3bsyWLVucq9B1Xn/9dT7++GM++eQTm1WW27dvz+7dux0u1+6AZ+PGjTRp0oTt27fz/fffk5qaCsC+ffuYOnWqXWUtX76cVq1aMWDAAEJDQ2nevDmffPKJ9byu6/z000/Uq1ePHj16EBoaSps2bVi2bFm+Zaanp5OcnGxzCCGEEKWKi8bwKKVyfebltIgUZNmyZVy6dInhw4db03r16sXixYv59ddfmTlzJjt37uTOO++0lhcfH4+Pjw+VK1e2KSssLIz4+Hhn/ho2Dh06RMeOHXOlBwUFcenSJYfLtTvgef7553n99ddZu3YtPj4+1vQuXbqwdetWu8r6559/+Oijj6hbty6rV6/mqaeeYsyYMSxatAiAhIQEUlNTefPNN+nZsydr1qzhvvvuo3///rmWm84xY8YMTCaT9YiKirL3EoUQQogyIT4+3uYzz2QyMWPGjEIfN3/+fHr16kVkZKQ17cEHH6R37940btyYe+65h5UrV3L48GF++umnAstSStm0EjkrIiKCo0eP5krfvHkztWvXdrhcu6el79+/n6+++ipXetWqVblw4YJdZem6TqtWrax9cs2bN+fgwYN89NFHDB061LrgYb9+/Rg3bhwAzZo1Y8uWLXz88cc2/Y45pkyZwvjx462/JycnS9AjhBCiVHHF1hKagvDwcA4dOmST7uvrW+DjTpw4wbp16/j+++8LzBcREUGNGjU4cuQIYHmujIwMEhMTbVp5EhISaN++vYNXkdvIkSN59tln+eyzz9A0jdOnT7N161YmTpzIyy+/7HC5drfwVKpUiTNnzuRK37NnDzfddJNdZUVERNCoUSObtIYNG1pnYIWEhODl5VVgnhv5+voSFBRkcwghhBCljgvG8Gialuszr7CAZ8GCBYSGhtK7d+8C8124cIGTJ08SEREBQMuWLfH29rbO7gI4c+YMBw4ccGnAM3nyZO699166dOlCamoqHTt25IknnmDkyJGMHj3a4XLtbuEZNGgQzz33HP/73//QNA1d1/n999+ZOHEiQ4cOtausDh065IpMDx8+bN1l3cfHh9tuu63APEIIIUSZ46a9tHRdZ8GCBQwbNgwvr2shQGpqKtOmTeP+++8nIiKC48eP8+9//5uQkBDuu+8+AEwmE48//jgTJkygSpUqBAcHM3HiRJo0aULXrl2dvBhbb7zxBi+88AJ//vknuq7TqFEjKlSo4FSZdgc8b7zxBsOHD+emm25CKUWjRo0wm80MGjSIF1980a6yxo0bR/v27Zk+fToDBw5kx44dzJs3j3nz5lnzTJo0iQcffJCOHTvSpUsXVq1axY8//siGDRvsrboQQghRrq1bt47Y2Fgee+wxm3Sj0cj+/ftZtGgRly5dIiIigi5duvDNN99QsWJFa77Zs2fj5eXFwIEDSUtL46677mLhwoUYjUaX1TEpKQmz2UxwcDCtWrWypl+8eBEvLy+He240pZRDMeaxY8fYs2cPuq7TvHlz6tat61AFVqxYwZQpUzhy5Ai1atVi/PjxjBgxwibPZ599xowZMzh16hT169fnlVdeoV+/fkUqPzk5GZPJRFJSknRvCSGEKFBJfGa0bt2a+IhGBNVv6lQ5yUcOEHJij1NTtUujXr16cc899zBq1Cib9I8//pjly5fnWgyxqBwOeMoKCXiEEEIUVYkGPPWcDHiOembAExwczO+//07Dhg1t0v/++286dOhg9wSpHEXq0rp+1lNhZs2a5VBFhBBCiHJDNg/NV3p6OllZWbnSMzMzSUtLc7jcIgU8e/bssfk9Ojoas9lM/fr1AcsgYqPRSMuWLR2uiBBCCFFuuGnQcllw2223MW/ePN5//32b9I8//tipOKNIAc/69eutP8+aNYuKFSvy+eefW+fhJyYm8uijj3LHHXc4XBEhhBBCiDfeeIOuXbvyxx9/cNdddwHwyy+/sHPnTtasWeNwuXavwzNz5kxmzJhhs+hQ5cqVef3115k5c6bDFRFCCCHKFTfupVWadejQga1btxIVFcV///tffvzxR26++Wb27dvnVMOK3dPSk5OTOXv2LLfccotNekJCAikpKQ5XRAghhCgvtOzD2TI8VbNmzVi8eLFLy7Q74Lnvvvt49NFHmTlzJm3btgVg27ZtTJo0if79+7u0ckIIIYRHkjE8uRR1s29HZ8/ZHfB8/PHHTJw4kUceeYTMzExLIV5ePP7447zzzjsOVUIIIYQQ5VulSpUK3IQ0Z5NSs9nsUPl2BzwBAQF8+OGHvPPOOxw7dgylFDfffDOBgYEOVUAIIYQob1yxeaintfBcP0GqONgd8OQIDAzk1ltvdWVdhBBCiPJDAh4bnTp1Ktby7Q54unTpUmCT06+//upUhYQQQgiP5+EzrUojuwOeZs2a2fyemZnJ3r17OXDgAMOGDXNVvYQQQgghXMbugGf27Nl5pk+bNo3U1FSnKySEEEJ4PNlaosTZvfBgfh555BE+++wzVxUnhBBCeDZnFx6UgMcuDg9avtHWrVvx8/NzVXFCCCGEx3LFLC1PXniwONgd8Ny4uKBSijNnzrBr1y5eeukll1VMCCGEEOWDPQsXf//99w49h90BT1BQkM0sLYPBQP369Xn11Vfp3r27Q5UQQgghyhVZadmGyWSy/qyUYunSpZhMJlq1agVAdHQ0ly5dcmpHB7sDnoULFzr8ZEIIIYTI3ktLAh6rBQsWWH9+7rnnGDhwIB9//DFGoxEAs9nMqFGjHN5WAhwYtFy7dm0uXLiQK/3SpUvUrl3b4YoIIYQQ5YYMWM7XZ599xsSJE63BDoDRaGT8+PFOTY6yO+A5fvx4nvtYpKenExcX53BFhBBCCCGysrL466+/cqX/9ddf6LrucLlF7tJavny59efVq1fb9LeZzWZ++eUXatas6XBFhBBlj1KZaJo3SlluQprmspUuhPBsMoYnX48++iiPPfYYR48epW3btgBs27aNN998k0cffdThcosc8Nx7770AaJqWa0Vlb29vatasycyZMx2uiBCi7FAqC9Ah7Qf0jO1gCEELeBhljJKgR4gikoUH8/af//yH8PBwZs+ezZkzZwCIiIhg8uTJTJgwweFyixzw5DQj1apVi507dxISEuLwkwohyjoz6uIToPmCZoCrW1FXvkCr9D7KtyOa5rIlvoTwTB4+DscZBoOByZMnM3nyZJKTkwGcGqycw+67UkxMjNNPKoQou5TKgqxjaJXnoRn8r6VdXY1KfQ/Nt7N7KyhEGWBZeNC5iMfZx5cFrgh0chQp4Hnvvfd48skn8fPz47333isw75gxY1xSMSFEaWUAr/qAZh27Awbw7YrmdTOYY8GrphvrJ4Qoy86ePcvEiRP55ZdfSEhIQN0Q2OU1caooihTwzJ49m8GDB+Pn55fv5qFgGd8jAY8Q5YEByMr+vw54geYNXjeDSnNv1YQoK2TQcp6GDx9ObGwsL730EhERETaLHTujSAHP9d1Y0qUlRPll+aaV/e3q6gpU5l9oXnXAvx+W24kBNNlTT4jCuGIvLU8NeDZv3symTZto1qyZS8u1ezrFq6++ypUrV3Klp6Wl8eqrr7qkUkKI0soMKhWVOg9lCAHfO1CZe1HneoB+znLe/tuKEOWPLDyYr6ioqFzdWK5g953plVdeITU1NVf6lStXeOWVV1xSKSFEaWUAgtAqPInm0wHNpz1a0BtoIatRl79G07yRPZyFEM6YM2cOzz//PMePH3dpuXYHPEqpPPvT/vjjD4KDg11SKSFEaaVA0wAj2bsBWQ7NB63CswAu628XwtPldGs5c9hj2rRpaJpmc4SHh1vPK6WYNm0akZGR+Pv707lzZw4ePGhTRnp6Os888wwhISEEBgbSt29fTp065Yo/h9WDDz7Ihg0bqFOnDhUrViQ4ONjmcFSRp6VXrlzZ+geqV6+ezU3NbDaTmprKU0895XBFhBBlgZbP/8kOhIQQReKmlZZvueUW1q1bZ/39+v2q3n77bWbNmsXChQupV68er7/+Ot26dePQoUNUrFgRgLFjx/Ljjz+yZMkSqlSpwoQJE+jTpw/R0dE2ZTljzpw5LinnRkUOeObMmYNSiscee4xXXnnFZmsJHx8fatasSbt27YqlkkII97NMQdfRNC+Uugp6Cpqxavaqy0ZAoZQuKy0LUQSuGLTsyFcMLy8vm1adHEop5syZwwsvvED//v0B+PzzzwkLC+Orr75i5MiRJCUlMX/+fL744gu6du0KwJdffklUVBTr1q2jR48ezlyO1Y27ObhKkQOenArUqlWL9u3b4+3tXSwVEkKUVjpgRk96B/CGzCMo9Q9axcngexcydkeI0u/IkSNERkbi6+tLmzZtmD59OrVr1yYmJob4+Hi6d+9uzevr60unTp3YsmULI0eOJDo6mszMTJs8kZGRNG7cmC1btrgs4LleWloamZmZNmmOLkZo90rLnTp1KpaKCCFKN0vLjgEt6DmuBTc6KvMYWtbf4FUPS0uPEKJIXNClpZSybr+Qw9fXF19f31zZ27Rpw6JFi6hXrx5nz57l9ddfp3379hw8eJD4+HgAwsLCbB4TFhbGiRMnAIiPj8fHx4fKlSvnypPzeFe4fPkyzz33HP/973+5cOFCrvOOLjxod9vzlStXGD16NKGhoVSoUIHKlSvbHEIIz3StS8tgHc8HOpp3XZShBprmJQOWhSgilwxYVpYgxGQy2RwzZszI8zl79erF/fffT5MmTejatSs//fQTYOm6stbrhvdwfhOV7M1jj8mTJ/Prr7/y4Ycf4uvry6effsorr7xCZGQkixYtcrhcuwOeSZMmubQicXFxPPLII1SpUoWAgACaNWtGdHR0nnlHjhyJpmnFNqBJCFEYDaXMKKWyx+4YAIVmCHB3xYQoW5Ry/kARHh5OUlKSzTFlypQiVSEwMJAmTZpw5MgR67ieG1tqEhISrK0+4eHhZGRkkJiYmG8eV/jxxx/58MMPeeCBB/Dy8uKOO+7gxRdfZPr06SxevNjhcu0OeFxZkcTERDp06IC3tzcrV67kzz//ZObMmVSqVClX3mXLlrF9+3YiIyPtrbIQwkmW1h0F+lnUlfWolEVwdY0lDUvLz7V9tYQQJUXTNIKCgmyOvLqz8pKens5ff/1FREQEtWrVIjw8nLVr11rPZ2RksHHjRtq3bw9Ay5Yt8fb2tslz5swZDhw4YM3jChcvXqRWrVqAZZjMxYsXAbj99tv57bffHC7X7jE8BVXkX//6l11lvfXWW0RFRbFgwQJrWs2aNXPli4uLY/To0axevZrevXvbW2UhhNN0UAYwhKMFRGSnKZT5MprRD9BkdpYQdnJ6lpadj584cSL33HMP1atXJyEhgddff53k5GSGDRuGpmmMHTuW6dOnU7duXerWrcv06dMJCAhg0KBBAJhMJh5//HEmTJhAlSpVCA4OZuLEidYuMlepXbs2x48fp0aNGjRq1Ij//ve/tG7dmh9//DHPBpGisvsOlVMRwFoRwKGKLF++nFatWjFgwABCQ0Np3rw5n3zyiU0eXdcZMmQIkyZN4pZbbim0zPT0dJKTk20OIYSzDNets5OzgIiGZgwAZcSj17kXoji4YmsJO992p06d4uGHH6Z+/fr0798fHx8ftm3bRo0aNQDL2JmxY8cyatQoWrVqRVxcHGvWrLGuwQOWzcTvvfdeBg4cSIcOHQgICODHH3902Ro8AI8++ih//PEHAFOmTLEOoRk3bhyTJk1yuFxN2blhxezZszEajYwZM4b169fTu3dvzGYzWVlZzJo1i2effbbIZfn5WTYZHD9+PAMGDGDHjh2MHTuWuXPnMnToUABmzJjB+vXrWb16NZqmUbNmTcaOHcvYsWPzLHPatGl5bnGRlJQkM8iEcJClu8oySPmaawGQpsnsLOEZkpOTMZlMxfqZ0bp1a5K8G1Kl2q1OlXMx7gABV/5g9+7dLqpZ6RQbG8uuXbuoU6cOTZs2dbgcuwMeV1bEx8eHVq1asWXLFmvamDFj2LlzJ1u3biU6OprevXuze/du69idwgKe9PR00tPTrb8nJycTFRUlAY8QDlIq56ukOXuvrOvG9ADSnSU8iQQ8pdfJkyeZOnUqn332mUOPd/ouVb16dfr3709wcDCPPfaYXY+NiIigUaNGNmkNGzYkNjYWgE2bNpGQkED16tXx8vLCy8uLEydOMGHChDzH+oBl/YEbB3AJIZyjaQa4ugL9wiD0871RKW+DSsHS4qMVy87GQng0N3RplXUXL160mUJvL5d9LXOkIh06dODQoUM2aYcPH7b2Jw4ZMoR9+/axd+9e6xEZGcmkSZNYvXq1q6ouhCiApmnoKV+jfLqhVV4Ewd9BVirqwgBQmdY8Qoiic8U6PPKus4/ds7Rcady4cbRv357p06czcOBAduzYwbx585g3bx4AVapUoUqVKjaP8fb2Jjw8nPr167ujykKUO0rX0SoMyF5pWceg+aEqTwOlQdrXEPAQbr6VCFEG5ayl40wR5ayJx0lu7Xi/7bbbWLp0KV9//TWNGzfmtddeY86cOQwePNid1RJCXE9TlmAn6yRkbEfpiZZVlQ1G8H8YTZNgRwi7uWilZVF0br9T9enThz59+hQ5f86UeCFE8bOsppyJnjgR0tdhucP6oAKHYqg4GTRQyiyztIQQTsvZpT0/ly5dcqr8Igc8xV0RIURpZEQlvwrpv4BWAVQakAGXP0UZ64B/P2TDUCEc4IoWGg9r4TGZTIWez1myxhFFDniKuyJCiNLIjObVAEKj0QyBKJUJV1ehUj9Epf0PQ8D97q6gEGWStVvKmTJcU5VS4/pdF4pDkQOe4q6IEKI00iDgYUBlr71jBL/eaL7dUEnPu7tyQpRtTg9adk01ygtZLUwIkadriwteW2DQsu6OAs0HzfSabBgqhCgz3D5oWQhRWiks34mubzg3XDunVSj5KgnhIVzSpSUtPHaRgEcIkY/rNwvVrvu/bv1dtpQQwkEyrbzEScAjhMhHTsBjxhLkGLDMyDIgd2ohnOd0C428De0iX8+EELlY9sbKyt4yQgOMoPTs383ZaZ42R0QI4cmkhUcIkQfzdT9nBzbZW0vYdm8JIRyiK8vhDNlawi4S8Agh8mAJZpTSr5uklfODgWvjeIQQDpMurRIlAY8QIh9GLLOxcgKbnP9bpqbLDulCOE5maZU8GcMjhMhD9q1BXYWsw6AuZwc4OV1Zsp2EEKJskRYeIYQNpSytN3rKR6AugDJD+gaU351oFV/AEvBkAd5urqkQZZhSLhiDI0089pCARwhxAzPKnIFW4UmuDV5+CcwX4fICCByO3DqEcI6Gi7q0pGe5yOSuJYS4gQHNGJA9I8sL66wsYzAEDEPTjNnT1oUQDnPVbukS8BSZBDxCiBtoKJWFpl27PSiVBRgge2VlGbAshChrJOARQlhZNwzN+gf98jzI/BuMwWgBj6H5dUYp3TrGRwjhBAWa7JZeoiTgEUJcRwc9FYy10UzvWNNU5n5IWw5+d5N7Q1EhhN0UlhUenC1DFJkEPEIIK03zQhkCLf83n7ZsJ+FVDbwbg1cjS7qM3xHCaZpSTrfwON1CVM5IwCOEsFIqE8xx6EmTIPMPS5pXAzTTm+BVD6VnoRnktiGES0i8UqJk4UEhxHUMqIvDrcEOAFl/oy4+CmSCJgsOCiHKJgl4hBBA9kys9PWgn87jZCKkrQAyS7xeQniknIUHnT1EkUnbtBAimw76uQJOJ5RcVYTwcLKXVsmTFh4hRDYv8Gmf/2mfDsgtQwgXKuHWnRkzZnDbbbdRsWJFQkNDuffeezl06JBNnuHDh6Npms3Rtm1bmzzp6ek888wzhISEEBgYSN++fTl16pRTf4qSIHcvIQQAmmZA86oB/g/lPunbA82nmc1ihEKIsmXjxo08/fTTbNu2jbVr15KVlUX37t25fPmyTb6ePXty5swZ6/Hzzz/bnB87dixLly5lyZIlbN68mdTUVPr06YPZbKY0k7uXEMJKKYXB9CrKpy3q6k9AFppfT/Drh1JmNBm0LIRr6KA5uw6PnY9ftWqVze8LFiwgNDSU6OhoOnbsaE339fUlPDw8zzKSkpKYP38+X3zxBV27dgXgyy+/JCoqinXr1tGjRw/7KlWCpIVHCGFlXUHZrxuGyv+HofJc8Otjaf2RYEcIF3LFgGXnBvEkJSUBEBwcbJO+YcMGQkNDqVevHiNGjCAh4dr4vejoaDIzM+nevbs1LTIyksaNG7Nlyxan6lPcpIVHCJGLpnnn+bMQwkVctHmoUork5GSbZF9fX3x9fQt+qFKMHz+e22+/ncaNG1vTe/XqxYABA6hRowYxMTG89NJL3HnnnURHR+Pr60t8fDw+Pj5UrlzZprywsDDi4+OdvKDiJQGPEEIIUUbFx8djMpls0qZOncq0adMKfNzo0aPZt28fmzdvtkl/8MEHrT83btyYVq1aUaNGDX766Sf69++fb3llYY89CXiEEEKIEuaqrSXCw8NzzbQqrHXnmWeeYfny5fz2229Uq1atwLwRERHUqFGDI0eOABAeHk5GRgaJiYk2rTwJCQm0b1/ALM9SQMbwCCGEEO7g9MKDlnF3QUFBNkd+AY9SitGjR/P999/z66+/UqtWrUKreOHCBU6ePElERAQALVu2xNvbm7Vr11rznDlzhgMHDpT6gEdaeIQQQoiSplPiu6U//fTTfPXVV/zwww9UrFjROubGZDLh7+9Pamoq06ZN4/777yciIoLjx4/z73//m5CQEO677z5r3scff5wJEyZQpUoVgoODmThxIk2aNLHO2iqtJOARQgghyoGPPvoIgM6dO9ukL1iwgOHDh2M0Gtm/fz+LFi3i0qVLRERE0KVLF7755hsqVqxozT979my8vLwYOHAgaWlp3HXXXSxcuBCjsXTP5HR7wBMXF8dzzz3HypUrSUtLo169esyfP5+WLVuSmZnJiy++yM8//8w///yDyWSia9euvPnmm0RGRrq76kIIIYRDNFwzhsceqpD8/v7+rF69utBy/Pz8eP/993n//fften53c+sYnsTERDp06IC3tzcrV67kzz//ZObMmVSqVAmAK1eusHv3bl566SV2797N999/z+HDh+nbt687qy2EEEI4xyUbh8pmWvZwawvPW2+9RVRUFAsWLLCm1axZ0/qzyWSyGRgF8P7779O6dWtiY2OpXr16SVVVCCGEcB2F87udS7xjF7e28CxfvpxWrVoxYMAAQkNDad68OZ988kmBj0lKSkLTNGsrkBBCCCFEYdwa8Pzzzz989NFH1K1bl9WrV/PUU08xZswYFi1alGf+q1ev8vzzzzNo0CCCgoLyzJOenk5ycrLNIYQQQpQqimsztRw9pIXHLm7t0tJ1nVatWjF9+nQAmjdvzsGDB/noo48YOnSoTd7MzEweeughdF3nww8/zLfM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rb7++us8y1i8eLHy8fHJld61a1c1cuTIYrmWd999V7Vv397anx4TE1Ngl8mWLVsUoHbt2mVXfZQqmdfG3uvJ8Z///EcFBQXle96Vr01xXo873juuvBZ3v2/suZ4c586dU4cOHVJr1qxRHTp0UHfffbfSdT1Xue547xTXteQo6feNKN08uoVn9OjRhc4cqFmzZp7pbdu2BeDo0aNUqVLFmv7nn39y5513MmLEiHy/NRSkRYsWeHt7c+TIEVq0aGHXY115PeHh4Wzfvt0mT2JiIpmZmbm+weYIDw8nIyODxMREm29ECQkJtG/f3o4rKfq1vP7662zbti3XcvGtWrVi8ODBfP755zbpn376Kc2aNaNly5Z21QdK5rWx93pytG3bluTkZM6ePZvn6+PK16a4rsdd7x1XXou73zf2XE+OkJAQQkJCqFevHg0bNiQqKopt27bRrl07m8e4471TXNeSo6TfN6KUc3fEVVr9+OOPClAnTpywph04cECFhoaqSZMmOVzu/v37FaA2btzoimoW2Y3XkzP48vTp09Y8S5YsKdLgy2+++caadvr06WId4HfixAm1f/9+67F69WoFqG+//VadPHnSJm9KSoqqUKFCobN/8lMSr40913O9999/X/n5+amrV6/med4dr41SRb+esvDeKcq1lJX3TX5iY2MVoNavX2+TXhbeOzfK71quV1rfN8I9JOBRlqbcWbNmqT179qh//vlHffPNNyoyMlL17dvXmienKX7w4ME2Ux4TEhKseU6dOqXq16+vtm/frpRS6ujRo+qVV15RO3fuVDExMeqnn35SDRo0UM2bNy/WKY9FuZ6c6bV33XWX2r17t1q3bp2qVq2azfTaG69HKcsUzmrVqql169ap3bt3qzvvvLNEp3AW1GXy6aefKj8/P3Xx4sVc50rLa3OjvK5n+fLlat68eWr//v3q6NGj6pNPPlFBQUFqzJgx+V6PUu5/bfK7nrL03insWsrS+2b79u3q/fffV3v27FHHjx9Xv/76q7r99ttVnTp1cgUApf29U5RrKcvvG1EyJOBRSkVHR6s2bdook8mk/Pz8VP369dXUqVPV5cuXrXny62uuUaOGNU/ODTLnG0dsbKzq2LGjCg4OVj4+PqpOnTpqzJgx6sKFC26/HqUs32h79+6t/P39VXBwsBo9erTNjfDG61FKqbS0NDV69GgVHBys/P39VZ8+fVRsbGyxXs/1Cgp42rVrpwYNGlTg49z92uRXr+uvZ+XKlapZs2aqQoUKKiAgQDVu3FjNmTNHZWZm5ns9Srn/tbm+XtdfT1l67xR2LUqVnffNvn37VJcuXVRwcLDy9fVVNWvWVE899ZQ6depUrryl/b1TlGspy+8bUTJkt3QhhBBCeDxZh0cIIYQQHk8CHiGEEEJ4PAl4hBBCCOHxJOARQgghhMeTgEcIIYQQHk8CHiGEEEJ4PAl4hBBCCOHxJOARQgghhMeTgEeIQhw/fhxN09i7d2+xlK9pGsuWLXP48Rs2bEDTNDRN49577y0wb+fOnRk7dqzDzyUKlvM6VKpUyd1VEULcQAIeUaoNHz680A/x4hYVFcWZM2do3LgxcC3AuHTpklvrdaNDhw6xcOFCd1ejXMjv3+WZM2eYM2dOiddHCFE4CXiEKITRaCQ8PBwvLy93V6VAoaGhpaJlITMz091VcJvw8HBMJpO7qyGEyIMEPKJM27hxI61bt8bX15eIiAief/55srKyrOc7d+7MmDFjmDx5MsHBwYSHhzNt2jSbMv7++29uv/12/Pz8aNSoEevWrbPpZrq+S+v48eN06dIFgMqVK6NpGsOHDwegZs2aub7dN2vWzOb5jhw5QseOHa3PtXbt2lzXFBcXx4MPPkjlypWpUqUK/fr14/jx43b/bS5fvszQoUOpUKECERERzJw5M1eejIwMJk+ezE033URgYCBt2rRhw4YNNnk++eQToqKiCAgI4L777mPWrFk2gdW0adNo1qwZn332GbVr18bX1xelFElJSTz55JOEhoYSFBTEnXfeyR9//GFT9o8//kjLli3x8/Ojdu3avPLKKzav37Rp06hevTq+vr5ERkYyZsyYIl17Ydd14cIFHn74YapVq0ZAQABNmjTh66+/tinj22+/pUmTJvj7+1OlShW6du3K5cuXmTZtGp9//jk//PCDtQvrxr+ZEKL0Kd1fWYUoQFxcHHfffTfDhw9n0aJF/P3334wYMQI/Pz+bIOPzzz9n/PjxbN++na1btzJ8+HA6dOhAt27d0HWde++9l+rVq7N9+3ZSUlKYMGFCvs8ZFRXFd999x/3338+hQ4cICgrC39+/SPXVdZ3+/fsTEhLCtm3bSE5OzjWe5sqVK3Tp0oU77riD3377DS8vL15//XV69uzJvn378PHxKfLfZ9KkSaxfv56lS5cSHh7Ov//9b6Kjo2nWrJk1z6OPPsrx48dZsmQJkZGRLF26lJ49e7J//37q1q3L77//zlNPPcVbb71F3759WbduHS+99FKu5zp69Cj//e9/+e677zAajQD07t2b4OBgfv75Z0wmE3PnzuWuu+7i8OHDBAcHs3r1ah555BHee+897rjjDo4dO8aTTz4JwNSpU/n222+ZPXs2S5Ys4ZZbbiE+Pj5XwJSfwq7r6tWrtGzZkueee46goCB++uknhgwZQu3atWnTpg1nzpzh4Ycf5u233+a+++4jJSWFTZs2oZRi4sSJ/PXXXyQnJ7NgwQIAgoODi/y6CCHcxL2btQtRsGHDhql+/frlee7f//63ql+/vtJ13Zr2f//3f6pChQrKbDYrpZTq1KmTuv32220ed9ttt6nnnntOKaXUypUrlZeXlzpz5oz1/Nq1axWgli5dqpRSKiYmRgFqz549Siml1q9frwCVmJhoU26NGjXU7NmzbdKaNm2qpk6dqpRSavXq1cpoNKqTJ09az69cudLmuebPn5/rmtLT05W/v79avXp1nn+HvOqTkpKifHx81JIlS6xpFy5cUP7+/urZZ59VSil19OhRpWmaiouLsynvrrvuUlOmTFFKKfXggw+q3r1725wfPHiwMplM1t+nTp2qvL29VUJCgjXtl19+UUFBQerq1as2j61Tp46aO3euUkqpO+64Q02fPt3m/BdffKEiIiKUUkrNnDlT1atXT2VkZOR53fkpynXl5e6771YTJkxQSikVHR2tAHX8+PE88xb073LBggU2fx8hROkgLTyizPrrr79o164dmqZZ0zp06EBqaiqnTp2ievXqANx66602j4uIiCAhIQGwDPSNiooiPDzcer5169bFVt/q1atTrVo1a1q7du1s8kRHR3P06FEqVqxok3716lWOHTtW5Oc6duwYGRkZNuUHBwdTv3596++7d+9GKUW9evVsHpuenk6VKlUAy9/nvvvusznfunVrVqxYYZNWo0YNqlatanMdqamp1nJypKWlWa8jOjqanTt38sYbb1jPm81mrl69ypUrVxgwYABz5syhdu3a9OzZk7vvvpt77rmn0LFURbkus9nMm2++yTfffENcXBzp6emkp6cTGBgIQNOmTbnrrrto0qQJPXr0oHv37jzwwANUrly5wOcWQpReEvCI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", - "text/plain": [ - "
" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "ds.plot.scatter(x=\"longitude\", y=\"latitude\", hue=\"h_li\", vmin=-100, vmax=2000)" ] @@ -754,7 +132,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "63da2b3c", "metadata": {}, "outputs": [], @@ -765,24 +143,10 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": null, "id": "e6f7c047", "metadata": {}, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "'Query' object has no attribute '_session'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", - "Cell \u001b[0;32mIn[10], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mregion_a\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mdownload_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mpath_root\u001b[49m\u001b[43m)\u001b[49m\n", - "File \u001b[0;32m~/envs/general/lib/python3.11/site-packages/icepyx/core/query.py:1129\u001b[0m, in \u001b[0;36mQuery.download_granules\u001b[0;34m(self, path, verbose, subset, restart, **kwargs)\u001b[0m\n\u001b[1;32m 1124\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1125\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m (\n\u001b[1;32m 1126\u001b[0m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28mhasattr\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules, \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124morderIDs\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 1127\u001b[0m \u001b[38;5;129;01mor\u001b[39;00m \u001b[38;5;28mlen\u001b[39m(\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39morderIDs) \u001b[38;5;241m==\u001b[39m \u001b[38;5;241m0\u001b[39m\n\u001b[1;32m 1128\u001b[0m ):\n\u001b[0;32m-> 1129\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43morder_granules\u001b[49m\u001b[43m(\u001b[49m\u001b[43mverbose\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mverbose\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msubset\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43msubset\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 1131\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39mdownload(verbose, path, session\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_session, restart\u001b[38;5;241m=\u001b[39mrestart)\n", - "File \u001b[0;32m~/envs/general/lib/python3.11/site-packages/icepyx/core/query.py:1065\u001b[0m, in \u001b[0;36mQuery.order_granules\u001b[0;34m(self, verbose, subset, email, **kwargs)\u001b[0m\n\u001b[1;32m 1048\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39mplace_order(\n\u001b[1;32m 1049\u001b[0m tempCMRparams,\n\u001b[1;32m 1050\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreqparams,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 1055\u001b[0m geom_filepath\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_spatial\u001b[38;5;241m.\u001b[39m_geom_file,\n\u001b[1;32m 1056\u001b[0m )\n\u001b[1;32m 1058\u001b[0m \u001b[38;5;28;01melse\u001b[39;00m:\n\u001b[1;32m 1059\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_granules\u001b[38;5;241m.\u001b[39mplace_order(\n\u001b[1;32m 1060\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mCMRparams,\n\u001b[1;32m 1061\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mreqparams,\n\u001b[1;32m 1062\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39msubsetparams(\u001b[38;5;241m*\u001b[39m\u001b[38;5;241m*\u001b[39mkwargs),\n\u001b[1;32m 1063\u001b[0m verbose,\n\u001b[1;32m 1064\u001b[0m subset,\n\u001b[0;32m-> 1065\u001b[0m session\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43m_session\u001b[49m,\n\u001b[1;32m 1066\u001b[0m geom_filepath\u001b[38;5;241m=\u001b[39m\u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_spatial\u001b[38;5;241m.\u001b[39m_geom_file,\n\u001b[1;32m 1067\u001b[0m )\n", - "\u001b[0;31mAttributeError\u001b[0m: 'Query' object has no attribute '_session'" - ] - } - ], + "outputs": [], "source": [ "region_a.download_granules(path=path_root)" ] @@ -823,7 +187,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": null, "id": "9cde6679", "metadata": {}, "outputs": [], @@ -833,7 +197,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": null, "id": "8b6edf0c", "metadata": {}, "outputs": [], @@ -843,7 +207,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": null, "id": "e683ebf7", "metadata": {}, "outputs": [], @@ -870,7 +234,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": null, "id": "7318abd0", "metadata": {}, "outputs": [], @@ -881,7 +245,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "id": "f43e8664", "metadata": {}, "outputs": [], @@ -891,7 +255,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": null, "id": "992a77fb", "metadata": {}, "outputs": [], @@ -901,7 +265,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "id": "6aec1a70", "metadata": {}, "outputs": [], @@ -928,46 +292,22 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": null, "id": "39bd7eb8", "metadata": { "scrolled": true }, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "You have 6 files matching the filename pattern to be read in.\n" - ] - } - ], + "outputs": [], "source": [ "reader = ipx.Read(data_source=path_root, product=\"ATL06\", filename_pattern=pattern) # or ipx.Read(filepath, \"ATLXX\") if your filenames match the default pattern" ] }, { "cell_type": "code", - "execution_count": 20, + "execution_count": null, "id": "6c9ebc4a", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "['../../../../data/ATL06/processed_ATL06_20190226005526_09100205_006_02.h5',\n", - " '../../../../data/ATL06/processed_ATL06_20191201105502_10010505_006_01.h5',\n", - " '../../../../data/ATL06/processed_ATL06_20190225121032_09020203_006_02.h5',\n", - " '../../../../data/ATL06/processed_ATL06_20190222010344_08490205_006_02.h5',\n", - " '../../../../data/ATL06/processed_ATL06_20191130112041_09860505_006_01.h5',\n", - " '../../../../data/ATL06/processed_ATL06_20191202102922_10160505_006_01.h5']" - ] - }, - "execution_count": 20, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "reader._filelist" ] @@ -990,616 +330,12 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": null, "id": "18f65f67", "metadata": { "scrolled": true }, - "outputs": [ - { - "data": { - "text/plain": [ - "['ancillary_data/atlas_sdp_gps_epoch',\n", - " 'ancillary_data/control',\n", - " 'ancillary_data/data_end_utc',\n", - " 'ancillary_data/data_start_utc',\n", - " 'ancillary_data/end_cycle',\n", - " 'ancillary_data/end_delta_time',\n", - " 'ancillary_data/end_geoseg',\n", - " 'ancillary_data/end_gpssow',\n", - " 'ancillary_data/end_gpsweek',\n", - " 'ancillary_data/end_orbit',\n", - " 'ancillary_data/end_region',\n", - " 'ancillary_data/end_rgt',\n", - " 'ancillary_data/granule_end_utc',\n", - " 'ancillary_data/granule_start_utc',\n", - " 'ancillary_data/land_ice/dt_hist',\n", - " 'ancillary_data/land_ice/fit_maxiter',\n", - " 'ancillary_data/land_ice/fpb_maxiter',\n", - " 'ancillary_data/land_ice/max_res_ids',\n", - " 'ancillary_data/land_ice/min_dist',\n", - " 'ancillary_data/land_ice/min_gain_th',\n", - " 'ancillary_data/land_ice/min_n_pe',\n", - " 'ancillary_data/land_ice/min_n_sel',\n", - " 'ancillary_data/land_ice/min_signal_conf',\n", - " 'ancillary_data/land_ice/n_hist',\n", - " 'ancillary_data/land_ice/n_sigmas',\n", - " 'ancillary_data/land_ice/nhist_bins',\n", - " 'ancillary_data/land_ice/proc_interval',\n", - " 'ancillary_data/land_ice/qs_lim_bsc',\n", - " 'ancillary_data/land_ice/qs_lim_hrs',\n", - " 'ancillary_data/land_ice/qs_lim_hsigma',\n", - " 'ancillary_data/land_ice/qs_lim_msw',\n", - " 'ancillary_data/land_ice/qs_lim_snr',\n", - " 'ancillary_data/land_ice/qs_lim_sss',\n", - " 'ancillary_data/land_ice/rbin_width',\n", - " 'ancillary_data/land_ice/sigma_beam',\n", - " 'ancillary_data/land_ice/sigma_tx',\n", - " 'ancillary_data/land_ice/t_dead',\n", - " 'ancillary_data/land_ice/txp_maxiter',\n", - " 'ancillary_data/qa_at_interval',\n", - " 'ancillary_data/release',\n", - " 'ancillary_data/start_cycle',\n", - " 'ancillary_data/start_delta_time',\n", - " 'ancillary_data/start_geoseg',\n", - " 'ancillary_data/start_gpssow',\n", - " 'ancillary_data/start_gpsweek',\n", - " 'ancillary_data/start_orbit',\n", - " 'ancillary_data/start_region',\n", - " 'ancillary_data/start_rgt',\n", - " 'ancillary_data/version',\n", - " 'gt1l/land_ice_segments/atl06_quality_summary',\n", - " 'gt1l/land_ice_segments/bias_correction/fpb_mean_corr',\n", - " 'gt1l/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", - " 'gt1l/land_ice_segments/bias_correction/fpb_med_corr',\n", - " 'gt1l/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", - " 'gt1l/land_ice_segments/bias_correction/fpb_n_corr',\n", - " 'gt1l/land_ice_segments/bias_correction/med_r_fit',\n", - " 'gt1l/land_ice_segments/bias_correction/tx_mean_corr',\n", - " 'gt1l/land_ice_segments/bias_correction/tx_med_corr',\n", - " 'gt1l/land_ice_segments/delta_time',\n", - " 'gt1l/land_ice_segments/dem/dem_flag',\n", - " 'gt1l/land_ice_segments/dem/dem_h',\n", - " 'gt1l/land_ice_segments/dem/geoid_free2mean',\n", - " 'gt1l/land_ice_segments/dem/geoid_h',\n", - " 'gt1l/land_ice_segments/fit_statistics/dh_fit_dx',\n", - " 'gt1l/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", - " 'gt1l/land_ice_segments/fit_statistics/dh_fit_dy',\n", - " 'gt1l/land_ice_segments/fit_statistics/h_expected_rms',\n", - " 'gt1l/land_ice_segments/fit_statistics/h_mean',\n", - " 'gt1l/land_ice_segments/fit_statistics/h_rms_misfit',\n", - " 'gt1l/land_ice_segments/fit_statistics/h_robust_sprd',\n", - " 'gt1l/land_ice_segments/fit_statistics/n_fit_photons',\n", - " 'gt1l/land_ice_segments/fit_statistics/n_seg_pulses',\n", - " 'gt1l/land_ice_segments/fit_statistics/sigma_h_mean',\n", - " 'gt1l/land_ice_segments/fit_statistics/signal_selection_source',\n", - " 'gt1l/land_ice_segments/fit_statistics/signal_selection_source_status',\n", - " 'gt1l/land_ice_segments/fit_statistics/snr',\n", - " 'gt1l/land_ice_segments/fit_statistics/snr_significance',\n", - " 'gt1l/land_ice_segments/fit_statistics/w_surface_window_final',\n", - " 'gt1l/land_ice_segments/geophysical/bckgrd',\n", - " 'gt1l/land_ice_segments/geophysical/bsnow_conf',\n", - " 'gt1l/land_ice_segments/geophysical/bsnow_h',\n", - " 'gt1l/land_ice_segments/geophysical/bsnow_od',\n", - " 'gt1l/land_ice_segments/geophysical/cloud_flg_asr',\n", - " 'gt1l/land_ice_segments/geophysical/cloud_flg_atm',\n", - " 'gt1l/land_ice_segments/geophysical/dac',\n", - " 'gt1l/land_ice_segments/geophysical/e_bckgrd',\n", - " 'gt1l/land_ice_segments/geophysical/layer_flag',\n", - " 'gt1l/land_ice_segments/geophysical/msw_flag',\n", - " 'gt1l/land_ice_segments/geophysical/neutat_delay_total',\n", - " 'gt1l/land_ice_segments/geophysical/r_eff',\n", - " 'gt1l/land_ice_segments/geophysical/solar_azimuth',\n", - " 'gt1l/land_ice_segments/geophysical/solar_elevation',\n", - " 'gt1l/land_ice_segments/geophysical/tide_earth',\n", - " 'gt1l/land_ice_segments/geophysical/tide_earth_free2mean',\n", - " 'gt1l/land_ice_segments/geophysical/tide_equilibrium',\n", - " 'gt1l/land_ice_segments/geophysical/tide_load',\n", - " 'gt1l/land_ice_segments/geophysical/tide_ocean',\n", - " 'gt1l/land_ice_segments/geophysical/tide_pole',\n", - " 'gt1l/land_ice_segments/ground_track/ref_azimuth',\n", - " 'gt1l/land_ice_segments/ground_track/ref_coelv',\n", - " 'gt1l/land_ice_segments/ground_track/seg_azimuth',\n", - " 'gt1l/land_ice_segments/ground_track/sigma_geo_at',\n", - " 'gt1l/land_ice_segments/ground_track/sigma_geo_r',\n", - " 'gt1l/land_ice_segments/ground_track/sigma_geo_xt',\n", - " 'gt1l/land_ice_segments/ground_track/x_atc',\n", - " 'gt1l/land_ice_segments/ground_track/y_atc',\n", - " 'gt1l/land_ice_segments/h_li',\n", - " 'gt1l/land_ice_segments/h_li_sigma',\n", - " 'gt1l/land_ice_segments/latitude',\n", - " 'gt1l/land_ice_segments/longitude',\n", - " 'gt1l/land_ice_segments/segment_id',\n", - " 'gt1l/land_ice_segments/sigma_geo_h',\n", - " 'gt1l/residual_histogram/bckgrd_per_m',\n", - " 'gt1l/residual_histogram/bin_top_h',\n", - " 'gt1l/residual_histogram/count',\n", - " 'gt1l/residual_histogram/delta_time',\n", - " 'gt1l/residual_histogram/ds_segment_id',\n", - " 'gt1l/residual_histogram/lat_mean',\n", - " 'gt1l/residual_histogram/lon_mean',\n", - " 'gt1l/residual_histogram/pulse_count',\n", - " 'gt1l/residual_histogram/segment_id_list',\n", - " 'gt1l/residual_histogram/x_atc_mean',\n", - " 'gt1l/segment_quality/delta_time',\n", - " 'gt1l/segment_quality/record_number',\n", - " 'gt1l/segment_quality/reference_pt_lat',\n", - " 'gt1l/segment_quality/reference_pt_lon',\n", - " 'gt1l/segment_quality/segment_id',\n", - " 'gt1l/segment_quality/signal_selection_source',\n", - " 'gt1l/segment_quality/signal_selection_status/signal_selection_status_all',\n", - " 'gt1l/segment_quality/signal_selection_status/signal_selection_status_backup',\n", - " 'gt1l/segment_quality/signal_selection_status/signal_selection_status_confident',\n", - " 'gt1r/land_ice_segments/atl06_quality_summary',\n", - " 'gt1r/land_ice_segments/bias_correction/fpb_mean_corr',\n", - " 'gt1r/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", - " 'gt1r/land_ice_segments/bias_correction/fpb_med_corr',\n", - " 'gt1r/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", - " 'gt1r/land_ice_segments/bias_correction/fpb_n_corr',\n", - " 'gt1r/land_ice_segments/bias_correction/med_r_fit',\n", - " 'gt1r/land_ice_segments/bias_correction/tx_mean_corr',\n", - " 'gt1r/land_ice_segments/bias_correction/tx_med_corr',\n", - " 'gt1r/land_ice_segments/delta_time',\n", - " 'gt1r/land_ice_segments/dem/dem_flag',\n", - " 'gt1r/land_ice_segments/dem/dem_h',\n", - " 'gt1r/land_ice_segments/dem/geoid_free2mean',\n", - " 'gt1r/land_ice_segments/dem/geoid_h',\n", - " 'gt1r/land_ice_segments/fit_statistics/dh_fit_dx',\n", - " 'gt1r/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", - " 'gt1r/land_ice_segments/fit_statistics/dh_fit_dy',\n", - " 'gt1r/land_ice_segments/fit_statistics/h_expected_rms',\n", - " 'gt1r/land_ice_segments/fit_statistics/h_mean',\n", - " 'gt1r/land_ice_segments/fit_statistics/h_rms_misfit',\n", - " 'gt1r/land_ice_segments/fit_statistics/h_robust_sprd',\n", - " 'gt1r/land_ice_segments/fit_statistics/n_fit_photons',\n", - " 'gt1r/land_ice_segments/fit_statistics/n_seg_pulses',\n", - " 'gt1r/land_ice_segments/fit_statistics/sigma_h_mean',\n", - " 'gt1r/land_ice_segments/fit_statistics/signal_selection_source',\n", - " 'gt1r/land_ice_segments/fit_statistics/signal_selection_source_status',\n", - " 'gt1r/land_ice_segments/fit_statistics/snr',\n", - " 'gt1r/land_ice_segments/fit_statistics/snr_significance',\n", - " 'gt1r/land_ice_segments/fit_statistics/w_surface_window_final',\n", - " 'gt1r/land_ice_segments/geophysical/bckgrd',\n", - " 'gt1r/land_ice_segments/geophysical/bsnow_conf',\n", - " 'gt1r/land_ice_segments/geophysical/bsnow_h',\n", - " 'gt1r/land_ice_segments/geophysical/bsnow_od',\n", - " 'gt1r/land_ice_segments/geophysical/cloud_flg_asr',\n", - " 'gt1r/land_ice_segments/geophysical/cloud_flg_atm',\n", - " 'gt1r/land_ice_segments/geophysical/dac',\n", - " 'gt1r/land_ice_segments/geophysical/e_bckgrd',\n", - " 'gt1r/land_ice_segments/geophysical/layer_flag',\n", - " 'gt1r/land_ice_segments/geophysical/msw_flag',\n", - " 'gt1r/land_ice_segments/geophysical/neutat_delay_total',\n", - " 'gt1r/land_ice_segments/geophysical/r_eff',\n", - " 'gt1r/land_ice_segments/geophysical/solar_azimuth',\n", - " 'gt1r/land_ice_segments/geophysical/solar_elevation',\n", - " 'gt1r/land_ice_segments/geophysical/tide_earth',\n", - " 'gt1r/land_ice_segments/geophysical/tide_earth_free2mean',\n", - " 'gt1r/land_ice_segments/geophysical/tide_equilibrium',\n", - " 'gt1r/land_ice_segments/geophysical/tide_load',\n", - " 'gt1r/land_ice_segments/geophysical/tide_ocean',\n", - " 'gt1r/land_ice_segments/geophysical/tide_pole',\n", - " 'gt1r/land_ice_segments/ground_track/ref_azimuth',\n", - " 'gt1r/land_ice_segments/ground_track/ref_coelv',\n", - " 'gt1r/land_ice_segments/ground_track/seg_azimuth',\n", - " 'gt1r/land_ice_segments/ground_track/sigma_geo_at',\n", - " 'gt1r/land_ice_segments/ground_track/sigma_geo_r',\n", - " 'gt1r/land_ice_segments/ground_track/sigma_geo_xt',\n", - " 'gt1r/land_ice_segments/ground_track/x_atc',\n", - " 'gt1r/land_ice_segments/ground_track/y_atc',\n", - " 'gt1r/land_ice_segments/h_li',\n", - " 'gt1r/land_ice_segments/h_li_sigma',\n", - " 'gt1r/land_ice_segments/latitude',\n", - " 'gt1r/land_ice_segments/longitude',\n", - " 'gt1r/land_ice_segments/segment_id',\n", - " 'gt1r/land_ice_segments/sigma_geo_h',\n", - " 'gt1r/residual_histogram/bckgrd_per_m',\n", - " 'gt1r/residual_histogram/bin_top_h',\n", - " 'gt1r/residual_histogram/count',\n", - " 'gt1r/residual_histogram/delta_time',\n", - " 'gt1r/residual_histogram/ds_segment_id',\n", - " 'gt1r/residual_histogram/lat_mean',\n", - " 'gt1r/residual_histogram/lon_mean',\n", - " 'gt1r/residual_histogram/pulse_count',\n", - " 'gt1r/residual_histogram/segment_id_list',\n", - " 'gt1r/residual_histogram/x_atc_mean',\n", - " 'gt1r/segment_quality/delta_time',\n", - " 'gt1r/segment_quality/record_number',\n", - " 'gt1r/segment_quality/reference_pt_lat',\n", - " 'gt1r/segment_quality/reference_pt_lon',\n", - " 'gt1r/segment_quality/segment_id',\n", - " 'gt1r/segment_quality/signal_selection_source',\n", - " 'gt1r/segment_quality/signal_selection_status/signal_selection_status_all',\n", - " 'gt1r/segment_quality/signal_selection_status/signal_selection_status_backup',\n", - " 'gt1r/segment_quality/signal_selection_status/signal_selection_status_confident',\n", - " 'gt2l/land_ice_segments/atl06_quality_summary',\n", - " 'gt2l/land_ice_segments/bias_correction/fpb_mean_corr',\n", - " 'gt2l/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", - " 'gt2l/land_ice_segments/bias_correction/fpb_med_corr',\n", - " 'gt2l/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", - " 'gt2l/land_ice_segments/bias_correction/fpb_n_corr',\n", - " 'gt2l/land_ice_segments/bias_correction/med_r_fit',\n", - " 'gt2l/land_ice_segments/bias_correction/tx_mean_corr',\n", - " 'gt2l/land_ice_segments/bias_correction/tx_med_corr',\n", - " 'gt2l/land_ice_segments/delta_time',\n", - " 'gt2l/land_ice_segments/dem/dem_flag',\n", - " 'gt2l/land_ice_segments/dem/dem_h',\n", - " 'gt2l/land_ice_segments/dem/geoid_free2mean',\n", - " 'gt2l/land_ice_segments/dem/geoid_h',\n", - " 'gt2l/land_ice_segments/fit_statistics/dh_fit_dx',\n", - " 'gt2l/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", - " 'gt2l/land_ice_segments/fit_statistics/dh_fit_dy',\n", - " 'gt2l/land_ice_segments/fit_statistics/h_expected_rms',\n", - " 'gt2l/land_ice_segments/fit_statistics/h_mean',\n", - " 'gt2l/land_ice_segments/fit_statistics/h_rms_misfit',\n", - " 'gt2l/land_ice_segments/fit_statistics/h_robust_sprd',\n", - " 'gt2l/land_ice_segments/fit_statistics/n_fit_photons',\n", - " 'gt2l/land_ice_segments/fit_statistics/n_seg_pulses',\n", - " 'gt2l/land_ice_segments/fit_statistics/sigma_h_mean',\n", - " 'gt2l/land_ice_segments/fit_statistics/signal_selection_source',\n", - " 'gt2l/land_ice_segments/fit_statistics/signal_selection_source_status',\n", - " 'gt2l/land_ice_segments/fit_statistics/snr',\n", - " 'gt2l/land_ice_segments/fit_statistics/snr_significance',\n", - " 'gt2l/land_ice_segments/fit_statistics/w_surface_window_final',\n", - " 'gt2l/land_ice_segments/geophysical/bckgrd',\n", - " 'gt2l/land_ice_segments/geophysical/bsnow_conf',\n", - " 'gt2l/land_ice_segments/geophysical/bsnow_h',\n", - " 'gt2l/land_ice_segments/geophysical/bsnow_od',\n", - " 'gt2l/land_ice_segments/geophysical/cloud_flg_asr',\n", - " 'gt2l/land_ice_segments/geophysical/cloud_flg_atm',\n", - " 'gt2l/land_ice_segments/geophysical/dac',\n", - " 'gt2l/land_ice_segments/geophysical/e_bckgrd',\n", - " 'gt2l/land_ice_segments/geophysical/layer_flag',\n", - " 'gt2l/land_ice_segments/geophysical/msw_flag',\n", - " 'gt2l/land_ice_segments/geophysical/neutat_delay_total',\n", - " 'gt2l/land_ice_segments/geophysical/r_eff',\n", - " 'gt2l/land_ice_segments/geophysical/solar_azimuth',\n", - " 'gt2l/land_ice_segments/geophysical/solar_elevation',\n", - " 'gt2l/land_ice_segments/geophysical/tide_earth',\n", - " 'gt2l/land_ice_segments/geophysical/tide_earth_free2mean',\n", - " 'gt2l/land_ice_segments/geophysical/tide_equilibrium',\n", - " 'gt2l/land_ice_segments/geophysical/tide_load',\n", - " 'gt2l/land_ice_segments/geophysical/tide_ocean',\n", - " 'gt2l/land_ice_segments/geophysical/tide_pole',\n", - " 'gt2l/land_ice_segments/ground_track/ref_azimuth',\n", - " 'gt2l/land_ice_segments/ground_track/ref_coelv',\n", - " 'gt2l/land_ice_segments/ground_track/seg_azimuth',\n", - " 'gt2l/land_ice_segments/ground_track/sigma_geo_at',\n", - " 'gt2l/land_ice_segments/ground_track/sigma_geo_r',\n", - " 'gt2l/land_ice_segments/ground_track/sigma_geo_xt',\n", - " 'gt2l/land_ice_segments/ground_track/x_atc',\n", - " 'gt2l/land_ice_segments/ground_track/y_atc',\n", - " 'gt2l/land_ice_segments/h_li',\n", - " 'gt2l/land_ice_segments/h_li_sigma',\n", - " 'gt2l/land_ice_segments/latitude',\n", - " 'gt2l/land_ice_segments/longitude',\n", - " 'gt2l/land_ice_segments/segment_id',\n", - " 'gt2l/land_ice_segments/sigma_geo_h',\n", - " 'gt2l/residual_histogram/bckgrd_per_m',\n", - " 'gt2l/residual_histogram/bin_top_h',\n", - " 'gt2l/residual_histogram/count',\n", - " 'gt2l/residual_histogram/delta_time',\n", - " 'gt2l/residual_histogram/ds_segment_id',\n", - " 'gt2l/residual_histogram/lat_mean',\n", - " 'gt2l/residual_histogram/lon_mean',\n", - " 'gt2l/residual_histogram/pulse_count',\n", - " 'gt2l/residual_histogram/segment_id_list',\n", - " 'gt2l/residual_histogram/x_atc_mean',\n", - " 'gt2l/segment_quality/delta_time',\n", - " 'gt2l/segment_quality/record_number',\n", - " 'gt2l/segment_quality/reference_pt_lat',\n", - " 'gt2l/segment_quality/reference_pt_lon',\n", - " 'gt2l/segment_quality/segment_id',\n", - " 'gt2l/segment_quality/signal_selection_source',\n", - " 'gt2l/segment_quality/signal_selection_status/signal_selection_status_all',\n", - " 'gt2l/segment_quality/signal_selection_status/signal_selection_status_backup',\n", - " 'gt2l/segment_quality/signal_selection_status/signal_selection_status_confident',\n", - " 'gt2r/land_ice_segments/atl06_quality_summary',\n", - " 'gt2r/land_ice_segments/bias_correction/fpb_mean_corr',\n", - " 'gt2r/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", - " 'gt2r/land_ice_segments/bias_correction/fpb_med_corr',\n", - " 'gt2r/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", - " 'gt2r/land_ice_segments/bias_correction/fpb_n_corr',\n", - " 'gt2r/land_ice_segments/bias_correction/med_r_fit',\n", - " 'gt2r/land_ice_segments/bias_correction/tx_mean_corr',\n", - " 'gt2r/land_ice_segments/bias_correction/tx_med_corr',\n", - " 'gt2r/land_ice_segments/delta_time',\n", - " 'gt2r/land_ice_segments/dem/dem_flag',\n", - " 'gt2r/land_ice_segments/dem/dem_h',\n", - " 'gt2r/land_ice_segments/dem/geoid_free2mean',\n", - " 'gt2r/land_ice_segments/dem/geoid_h',\n", - " 'gt2r/land_ice_segments/fit_statistics/dh_fit_dx',\n", - " 'gt2r/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", - " 'gt2r/land_ice_segments/fit_statistics/dh_fit_dy',\n", - " 'gt2r/land_ice_segments/fit_statistics/h_expected_rms',\n", - " 'gt2r/land_ice_segments/fit_statistics/h_mean',\n", - " 'gt2r/land_ice_segments/fit_statistics/h_rms_misfit',\n", - " 'gt2r/land_ice_segments/fit_statistics/h_robust_sprd',\n", - " 'gt2r/land_ice_segments/fit_statistics/n_fit_photons',\n", - " 'gt2r/land_ice_segments/fit_statistics/n_seg_pulses',\n", - " 'gt2r/land_ice_segments/fit_statistics/sigma_h_mean',\n", - " 'gt2r/land_ice_segments/fit_statistics/signal_selection_source',\n", - " 'gt2r/land_ice_segments/fit_statistics/signal_selection_source_status',\n", - " 'gt2r/land_ice_segments/fit_statistics/snr',\n", - " 'gt2r/land_ice_segments/fit_statistics/snr_significance',\n", - " 'gt2r/land_ice_segments/fit_statistics/w_surface_window_final',\n", - " 'gt2r/land_ice_segments/geophysical/bckgrd',\n", - " 'gt2r/land_ice_segments/geophysical/bsnow_conf',\n", - " 'gt2r/land_ice_segments/geophysical/bsnow_h',\n", - " 'gt2r/land_ice_segments/geophysical/bsnow_od',\n", - " 'gt2r/land_ice_segments/geophysical/cloud_flg_asr',\n", - " 'gt2r/land_ice_segments/geophysical/cloud_flg_atm',\n", - " 'gt2r/land_ice_segments/geophysical/dac',\n", - " 'gt2r/land_ice_segments/geophysical/e_bckgrd',\n", - " 'gt2r/land_ice_segments/geophysical/layer_flag',\n", - " 'gt2r/land_ice_segments/geophysical/msw_flag',\n", - " 'gt2r/land_ice_segments/geophysical/neutat_delay_total',\n", - " 'gt2r/land_ice_segments/geophysical/r_eff',\n", - " 'gt2r/land_ice_segments/geophysical/solar_azimuth',\n", - " 'gt2r/land_ice_segments/geophysical/solar_elevation',\n", - " 'gt2r/land_ice_segments/geophysical/tide_earth',\n", - " 'gt2r/land_ice_segments/geophysical/tide_earth_free2mean',\n", - " 'gt2r/land_ice_segments/geophysical/tide_equilibrium',\n", - " 'gt2r/land_ice_segments/geophysical/tide_load',\n", - " 'gt2r/land_ice_segments/geophysical/tide_ocean',\n", - " 'gt2r/land_ice_segments/geophysical/tide_pole',\n", - " 'gt2r/land_ice_segments/ground_track/ref_azimuth',\n", - " 'gt2r/land_ice_segments/ground_track/ref_coelv',\n", - " 'gt2r/land_ice_segments/ground_track/seg_azimuth',\n", - " 'gt2r/land_ice_segments/ground_track/sigma_geo_at',\n", - " 'gt2r/land_ice_segments/ground_track/sigma_geo_r',\n", - " 'gt2r/land_ice_segments/ground_track/sigma_geo_xt',\n", - " 'gt2r/land_ice_segments/ground_track/x_atc',\n", - " 'gt2r/land_ice_segments/ground_track/y_atc',\n", - " 'gt2r/land_ice_segments/h_li',\n", - " 'gt2r/land_ice_segments/h_li_sigma',\n", - " 'gt2r/land_ice_segments/latitude',\n", - " 'gt2r/land_ice_segments/longitude',\n", - " 'gt2r/land_ice_segments/segment_id',\n", - " 'gt2r/land_ice_segments/sigma_geo_h',\n", - " 'gt2r/residual_histogram/bckgrd_per_m',\n", - " 'gt2r/residual_histogram/bin_top_h',\n", - " 'gt2r/residual_histogram/count',\n", - " 'gt2r/residual_histogram/delta_time',\n", - " 'gt2r/residual_histogram/ds_segment_id',\n", - " 'gt2r/residual_histogram/lat_mean',\n", - " 'gt2r/residual_histogram/lon_mean',\n", - " 'gt2r/residual_histogram/pulse_count',\n", - " 'gt2r/residual_histogram/segment_id_list',\n", - " 'gt2r/residual_histogram/x_atc_mean',\n", - " 'gt2r/segment_quality/delta_time',\n", - " 'gt2r/segment_quality/record_number',\n", - " 'gt2r/segment_quality/reference_pt_lat',\n", - " 'gt2r/segment_quality/reference_pt_lon',\n", - " 'gt2r/segment_quality/segment_id',\n", - " 'gt2r/segment_quality/signal_selection_source',\n", - " 'gt2r/segment_quality/signal_selection_status/signal_selection_status_all',\n", - " 'gt2r/segment_quality/signal_selection_status/signal_selection_status_backup',\n", - " 'gt2r/segment_quality/signal_selection_status/signal_selection_status_confident',\n", - " 'gt3l/land_ice_segments/atl06_quality_summary',\n", - " 'gt3l/land_ice_segments/bias_correction/fpb_mean_corr',\n", - " 'gt3l/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", - " 'gt3l/land_ice_segments/bias_correction/fpb_med_corr',\n", - " 'gt3l/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", - " 'gt3l/land_ice_segments/bias_correction/fpb_n_corr',\n", - " 'gt3l/land_ice_segments/bias_correction/med_r_fit',\n", - " 'gt3l/land_ice_segments/bias_correction/tx_mean_corr',\n", - " 'gt3l/land_ice_segments/bias_correction/tx_med_corr',\n", - " 'gt3l/land_ice_segments/delta_time',\n", - " 'gt3l/land_ice_segments/dem/dem_flag',\n", - " 'gt3l/land_ice_segments/dem/dem_h',\n", - " 'gt3l/land_ice_segments/dem/geoid_free2mean',\n", - " 'gt3l/land_ice_segments/dem/geoid_h',\n", - " 'gt3l/land_ice_segments/fit_statistics/dh_fit_dx',\n", - " 'gt3l/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", - " 'gt3l/land_ice_segments/fit_statistics/dh_fit_dy',\n", - " 'gt3l/land_ice_segments/fit_statistics/h_expected_rms',\n", - " 'gt3l/land_ice_segments/fit_statistics/h_mean',\n", - " 'gt3l/land_ice_segments/fit_statistics/h_rms_misfit',\n", - " 'gt3l/land_ice_segments/fit_statistics/h_robust_sprd',\n", - " 'gt3l/land_ice_segments/fit_statistics/n_fit_photons',\n", - " 'gt3l/land_ice_segments/fit_statistics/n_seg_pulses',\n", - " 'gt3l/land_ice_segments/fit_statistics/sigma_h_mean',\n", - " 'gt3l/land_ice_segments/fit_statistics/signal_selection_source',\n", - " 'gt3l/land_ice_segments/fit_statistics/signal_selection_source_status',\n", - " 'gt3l/land_ice_segments/fit_statistics/snr',\n", - " 'gt3l/land_ice_segments/fit_statistics/snr_significance',\n", - " 'gt3l/land_ice_segments/fit_statistics/w_surface_window_final',\n", - " 'gt3l/land_ice_segments/geophysical/bckgrd',\n", - " 'gt3l/land_ice_segments/geophysical/bsnow_conf',\n", - " 'gt3l/land_ice_segments/geophysical/bsnow_h',\n", - " 'gt3l/land_ice_segments/geophysical/bsnow_od',\n", - " 'gt3l/land_ice_segments/geophysical/cloud_flg_asr',\n", - " 'gt3l/land_ice_segments/geophysical/cloud_flg_atm',\n", - " 'gt3l/land_ice_segments/geophysical/dac',\n", - " 'gt3l/land_ice_segments/geophysical/e_bckgrd',\n", - " 'gt3l/land_ice_segments/geophysical/layer_flag',\n", - " 'gt3l/land_ice_segments/geophysical/msw_flag',\n", - " 'gt3l/land_ice_segments/geophysical/neutat_delay_total',\n", - " 'gt3l/land_ice_segments/geophysical/r_eff',\n", - " 'gt3l/land_ice_segments/geophysical/solar_azimuth',\n", - " 'gt3l/land_ice_segments/geophysical/solar_elevation',\n", - " 'gt3l/land_ice_segments/geophysical/tide_earth',\n", - " 'gt3l/land_ice_segments/geophysical/tide_earth_free2mean',\n", - " 'gt3l/land_ice_segments/geophysical/tide_equilibrium',\n", - " 'gt3l/land_ice_segments/geophysical/tide_load',\n", - " 'gt3l/land_ice_segments/geophysical/tide_ocean',\n", - " 'gt3l/land_ice_segments/geophysical/tide_pole',\n", - " 'gt3l/land_ice_segments/ground_track/ref_azimuth',\n", - " 'gt3l/land_ice_segments/ground_track/ref_coelv',\n", - " 'gt3l/land_ice_segments/ground_track/seg_azimuth',\n", - " 'gt3l/land_ice_segments/ground_track/sigma_geo_at',\n", - " 'gt3l/land_ice_segments/ground_track/sigma_geo_r',\n", - " 'gt3l/land_ice_segments/ground_track/sigma_geo_xt',\n", - " 'gt3l/land_ice_segments/ground_track/x_atc',\n", - " 'gt3l/land_ice_segments/ground_track/y_atc',\n", - " 'gt3l/land_ice_segments/h_li',\n", - " 'gt3l/land_ice_segments/h_li_sigma',\n", - " 'gt3l/land_ice_segments/latitude',\n", - " 'gt3l/land_ice_segments/longitude',\n", - " 'gt3l/land_ice_segments/segment_id',\n", - " 'gt3l/land_ice_segments/sigma_geo_h',\n", - " 'gt3l/residual_histogram/bckgrd_per_m',\n", - " 'gt3l/residual_histogram/bin_top_h',\n", - " 'gt3l/residual_histogram/count',\n", - " 'gt3l/residual_histogram/delta_time',\n", - " 'gt3l/residual_histogram/ds_segment_id',\n", - " 'gt3l/residual_histogram/lat_mean',\n", - " 'gt3l/residual_histogram/lon_mean',\n", - " 'gt3l/residual_histogram/pulse_count',\n", - " 'gt3l/residual_histogram/segment_id_list',\n", - " 'gt3l/residual_histogram/x_atc_mean',\n", - " 'gt3l/segment_quality/delta_time',\n", - " 'gt3l/segment_quality/record_number',\n", - " 'gt3l/segment_quality/reference_pt_lat',\n", - " 'gt3l/segment_quality/reference_pt_lon',\n", - " 'gt3l/segment_quality/segment_id',\n", - " 'gt3l/segment_quality/signal_selection_source',\n", - " 'gt3l/segment_quality/signal_selection_status/signal_selection_status_all',\n", - " 'gt3l/segment_quality/signal_selection_status/signal_selection_status_backup',\n", - " 'gt3l/segment_quality/signal_selection_status/signal_selection_status_confident',\n", - " 'gt3r/land_ice_segments/atl06_quality_summary',\n", - " 'gt3r/land_ice_segments/bias_correction/fpb_mean_corr',\n", - " 'gt3r/land_ice_segments/bias_correction/fpb_mean_corr_sigma',\n", - " 'gt3r/land_ice_segments/bias_correction/fpb_med_corr',\n", - " 'gt3r/land_ice_segments/bias_correction/fpb_med_corr_sigma',\n", - " 'gt3r/land_ice_segments/bias_correction/fpb_n_corr',\n", - " 'gt3r/land_ice_segments/bias_correction/med_r_fit',\n", - " 'gt3r/land_ice_segments/bias_correction/tx_mean_corr',\n", - " 'gt3r/land_ice_segments/bias_correction/tx_med_corr',\n", - " 'gt3r/land_ice_segments/delta_time',\n", - " 'gt3r/land_ice_segments/dem/dem_flag',\n", - " 'gt3r/land_ice_segments/dem/dem_h',\n", - " 'gt3r/land_ice_segments/dem/geoid_free2mean',\n", - " 'gt3r/land_ice_segments/dem/geoid_h',\n", - " 'gt3r/land_ice_segments/fit_statistics/dh_fit_dx',\n", - " 'gt3r/land_ice_segments/fit_statistics/dh_fit_dx_sigma',\n", - " 'gt3r/land_ice_segments/fit_statistics/dh_fit_dy',\n", - " 'gt3r/land_ice_segments/fit_statistics/h_expected_rms',\n", - " 'gt3r/land_ice_segments/fit_statistics/h_mean',\n", - " 'gt3r/land_ice_segments/fit_statistics/h_rms_misfit',\n", - " 'gt3r/land_ice_segments/fit_statistics/h_robust_sprd',\n", - " 'gt3r/land_ice_segments/fit_statistics/n_fit_photons',\n", - " 'gt3r/land_ice_segments/fit_statistics/n_seg_pulses',\n", - " 'gt3r/land_ice_segments/fit_statistics/sigma_h_mean',\n", - " 'gt3r/land_ice_segments/fit_statistics/signal_selection_source',\n", - " 'gt3r/land_ice_segments/fit_statistics/signal_selection_source_status',\n", - " 'gt3r/land_ice_segments/fit_statistics/snr',\n", - " 'gt3r/land_ice_segments/fit_statistics/snr_significance',\n", - " 'gt3r/land_ice_segments/fit_statistics/w_surface_window_final',\n", - " 'gt3r/land_ice_segments/geophysical/bckgrd',\n", - " 'gt3r/land_ice_segments/geophysical/bsnow_conf',\n", - " 'gt3r/land_ice_segments/geophysical/bsnow_h',\n", - " 'gt3r/land_ice_segments/geophysical/bsnow_od',\n", - " 'gt3r/land_ice_segments/geophysical/cloud_flg_asr',\n", - " 'gt3r/land_ice_segments/geophysical/cloud_flg_atm',\n", - " 'gt3r/land_ice_segments/geophysical/dac',\n", - " 'gt3r/land_ice_segments/geophysical/e_bckgrd',\n", - " 'gt3r/land_ice_segments/geophysical/layer_flag',\n", - " 'gt3r/land_ice_segments/geophysical/msw_flag',\n", - " 'gt3r/land_ice_segments/geophysical/neutat_delay_total',\n", - " 'gt3r/land_ice_segments/geophysical/r_eff',\n", - " 'gt3r/land_ice_segments/geophysical/solar_azimuth',\n", - " 'gt3r/land_ice_segments/geophysical/solar_elevation',\n", - " 'gt3r/land_ice_segments/geophysical/tide_earth',\n", - " 'gt3r/land_ice_segments/geophysical/tide_earth_free2mean',\n", - " 'gt3r/land_ice_segments/geophysical/tide_equilibrium',\n", - " 'gt3r/land_ice_segments/geophysical/tide_load',\n", - " 'gt3r/land_ice_segments/geophysical/tide_ocean',\n", - " 'gt3r/land_ice_segments/geophysical/tide_pole',\n", - " 'gt3r/land_ice_segments/ground_track/ref_azimuth',\n", - " 'gt3r/land_ice_segments/ground_track/ref_coelv',\n", - " 'gt3r/land_ice_segments/ground_track/seg_azimuth',\n", - " 'gt3r/land_ice_segments/ground_track/sigma_geo_at',\n", - " 'gt3r/land_ice_segments/ground_track/sigma_geo_r',\n", - " 'gt3r/land_ice_segments/ground_track/sigma_geo_xt',\n", - " 'gt3r/land_ice_segments/ground_track/x_atc',\n", - " 'gt3r/land_ice_segments/ground_track/y_atc',\n", - " 'gt3r/land_ice_segments/h_li',\n", - " 'gt3r/land_ice_segments/h_li_sigma',\n", - " 'gt3r/land_ice_segments/latitude',\n", - " 'gt3r/land_ice_segments/longitude',\n", - " 'gt3r/land_ice_segments/segment_id',\n", - " 'gt3r/land_ice_segments/sigma_geo_h',\n", - " 'gt3r/residual_histogram/bckgrd_per_m',\n", - " 'gt3r/residual_histogram/bin_top_h',\n", - " 'gt3r/residual_histogram/count',\n", - " 'gt3r/residual_histogram/delta_time',\n", - " 'gt3r/residual_histogram/ds_segment_id',\n", - " 'gt3r/residual_histogram/lat_mean',\n", - " 'gt3r/residual_histogram/lon_mean',\n", - " 'gt3r/residual_histogram/pulse_count',\n", - " 'gt3r/residual_histogram/segment_id_list',\n", - " 'gt3r/residual_histogram/x_atc_mean',\n", - " 'gt3r/segment_quality/delta_time',\n", - " 'gt3r/segment_quality/record_number',\n", - " 'gt3r/segment_quality/reference_pt_lat',\n", - " 'gt3r/segment_quality/reference_pt_lon',\n", - " 'gt3r/segment_quality/segment_id',\n", - " 'gt3r/segment_quality/signal_selection_source',\n", - " 'gt3r/segment_quality/signal_selection_status/signal_selection_status_all',\n", - " 'gt3r/segment_quality/signal_selection_status/signal_selection_status_backup',\n", - " 'gt3r/segment_quality/signal_selection_status/signal_selection_status_confident',\n", - " 'orbit_info/bounding_polygon_lat1',\n", - " 'orbit_info/bounding_polygon_lon1',\n", - " 'orbit_info/crossing_time',\n", - " 'orbit_info/cycle_number',\n", - " 'orbit_info/lan',\n", - " 'orbit_info/orbit_number',\n", - " 'orbit_info/rgt',\n", - " 'orbit_info/sc_orient',\n", - " 'orbit_info/sc_orient_time',\n", - " 'quality_assessment/gt1l/delta_time',\n", - " 'quality_assessment/gt1l/lat_mean',\n", - " 'quality_assessment/gt1l/lon_mean',\n", - " 'quality_assessment/gt1l/signal_selection_source_fraction_0',\n", - " 'quality_assessment/gt1l/signal_selection_source_fraction_1',\n", - " 'quality_assessment/gt1l/signal_selection_source_fraction_2',\n", - " 'quality_assessment/gt1l/signal_selection_source_fraction_3',\n", - " 'quality_assessment/gt1r/delta_time',\n", - " 'quality_assessment/gt1r/lat_mean',\n", - " 'quality_assessment/gt1r/lon_mean',\n", - " 'quality_assessment/gt1r/signal_selection_source_fraction_0',\n", - " 'quality_assessment/gt1r/signal_selection_source_fraction_1',\n", - " 'quality_assessment/gt1r/signal_selection_source_fraction_2',\n", - " 'quality_assessment/gt1r/signal_selection_source_fraction_3',\n", - " 'quality_assessment/gt2l/delta_time',\n", - " 'quality_assessment/gt2l/lat_mean',\n", - " 'quality_assessment/gt2l/lon_mean',\n", - " 'quality_assessment/gt2l/signal_selection_source_fraction_0',\n", - " 'quality_assessment/gt2l/signal_selection_source_fraction_1',\n", - " 'quality_assessment/gt2l/signal_selection_source_fraction_2',\n", - " 'quality_assessment/gt2l/signal_selection_source_fraction_3',\n", - " 'quality_assessment/gt2r/delta_time',\n", - " 'quality_assessment/gt2r/lat_mean',\n", - " 'quality_assessment/gt2r/lon_mean',\n", - " 'quality_assessment/gt2r/signal_selection_source_fraction_0',\n", - " 'quality_assessment/gt2r/signal_selection_source_fraction_1',\n", - " 'quality_assessment/gt2r/signal_selection_source_fraction_2',\n", - " 'quality_assessment/gt2r/signal_selection_source_fraction_3',\n", - " 'quality_assessment/gt3l/delta_time',\n", - " 'quality_assessment/gt3l/lat_mean',\n", - " 'quality_assessment/gt3l/lon_mean',\n", - " 'quality_assessment/gt3l/signal_selection_source_fraction_0',\n", - " 'quality_assessment/gt3l/signal_selection_source_fraction_1',\n", - " 'quality_assessment/gt3l/signal_selection_source_fraction_2',\n", - " 'quality_assessment/gt3l/signal_selection_source_fraction_3',\n", - " 'quality_assessment/gt3r/delta_time',\n", - " 'quality_assessment/gt3r/lat_mean',\n", - " 'quality_assessment/gt3r/lon_mean',\n", - " 'quality_assessment/gt3r/signal_selection_source_fraction_0',\n", - " 'quality_assessment/gt3r/signal_selection_source_fraction_1',\n", - " 'quality_assessment/gt3r/signal_selection_source_fraction_2',\n", - " 'quality_assessment/gt3r/signal_selection_source_fraction_3',\n", - " 'quality_assessment/qa_granule_fail_reason',\n", - " 'quality_assessment/qa_granule_pass_fail']" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "reader.vars.avail()" ] @@ -1635,7 +371,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": null, "id": "e3734e09", "metadata": {}, "outputs": [], @@ -1655,44 +391,10 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": null, "id": "e5456e36", "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'sc_orient': ['orbit_info/sc_orient'],\n", - " 'atlas_sdp_gps_epoch': ['ancillary_data/atlas_sdp_gps_epoch'],\n", - " 'cycle_number': ['orbit_info/cycle_number'],\n", - " 'rgt': ['orbit_info/rgt'],\n", - " 'data_start_utc': ['ancillary_data/data_start_utc'],\n", - " 'data_end_utc': ['ancillary_data/data_end_utc'],\n", - " 'h_li': ['gt1l/land_ice_segments/h_li',\n", - " 'gt1r/land_ice_segments/h_li',\n", - " 'gt2l/land_ice_segments/h_li',\n", - " 'gt2r/land_ice_segments/h_li',\n", - " 'gt3l/land_ice_segments/h_li',\n", - " 'gt3r/land_ice_segments/h_li'],\n", - " 'latitude': ['gt1l/land_ice_segments/latitude',\n", - " 'gt1r/land_ice_segments/latitude',\n", - " 'gt2l/land_ice_segments/latitude',\n", - " 'gt2r/land_ice_segments/latitude',\n", - " 'gt3l/land_ice_segments/latitude',\n", - " 'gt3r/land_ice_segments/latitude'],\n", - " 'longitude': ['gt1l/land_ice_segments/longitude',\n", - " 'gt1r/land_ice_segments/longitude',\n", - " 'gt2l/land_ice_segments/longitude',\n", - " 'gt2r/land_ice_segments/longitude',\n", - " 'gt3l/land_ice_segments/longitude',\n", - " 'gt3r/land_ice_segments/longitude']}" - ] - }, - "execution_count": 29, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "reader.vars.wanted" ] @@ -1709,7 +411,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": null, "id": "69894391", "metadata": {}, "outputs": [], @@ -1739,113 +441,10 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": null, "id": "eaabc976", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:49: UserWarning: Converting non-nanosecond precision datetime values to nanosecond precision. This behavior can eventually be relaxed in xarray, as it is an artifact from pandas which is now beginning to support non-nanosecond precision values. This warning is caused by passing non-nanosecond np.datetime64 or np.timedelta64 values to the DataArray or Variable constructor; it can be silenced by converting the values to nanosecond precision ahead of time.\n", - " df.update({keyword: df[keyword].str[:-1].astype(np.datetime64)})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n", - "/home/jovyan/envs/general/lib/python3.11/site-packages/icepyx/core/read.py:490: UserWarning: rename 'delta_time' to 'photon_idx' does not create an index anymore. Try using swap_dims instead or use set_index after rename to create an indexed coordinate.\n", - " .rename({\"delta_time\": \"photon_idx\"})\n" - ] - } - ], + "outputs": [], "source": [ "ds = reader.load()" ] @@ -1866,549 +465,10 @@ }, { "cell_type": "code", - "execution_count": 26, + "execution_count": null, "id": "723256f7", "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "\n", - "
<xarray.Dataset>\n",
-       "Dimensions:              (photon_idx: 29027, spot: 2, gran_idx: 6)\n",
-       "Coordinates:\n",
-       "  * photon_idx           (photon_idx) int64 0 1 2 3 ... 29023 29024 29025 29026\n",
-       "  * spot                 (spot) uint8 2 5\n",
-       "  * gran_idx             (gran_idx) float64 8.49e+04 9.02e+04 ... 1.016e+05\n",
-       "    source_file          (gran_idx) <U72 '../../../../data/ATL06/processed_AT...\n",
-       "    delta_time           (gran_idx, photon_idx) datetime64[ns] 2019-02-22T01:...\n",
-       "Data variables:\n",
-       "    sc_orient            (gran_idx) int8 0 0 0 1 1 1\n",
-       "    cycle_number         (gran_idx) int8 2 2 2 5 5 5\n",
-       "    rgt                  (gran_idx) int16 849 902 910 986 1001 1016\n",
-       "    atlas_sdp_gps_epoch  (gran_idx) datetime64[ns] 2018-01-01T00:00:18 ... 20...\n",
-       "    data_start_utc       (gran_idx) datetime64[ns] 2019-02-22T01:03:44.199777...\n",
-       "    data_end_utc         (gran_idx) datetime64[ns] 2019-02-22T01:07:38.112326...\n",
-       "    h_li                 (spot, gran_idx, photon_idx) float32 nan nan ... nan\n",
-       "    latitude             (spot, gran_idx, photon_idx) float64 nan nan ... nan\n",
-       "    longitude            (spot, gran_idx, photon_idx) float64 nan nan ... nan\n",
-       "    gt                   (gran_idx, spot) <U4 'gt3r' 'gt1l' ... 'gt1l' 'gt3r'\n",
-       "Attributes:\n",
-       "    data_product:  ATL06\n",
-       "    Description:   The land_ice_height group contains the primary set of deri...\n",
-       "    data_rate:     Data within this group are sparse.  Data values are provid...
" - ], - "text/plain": [ - "\n", - "Dimensions: (photon_idx: 29027, spot: 2, gran_idx: 6)\n", - "Coordinates:\n", - " * photon_idx (photon_idx) int64 0 1 2 3 ... 29023 29024 29025 29026\n", - " * spot (spot) uint8 2 5\n", - " * gran_idx (gran_idx) float64 8.49e+04 9.02e+04 ... 1.016e+05\n", - " source_file (gran_idx) " - ] - }, - "execution_count": 27, - "metadata": {}, - "output_type": "execute_result" - } - ], + "outputs": [], "source": [ "ds.plot.scatter(x=\"longitude\", y=\"latitude\", hue=\"h_li\", vmin=-100, vmax=2000)" ] From b26ca4eb0ed54cf075bf6c53f31cd78114e5c182 Mon Sep 17 00:00:00 2001 From: Rachel Wegener <35503632+rwegener2@users.noreply.github.com> Date: Fri, 1 Sep 2023 13:38:37 -0400 Subject: [PATCH 49/63] Update icepyx/core/read.py Co-authored-by: Wei Ji <23487320+weiji14@users.noreply.github.com> --- icepyx/core/read.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index d3ca0d82a..2ffe32cb7 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -680,7 +680,7 @@ def _build_dataset_template(self, file): def _read_single_grp(self, file, grp_path): """ - For a given file and variable group path, construct an an xarray Dataset. + For a given file and variable group path, construct an xarray Dataset. Parameters ---------- From ce1ca76b7e2d586eaba3695308fae0e0bcd4805f Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Fri, 1 Sep 2023 17:40:10 +0000 Subject: [PATCH 50/63] remove intake and related modules --- requirements.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 86618f108..06f4ad9a7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,8 +7,6 @@ h5netcdf h5py holoviews hvplot -intake -intake-xarray matplotlib numpy requests From 431af78cd55d51fd08881e440d1a55681816db5b Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 5 Sep 2023 16:27:50 +0000 Subject: [PATCH 51/63] mvp with new read parameters --- icepyx/core/read.py | 114 +++++++++++++++++++++++++++++--------------- 1 file changed, 75 insertions(+), 39 deletions(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index 2ffe32cb7..c15957210 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -1,11 +1,14 @@ import fnmatch +import glob import os import warnings +import h5py import numpy as np import xarray as xr import icepyx.core.is2ref as is2ref +from icepyx.core.query import Query from icepyx.core.variables import Variables as Variables from icepyx.core.variables import list_of_dict_vals @@ -297,56 +300,79 @@ class Read: def __init__( self, - data_source=None, + path, # TODO how to deal with the fact that this is required in later versions + # but does not exist in past versions? + out_obj_type=None, # xr.Dataset, product=None, + data_source=None, filename_pattern="ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5", - out_obj_type=None, # xr.Dataset, ): - if data_source is None: - raise ValueError("Please provide a data source.") - else: - self._source_type = _check_datasource(data_source) - self.data_source = data_source - - if product is None: - raise ValueError( - "Please provide the ICESat-2 data product of your file(s)." - ) - else: - self._prod = is2ref._validate_product(product) - pattern_ck, filelist = Read._check_source_for_pattern( - data_source, filename_pattern - ) - assert pattern_ck - # Note: need to check if this works for subset and non-subset NSIDC files (processed_ prepends the former) - self._pattern = filename_pattern - - # this is a first pass at getting rid of mixed product types and warning the user. - # it takes an approach assuming the product name is in the filename, but needs reworking if we let multiple products be loaded - # one way to handle this would be bring in the product info during the loading step and fill in product there instead of requiring it from the user - filtered_filelist = [file for file in filelist if self._prod in file] - if len(filtered_filelist) == 0: - warnings.warn( - "Your filenames do not contain a product identifier (e.g. ATL06). " - "You will likely need to manually merge your dataframes." - ) - self._filelist = filelist - elif len(filtered_filelist) < len(filelist): - warnings.warn( - "Some files matching your filename pattern were removed as they were not the specified product." - ) - self._filelist = filtered_filelist + # Raise warnings for depreciated arguments + if data_source: + warnings.warn('The `data_source` argument is depreciated. Please use the path argument instead.') + # TODO this check doesn't work because default isn't None + if filename_pattern: + warnings.warn('The `filename_pattern` argument is depreciated. Instead please provide a glob string to the `path` argument') + + # CREATE THE FILELIST + # Create the filelist from the user `path` argument + if isinstance(path, list): + self._filelist = path + # Discussion: I think actually this parameter type will only exist for cloud? + # Unless we really want to abstract more stuff, i.e. the downloading + # elif isinstance(path, Query): + # self._filelist = path. + elif os.path.isdir(path): + path = os.path.join(path, '*') + # TODO better flow so ths glob doesn't happen twice + self._filelist = glob.glob(path) else: - self._filelist = filelist - + # Discussion: should we default to recursive or not? + # Could allow for glob kwargs, but at that point I think we should just tell + # the user to run glob themself to create the filelist. + self._filelist = glob.glob(path) + + # EXTRACT THE PRODUCT FOR EACH FILE + # Note for ticket: this logic got a little complex in the attempt to maintain a + # user-given product argument. If this gets depreciated we could depricate this + # Create a dictionary of the metadata extracted + product_dict = {} + for file_ in self._filelist: + product_dict[file_] = self._extract_product(file_) + # DEAL WITH MULTIPLE PRODUCTS IN THE LIST + # raise warning if there are multiple products present + if len(set(product_dict.values())) > 1: + # filter to only one product + if product: + warnings.warn(f'Multiple products found in list of files: {product_dict}. Files that do not match the user specified product will be removed from processing.') + # TODO thoughts on making filelist public read-only? It seems fair as I write + # all these warnings/error messages that reference a filelist. + self._filelist = [] + for key, value in product_dict.items(): + if value == product: + self._filelist.append(key) + product_dict.pop(key) + if len(self._filelist) == 0: + raise 'No files found in the file list matching the user-specified product type' + else: + raise TypeError(f'Multiple product types were found in the file list: {product_dict}. Please provide a valid `path` parameter indicating files of a single product') + # ASSIGN A PRODUCT TO THIS FILELIST + self.product = list(product_dict.values())[0] + if product and self.product != product: + warnings.warn(f'User specified product {product} does not match the product from the file metadata {self.product}') + + # Discussion: is this code meaningful to others? or can it be cleaned up? # after validation, use the notebook code and code outline to start implementing the rest of the class - + if out_obj_type is not None: print( "Output object type will be an xarray DataSet - " "no other output types are implemented yet" ) self._out_obj = xr.Dataset + + print('filelist:', self._filelist) + print('product', self.product) # ---------------------------------------------------------------------- # Properties @@ -379,6 +405,16 @@ def vars(self): # ---------------------------------------------------------------------- # Methods + + @staticmethod + def _extract_product(filepath): + with h5py.File(filepath, 'r') as f: + try: + product = f['METADATA']['DatasetIdentification'].attrs['shortName'].decode() + # TODO test that this is the proper error + except KeyError: + raise 'Unable to parse the product name from file metadata' + return product @staticmethod def _check_source_for_pattern(source, filename_pattern): From 612662e3ffc9395bc90557c4fdaba0a88500b068 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 5 Sep 2023 17:45:54 +0000 Subject: [PATCH 52/63] clean up remainder of file and remove extraneous comments --- icepyx/core/read.py | 137 +++++++++++++++++++++++++++----------------- 1 file changed, 83 insertions(+), 54 deletions(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index c15957210..c8fe4f276 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -300,69 +300,83 @@ class Read: def __init__( self, - path, # TODO how to deal with the fact that this is required in later versions - # but does not exist in past versions? - out_obj_type=None, # xr.Dataset, + path=None, product=None, data_source=None, filename_pattern="ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5", + out_obj_type=None, # xr.Dataset, ): # Raise warnings for depreciated arguments if data_source: - warnings.warn('The `data_source` argument is depreciated. Please use the path argument instead.') - # TODO this check doesn't work because default isn't None - if filename_pattern: - warnings.warn('The `filename_pattern` argument is depreciated. Instead please provide a glob string to the `path` argument') + warnings.warn( + 'The `data_source` argument is depreciated. Please use the path argument ' + 'instead.' + ) + if filename_pattern != "ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5": + warnings.warn( + 'The `filename_pattern` argument is depreciated. Instead please provide a ' + 'glob string to the `path` argument' + ) + if product: + product = is2ref._validate_product(product) + warnings.warn( + 'The `product` argument is no longer required. If the `path` argument given ' + 'contains files with multiple products the `product` argument will be used ' + 'to filter that list. In all other cases the product argument is ignored. ' + 'The recommended approach is to not include a `product` argument and instead ' + 'provide a `path` with files of only a single product type`.' + ) - # CREATE THE FILELIST # Create the filelist from the user `path` argument if isinstance(path, list): self._filelist = path - # Discussion: I think actually this parameter type will only exist for cloud? - # Unless we really want to abstract more stuff, i.e. the downloading - # elif isinstance(path, Query): - # self._filelist = path. elif os.path.isdir(path): path = os.path.join(path, '*') - # TODO better flow so ths glob doesn't happen twice self._filelist = glob.glob(path) else: - # Discussion: should we default to recursive or not? - # Could allow for glob kwargs, but at that point I think we should just tell - # the user to run glob themself to create the filelist. self._filelist = glob.glob(path) + # Remove any directories from the list + self._filelist = [f for f in self._filelist if not os.path.isdir(f)] - # EXTRACT THE PRODUCT FOR EACH FILE - # Note for ticket: this logic got a little complex in the attempt to maintain a - # user-given product argument. If this gets depreciated we could depricate this - # Create a dictionary of the metadata extracted + # Create a dictionary of the products as read from the metadata product_dict = {} for file_ in self._filelist: product_dict[file_] = self._extract_product(file_) - # DEAL WITH MULTIPLE PRODUCTS IN THE LIST - # raise warning if there are multiple products present - if len(set(product_dict.values())) > 1: - # filter to only one product + + # Raise warnings or errors for muliple products or products not matching the user-specified product + all_products = list(set(product_dict.values())) + if len(all_products) > 1: if product: - warnings.warn(f'Multiple products found in list of files: {product_dict}. Files that do not match the user specified product will be removed from processing.') - # TODO thoughts on making filelist public read-only? It seems fair as I write - # all these warnings/error messages that reference a filelist. + warnings.warn( + f'Multiple products found in list of files: {product_dict}. Files that ' + 'do not match the user specified product will be removed from processing.' + ) self._filelist = [] for key, value in product_dict.items(): if value == product: self._filelist.append(key) - product_dict.pop(key) if len(self._filelist) == 0: - raise 'No files found in the file list matching the user-specified product type' + raise TypeError( + 'No files found in the file list matching the user-specified ' + 'product type' + ) + # Use the cleaned filelist to assign a product + self._product = product else: - raise TypeError(f'Multiple product types were found in the file list: {product_dict}. Please provide a valid `path` parameter indicating files of a single product') - # ASSIGN A PRODUCT TO THIS FILELIST - self.product = list(product_dict.values())[0] - if product and self.product != product: - warnings.warn(f'User specified product {product} does not match the product from the file metadata {self.product}') - - # Discussion: is this code meaningful to others? or can it be cleaned up? - # after validation, use the notebook code and code outline to start implementing the rest of the class + raise TypeError( + f'Multiple product types were found in the file list: {product_dict}.' + 'Please provide a valid `path` parameter indicating files of a single ' + 'product' + ) + else: + # Assign the identified product to the property + self._product = all_products[0] + # Raise a warning if the metadata-located product differs from the user-specified product + if product and self._product != product: + warnings.warn( + f'User specified product {product} does not match the product from the file' + ' metadata {self._product}' + ) if out_obj_type is not None: print( @@ -370,9 +384,6 @@ def __init__( "no other output types are implemented yet" ) self._out_obj = xr.Dataset - - print('filelist:', self._filelist) - print('product', self.product) # ---------------------------------------------------------------------- # Properties @@ -398,18 +409,45 @@ def vars(self): if not hasattr(self, "_read_vars"): self._read_vars = Variables( - "file", path=self._filelist[0], product=self._prod + "file", path=self.filelist[0], product=self.product ) return self._read_vars + + @property + def filelist(self): + """ + A read-only property for the user to view the list of files represented by this + Read object. + """ + return self._filelist + + @property + def num_files(self): + """ + Return the number of files that is being processed by the object + """ + return len(self.filelist) + + @property + def product(self): + """ + A read-only property for the user to view the product associated with the Read + object. + """ + return self._product # ---------------------------------------------------------------------- # Methods @staticmethod def _extract_product(filepath): + """ + Read the product type from the metadata of the file. Return the product as a string. + """ with h5py.File(filepath, 'r') as f: try: + # TODO consider: should we get this from the top level attrs instead? product = f['METADATA']['DatasetIdentification'].attrs['shortName'].decode() # TODO test that this is the proper error except KeyError: @@ -675,7 +713,7 @@ def load(self): # However, this led to errors when I tried to combine two identical datasets because the single dimension was equal. # In these situations, xarray recommends manually controlling the merge/concat process yourself. # While unlikely to be a broad issue, I've heard of multiple matching timestamps causing issues for combining multiple IS2 datasets. - for file in self._filelist: + for file in self.filelist: all_dss.append( self._build_single_file_dataset(file, groups_list) ) # wanted_groups, vgrp.keys())) @@ -710,7 +748,7 @@ def _build_dataset_template(self, file): gran_idx=[np.uint64(999999)], source_file=(["gran_idx"], [file]), ), - attrs=dict(data_product=self._prod), + attrs=dict(data_product=self.product), ) return is2ds @@ -754,20 +792,11 @@ def _build_single_file_dataset(self, file, groups_list): ------- Xarray Dataset """ - file_product = self._read_single_grp(file, "/").attrs["identifier_product_type"] - assert ( - file_product == self._prod - ), "Your product specification does not match the product specification within your files." - # I think the below method might NOT read the file into memory as the above might? - # import h5py - # with h5py.File(filepath,'r') as h5pt: - # prod_id = h5pt.attrs["identifier_product_type"] - # DEVNOTE: if and elif does not actually apply wanted variable list, and has not been tested for merging multiple files into one ds # if a gridded product # TODO: all products need to be tested, and quicklook products added or explicitly excluded # Level 3b, gridded (netcdf): ATL14, 15, 16, 17, 18, 19, 20, 21 - if self._prod in [ + if self.product in [ "ATL14", "ATL15", "ATL16", @@ -780,7 +809,7 @@ def _build_single_file_dataset(self, file, groups_list): is2ds = xr.open_dataset(file) # Level 3b, hdf5: ATL11 - elif self._prod in ["ATL11"]: + elif self.product in ["ATL11"]: is2ds = self._build_dataset_template(file) # returns the wanted groups as a single list of full group path strings From c16a00359034b5920780ce0f7719ea6c9000891d Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 5 Sep 2023 21:06:39 +0000 Subject: [PATCH 53/63] maintain backward compatibility and combine arguments --- icepyx/core/is2ref.py | 5 +++-- icepyx/core/read.py | 51 +++++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/icepyx/core/is2ref.py b/icepyx/core/is2ref.py index 883772a9e..6003d91b8 100644 --- a/icepyx/core/is2ref.py +++ b/icepyx/core/is2ref.py @@ -15,6 +15,7 @@ def _validate_product(product): """ Confirm a valid ICESat-2 product was specified """ + error_msg = "A valid product string was not provided. Check user input, if given, or file metadata." if isinstance(product, str): product = str.upper(product) assert product in [ @@ -39,9 +40,9 @@ def _validate_product(product): "ATL19", "ATL20", "ATL21", - ], "Please enter a valid product" + ], error_msg else: - raise TypeError("Please enter a product string") + raise TypeError(error_msg) return product diff --git a/icepyx/core/read.py b/icepyx/core/read.py index c8fe4f276..c900ed6c4 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -297,26 +297,23 @@ class Read: # ---------------------------------------------------------------------- # Constructors - + + # TODO -- update docstring + def __init__( self, - path=None, + data_source, product=None, - data_source=None, - filename_pattern="ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5", + filename_pattern=None, out_obj_type=None, # xr.Dataset, ): # Raise warnings for depreciated arguments - if data_source: - warnings.warn( - 'The `data_source` argument is depreciated. Please use the path argument ' - 'instead.' - ) - if filename_pattern != "ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5": + if filename_pattern: warnings.warn( 'The `filename_pattern` argument is depreciated. Instead please provide a ' - 'glob string to the `path` argument' + 'string, list, or glob string to the `data_source` argument.' ) + if product: product = is2ref._validate_product(product) warnings.warn( @@ -327,14 +324,21 @@ def __init__( 'provide a `path` with files of only a single product type`.' ) - # Create the filelist from the user `path` argument - if isinstance(path, list): - self._filelist = path - elif os.path.isdir(path): - path = os.path.join(path, '*') - self._filelist = glob.glob(path) + # Create the filelist from the `data_source` argument + if filename_pattern: + # maintained for backward compatibility + pattern_ck, filelist = Read._check_source_for_pattern( + data_source, filename_pattern + ) + assert pattern_ck + self._filelist = filelist + elif isinstance(data_source, list): + self._filelist = data_source + elif os.path.isdir(data_source): + data_source = os.path.join(data_source, '*') + self._filelist = glob.glob(data_source) else: - self._filelist = glob.glob(path) + self._filelist = glob.glob(data_source) # Remove any directories from the list self._filelist = [f for f in self._filelist if not os.path.isdir(f)] @@ -342,7 +346,7 @@ def __init__( product_dict = {} for file_ in self._filelist: product_dict[file_] = self._extract_product(file_) - + # Raise warnings or errors for muliple products or products not matching the user-specified product all_products = list(set(product_dict.values())) if len(all_products) > 1: @@ -417,23 +421,21 @@ def vars(self): @property def filelist(self): """ - A read-only property for the user to view the list of files represented by this - Read object. + A read-only property for viewing the list of files represented by this Read object. """ return self._filelist @property def num_files(self): """ - Return the number of files that is being processed by the object + Return the number of files that are being processed """ return len(self.filelist) @property def product(self): """ - A read-only property for the user to view the product associated with the Read - object. + A read-only property for the user to view the product associated with the Read object. """ return self._product @@ -449,6 +451,7 @@ def _extract_product(filepath): try: # TODO consider: should we get this from the top level attrs instead? product = f['METADATA']['DatasetIdentification'].attrs['shortName'].decode() + product = is2ref._validate_product(product) # TODO test that this is the proper error except KeyError: raise 'Unable to parse the product name from file metadata' From 76480783444165519b66590b31e99248b27ad35b Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 5 Sep 2023 22:15:31 +0000 Subject: [PATCH 54/63] update to new error message --- icepyx/tests/test_is2ref.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/icepyx/tests/test_is2ref.py b/icepyx/tests/test_is2ref.py index c2ddf6e5e..7d1bba7bf 100644 --- a/icepyx/tests/test_is2ref.py +++ b/icepyx/tests/test_is2ref.py @@ -8,14 +8,14 @@ def test_num_product(): dsnum = 6 - ermsg = "Please enter a product string" + ermsg = "A valid product string was not provided. Check user input, if given, or file metadata." with pytest.raises(TypeError, match=ermsg): is2ref._validate_product(dsnum) def test_bad_product(): wrngds = "atl-6" - ermsg = "Please enter a valid product" + ermsg = "A valid product string was not provided. Check user input, if given, or file metadata." with pytest.raises(AssertionError, match=ermsg): is2ref._validate_product(wrngds) From 4cfbfdbd7cda2701ab3036cd381cd16f7f889c6c Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Fri, 8 Sep 2023 14:16:25 +0000 Subject: [PATCH 55/63] update docs --- .../example_notebooks/IS2_data_read-in.ipynb | 180 +++++++++++++----- doc/source/user_guide/documentation/read.rst | 3 + icepyx/core/read.py | 44 +++-- 3 files changed, 165 insertions(+), 62 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index 115c63044..9288e7da3 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -63,9 +63,8 @@ "metadata": {}, "outputs": [], "source": [ - "path_root = '/full/path/to/your/data/'\n", - "pattern = \"processed_ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5\"\n", - "reader = ipx.Read(path_root, \"ATL06\", pattern) # or ipx.Read(filepath, \"ATLXX\") if your filenames match the default pattern" + "path_root = '/full/path/to/your/ATL06_data/'\n", + "reader = ipx.Read(path_root)" ] }, { @@ -111,10 +110,9 @@ "\n", "Reading in ICESat-2 data with icepyx happens in a few simple steps:\n", "1. Let icepyx know where to find your data (this might be local files or urls to data in cloud storage)\n", - "2. Tell icepyx how to interpret the filename format\n", - "3. Create an icepyx `Read` object\n", - "4. Make a list of the variables you want to read in (does not apply for gridded products)\n", - "5. Load your data into memory (or read it in lazily, if you're using Dask)\n", + "2. Create an icepyx `Read` object\n", + "3. Make a list of the variables you want to read in (does not apply for gridded products)\n", + "4. Load your data into memory (or read it in lazily, if you're using Dask)\n", "\n", "We go through each of these steps in more detail in this notebook." ] @@ -168,17 +166,18 @@ { "cell_type": "markdown", "id": "e8da42c1", - "metadata": {}, + "metadata": { + "user_expressions": [] + }, "source": [ "### Step 1: Set data source path\n", "\n", "Provide a full path to the data to be read in (i.e. opened).\n", "Currently accepted inputs are:\n", - "* a directory\n", - "* a single file\n", - "\n", - "All files to be read in *must* have a consistent filename pattern.\n", - "If a directory is supplied as the data source, all files in any subdirectories that match the filename pattern will be included.\n", + "* a string path to directory - all files from the directory will be opened\n", + "* a string path to single file - one file will be opened\n", + "* a list of filepaths - all files in the list will be opened\n", + "* a glob string (see [glob](https://docs.python.org/3/library/glob.html)) - any files matching the glob pattern will be opened\n", "\n", "S3 bucket data access is currently under development, and requires you are registered with NSIDC as a beta tester for cloud-based ICESat-2 data.\n", "icepyx is working to ensure a smooth transition to working with remote files.\n", @@ -205,6 +204,17 @@ "# filepath = path_root + 'ATL06-20181214041627-Sample.h5'" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "fac636c2-e0eb-4e08-adaa-8f47623e46a1", + "metadata": {}, + "outputs": [], + "source": [ + "# list_of_files = ['/my/data/ATL06/processed_ATL06_20190226005526_09100205_006_02.h5', \n", + "# '/my/other/data/ATL06/processed_ATL06_20191202102922_10160505_006_01.h5']" + ] + }, { "cell_type": "code", "execution_count": null, @@ -217,77 +227,123 @@ }, { "cell_type": "markdown", - "id": "92743496", + "id": "ba3ebeb0-3091-4712-b0f7-559ddb95ca5a", "metadata": { "user_expressions": [] }, "source": [ - "### Step 2: Create a filename pattern for your data files\n", + "#### Glob Strings\n", + "\n", + "[glob](https://docs.python.org/3/library/glob.html) is a Python library which allows users to list files in their file systems whose paths match a given pattern. Icepyx uses the glob library to give users greater flexibility over their input file lists.\n", "\n", - "Files provided by NSIDC typically match the format `\"ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5\"` where the parameters in curly brackets indicate a parameter name (left of the colon) and character length or format (right of the colon).\n", - "Some of this information is used during data opening to help correctly read and label the data within the data structure, particularly when multiple files are opened simultaneously.\n", + "glob works using `*` and `?` as wildcard characters, where `*` matches any number of characters and `?` matches a single character. For example:\n", "\n", - "By default, icepyx will assume your filenames follow the default format.\n", - "However, you can easily read in other ICESat-2 data files by supplying your own filename pattern.\n", - "For instance, `pattern=\"ATL{product:2}-{datetime:%Y%m%d%H%M%S}-Sample.h5\"`. A few example patterns are provided below." + "* `/this/path/*.h5`: refers to all files `.h5` files in the `/this/path` folder\n", + "* `ATL??.h5`: refers to any `.h5` file that starts with `ATL` and then has any 2 characters after it\n", + "* `/this/path/ATL??/*.h5`: refers to all `.h5` files that are in a subfolder of `/this/path` which has a filename of `ATL` followed by any 2 characters\n", + "\n", + "See the glob documentation or other online explainer tutorials for more in depth explanation, or advanced glob paths such as character classes and ranges." ] }, { - "cell_type": "code", - "execution_count": null, - "id": "7318abd0", - "metadata": {}, - "outputs": [], + "cell_type": "markdown", + "id": "20286c76-5632-4420-b2c9-a5a6b1952672", + "metadata": { + "user_expressions": [] + }, "source": [ - "# pattern = 'ATL06-{datetime:%Y%m%d%H%M%S}-Sample.h5'\n", - "# pattern = 'ATL{product:2}-{datetime:%Y%m%d%H%M%S}-Sample.h5'" + "#### Recursive Directory Search" + ] + }, + { + "cell_type": "markdown", + "id": "632bd1ce-2397-4707-a63f-9d5d2fc02fbc", + "metadata": { + "user_expressions": [] + }, + "source": [ + "If specifying a directory, glob will not by default search all of the subdirectories for matching filepaths. If this is the search method you would like, you can achieve this by either:\n", + "1. passing the `recursive` argument into `glob_kwargs`\n", + "2. using glob directly to create a list of filepaths" + ] + }, + { + "cell_type": "markdown", + "id": "da0cacd8-9ddc-4c31-86b6-167d850b989e", + "metadata": { + "user_expressions": [] + }, + "source": [ + "Method 1: passing the `recursive` argument into `glob_kwargs`" ] }, { "cell_type": "code", "execution_count": null, - "id": "f43e8664", + "id": "be79b0dd-efcf-4d50-bdb0-8e3ae8e8e38c", "metadata": {}, "outputs": [], "source": [ - "# pattern = \"ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5\"" + "import glob" ] }, { "cell_type": "code", "execution_count": null, - "id": "992a77fb", - "metadata": {}, + "id": "5d088571-496d-479a-9fb7-833ed7e98676", + "metadata": { + "tags": [] + }, "outputs": [], "source": [ - "# grid_pattern = \"ATL{product:2}_GL_0311_{res:3}m_{version:3}_{revision:2}.nc\"" + "list_of_files = glob.glob('/path/to/my/folder', recursive=True)\n", + "ipx.Read(list_of_files)" + ] + }, + { + "cell_type": "markdown", + "id": "76de9539-710c-49f6-9e9e-238849382c33", + "metadata": { + "user_expressions": [] + }, + "source": [ + "Method 2: using glob directly to create a list of filepaths" ] }, { "cell_type": "code", "execution_count": null, - "id": "6aec1a70", + "id": "e276b876-9ec7-4991-8520-05c97824b896", "metadata": {}, "outputs": [], "source": [ - "pattern = \"processed_ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5\"" + "ipx.Read('/path/to/my/folder', glob_kwargs={'recursive': True})" ] }, { "cell_type": "markdown", - "id": "4275b04c", + "id": "08df2874-7c54-4670-8f37-9135ea296ff5", "metadata": { "user_expressions": [] }, "source": [ - "### Step 3: Create an icepyx read object\n", + "```{admonition} Read Module Update\n", + "Previously, icepyx required two additional things: 1) that you specify a `product` and 2) that your files either matched the default `filename_pattern` or that the user provided their own `filename_pattern`. These two requirements have been removed. `product` is not read directly from the file metadata (the root group's `short_name` attribute). Flexibility to specify multiple files via the `filename_pattern` has been replaced with [glob string](https://docs.python.org/3/library/glob.html) and allowing a list of filepaths as an argument.\n", "\n", - "The `Read` object has two required inputs:\n", - "- `path` = a string with the full file path or full directory path to your hdf5 (.h5) format files.\n", - "- `product` = the data product you're working with, also known as the \"short name\".\n", + "These arguments have been maintained for backward compatibility, but will be fully removed in icepyx version 1.0.0.\n", + "```" + ] + }, + { + "cell_type": "markdown", + "id": "4275b04c", + "metadata": { + "user_expressions": [] + }, + "source": [ + "### Step 2: Create an icepyx read object\n", "\n", - "The `Read` object also accepts the optional keyword input:\n", - "- `pattern` = a formatted string indicating the filename pattern required for Intake's path_as_pattern argument." + "Using the `data_source` described in Step 1, we can create our Read object." ] }, { @@ -299,7 +355,17 @@ }, "outputs": [], "source": [ - "reader = ipx.Read(data_source=path_root, product=\"ATL06\", filename_pattern=pattern) # or ipx.Read(filepath, \"ATLXX\") if your filenames match the default pattern" + "reader = ipx.Read(data_source=path_root)" + ] + }, + { + "cell_type": "markdown", + "id": "7b2acfdb-75eb-4c64-b583-2ab19326aaee", + "metadata": { + "user_expressions": [] + }, + "source": [ + "The Read object now contains the list of matching files that will eventually be loaded into Python. You can inspect its properties, such as the files that were located or the identified product, directly on the Read object." ] }, { @@ -309,7 +375,27 @@ "metadata": {}, "outputs": [], "source": [ - "reader._filelist" + "reader.filelist" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "248590ba-b468-4ca5-999f-4323b704008e", + "metadata": {}, + "outputs": [], + "source": [ + "reader.num_files" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7455ee3f-f9ab-486e-b4c7-2fa2314d4084", + "metadata": {}, + "outputs": [], + "source": [ + "reader.product" ] }, { @@ -319,7 +405,7 @@ "user_expressions": [] }, "source": [ - "### Step 4: Specify variables to be read in\n", + "### Step 3: Specify variables to be read in\n", "\n", "To load your data into memory or prepare it for analysis, icepyx needs to know which variables you'd like to read in.\n", "If you've used icepyx to download data from NSIDC with variable subsetting (which is the default), then you may already be familiar with the icepyx `Variables` module and how to create and modify lists of variables.\n", @@ -426,7 +512,7 @@ "user_expressions": [] }, "source": [ - "### Step 5: Loading your data\n", + "### Step 4: Loading your data\n", "\n", "Now that you've set up all the options, you're ready to read your ICESat-2 data into memory!" ] @@ -541,9 +627,9 @@ ], "metadata": { "kernelspec": { - "display_name": "general", + "display_name": "icepyx-dev", "language": "python", - "name": "general" + "name": "icepyx-dev" }, "language_info": { "codemirror_mode": { diff --git a/doc/source/user_guide/documentation/read.rst b/doc/source/user_guide/documentation/read.rst index a5beedf4e..892f98087 100644 --- a/doc/source/user_guide/documentation/read.rst +++ b/doc/source/user_guide/documentation/read.rst @@ -19,6 +19,9 @@ Attributes .. autosummary:: :toctree: ../../_icepyx/ + Read.filelist + Read.num_files + Read.product Read.vars diff --git a/icepyx/core/read.py b/icepyx/core/read.py index c900ed6c4..90bc6be9d 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -8,12 +8,9 @@ import xarray as xr import icepyx.core.is2ref as is2ref -from icepyx.core.query import Query from icepyx.core.variables import Variables as Variables from icepyx.core.variables import list_of_dict_vals -# from icepyx.core.query import Query - def _make_np_datetime(df, keyword): """ @@ -267,19 +264,19 @@ class Read: Parameters ---------- - data_source : string - A string with a full file path or full directory path to ICESat-2 hdf5 (.h5) format files. - Files within a directory must have a consistent filename pattern that includes the "ATL??" data product name. - Files must all be within a single directory. + data_source : string, List + A string or list which specifies the files to be read. The string can be either: 1) the path of a single file 2) the path to a directory or 3) a [glob string](https://docs.python.org/3/library/glob.html). product : string ICESat-2 data product ID, also known as "short name" (e.g. ATL03). Available data products can be found at: https://nsidc.org/data/icesat-2/data-sets + **Depreciation warning:** This argument is no longer required and will be depreciated in version 1.0.0. The dataset product is read from the file metadata. filename_pattern : string, default 'ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5' String that shows the filename pattern as required for Intake's path_as_pattern argument. The default describes files downloaded directly from NSIDC (subsetted and non-subsetted) for most products (e.g. ATL06). The ATL11 filename pattern from NSIDC is: 'ATL{product:2}_{rgt:4}{orbitsegment:2}_{cycles:4}_{version:3}_{revision:2}.h5'. + **Depreciation warning:** This argument is no longer required and will be depreciated in version 1.0.0. out_obj_type : object, default xarray.Dataset The desired format for the data to be read in. @@ -292,13 +289,31 @@ class Read: Examples -------- + Reading a single file + ``` + ipx.Read('/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5') # doctest: +SKIP + ``` + Reading all files in a directory + ``` + ipx.Read('/path/to/data/') # doctest: +SKIP + ``` + Reading files that match a particular pattern (here, all .h5 files that start with `processed_ATL06_`). + ``` + ipx.Read('/path/to/data/processed_ATL06_*.h5') # doctest: +SKIP + ``` + Reading a specific list of files + ``` + list_of_files = ['/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5', + '/path/to/more/data/processed_ATL06_20191202102922_10160505_006_01.h5'] + ipx.Read(list_of_files) # doctest: +SKIP + ``` """ # ---------------------------------------------------------------------- # Constructors - # TODO -- update docstring + # TODO -- what if user passes an empty list, or the glob string returns empty def __init__( self, @@ -317,11 +332,11 @@ def __init__( if product: product = is2ref._validate_product(product) warnings.warn( - 'The `product` argument is no longer required. If the `path` argument given ' + 'The `product` argument is no longer required. If the `data_source` argument given ' 'contains files with multiple products the `product` argument will be used ' 'to filter that list. In all other cases the product argument is ignored. ' 'The recommended approach is to not include a `product` argument and instead ' - 'provide a `path` with files of only a single product type`.' + 'provide a `data_source` with files of only a single product type`.' ) # Create the filelist from the `data_source` argument @@ -369,7 +384,7 @@ def __init__( else: raise TypeError( f'Multiple product types were found in the file list: {product_dict}.' - 'Please provide a valid `path` parameter indicating files of a single ' + 'Please provide a valid `data_source` parameter indicating files of a single ' 'product' ) else: @@ -448,15 +463,14 @@ def _extract_product(filepath): Read the product type from the metadata of the file. Return the product as a string. """ with h5py.File(filepath, 'r') as f: - try: - # TODO consider: should we get this from the top level attrs instead? - product = f['METADATA']['DatasetIdentification'].attrs['shortName'].decode() + try: + product = f.attrs['short_name'].decode() product = is2ref._validate_product(product) # TODO test that this is the proper error except KeyError: raise 'Unable to parse the product name from file metadata' return product - + @staticmethod def _check_source_for_pattern(source, filename_pattern): """ From f7f823b40674fee5e83329d34518403ae285a81f Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Fri, 8 Sep 2023 14:32:45 +0000 Subject: [PATCH 56/63] glob kwargs and list error --- icepyx/core/read.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index 90bc6be9d..9176e6cc4 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -277,6 +277,8 @@ class Read: The default describes files downloaded directly from NSIDC (subsetted and non-subsetted) for most products (e.g. ATL06). The ATL11 filename pattern from NSIDC is: 'ATL{product:2}_{rgt:4}{orbitsegment:2}_{cycles:4}_{version:3}_{revision:2}.h5'. **Depreciation warning:** This argument is no longer required and will be depreciated in version 1.0.0. + glob_kwargs : dict, default {} + Additional arguments to be passed into the [glob.glob()](https://docs.python.org/3/library/glob.html#glob.glob)function out_obj_type : object, default xarray.Dataset The desired format for the data to be read in. @@ -313,13 +315,12 @@ class Read: # ---------------------------------------------------------------------- # Constructors - # TODO -- what if user passes an empty list, or the glob string returns empty - def __init__( self, data_source, product=None, filename_pattern=None, + glob_kwargs = {}, out_obj_type=None, # xr.Dataset, ): # Raise warnings for depreciated arguments @@ -351,9 +352,9 @@ def __init__( self._filelist = data_source elif os.path.isdir(data_source): data_source = os.path.join(data_source, '*') - self._filelist = glob.glob(data_source) + self._filelist = glob.glob(data_source, **glob_kwargs) else: - self._filelist = glob.glob(data_source) + self._filelist = glob.glob(data_source, **glob_kwargs) # Remove any directories from the list self._filelist = [f for f in self._filelist if not os.path.isdir(f)] @@ -387,6 +388,11 @@ def __init__( 'Please provide a valid `data_source` parameter indicating files of a single ' 'product' ) + elif len(all_products) == 0: + raise TypeError( + 'No files found matching the specified `data_source`. Check your glob ' + 'string or file list.' + ) else: # Assign the identified product to the property self._product = all_products[0] From 203f3adafc085bce44d0fd993b5932f60366f33c Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Fri, 8 Sep 2023 14:44:22 +0000 Subject: [PATCH 57/63] formatting updates --- .../example_notebooks/IS2_data_read-in.ipynb | 42 ++++++++++--------- icepyx/core/read.py | 18 ++++---- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index 9288e7da3..0ab4a4dfa 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -262,7 +262,9 @@ "user_expressions": [] }, "source": [ - "If specifying a directory, glob will not by default search all of the subdirectories for matching filepaths. If this is the search method you would like, you can achieve this by either:\n", + "glob will not by default search all of the subdirectories for matching filepaths, but it has the ability to do so. To search recursively you need to 1) use `/**/` in the filepath to match any level of nested folders and 2) use the `recursive=True` argument. \n", + "\n", + "If you would like to search recursively, you can achieve this by either:\n", "1. passing the `recursive` argument into `glob_kwargs`\n", "2. using glob directly to create a list of filepaths" ] @@ -280,24 +282,11 @@ { "cell_type": "code", "execution_count": null, - "id": "be79b0dd-efcf-4d50-bdb0-8e3ae8e8e38c", + "id": "e276b876-9ec7-4991-8520-05c97824b896", "metadata": {}, "outputs": [], "source": [ - "import glob" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5d088571-496d-479a-9fb7-833ed7e98676", - "metadata": { - "tags": [] - }, - "outputs": [], - "source": [ - "list_of_files = glob.glob('/path/to/my/folder', recursive=True)\n", - "ipx.Read(list_of_files)" + "ipx.Read('/path/to/**/folder', glob_kwargs={'recursive': True})" ] }, { @@ -313,11 +302,24 @@ { "cell_type": "code", "execution_count": null, - "id": "e276b876-9ec7-4991-8520-05c97824b896", + "id": "be79b0dd-efcf-4d50-bdb0-8e3ae8e8e38c", "metadata": {}, "outputs": [], "source": [ - "ipx.Read('/path/to/my/folder', glob_kwargs={'recursive': True})" + "import glob" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5d088571-496d-479a-9fb7-833ed7e98676", + "metadata": { + "tags": [] + }, + "outputs": [], + "source": [ + "list_of_files = glob.glob('/path/to/**/folder', recursive=True)\n", + "ipx.Read(list_of_files)" ] }, { @@ -328,9 +330,9 @@ }, "source": [ "```{admonition} Read Module Update\n", - "Previously, icepyx required two additional things: 1) that you specify a `product` and 2) that your files either matched the default `filename_pattern` or that the user provided their own `filename_pattern`. These two requirements have been removed. `product` is not read directly from the file metadata (the root group's `short_name` attribute). Flexibility to specify multiple files via the `filename_pattern` has been replaced with [glob string](https://docs.python.org/3/library/glob.html) and allowing a list of filepaths as an argument.\n", + "Previously, icepyx required two additional conditions: 1) a `product` argument and 2) that your files either matched the default `filename_pattern` or that the user provided their own `filename_pattern`. These two requirements have been removed. `product` is now read directly from the file metadata (the root group's `short_name` attribute). Flexibility to specify multiple files via the `filename_pattern` has been replaced with the [glob string](https://docs.python.org/3/library/glob.html) feature, and by allowing a list of filepaths as an argument.\n", "\n", - "These arguments have been maintained for backward compatibility, but will be fully removed in icepyx version 1.0.0.\n", + "The `product` and `filename_pattern` arguments have been maintained for backwards compatibility, but will be fully removed in icepyx version 1.0.0.\n", "```" ] }, diff --git a/icepyx/core/read.py b/icepyx/core/read.py index 9176e6cc4..f5cb53f8f 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -327,7 +327,8 @@ def __init__( if filename_pattern: warnings.warn( 'The `filename_pattern` argument is depreciated. Instead please provide a ' - 'string, list, or glob string to the `data_source` argument.' + 'string, list, or glob string to the `data_source` argument.', + stacklevel=2, ) if product: @@ -337,7 +338,8 @@ def __init__( 'contains files with multiple products the `product` argument will be used ' 'to filter that list. In all other cases the product argument is ignored. ' 'The recommended approach is to not include a `product` argument and instead ' - 'provide a `data_source` with files of only a single product type`.' + 'provide a `data_source` with files of only a single product type`.', + stacklevel=2, ) # Create the filelist from the `data_source` argument @@ -369,7 +371,8 @@ def __init__( if product: warnings.warn( f'Multiple products found in list of files: {product_dict}. Files that ' - 'do not match the user specified product will be removed from processing.' + 'do not match the user specified product will be removed from processing.', + stacklevel=2, ) self._filelist = [] for key, value in product_dict.items(): @@ -400,7 +403,8 @@ def __init__( if product and self._product != product: warnings.warn( f'User specified product {product} does not match the product from the file' - ' metadata {self._product}' + ' metadata {self._product}', + stacklevel=2, ) if out_obj_type is not None: @@ -442,21 +446,21 @@ def vars(self): @property def filelist(self): """ - A read-only property for viewing the list of files represented by this Read object. + Return the list of files represented by this Read object. """ return self._filelist @property def num_files(self): """ - Return the number of files that are being processed + Return the number of files that are being processed. """ return len(self.filelist) @property def product(self): """ - A read-only property for the user to view the product associated with the Read object. + Return the product associated with the Read object. """ return self._product From 10d15910a1f82ec2b18ba61eff647e243d44651c Mon Sep 17 00:00:00 2001 From: Rachel Wegener <35503632+rwegener2@users.noreply.github.com> Date: Tue, 12 Sep 2023 09:18:22 -0400 Subject: [PATCH 58/63] Apply suggestions from code review Co-authored-by: Jessica Scheick --- icepyx/core/read.py | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index f5cb53f8f..c45a72fa9 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -272,8 +272,8 @@ class Read: Available data products can be found at: https://nsidc.org/data/icesat-2/data-sets **Depreciation warning:** This argument is no longer required and will be depreciated in version 1.0.0. The dataset product is read from the file metadata. - filename_pattern : string, default 'ATL{product:2}_{datetime:%Y%m%d%H%M%S}_{rgt:4}{cycle:2}{orbitsegment:2}_{version:3}_{revision:2}.h5' - String that shows the filename pattern as required for Intake's path_as_pattern argument. + filename_pattern : string, default None + String that shows the filename pattern as previously required for Intake's path_as_pattern argument. The default describes files downloaded directly from NSIDC (subsetted and non-subsetted) for most products (e.g. ATL06). The ATL11 filename pattern from NSIDC is: 'ATL{product:2}_{rgt:4}{orbitsegment:2}_{cycles:4}_{version:3}_{revision:2}.h5'. **Depreciation warning:** This argument is no longer required and will be depreciated in version 1.0.0. @@ -292,23 +292,18 @@ class Read: Examples -------- Reading a single file - ``` - ipx.Read('/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5') # doctest: +SKIP - ``` + >>> ipx.Read('/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5') # doctest: +SKIP + Reading all files in a directory - ``` - ipx.Read('/path/to/data/') # doctest: +SKIP - ``` + >>> ipx.Read('/path/to/data/') # doctest: +SKIP + Reading files that match a particular pattern (here, all .h5 files that start with `processed_ATL06_`). - ``` - ipx.Read('/path/to/data/processed_ATL06_*.h5') # doctest: +SKIP - ``` + >>> ipx.Read('/path/to/data/processed_ATL06_*.h5') # doctest: +SKIP + Reading a specific list of files - ``` - list_of_files = ['/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5', + >>> list_of_files = ['/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5', '/path/to/more/data/processed_ATL06_20191202102922_10160505_006_01.h5'] - ipx.Read(list_of_files) # doctest: +SKIP - ``` + >>> ipx.Read(list_of_files) # doctest: +SKIP """ @@ -326,7 +321,7 @@ def __init__( # Raise warnings for depreciated arguments if filename_pattern: warnings.warn( - 'The `filename_pattern` argument is depreciated. Instead please provide a ' + 'The `filename_pattern` argument is deprecated. Instead please provide a ' 'string, list, or glob string to the `data_source` argument.', stacklevel=2, ) From 0b23d1e12808fb69afa85d1fa5168c17221f52f2 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 12 Sep 2023 13:24:45 +0000 Subject: [PATCH 59/63] remove num_files --- doc/source/user_guide/documentation/read.rst | 1 - icepyx/core/read.py | 7 ------- 2 files changed, 8 deletions(-) diff --git a/doc/source/user_guide/documentation/read.rst b/doc/source/user_guide/documentation/read.rst index 892f98087..68da03b1d 100644 --- a/doc/source/user_guide/documentation/read.rst +++ b/doc/source/user_guide/documentation/read.rst @@ -20,7 +20,6 @@ Attributes :toctree: ../../_icepyx/ Read.filelist - Read.num_files Read.product Read.vars diff --git a/icepyx/core/read.py b/icepyx/core/read.py index c45a72fa9..b139ca567 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -444,13 +444,6 @@ def filelist(self): Return the list of files represented by this Read object. """ return self._filelist - - @property - def num_files(self): - """ - Return the number of files that are being processed. - """ - return len(self.filelist) @property def product(self): From 6f5beadcb8bca332fbf9fbda79310e075bbd8af3 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 12 Sep 2023 13:28:03 +0000 Subject: [PATCH 60/63] fix docs test typo --- icepyx/core/read.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index b139ca567..4300cebbc 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -301,8 +301,10 @@ class Read: >>> ipx.Read('/path/to/data/processed_ATL06_*.h5') # doctest: +SKIP Reading a specific list of files - >>> list_of_files = ['/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5', - '/path/to/more/data/processed_ATL06_20191202102922_10160505_006_01.h5'] + >>> list_of_files = [ + '/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5', + '/path/to/more/data/processed_ATL06_20191202102922_10160505_006_01.h5', + ] >>> ipx.Read(list_of_files) # doctest: +SKIP """ From 035ee5ab1e33dc43a471c36286a59c036d0cb292 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 12 Sep 2023 13:37:15 +0000 Subject: [PATCH 61/63] trying again to fix the build --- icepyx/core/read.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index 4300cebbc..b9a6e672e 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -302,9 +302,9 @@ class Read: Reading a specific list of files >>> list_of_files = [ - '/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5', - '/path/to/more/data/processed_ATL06_20191202102922_10160505_006_01.h5', - ] + ... '/path/to/data/processed_ATL06_20190226005526_09100205_006_02.h5', + ... '/path/to/more/data/processed_ATL06_20191202102922_10160505_006_01.h5', + ... ] >>> ipx.Read(list_of_files) # doctest: +SKIP """ From 903c351007bc7245bf4d107b48b1f38c67acf900 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Tue, 12 Sep 2023 13:48:27 +0000 Subject: [PATCH 62/63] add feedback to docs page --- .../example_notebooks/IS2_data_read-in.ipynb | 42 +++++++------------ 1 file changed, 14 insertions(+), 28 deletions(-) diff --git a/doc/source/example_notebooks/IS2_data_read-in.ipynb b/doc/source/example_notebooks/IS2_data_read-in.ipynb index 0ab4a4dfa..4cdd3bf5a 100644 --- a/doc/source/example_notebooks/IS2_data_read-in.ipynb +++ b/doc/source/example_notebooks/IS2_data_read-in.ipynb @@ -177,11 +177,7 @@ "* a string path to directory - all files from the directory will be opened\n", "* a string path to single file - one file will be opened\n", "* a list of filepaths - all files in the list will be opened\n", - "* a glob string (see [glob](https://docs.python.org/3/library/glob.html)) - any files matching the glob pattern will be opened\n", - "\n", - "S3 bucket data access is currently under development, and requires you are registered with NSIDC as a beta tester for cloud-based ICESat-2 data.\n", - "icepyx is working to ensure a smooth transition to working with remote files.\n", - "We'd love your help exploring and testing these features as they become available!" + "* a glob string (see [glob](https://docs.python.org/3/library/glob.html)) - any files matching the glob pattern will be opened" ] }, { @@ -215,16 +211,6 @@ "# '/my/other/data/ATL06/processed_ATL06_20191202102922_10160505_006_01.h5']" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "e683ebf7", - "metadata": {}, - "outputs": [], - "source": [ - "# urlpath = 's3://nsidc-cumulus-prod-protected/ATLAS/ATL03/004/2019/11/30/ATL03_20191130221008_09930503_004_01.h5'" - ] - }, { "cell_type": "markdown", "id": "ba3ebeb0-3091-4712-b0f7-559ddb95ca5a", @@ -238,9 +224,9 @@ "\n", "glob works using `*` and `?` as wildcard characters, where `*` matches any number of characters and `?` matches a single character. For example:\n", "\n", - "* `/this/path/*.h5`: refers to all files `.h5` files in the `/this/path` folder\n", - "* `ATL??.h5`: refers to any `.h5` file that starts with `ATL` and then has any 2 characters after it\n", - "* `/this/path/ATL??/*.h5`: refers to all `.h5` files that are in a subfolder of `/this/path` which has a filename of `ATL` followed by any 2 characters\n", + "* `/this/path/*.h5`: refers to all `.h5` files in the `/this/path` folder (Example matches: \"/this/path/processed_ATL03_20191130221008_09930503_006_01.h5\" or \"/this/path/myfavoriteicsat-2file.h5\")\n", + "* `/this/path/*ATL07*.h5`: refers to all `.h5` files in the `/this/path` folder that have ATL07 in the filename. (Example matches: \"/this/path/ATL07-02_20221012220720_03391701_005_01.h5\" or \"/this/path/processed_ATL07.h5\")\n", + "* `/this/path/ATL??/*.h5`: refers to all `.h5` files that are in a subfolder of `/this/path` and a subdirectory of `ATL` followed by any 2 characters (Example matches: \"/this/path/ATL03/processed_ATL03_20191130221008_09930503_006_01.h5\", \"/this/path/ATL06/myfile.h5\")\n", "\n", "See the glob documentation or other online explainer tutorials for more in depth explanation, or advanced glob paths such as character classes and ranges." ] @@ -289,6 +275,16 @@ "ipx.Read('/path/to/**/folder', glob_kwargs={'recursive': True})" ] }, + { + "cell_type": "markdown", + "id": "f5a1e85e-fc4a-405f-9710-0cb61b827f2c", + "metadata": { + "user_expressions": [] + }, + "source": [ + "You can use `glob_kwargs` for any additional argument to Python's builtin `glob.glob` that you would like to pass in via icepyx." + ] + }, { "cell_type": "markdown", "id": "76de9539-710c-49f6-9e9e-238849382c33", @@ -380,16 +376,6 @@ "reader.filelist" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "248590ba-b468-4ca5-999f-4323b704008e", - "metadata": {}, - "outputs": [], - "source": [ - "reader.num_files" - ] - }, { "cell_type": "code", "execution_count": null, From 5e06de94da0c492b4b3cc94a5b4d834b0dc829a4 Mon Sep 17 00:00:00 2001 From: Rachel Wegener Date: Thu, 14 Sep 2023 13:32:52 +0000 Subject: [PATCH 63/63] fix typo --- icepyx/core/read.py | 1 - 1 file changed, 1 deletion(-) diff --git a/icepyx/core/read.py b/icepyx/core/read.py index baeba27f4..966df8d08 100644 --- a/icepyx/core/read.py +++ b/icepyx/core/read.py @@ -338,7 +338,6 @@ def __init__( if data_source is None: raise ValueError("data_source is a required arguemnt") - ) # Raise warnings for deprecated arguments if filename_pattern: