From fa47b453e91e04ca1500db09c7bff7b484a69cb5 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 00:38:46 +0100 Subject: [PATCH 01/36] add an abstract class --- earth2observe/datasource.py | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 earth2observe/datasource.py diff --git a/earth2observe/datasource.py b/earth2observe/datasource.py new file mode 100644 index 0000000..5a94ae3 --- /dev/null +++ b/earth2observe/datasource.py @@ -0,0 +1,8 @@ +from abc import ABC, abstractmethod + + +class DataSource: + + @abstractmethod + def download(self): + pass \ No newline at end of file From 9bcf11cef887fedf77733b66efd9b1c24a2c5a76 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 01:55:27 +0100 Subject: [PATCH 02/36] add mswep module --- earth2observe/mswep.py | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 earth2observe/mswep.py diff --git a/earth2observe/mswep.py b/earth2observe/mswep.py new file mode 100644 index 0000000..d2b779e --- /dev/null +++ b/earth2observe/mswep.py @@ -0,0 +1,2 @@ +# class MSWEP(): +"http://www.gloh2o.org/mswx/" \ No newline at end of file From 5d4eed2d3a98d32404342349d4f2bc4deba014c9 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 02:42:33 +0100 Subject: [PATCH 03/36] refactor ecmwf to the abstract class way --- earth2observe/ecmwf.py | 287 ++++++++++++++++---------- earth2observe/ecmwf_data_catalog.yaml | 1 + examples/ecmwf_data.py | 30 +-- 3 files changed, 183 insertions(+), 135 deletions(-) diff --git a/earth2observe/ecmwf.py b/earth2observe/ecmwf.py index 3c9823a..91b420d 100644 --- a/earth2observe/ecmwf.py +++ b/earth2observe/ecmwf.py @@ -5,7 +5,7 @@ import calendar import datetime as dt import os - +from typing import Dict import numpy as np import pandas as pd import yaml @@ -17,7 +17,6 @@ from earth2observe import __path__ from earth2observe.utils import print_progress_bar - class ECMWF: """RemoteSensing. @@ -33,12 +32,12 @@ class ECMWF: def __init__( self, time: str = "daily", - start: str = "", - end: str = "", + start: str = None, + end: str = None, path: str = "", - variables: list = [], - lat_lim: list = [], - lon_lim: list = [], + variables: list = None, + lat_lim: list = None, + lon_lim: list = None, fmt: str = "%Y-%m-%d", ): """RemoteSensing. @@ -56,9 +55,9 @@ def __init__( variables (list, optional): Variable code: VariablesInfo('day').descriptions.keys(). Defaults to []. lat_lim (list, optional): - [ymin, ymax]. Defaults to []. + [ymin, ymax]. Defaults to None. lon_lim (list, optional): - [xmin, xmax]. Defaults to []. + [xmin, xmax]. Defaults to None. fmt (str, optional): [description]. Defaults to "%Y-%m-%d". """ @@ -78,6 +77,22 @@ def __init__( self.path = path self.vars = variables + self.date_str = f"{self.start}/to/{self.end}" + self.create_grid(lat_lim, lon_lim) + + + def create_grid(self, lat_lim: list, lon_lim: list): + """Create_grid + + create grid from the lat/lon boundaries + + Parameters + ---------- + lat_lim: [] + latitude boundaries + lon_lim: [] + longitude boundaries + """ # correct latitude and longitude limits latlim_corr_one = np.floor(lat_lim[0] / 0.125) * 0.125 latlim_corr_two = np.ceil(lat_lim[1] / 0.125) * 0.125 @@ -87,9 +102,7 @@ def __init__( lonlim_corr_one = np.floor(lon_lim[0] / 0.125) * 0.125 lonlim_corr_two = np.ceil(lon_lim[1] / 0.125) * 0.125 self.lonlim_corr = [lonlim_corr_one, lonlim_corr_two] - # TODO move it to the ECMWF method later - # for ECMWF only - self.date_str = f"{self.start}/to/{self.end}" + def download(self, dataset: str = "interim", progress_bar: bool = True): """ECMWF. @@ -109,41 +122,85 @@ def download(self, dataset: str = "interim", progress_bar: bool = True): ------- None. """ + # read the datasource catalog + catalog = Catalog() + for var in self.vars: # Download data logger.info( f"Download ECMWF {var} data for period {self.start} till {self.end}" ) - self.downloadData( - var, dataset=dataset, progress_bar=progress_bar + var_info = catalog.get_variable(var) + self.downloadDataset( + var_info, dataset=dataset, progress_bar=progress_bar ) # CaseParameters=[SumMean, Min, Max] # delete the downloaded netcdf del_ecmwf_dataset = os.path.join(self.path, "data_interim.nc") os.remove(del_ecmwf_dataset) - def downloadData( - self, var: str, dataset: str = "interim", progress_bar: bool = True + def downloadDataset( + self, var_info: Dict[str, str], dataset: str = "interim", progress_bar: bool = True ): """This function downloads ECMWF six-hourly, daily or monthly data. Parameters ---------- - var: [str] - variable name + var_info: [str] + variable detailed information + >>> { + >>> 'descriptions': 'Evaporation [m of water]', + >>> 'units': 'mm', + >>> 'types': 'flux', + >>> 'temporal resolution': ['six hours', 'daily', 'monthly'], + >>> 'file name': 'Evaporation', + >>> 'download type': 2, + >>> 'number_para': 182, + >>> 'var_name': 'e', + >>> 'factors_add': 0, + >>> 'factors_mul': 1000 + >>> } dataset: [str] Default is "interm" progress_bar: [bool] True if you want to display a progress bar. """ # Load factors / unit / type of variables / accounts - VarInfo = Variables(self.time) - var_info = VarInfo.catalog.get(var) + # Create Out directory - out_dir = f"{self.path}, {self.time}, {VarInfo.catalog.get('file name')}" + out_dir = f"{self.path}/{self.time}/{var_info.get('file name')}" if not os.path.exists(out_dir): os.makedirs(out_dir) + # trigger the request to the server + self.api(var_info, dataset) + # process the downloaded data + self.post_download(var_info, out_dir, dataset, progress_bar) + + + + def api(self, var_info, dataset): + """form the request url abd trigger the request + + Parameters + ---------- + dataset: [str] + dataset name + var_info: [str] + variable detailed information + >>> { + >>> 'descriptions': 'Evaporation [m of water]', + >>> 'units': 'mm', + >>> 'types': 'flux', + >>> 'temporal resolution': ['six hours', 'daily', 'monthly'], + >>> 'file name': 'Evaporation', + >>> 'download type': 2, + >>> 'number_para': 182, + >>> 'var_name': 'e', + >>> 'factors_add': 0, + >>> 'factors_mul': 1000 + >>> } + """ download_type = var_info.get("download type") # https://www.ecmwf.int/en/computing/software/ecmwf-web-api stream = "oper" # https://apps.ecmwf.int/codes/grib/format/mars/stream/ @@ -182,7 +239,7 @@ def downloadData( # Download data by using the ECMWF API logger.info("Use API ECMWF to collect the data, please wait") - ECMWF.API( + self.call_api( self.path, download_type, stream, @@ -198,6 +255,92 @@ def downloadData( dataset=dataset, ) + + @staticmethod + def call_api( + output_folder: str, + download_type: str, + stream: str, + levtype: str, + param: str, + step: str, + grid: str, + time_str: str, + date_str: str, + type_str: str, + class_str: str, + area_str: str, + dataset: str = "interim", + ): + + os.chdir(output_folder) + server = ECMWFDataServer() + # url = os.environ['ECMWF_API_URL'], + # key = os.environ['ECMWF_API_KEY'], + # email = os.environ['ECMWF_API_EMAIL'], + if download_type == 1 or download_type == 2: + server.retrieve( + { + "stream": stream, + "levtype": levtype, + "param": param, + "dataset": dataset, + "step": step, + "grid": grid, + "time": time_str, + "date": date_str, + "type": type_str, # http://apps.ecmwf.int/codes/grib/format/mars/type/ + "class": class_str, # http://apps.ecmwf.int/codes/grib/format/mars/class/ + "area": area_str, + "format": "netcdf", + "target": f"data_{dataset}.nc", + } + ) + + if download_type == 3: + server.retrieve( + { + "levelist": "1000", + "stream": stream, + "levtype": levtype, + "param": param, + "dataset": dataset, + "step": step, + "grid": grid, + "time": time_str, + "date": date_str, + "type": type_str, # http://apps.ecmwf.int/codes/grib/format/mars/type/ + "class": class_str, # http://apps.ecmwf.int/codes/grib/format/mars/class/ + "area": area_str, + "format": "netcdf", + "target": f"data_{dataset}.nc", + } + ) + + def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progress_bar: bool=True): + """ clip the downloaded data to the extent we want + + Parameters + ---------- + var_info: [str] + variable detailed information + >>> { + >>> 'descriptions': 'Evaporation [m of water]', + >>> 'units': 'mm', + >>> 'types': 'flux', + >>> 'temporal resolution': ['six hours', 'daily', 'monthly'], + >>> 'file name': 'Evaporation', + >>> 'download type': 2, + >>> 'number_para': 182, + >>> 'var_name': 'e', + >>> 'factors_add': 0, + >>> 'factors_mul': 1000 + >>> } + dataset: [str] + dataset name. Default is interm + progress_bar: [bool] + True to display a progress bar + """ # Open the downloaded data NC_filename = os.path.join(self.path, f"data_{dataset}.nc") fh = Dataset(NC_filename, mode="r") @@ -289,96 +432,20 @@ def downloadData( fh.close() - @staticmethod - def API( - output_folder: str, - download_type: str, - stream: str, - levtype: str, - param: str, - step: str, - grid: str, - time_str: str, - date_str: str, - type_str: str, - class_str: str, - area_str: str, - dataset: str = "interim", - ): - - os.chdir(output_folder) - server = ECMWFDataServer() - # url = os.environ['ECMWF_API_URL'], - # key = os.environ['ECMWF_API_KEY'], - # email = os.environ['ECMWF_API_EMAIL'], - if download_type == 1 or download_type == 2: - server.retrieve( - { - "stream": stream, - "levtype": levtype, - "param": param, - "dataset": dataset, - "step": step, - "grid": grid, - "time": time_str, - "date": date_str, - "type": type_str, # http://apps.ecmwf.int/codes/grib/format/mars/type/ - "class": class_str, # http://apps.ecmwf.int/codes/grib/format/mars/class/ - "area": area_str, - "format": "netcdf", - "target": f"data_{dataset}.nc", - } - ) - - if download_type == 3: - server.retrieve( - { - "levelist": "1000", - "stream": stream, - "levtype": levtype, - "param": param, - "dataset": dataset, - "step": step, - "grid": grid, - "time": time_str, - "date": date_str, - "type": type_str, # http://apps.ecmwf.int/codes/grib/format/mars/type/ - "class": class_str, # http://apps.ecmwf.int/codes/grib/format/mars/class/ - "area": area_str, - "format": "netcdf", - "target": f"data_{dataset}.nc", - } - ) - +class Catalog: + """This class contains the information about the ECMWF variables + http://rda.ucar.edu/cgi-bin/transform?xml=/metadata/ParameterTables/WMO_GRIB1.98-0.128.xml&view=gribdoc. + """ -class Variables: - """This class contains the information about the ECMWF variables http://rda.ucar.edu/cgi-bin/transform?xml=/metadata/ParameterTables/WMO_GRIB1.98-0.128.xml&view=gribdoc.""" + def __init__(self, version: int = 1): + # get the catalog + with open(f"{__path__[0]}/ecmwf_data_catalog.yaml", "r") as stream: + catalog = yaml.safe_load(stream) - with open(f"{__path__[0]}/ecmwf_data_catalog.yaml", "r") as stream: - catalog = yaml.safe_load(stream) + self.catalog = catalog - def __init__(self, step, version: int = 1): self.version = version - # def __str__(self): - # print( - # f"Variable name:\n {self.var_name}\nDescriptions\n{self.descriptions}\nUnits : \n{self.units}" - # ) - - def ListAttributes(self): - """Print Attributes List.""" - print("\n") - print( - f"Attributes List of: {repr(self.__dict__['name'])} - {self.__class__.__name__} Instance\n" - ) - self_keys = list(self.__dict__.keys()) - self_keys.sort() - for key in self_keys: - if key != "name": - print(str(key) + " : " + repr(self.__dict__[key])) - - print("\n") - - -# class MSWEP(): -"http://www.gloh2o.org/mswx/" + def get_variable(self, var_name): + """retrieve a variable form the datasource catalog""" + return self.catalog.get(var_name) diff --git a/earth2observe/ecmwf_data_catalog.yaml b/earth2observe/ecmwf_data_catalog.yaml index 63d2699..3a2d131 100644 --- a/earth2observe/ecmwf_data_catalog.yaml +++ b/earth2observe/ecmwf_data_catalog.yaml @@ -5,6 +5,7 @@ version: 1 # available datasets #https://confluence.ecmwf.int/display/WEBAPI/Available+ECMWF+Public+Datasets datasets: [cams_gfas, cams_nrealtime, cera20c, cera_sat, era15, era20c, era20cm, era20cmv0, era40, geff_reanalysis, icoads, interim, interim_land, ispd, macc, macc_nrealtime, s2s, tigge, uerra, yopp, yotc] +variables: [T, 2T, SRO, SSRO, WIND, 10SI, SP, Q, SSR, R, E, SUND, RO, TP, 10U, 10V, 2D, SR, AL, HCC] T: descriptions: Temperature [K] diff --git a/examples/ecmwf_data.py b/examples/ecmwf_data.py index 9440ea0..c011871 100644 --- a/examples/ecmwf_data.py +++ b/examples/ecmwf_data.py @@ -6,7 +6,7 @@ """ import os -from earth2observe.ecmwf import ECMWF, Variables +from earth2observe.ecmwf import ECMWF, Catalog rpath = os.getcwd() path = rf"{rpath}\examples\data\ecmwf" @@ -16,12 +16,11 @@ time = "daily" lat = [4.190755, 4.643963] lon = [-75.649243, -74.727286] -path = "/data/satellite_data/" # Temperature, Evapotranspiration variables = ["T", "E"] #%% -Vars = Variables("daily") -Vars.__str__() +Vars = Catalog() #"daily" +print(Vars.catalog) #%% Temperature start = "2009-01-01" end = "2009-02-01" @@ -29,33 +28,14 @@ latlim = [4.19, 4.64] lonlim = [-75.65, -74.73] # %% -Vars = Variables("daily") -print(Vars.catalog) -# %% # Temperature, Evapotranspiration variables = ["E"] # "T", -Coello = ECMWF( - time=time, - start=start, - end=end, - lat_lim=latlim, - lon_lim=lonlim, - path=path, - variables=variables, -) +Coello = ECMWF(time=time, start=start, end=end, path=path, variables=variables, lat_lim=latlim, lon_lim=lonlim) Coello.download(dataset="interim") #%% variables = ["SRO"] -Coello = ECMWF( - time=time, - start=start, - end=end, - lat_lim=latlim, - lon_lim=lonlim, - path=path, - variables=variables, -) +Coello = ECMWF(time=time, start=start, end=end, path=path, variables=variables, lat_lim=latlim, lon_lim=lonlim) Coello.download() From dc841b6c0a8e44cb2e153bec00496b7e6554bc4e Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 16:45:56 +0100 Subject: [PATCH 04/36] add codacy badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index 9440c64..27fa90b 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ [![codecov](https://codecov.io/gh/Serapieum-of-alex/earth2observe/branch/main/graph/badge.svg?token=2nBcI5ijvB)](https://codecov.io/gh/Serapieum-of-alex/earth2observe) +[![Codacy Badge](https://app.codacy.com/project/badge/Grade/4c95cf4c0dd044e4b451e08355fe6ee7)](https://www.codacy.com/gh/Serapieum-of-alex/earth2observe/dashboard?utm_source=github.com&utm_medium=referral&utm_content=Serapieum-of-alex/earth2observe&utm_campaign=Badge_Grade) ![GitHub last commit](https://img.shields.io/github/last-commit/MAfarrag/earthobserve) ![GitHub forks](https://img.shields.io/github/forks/MAfarrag/earthobserve?style=social) ![GitHub Repo stars](https://img.shields.io/github/stars/MAfarrag/earthobserve?style=social) From a48bddb245d592194fe808fe0f205dc3ccab5ad0 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 20:57:13 +0100 Subject: [PATCH 05/36] move extractFromGZ to pyramids package and bumpy up pyramids version --- HISTORY.rst | 6 ++ earth2observe/chirps.py | 210 +++++++++++++++++++++++++--------------- earth2observe/utils.py | 31 +----- environment.yml | 4 +- requirements.txt | 4 +- setup.py | 2 +- 6 files changed, 146 insertions(+), 111 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 367a939..a53ac67 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -18,3 +18,9 @@ History * fix pypi package names in the requirements.txt file * fix python version in requirement.txt + +0.2.0 (2023-01-14) +------------------ + +* bump up numpy and pyramids versions +* create an abstract class for datasource and catalog as a bluebrint for all data sources diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index 3f6cd7e..5ae4939 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -1,3 +1,4 @@ +from typing import List import datetime as dt import os from ftplib import FTP @@ -7,22 +8,24 @@ from joblib import Parallel, delayed from osgeo import gdal from pyramids.raster import Raster +from pyramids.utils import extractFromGZ +from earth2observe.datasource import DataSource, CatalogTemplate +from earth2observe.utils import print_progress_bar -from earth2observe.utils import extractFromGZ, print_progress_bar - -class CHIRPS: +class CHIRPS(DataSource): """CHIRPS.""" + api_url: str = "data.chc.ucsb.edu" def __init__( - self, - start: str = "", - end: str = "", - lat_lim: list = [], - lon_lim: list = [], - time: str = "daily", - path: str = "", - fmt: str = "%Y-%m-%d", + self, + time: str = "daily", + start: str = None, + end: str = None, + path: str = "", + lat_lim: list = None, + lon_lim: list = None, + fmt: str = "%Y-%m-%d", ): """CHIRPS. @@ -46,8 +49,6 @@ def __init__( [description]. Defaults to "%Y-%m-%d". """ # Define timestep for the timedates - self.lat_lim = [] - self.lon_lim = [] if time.lower() == "daily": self.time_freq = "D" self.output_folder = os.path.join(path, "Precipitation", "CHIRPS", "Daily") @@ -58,6 +59,7 @@ def __init__( ) else: raise KeyError("The input time interval is not supported") + self.time = time # make directory if it not exists @@ -65,18 +67,34 @@ def __init__( os.makedirs(self.output_folder) # check time variables - if start == "": + if start is None: self.start = pd.Timestamp("1981-01-01") else: self.start = dt.datetime.strptime(start, fmt) - if end == "": + if end is None: self.end = pd.Timestamp("Now") else: self.end = dt.datetime.strptime(end, fmt) # Create days self.Dates = pd.date_range(self.start, self.end, freq=self.time_freq) + self.create_grid(lat_lim, lon_lim) + + def create_grid(self, lat_lim: list, lon_lim: list): + """Create_grid + + create grid from the lat/lon boundaries + + Parameters + ---------- + lat_lim: [] + latitude boundaries + lon_lim: [] + longitude boundaries + """ + self.lat_lim = [] + self.lon_lim = [] # Check space variables if lat_lim[0] < -50 or lat_lim[1] > 50: print( @@ -107,10 +125,11 @@ def __init__( ) ) - def Download(self, progress_bar: bool = True, cores=None): + + def download(self, progress_bar: bool = True, cores=None): """Download. - Download method downloads CHIRPS data + downloads CHIRPS data Parameters ---------- @@ -149,7 +168,7 @@ def Download(self, progress_bar: bool = True, cores=None): ) for Date in self.Dates: - CHIRPS.RetrieveData(Date, args) + self.API(Date, args) if progress_bar: amount = amount + 1 print_progress_bar( @@ -162,101 +181,118 @@ def Download(self, progress_bar: bool = True, cores=None): results = True else: results = Parallel(n_jobs=cores)( - delayed(CHIRPS.RetrieveData)(Date, args) for Date in self.Dates + delayed(self.API)(Date, args) for Date in self.Dates ) return results - @staticmethod - def RetrieveData(Date, args): - """RetrieveData. - - RetrieveData method retrieves CHIRPS data for a given date from the - https://data.chc.ucsb.edu/ + def API(self, Date, args): + """form the request url abd trigger the request Parameters ---------- - Date : TYPE - DESCRIPTION. - args : TYPE - A list of parameters defined in the DownloadData function. + Date: - Raises - ------ - KeyError - DESCRIPTION. + args: [list] - Returns - ------- - bool - DESCRIPTION. """ - # Argument [output_folder, TimeCase, xID, yID, lon_lim, latlim] = args - # open ftp server - # ftp = FTP("chg-ftpout.geog.ucsb.edu", "", "") - ftp = FTP("data.chc.ucsb.edu") - ftp.login() - # Define FTP path to directory if TimeCase.lower() == "daily": - pathFTP = ( - "pub/org/chg/products/CHIRPS-2.0/global_daily/tifs/p05/%s/" - % Date.strftime("%Y") - ) + pathFTP = f"pub/org/chg/products/CHIRPS-2.0/global_daily/tifs/p05/{Date.strftime('%Y')}/" elif TimeCase == "monthly": pathFTP = "pub/org/chg/products/CHIRPS-2.0/global_monthly/tifs/" else: raise KeyError("The input time interval is not supported") - # find the document name in this directory - ftp.cwd(pathFTP) - listing = [] - - # read all the file names in the directory - ftp.retrlines("LIST", listing.append) - # create all the input name (filename) and output (outfilename, filetif, DiFileEnd) names if TimeCase.lower() == "daily": - filename = "chirps-v2.0.%s.%02s.%02s.tif.gz" % ( - Date.strftime("%Y"), - Date.strftime("%m"), - Date.strftime("%d"), - ) + filename = f"chirps-v2.0.{Date.strftime('%Y')}.{Date.strftime('%m')}.{Date.strftime('%d')}.tif.gz" outfilename = os.path.join( output_folder, - "chirps-v2.0.%s.%02s.%02s.tif" - % (Date.strftime("%Y"), Date.strftime("%m"), Date.strftime("%d")), + f"chirps-v2.0.{Date.strftime('%Y')}.{Date.strftime('%m')}.{Date.strftime('%d')}.tif" ) DirFileEnd = os.path.join( output_folder, - "P_CHIRPS.v2.0_mm-day-1_daily_%s.%02s.%02s.tif" - % (Date.strftime("%Y"), Date.strftime("%m"), Date.strftime("%d")), + f"P_CHIRPS.v2.0_mm-day-1_daily_{Date.strftime('%Y')}.{Date.strftime('%m')}.{Date.strftime('%d')}.tif" ) elif TimeCase == "monthly": - filename = "chirps-v2.0.%s.%02s.tif.gz" % ( - Date.strftime("%Y"), - Date.strftime("%m"), - ) + filename = f"chirps-v2.0.{Date.strftime('%Y')}.{Date.strftime('%m')}.tif.gz" outfilename = os.path.join( output_folder, - "chirps-v2.0.%s.%02s.tif" % (Date.strftime("%Y"), Date.strftime("%m")), + f"chirps-v2.0.{Date.strftime('%Y')}.{Date.strftime('%m')}.tif" ) DirFileEnd = os.path.join( output_folder, - "P_CHIRPS.v2.0_mm-month-1_monthly_%s.%02s.%02s.tif" - % (Date.strftime("%Y"), Date.strftime("%m"), Date.strftime("%d")), + f"P_CHIRPS.v2.0_mm-month-1_monthly_{Date.strftime('%Y')}.{Date.strftime('%m')}.{Date.strftime('%d')}.tif" ) else: raise KeyError("The input time interval is not supported") + self.callAPI(pathFTP, output_folder, filename) + self.post_download(output_folder, filename, lon_lim, latlim, xID, yID, outfilename, DirFileEnd) + + + @staticmethod + def callAPI(pathFTP: str, output_folder: str, filename: str): + """send the request to the server. + + RetrieveData method retrieves CHIRPS data for a given date from the + https://data.chc.ucsb.edu/ + + Parameters + ---------- + filename + output_folder + pathFTP + + + Raises + ------ + KeyError + DESCRIPTION. + + Returns + ------- + bool + DESCRIPTION. + """ + # open ftp server + # ftp = FTP("chg-ftpout.geog.ucsb.edu", "", "") + ftp = FTP(CHIRPS.api_url) + ftp.login() + + # find the document name in this directory + ftp.cwd(pathFTP) + listing = [] + + # read all the file names in the directory + ftp.retrlines("LIST", listing.append) + # download the global rainfall file - try: - local_filename = os.path.join(output_folder, filename) - lf = open(local_filename, "wb") - ftp.retrbinary("RETR " + filename, lf.write, 8192) - lf.close() + local_filename = os.path.join(output_folder, filename) + lf = open(local_filename, "wb") + ftp.retrbinary("RETR " + filename, lf.write, 8192) + lf.close() + + + def post_download(self, output_folder, filename, lon_lim, latlim, xID, yID, outfilename, DirFileEnd): + """clip the downloaded data to the extent we want + Parameters + ---------- + output_folder: [str] + directory where files will be saved + filename: [str] + file name + lon_lim: [list] + latlim: [list] + xID: [list] + yID: [list] + outfilename: [str] + DirFileEnd: [str] + """ + try: # unzip the file zip_filename = os.path.join(output_folder, filename) extractFromGZ(zip_filename, outfilename, delete=True) @@ -289,7 +325,7 @@ def RetrieveData(Date, args): ) return True - def ListAttributes(self): + def listAttributes(self): """Print Attributes List.""" print("\n") @@ -303,3 +339,25 @@ def ListAttributes(self): print(str(key) + " : " + repr(self.__dict__[key])) print("\n") + +class Catalog(CatalogTemplate): + """ CHIRPS data catalog""" + + def __init__(self): + self.catalog = self.get_catalog() + + def get_catalog(self): + """return the catalog""" + return { + "Precipitation": { + "descriptions": "rainfall [mm/time step]", + "units": "mm/time step", + "temporal resolution": ["daily", "monthly"], + "file name": "rainfall", + "var_name": "R", + } + } + + def get_variable(self, var_name): + """get the details of a specific variable""" + return self.catalog.get(var_name) diff --git a/earth2observe/utils.py b/earth2observe/utils.py index 9f57fec..cc6d4c9 100644 --- a/earth2observe/utils.py +++ b/earth2observe/utils.py @@ -1,4 +1,3 @@ -import gzip import os import sys @@ -43,32 +42,4 @@ def print_progress_bar( sys.stdout.flush() if i == total: - print() - - -def extractFromGZ(input_file, output_file, delete=False): - """ExtractFromGZ method extract data from the zip/.gz files, save the data. - - Parameters - ---------- - input_file : [str] - zipped file name . - output_file : [str] - directory where the unzipped data must be - stored. - delete : [bool] - True if you want to delete the zipped file after the extracting the data - Returns - ------- - None. - """ - with gzip.GzipFile(input_file, "rb") as zf: - content = zf.read() - save_file_content = open(output_file, "wb") - save_file_content.write(content) - - save_file_content.close() - zf.close() - - if delete: - os.remove(input_file) + print() \ No newline at end of file diff --git a/environment.yml b/environment.yml index efac3f8..83c3bdc 100644 --- a/environment.yml +++ b/environment.yml @@ -2,7 +2,7 @@ channels: - conda-forge dependencies: - python >=3.9,<3.11 - - numpy ==1.23.5 + - numpy ==1.24.1 - pip >=22.3.1 - gdal >=3.5.3 - netCDF4 >=1.6.1 @@ -10,7 +10,7 @@ dependencies: - ecmwf-api-client >=1.6.3 - earthengine-api >=0.1.324 - joblib >=1.2.0 - - pyramids >=0.2.11 + - pyramids >=0.2.12 - loguru >=0.6.0 - pytest >=7.2.0 - pytest-cov ==4.0.0 diff --git a/requirements.txt b/requirements.txt index 55154c4..98739df 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,8 +4,8 @@ gdal >=3.5.3 joblib >=1.2.0 loguru >=0.6.0 netCDF4 >=1.6.1 -numpy ==1.23.5 +numpy ==1.24.1 pandas >=1.4.4 pip >=22.3.1 -pyramids-gis >=0.2.11 +pyramids-gis >=0.2.12 requests >=2.28.1 diff --git a/setup.py b/setup.py index 00daa8a..2fa0ea2 100644 --- a/setup.py +++ b/setup.py @@ -11,7 +11,7 @@ setup( name="earth2observe", - version="0.1.7", + version="0.2.0", description="remote sensing package", author="Mostafa Farrag", author_email="moah.farag@gmail.come", From 7a1a5d45c0ba25e7672f4a72431f23e0da7f91ca Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 21:01:19 +0100 Subject: [PATCH 06/36] add get_variable method to the Catalog abstract class --- earth2observe/datasource.py | 42 +++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/earth2observe/datasource.py b/earth2observe/datasource.py index 5a94ae3..efdbb88 100644 --- a/earth2observe/datasource.py +++ b/earth2observe/datasource.py @@ -1,8 +1,46 @@ +from typing import Dict from abc import ABC, abstractmethod -class DataSource: +class DataSource(ABC): + """ + Bluebrint for all class for different datasources + """ @abstractmethod def download(self): - pass \ No newline at end of file + """Wrapper over all the given variables.""" + pass + + + # @abstractmethod + def downloadDataset(self): + """Download single variable/dataset""" + pass + + @abstractmethod + def API(self): + """send/recieve request to the dataset server""" + pass + + + @abstractmethod + def create_grid(self): + """create a grid from the lat/lon boundaries""" + pass + + +class CatalogTemplate(ABC): + """abstrach class for the datasource catalog""" + + + @abstractmethod + def get_catalog(self): + """read the catalog of the datasource from disk or retrieve it from server""" + pass + + + @abstractmethod + def get_variable(self, var_name) -> Dict[str, str]: + """get the details of a specific variable""" + pass From d4fb872df95537b1408b6a1c84395e8673b8bd82 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 21:01:41 +0100 Subject: [PATCH 07/36] add get_variable method to the Catalog abstract class --- earth2observe/datasource.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/earth2observe/datasource.py b/earth2observe/datasource.py index efdbb88..5e5ef4f 100644 --- a/earth2observe/datasource.py +++ b/earth2observe/datasource.py @@ -23,7 +23,6 @@ def API(self): """send/recieve request to the dataset server""" pass - @abstractmethod def create_grid(self): """create a grid from the lat/lon boundaries""" @@ -33,13 +32,11 @@ def create_grid(self): class CatalogTemplate(ABC): """abstrach class for the datasource catalog""" - @abstractmethod def get_catalog(self): """read the catalog of the datasource from disk or retrieve it from server""" pass - @abstractmethod def get_variable(self, var_name) -> Dict[str, str]: """get the details of a specific variable""" From b925a982f0d48ab6d1ec0511989a8a93d62bb4b2 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 21:59:29 +0100 Subject: [PATCH 08/36] add chirps tests --- earth2observe/chirps.py | 74 +++++++++++++++++++++++------------------ tests/conftest.py | 27 +++++++++++---- tests/test_chirps.py | 41 +++++++++++++++++++++++ 3 files changed, 103 insertions(+), 39 deletions(-) create mode 100644 tests/test_chirps.py diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index 5ae4939..07c70b6 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -16,10 +16,15 @@ class CHIRPS(DataSource): """CHIRPS.""" api_url: str = "data.chc.ucsb.edu" + start_date: str = "1981-01-01" + end_date: str = "Now" + temporal_resolution = ["daily", "monthly"] + lat_bondaries = [-50, 50] + lon_boundaries = [-180, 180] def __init__( self, - time: str = "daily", + temporal_resolution: str = "daily", start: str = None, end: str = None, path: str = "", @@ -31,7 +36,7 @@ def __init__( Parameters ---------- - time (str, optional): + temporal_resolution (str, optional): 'daily' or 'monthly'. Defaults to 'daily'. start (str, optional): [description]. Defaults to ''. @@ -49,35 +54,35 @@ def __init__( [description]. Defaults to "%Y-%m-%d". """ # Define timestep for the timedates - if time.lower() == "daily": + if temporal_resolution.lower() == "daily": self.time_freq = "D" self.output_folder = os.path.join(path, "Precipitation", "CHIRPS", "Daily") - elif time.lower() == "monthly": + elif temporal_resolution.lower() == "monthly": self.time_freq = "MS" self.output_folder = os.path.join( path, "Precipitation", "CHIRPS", "Monthly" ) else: - raise KeyError("The input time interval is not supported") + raise KeyError("The input temporal_resolution interval is not supported") - self.time = time + self.time = temporal_resolution # make directory if it not exists if not os.path.exists(self.output_folder): os.makedirs(self.output_folder) - # check time variables + # check temporal_resolution variables if start is None: - self.start = pd.Timestamp("1981-01-01") + self.start = pd.Timestamp(self.start_date) else: self.start = dt.datetime.strptime(start, fmt) if end is None: - self.end = pd.Timestamp("Now") + self.end = pd.Timestamp(self.end_date) else: self.end = dt.datetime.strptime(end, fmt) # Create days - self.Dates = pd.date_range(self.start, self.end, freq=self.time_freq) + self.dates = pd.date_range(self.start, self.end, freq=self.time_freq) self.create_grid(lat_lim, lon_lim) @@ -96,23 +101,26 @@ def create_grid(self, lat_lim: list, lon_lim: list): self.lat_lim = [] self.lon_lim = [] # Check space variables - if lat_lim[0] < -50 or lat_lim[1] > 50: + # -50 , 50 + if lat_lim[0] < self.lat_bondaries[0] or lat_lim[1] > self.lat_bondaries[1]: print( "Latitude above 50N or below 50S is not possible." " Value set to maximum" ) - self.lat_lim[0] = np.max(lat_lim[0], -50) - self.lat_lim[1] = np.min(lon_lim[1], 50) - if lon_lim[0] < -180 or lon_lim[1] > 180: + self.lat_lim[0] = np.max(lat_lim[0], self.lat_bondaries[0]) + self.lat_lim[1] = np.min(lon_lim[1], self.lat_bondaries[1]) + # -180, 180 + if lon_lim[0] < self.lon_boundaries[0] or lon_lim[1] > self.lon_boundaries[1]: print( "Longitude must be between 180E and 180W." " Now value is set to maximum" ) - self.lon_lim[0] = np.max(lat_lim[0], -180) - self.lon_lim[1] = np.min(lon_lim[1], 180) + self.lon_lim[0] = np.max(lat_lim[0], self.lon_boundaries[0]) + self.lon_lim[1] = np.min(lon_lim[1], self.lon_boundaries[1]) else: self.lat_lim = lat_lim self.lon_lim = lon_lim + # Define IDs self.yID = 2000 - np.int16( np.array( @@ -157,7 +165,7 @@ def download(self, progress_bar: bool = True, cores=None): if not cores: # Create Waitbar if progress_bar: - total_amount = len(self.Dates) + total_amount = len(self.dates) amount = 0 print_progress_bar( amount, @@ -167,8 +175,8 @@ def download(self, progress_bar: bool = True, cores=None): length=50, ) - for Date in self.Dates: - self.API(Date, args) + for date in self.dates: + self.API(date, args) if progress_bar: amount = amount + 1 print_progress_bar( @@ -181,16 +189,16 @@ def download(self, progress_bar: bool = True, cores=None): results = True else: results = Parallel(n_jobs=cores)( - delayed(self.API)(Date, args) for Date in self.Dates + delayed(self.API)(date, args) for date in self.dates ) return results - def API(self, Date, args): + def API(self, date, args): """form the request url abd trigger the request Parameters ---------- - Date: + date: args: [list] @@ -199,35 +207,35 @@ def API(self, Date, args): # Define FTP path to directory if TimeCase.lower() == "daily": - pathFTP = f"pub/org/chg/products/CHIRPS-2.0/global_daily/tifs/p05/{Date.strftime('%Y')}/" + pathFTP = f"pub/org/chg/products/CHIRPS-2.0/global_daily/tifs/p05/{date.strftime('%Y')}/" elif TimeCase == "monthly": pathFTP = "pub/org/chg/products/CHIRPS-2.0/global_monthly/tifs/" else: - raise KeyError("The input time interval is not supported") + raise KeyError("The input temporal_resolution interval is not supported") # create all the input name (filename) and output (outfilename, filetif, DiFileEnd) names if TimeCase.lower() == "daily": - filename = f"chirps-v2.0.{Date.strftime('%Y')}.{Date.strftime('%m')}.{Date.strftime('%d')}.tif.gz" + filename = f"chirps-v2.0.{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif.gz" outfilename = os.path.join( output_folder, - f"chirps-v2.0.{Date.strftime('%Y')}.{Date.strftime('%m')}.{Date.strftime('%d')}.tif" + f"chirps-v2.0.{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" ) DirFileEnd = os.path.join( output_folder, - f"P_CHIRPS.v2.0_mm-day-1_daily_{Date.strftime('%Y')}.{Date.strftime('%m')}.{Date.strftime('%d')}.tif" + f"P_CHIRPS.v2.0_mm-day-1_daily_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" ) elif TimeCase == "monthly": - filename = f"chirps-v2.0.{Date.strftime('%Y')}.{Date.strftime('%m')}.tif.gz" + filename = f"chirps-v2.0.{date.strftime('%Y')}.{date.strftime('%m')}.tif.gz" outfilename = os.path.join( output_folder, - f"chirps-v2.0.{Date.strftime('%Y')}.{Date.strftime('%m')}.tif" + f"chirps-v2.0.{date.strftime('%Y')}.{date.strftime('%m')}.tif" ) DirFileEnd = os.path.join( output_folder, - f"P_CHIRPS.v2.0_mm-month-1_monthly_{Date.strftime('%Y')}.{Date.strftime('%m')}.{Date.strftime('%d')}.tif" + f"P_CHIRPS.v2.0_mm-month-1_monthly_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" ) else: - raise KeyError("The input time interval is not supported") + raise KeyError("The input temporal_resolution interval is not supported") self.callAPI(pathFTP, output_folder, filename) self.post_download(output_folder, filename, lon_lim, latlim, xID, yID, outfilename, DirFileEnd) @@ -350,8 +358,8 @@ def get_catalog(self): """return the catalog""" return { "Precipitation": { - "descriptions": "rainfall [mm/time step]", - "units": "mm/time step", + "descriptions": "rainfall [mm/temporal_resolution step]", + "units": "mm/temporal_resolution step", "temporal resolution": ["daily", "monthly"], "file name": "rainfall", "var_name": "R", diff --git a/tests/conftest.py b/tests/conftest.py index 7369fbd..7fc5007 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,11 +1,26 @@ -import pandas as pd import pytest - +from typing import List from tests.gee.conftest import * -# from typing import List -# @pytest.fixture(scope="module") -# def time_series1() -> list: -# return pd.read_csv("examples/data/time_series1.txt", header=None)[0].tolist() +@pytest.fixture(scope="session") +def chirps_dates() -> list: + return ["2009-01-01", "2009-01-10"] + +@pytest.fixture(scope="session") +def daily_temporal_resolution() -> str: + return "daily" + +@pytest.fixture(scope="session") +def lat_bounds() -> List: + return [4.19, 4.64] + + +@pytest.fixture(scope="session") +def lon_bounds() -> List: + return [-75.65, -74.73] + +@pytest.fixture(scope="session") +def chirps_base_dir() -> str: + return "tests/data/chirps" \ No newline at end of file diff --git a/tests/test_chirps.py b/tests/test_chirps.py new file mode 100644 index 0000000..c376da7 --- /dev/null +++ b/tests/test_chirps.py @@ -0,0 +1,41 @@ +import os +from typing import List +import glob +import shutil +import pytest +from earth2observe.chirps import CHIRPS + + +@pytest.fixture(scope="session") +def test_download_chirps( + chirps_dates: list, + daily_temporal_resolution: str, + lat_bounds: List, + lon_bounds: List, + chirps_base_dir: str, +): + Coello = CHIRPS( + start=chirps_dates[0], + end=chirps_dates[1], + lat_lim=lat_bounds, + lon_lim=lon_bounds, + temporal_resolution=daily_temporal_resolution, + path=chirps_base_dir + ) + assert Coello.api_url == "data.chc.ucsb.edu" + assert Coello.lon_boundaries == [-180, 180] + assert Coello.lat_bondaries == [-50, 50] + assert str(Coello.dates[0].date()) == chirps_dates[0] + assert str(Coello.dates[-1].date()) == chirps_dates[1] + + return Coello + + +def test_download( + test_download_chirps: CHIRPS, + chirps_base_dir: str, +): + test_download_chirps.download() + filelist = glob.glob(os.path.join(f"{chirps_base_dir}/Precipitation/CHIRPS/Daily", "chirps*.tif")) + [os.remove(i) for i in filelist] + assert len(filelist) == 10 \ No newline at end of file From 4f6de23661ff18baa808bd429bccf18528fca6c2 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 22:00:26 +0100 Subject: [PATCH 09/36] refactor code --- earth2observe/ecmwf.py | 71 +++++++++++++-------- examples/{chirps data.py => chirps_data.py} | 14 +--- examples/ecmwf_data.py | 2 +- 3 files changed, 50 insertions(+), 37 deletions(-) rename examples/{chirps data.py => chirps_data.py} (53%) diff --git a/earth2observe/ecmwf.py b/earth2observe/ecmwf.py index 91b420d..7b97d47 100644 --- a/earth2observe/ecmwf.py +++ b/earth2observe/ecmwf.py @@ -16,17 +16,12 @@ from earth2observe import __path__ from earth2observe.utils import print_progress_bar +from earth2observe.datasource import DataSource, CatalogTemplate -class ECMWF: +class ECMWF(DataSource): """RemoteSensing. RemoteSensing class contains methods to download ECMWF data - - Methods: - 1- main - 2- DownloadData - 3- API - 4- ListAttributes """ def __init__( @@ -44,7 +39,7 @@ def __init__( Parameters ---------- - time (str, optional): + temporal_resolution (str, optional): [description]. Defaults to 'daily'. start (str, optional): [description]. Defaults to ''. @@ -105,9 +100,9 @@ def create_grid(self, lat_lim: list, lon_lim: list): def download(self, dataset: str = "interim", progress_bar: bool = True): - """ECMWF. + """Download wrapper over all given variables. - ECMWF method downloads ECMWF daily data for a given variable, time + ECMWF method downloads ECMWF daily data for a given variable, temporal_resolution interval, and spatial extent. @@ -141,7 +136,9 @@ def download(self, dataset: str = "interim", progress_bar: bool = True): def downloadDataset( self, var_info: Dict[str, str], dataset: str = "interim", progress_bar: bool = True ): - """This function downloads ECMWF six-hourly, daily or monthly data. + """Download a climate variable. + + This function downloads ECMWF six-hourly, daily or monthly data. Parameters ---------- @@ -173,13 +170,13 @@ def downloadDataset( os.makedirs(out_dir) # trigger the request to the server - self.api(var_info, dataset) + self.API(var_info, dataset) # process the downloaded data self.post_download(var_info, out_dir, dataset, progress_bar) - def api(self, var_info, dataset): + def API(self, var_info, dataset): """form the request url abd trigger the request Parameters @@ -239,7 +236,7 @@ def api(self, var_info, dataset): # Download data by using the ECMWF API logger.info("Use API ECMWF to collect the data, please wait") - self.call_api( + self.callAPI( self.path, download_type, stream, @@ -257,7 +254,7 @@ def api(self, var_info, dataset): @staticmethod - def call_api( + def callAPI( output_folder: str, download_type: str, stream: str, @@ -272,6 +269,25 @@ def call_api( area_str: str, dataset: str = "interim", ): + """send the request to the server. + + Parameters + ---------- + output_folder: [str] + directory where files will be saved + download_type: [int] + stream + levtype + param + step + grid + time_str + date_str + type_str + class_str + area_str + dataset + """ os.chdir(output_folder) server = ECMWFDataServer() @@ -287,7 +303,7 @@ def call_api( "dataset": dataset, "step": step, "grid": grid, - "time": time_str, + "temporal_resolution": time_str, "date": date_str, "type": type_str, # http://apps.ecmwf.int/codes/grib/format/mars/type/ "class": class_str, # http://apps.ecmwf.int/codes/grib/format/mars/class/ @@ -307,7 +323,7 @@ def call_api( "dataset": dataset, "step": step, "grid": grid, - "time": time_str, + "temporal_resolution": time_str, "date": date_str, "type": type_str, # http://apps.ecmwf.int/codes/grib/format/mars/type/ "class": class_str, # http://apps.ecmwf.int/codes/grib/format/mars/class/ @@ -336,6 +352,8 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres >>> 'factors_add': 0, >>> 'factors_mul': 1000 >>> } + out_dir: [str] + root directory for where the files will be saved. dataset: [str] dataset name. Default is interm progress_bar: [bool] @@ -353,7 +371,7 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres # Open the NC data Data = fh.variables[parameter_var][:] - Data_time = fh.variables["time"][:] + Data_time = fh.variables["temporal_resolution"][:] lons = fh.variables["longitude"][:] lats = fh.variables["latitude"][:] @@ -432,19 +450,22 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres fh.close() -class Catalog: - """This class contains the information about the ECMWF variables +class Catalog(CatalogTemplate): + """ECMWF data catalog + This class contains the information about the ECMWF variables http://rda.ucar.edu/cgi-bin/transform?xml=/metadata/ParameterTables/WMO_GRIB1.98-0.128.xml&view=gribdoc. """ - def __init__(self, version: int = 1): # get the catalog - with open(f"{__path__[0]}/ecmwf_data_catalog.yaml", "r") as stream: - catalog = yaml.safe_load(stream) + self.catalog = self.get_catalog() + self.version = version - self.catalog = catalog - self.version = version + def get_catalog(self): + """readthe data catalog from disk""" + with open(f"{__path__[0]}/ecmwf_data_catalog.yaml", "r") as stream: + catalog = yaml.safe_load(stream) + return catalog def get_variable(self, var_name): """retrieve a variable form the datasource catalog""" diff --git a/examples/chirps data.py b/examples/chirps_data.py similarity index 53% rename from examples/chirps data.py rename to examples/chirps_data.py index e3c92ea..d11026a 100644 --- a/examples/chirps data.py +++ b/examples/chirps_data.py @@ -1,5 +1,4 @@ from earth2observe.chirps import CHIRPS - # %% precipitation start = "2009-01-01" end = "2009-01-10" @@ -8,15 +7,8 @@ lonlim = [-75.65, -74.73] path = r"examples\data\chirps" -Coello = CHIRPS( - time=time, - start=start, - end=end, - lat_lim=latlim, - lon_lim=lonlim, - path=path, -) +Coello = CHIRPS(start=start, end=end, lat_lim=latlim, lon_lim=lonlim, temporal_resolution=time, path=path) #%% -# Coello.Download() # cores=4 +Coello.download() # cores=4 #%% -Coello.Download(cores=4) +# Coello.download(cores=4) diff --git a/examples/ecmwf_data.py b/examples/ecmwf_data.py index c011871..2f26c26 100644 --- a/examples/ecmwf_data.py +++ b/examples/ecmwf_data.py @@ -19,7 +19,7 @@ # Temperature, Evapotranspiration variables = ["T", "E"] #%% -Vars = Catalog() #"daily" +Vars = Catalog() print(Vars.catalog) #%% Temperature start = "2009-01-01" From 3e229e460f64d38063b46d63c54a1d93b3d8883c Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 22:03:42 +0100 Subject: [PATCH 10/36] fix test --- tests/test_chirps.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/test_chirps.py b/tests/test_chirps.py index c376da7..ebb9980 100644 --- a/tests/test_chirps.py +++ b/tests/test_chirps.py @@ -37,5 +37,6 @@ def test_download( ): test_download_chirps.download() filelist = glob.glob(os.path.join(f"{chirps_base_dir}/Precipitation/CHIRPS/Daily", "chirps*.tif")) - [os.remove(i) for i in filelist] - assert len(filelist) == 10 \ No newline at end of file + assert len(filelist) == 10 + # delete the files + [os.remove(i) for i in filelist] \ No newline at end of file From 7e30d6a7b72a06411a6dc8d4727479697483bfdb Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 22:15:36 +0100 Subject: [PATCH 11/36] update internal folders --- conda-lock.yml | 2287 +++++++++++++++++++++------------------ earth2observe/chirps.py | 2 +- tests/test_chirps.py | 7 +- 3 files changed, 1231 insertions(+), 1065 deletions(-) diff --git a/conda-lock.yml b/conda-lock.yml index 2985414..e72d391 100644 --- a/conda-lock.yml +++ b/conda-lock.yml @@ -15,12 +15,12 @@ metadata: - url: conda-forge used_env_vars: [] content_hash: - linux-64: 9471042de6d15f085b36252dd3ffd90c6c591b2cdf0ddbb84e90d9aec48f6385 - osx-64: e1e606a34bbb0275838bc27ac329dd1e44cde2073097d8c7b0880cf6c298e06a - win-64: 43f5e8c4e79cd0ab062939291d1fe9e7b33a79028cb3cc5a093ceff22a5daba4 + linux-64: c03a2ae4429c0be064cfc9bfe6ca40013bd6a76fa524e2a683875d8ddf92f8ec + osx-64: 2555d349819e4da12527af854a47a625c748a9bdee7617ac11c91db5e7cb2177 + win-64: 07e55835584bb9e19c718819833a15235fad3eed30776a83019f6058b52bb9d7 platforms: - - osx-64 - linux-64 + - osx-64 - win-64 sources: - C:\gdrive\01Algorithms\Hydrology\earth2observe\environment.yml @@ -138,14 +138,14 @@ package: - category: main dependencies: {} hash: - md5: c2e2630ddb68cf52eec74dc7dfab20b5 - sha256: 2966a87dcb0b11fad28f9fe8216bfa4071115776b47ffc7547492fed176e1a1f + md5: 4eb33d14d794b0f4be116443ffed3853 + sha256: bcb15db27eb6fbc0fe15d23aa60dcfa58ef451d92771441068d4a911aea7bb9f manager: conda name: python_abi optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.11-3_cp311.conda - version: '3.11' + url: https://conda.anaconda.org/conda-forge/linux-64/python_abi-3.10-3_cp310.conda + version: '3.10' - category: main dependencies: {} hash: @@ -481,6 +481,18 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/linux-64/libiconv-1.17-h166bdaf_0.tar.bz2 version: '1.17' +- category: main + dependencies: + libgcc-ng: '>=12' + hash: + md5: b4f717df2d377410b462328bf0e8fb7d + sha256: 0d8b666ca4deabf948a76654df0fa1277145bed1c9e8a58e18a649c22c5f1c3e + manager: conda + name: libjpeg-turbo + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/libjpeg-turbo-2.1.4-h166bdaf_0.tar.bz2 + version: 2.1.4 - category: main dependencies: libgcc-ng: '>=9.4.0' @@ -823,17 +835,17 @@ package: libev: '>=4.33,<4.34.0a0' libgcc-ng: '>=12' libstdcxx-ng: '>=12' - libzlib: '>=1.2.12,<1.3.0a0' - openssl: '>=3.0.5,<4.0a0' + libzlib: '>=1.2.13,<1.3.0a0' + openssl: '>=3.0.7,<4.0a0' hash: - md5: 2b7dbfa6988a41f9d23ba6d4f0e1d74e - sha256: 66988eb178d6ffbad3de5e391dad49aaa298e1309ac197ab40996eac740fbfff + md5: dd682f0b6d65e75b2bc868fc8e93d87e + sha256: acb80dfd0b7be38c47101df812fc903374c8408daec127edb6f11a648a67c243 manager: conda name: libnghttp2 optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.47.0-hff17c54_1.tar.bz2 - version: 1.47.0 + url: https://conda.anaconda.org/conda-forge/linux-64/libnghttp2-1.51.0-hff17c54_0.conda + version: 1.51.0 - category: main dependencies: libgcc-ng: '>=12' @@ -1198,14 +1210,14 @@ package: xz: '>=5.2.6,<6.0a0' zstd: '>=1.5.2,<1.6.0a0' hash: - md5: e712a63a21f9db647982971dc121cdcf - sha256: f81d38e7458c6ba2fcf93bef4ed2c12c2977e89ca9a7f936ce53a3338a88352f + md5: a01611c54334d783847879ee40109657 + sha256: 7237772229da1058fae73ae6f04ad846551a44d7da602e9d328b81049d3219a2 manager: conda name: libtiff optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.4.0-h82bc61c_5.conda - version: 4.4.0 + url: https://conda.anaconda.org/conda-forge/linux-64/libtiff-4.5.0-h82bc61c_0.conda + version: 4.5.0 - category: main dependencies: libgcc-ng: '>=12' @@ -1226,27 +1238,27 @@ package: dependencies: bzip2: '>=1.0.8,<2.0a0' ld_impl_linux-64: '>=2.36.1' - libffi: '>=3.4.2,<3.5.0a0' + libffi: '>=3.4,<4.0a0' libgcc-ng: '>=12' libnsl: '>=2.0.0,<2.1.0a0' - libsqlite: '>=3.39.4,<4.0a0' + libsqlite: '>=3.40.0,<4.0a0' libuuid: '>=2.32.1,<3.0a0' libzlib: '>=1.2.13,<1.3.0a0' ncurses: '>=6.3,<7.0a0' - openssl: '>=3.0.5,<4.0a0' + openssl: '>=3.0.7,<4.0a0' readline: '>=8.1.2,<9.0a0' tk: '>=8.6.12,<8.7.0a0' tzdata: '' - xz: '>=5.2.6,<5.3.0a0' + xz: '>=5.2.6,<6.0a0' hash: - md5: 531b2b97ce96cc95a587bdf7c74e31c0 - sha256: 60cd4d442f851efd46640f7c212110721921f0ee9c664ea0d1c339567a82d7a3 + md5: be2a6d78752c2ab85f360ce37d2c64e2 + sha256: 79cc250d8f85da29c7a06116a51db4c9efbd46f62f21daef6cf10e8bccdc0523 manager: conda name: python optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/python-3.11.0-ha86cf86_0_cpython.tar.bz2 - version: 3.11.0 + url: https://conda.anaconda.org/conda-forge/linux-64/python-3.10.8-h4a9ceb5_0_cpython.conda + version: 3.10.8 - category: main dependencies: libgcc-ng: '>=12' @@ -1290,6 +1302,18 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/noarch/affine-2.3.1-pyhd8ed1ab_0.tar.bz2 version: 2.3.1 +- category: main + dependencies: + python: '' + hash: + md5: 5f095bc6454094e96f146491fd03633b + sha256: ae9fb8f68281f84482f2c234379aa12405a9e365151d43af20b3ae1f17312111 + manager: conda + name: appdirs + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/noarch/appdirs-1.4.4-pyh9f0ad1d_0.tar.bz2 + version: 1.4.4 - category: main dependencies: python: '>=3.5' @@ -1420,29 +1444,29 @@ package: - category: main dependencies: libgcc-ng: '>=12' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: b81ebef162551d6cf909263695fd6d6b - sha256: 2a34843d55d4a10dd9028a8e8f4d4b644cf8e1367060bf0897c6ae4b961f568b + md5: 25e1626333f9a0646579a162e7b174ee + sha256: 1a213bfa274e847d08cf0d8b068dc94be002c9f17acd040b5c9f2ead80c3c7c0 manager: conda name: frozenlist optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.3.3-py311hd4cff14_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/frozenlist-1.3.3-py310h5764c6d_0.tar.bz2 version: 1.3.3 - category: main dependencies: python: '>=3.8' hash: - md5: a6966947ba28bbe60f9904653da7fed5 - sha256: 286667d325d52cd866a410da18da5660eb8bcde10dd6eae90403fa462152eff6 + md5: fec8329fc739090f26a7d7803db254f1 + sha256: b3d34bf4924cb80363c1ab57ac821393f118ffaa94f05368bf4044941163b65e manager: conda name: future optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/future-0.18.2-pyhd8ed1ab_6.tar.bz2 - version: 0.18.2 + url: https://conda.anaconda.org/conda-forge/noarch/future-0.18.3-pyhd8ed1ab_0.conda + version: 0.18.3 - category: main dependencies: python: '>=3.6' @@ -1469,44 +1493,44 @@ package: version: '3.4' - category: main dependencies: - python: '' + python: '>=3.7' hash: - md5: 39161f81cc5e5ca45b8226fbb06c6905 - sha256: 9423ded508ebda87dae21d7876134e406ffeb88e6059f3fe1a909d180c351959 + md5: f800d2da156d08e289b14e87e43c1ae5 + sha256: 38740c939b668b36a50ef455b077e8015b8c9cf89860d421b3fff86048f49666 manager: conda name: iniconfig optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-1.1.1-pyh9f0ad1d_0.tar.bz2 - version: 1.1.1 + url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + version: 2.0.0 - category: main dependencies: libgcc-ng: '>=12' libstdcxx-ng: '>=12' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 46d451f575392c01dc193069bd89766d - sha256: b0d014c8d26e6c88deb9c0e0084387827e48fc83c5ca696b27a88f6683192ef7 + md5: ad5647e517ba68e2868ef2e6e6ff7723 + sha256: f56d1772472b90ddda6fd0963a80dcf1960f1277b9653667a9bde62ae125f972 manager: conda name: kiwisolver optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.4.4-py311h4dd048b_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/kiwisolver-1.4.4-py310hbf28c38_1.tar.bz2 version: 1.4.4 - category: main dependencies: jpeg: '>=9e,<10a' libgcc-ng: '>=12' - libtiff: '>=4.4.0,<4.5.0a0' + libtiff: '>=4.5.0,<4.6.0a0' hash: - md5: dcc588839de1445d90995a0a2c4f3a39 - sha256: cbadb4150850941bf0518ba948effbbdd89b2c28dfdfed54eae196037e015b43 + md5: c2566c2ea5f153ddd6bf4acaf7547d97 + sha256: 632f191ac65bc673f8fcef9947e2c8431b0db6ca357ceebde3bdc4ed187af814 manager: conda name: lcms2 optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.14-h6ed2654_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/lcms2-2.14-hfd0df8a_1.conda version: '2.14' - category: main dependencies: @@ -1549,55 +1573,55 @@ package: libzlib: '>=1.2.13,<1.3.0a0' openssl: '>=3.0.7,<4.0a0' hash: - md5: 509f08b3789d9e7e9a72871491ae08e2 - sha256: 37432e98a75ae1c7cf8f90da84b7a74b49e4e0fcf961a1ae8a6ef6ab2bb12bc7 + md5: 9873ab80ec8fab4a2c26c7580e0d7f58 + sha256: 02a8c83a4422e751a4119db62374d49a61eb41809d055e0bf4cb84cd23ba736f manager: conda name: libpq optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libpq-15.1-hb675445_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/libpq-15.1-hb675445_3.conda version: '15.1' - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 8495a2a957bbeacad2c25f277f407f24 - sha256: 202d08801360bd4da179428107cb12ed31816d42acf5d5df179fb2aa55014a1a + md5: 63995a6d7323a83eb1c9cbde5a8435e6 + sha256: 719b11562f270454e9054e66734e18b76a3269a3950c1fd8f6b02f201ba96003 manager: conda name: loguru optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/loguru-0.6.0-py311h38be061_2.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/loguru-0.6.0-py310hff52083_2.tar.bz2 version: 0.6.0 - category: main dependencies: libgcc-ng: '>=12' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 6b0d96114b4a841630ef7d0dff10d4e8 - sha256: 9af4a98774e0319242e4b5dbf3e1e0c0f1811ce98c7e820d6ebb44cec535aff2 + md5: 2d7028ea2a77f909931e1a173d952261 + sha256: 05a217ff2eea3fb0bada54f4c7c8efe5eb35e1ad7d142d662b364c686ff80da6 manager: conda name: markupsafe optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.1-py311hd4cff14_2.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/markupsafe-2.1.1-py310h5764c6d_2.tar.bz2 version: 2.1.1 - category: main dependencies: libgcc-ng: '>=12' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 62951b170fafc17f7dfe75c967a96b92 - sha256: bf646a1aec84df20d3f81f40c6dcd0e045bdb258cb459eea367940dbd40fa9ad + md5: b33287be963a70f8fb4b143b4561ba62 + sha256: 14312ac727a741224d45ab07f75253ca99235ec0534ba9603e627818666ff49a manager: conda name: multidict optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.0.2-py311hd4cff14_2.tar.bz2 - version: 6.0.2 + url: https://conda.anaconda.org/conda-forge/linux-64/multidict-6.0.4-py310h1fa729e_0.conda + version: 6.0.4 - category: main dependencies: python: '' @@ -1614,14 +1638,14 @@ package: dependencies: python: '>=3.8' hash: - md5: bb45ff9deddb045331fd039949f39650 - sha256: a8e3531fdb6f9acfde885dd94c8639c020013215dab98ff4ed82db7aa745277a + md5: 88e40007414ea9a13f8df20fcffa87e2 + sha256: edd149a40ea746ce17c1b135c72a1646810e99071bedb7d808914cc31b3c8a5d manager: conda name: networkx optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/networkx-2.8.8-pyhd8ed1ab_0.tar.bz2 - version: 2.8.8 + url: https://conda.anaconda.org/conda-forge/noarch/networkx-3.0-pyhd8ed1ab_0.conda + version: '3.0' - category: main dependencies: libblas: '>=3.9.0,<4.0a0' @@ -1629,45 +1653,45 @@ package: libgcc-ng: '>=12' liblapack: '>=3.9.0,<4.0a0' libstdcxx-ng: '>=12' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: de8cf17747d9efed488cafea2c39c9a1 - sha256: 50c6bc50773ff9eab9523753f0bd487d0e491719d5284eb6243ab23ddafbb695 + md5: 0d1f2e988c8810be90ffe441a303090a + sha256: 38a0f26b6e829739042aab9b4eec43df0f6df9f83ba9ce89735d627ff5fd90fd manager: conda name: numpy optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.23.5-py311h7d28db0_0.conda - version: 1.23.5 + url: https://conda.anaconda.org/conda-forge/linux-64/numpy-1.24.1-py310h08bbf29_0.conda + version: 1.24.1 - category: main dependencies: libgcc-ng: '>=12' - libpng: '>=1.6.37,<1.7.0a0' + libpng: '>=1.6.39,<1.7.0a0' libstdcxx-ng: '>=12' - libtiff: '>=4.4.0,<4.5.0a0' - libzlib: '>=1.2.12,<1.3.0a0' + libtiff: '>=4.5.0,<4.6.0a0' + libzlib: '>=1.2.13,<1.3.0a0' hash: - md5: a11b4df9271a8d7917686725aa04c8f2 - sha256: a715cba5649f12a1dca53dfd72fc49577152041f033d7595cf4b6a655a5b93b6 + md5: 5ce6a42505c6e9e6151c54c3ec8d68ea + sha256: 3cbfb1fe9bb492dcb672f98f0ddc7b4e029f51f77101d9c301caa3acaea8cba2 manager: conda name: openjpeg optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.0-h7d73246_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/openjpeg-2.5.0-hfec8fc6_2.conda version: 2.5.0 - category: main dependencies: python: '>=3.7' hash: - md5: 0e8e1bd93998978fc3125522266d12db - sha256: 163f26e55246c506a75551ca01f35c7d4d533aee6db5c4cf2d598ae253e956b8 + md5: 1ff2e3ca41f0ce16afec7190db28288b + sha256: 00288f5e5e841711e8b8fef1f1242c858d8ef99ccbe5d7e0df4789d5d8d40645 manager: conda name: packaging optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/packaging-22.0-pyhd8ed1ab_0.conda - version: '22.0' + url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.0-pyhd8ed1ab_0.conda + version: '23.0' - category: main dependencies: python: '>=3.8' @@ -1731,16 +1755,16 @@ package: - category: main dependencies: libspatialindex: '>=1.9.3,<1.9.4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 1b020e2257c97aea220dd46f3f57db4b - sha256: 92b35fcdb6e986a65713047c44f51f9d464753a25c32d7dfaf222b574792b57a + md5: 49ad4035b71bbf7289ac1523f8023ebe + sha256: 9d0c89343253cbf6cd669e86d5afe2f16a79d2f8cd80ed9c588eef87fe7ba620 manager: conda name: rtree optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/rtree-1.0.1-py311h3bb2b0f_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/rtree-1.0.1-py310hbdcdc62_1.tar.bz2 version: 1.0.1 - category: main dependencies: @@ -1814,6 +1838,20 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.4.0-pyha770c72_0.tar.bz2 version: 4.4.0 +- category: main + dependencies: + libgcc-ng: '>=12' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + hash: + md5: e972c5a1f472561cf4a91962cb01f4b4 + sha256: 332732c2b87445c3e071c86cacfbc72a99ba4ea55d0b9d65416894253782ca02 + manager: conda + name: unicodedata2 + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/unicodedata2-15.0.0-py310h5764c6d_0.tar.bz2 + version: 15.0.0 - category: main dependencies: python: '>=3.6' @@ -1936,16 +1974,16 @@ package: libffi: '>=3.4,<4.0a0' libgcc-ng: '>=12' pycparser: '' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 9025d0786dbbe4bc91fd8e85502decce - sha256: 7161bcdf1a304f76e88a05ed435c03ee92864ee5e8f4c938e35b089b3861b5a7 + md5: 800596144bb613cd7ac58b80900ce835 + sha256: f223c8782195f19dbe7cfd27e329de8b0e2205a090ee2a6891e0695d4d634854 manager: conda name: cffi optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.15.1-py311h409f033_3.conda + url: https://conda.anaconda.org/conda-forge/linux-64/cffi-1.15.1-py310h255011f_3.conda version: 1.15.1 - category: main dependencies: @@ -1967,17 +2005,17 @@ package: - category: main dependencies: libgcc-ng: '>=12' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: c7e54004ffd03f8db0a58ab949f2a00b - sha256: 11087a71d55d71617d13d1ab55755a6803b4ec17ec2514b816f9b4206c8396eb + md5: 94ce7a76b0c912279f6958e0b6b21d2b + sha256: fc5ff45e357bb63ca586b326e5cdd27f97934d45224af4501023e842436e3794 manager: conda name: cftime optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/cftime-1.6.2-py311h4c7f6c3_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/cftime-1.6.2-py310hde88566_1.tar.bz2 version: 1.6.2 - category: main dependencies: @@ -1998,32 +2036,32 @@ package: libgcc-ng: '>=12' libstdcxx-ng: '>=12' numpy: '>=1.16' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: d97ffb1b2692d8846d3fc1f20766eb08 - sha256: c9694f4e265e63cad4116af7007b8404b4c18a5ba052a9d803395a11950f1fb3 + md5: 7bf9d8c765b6b04882c719509652c6d6 + sha256: 670b736e895ed1b37187e0cbc73fd528414076f370068975135db2420af8663d manager: conda name: contourpy optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.0.6-py311h4dd048b_0.tar.bz2 - version: 1.0.6 + url: https://conda.anaconda.org/conda-forge/linux-64/contourpy-1.0.7-py310hdf3cbec_0.conda + version: 1.0.7 - category: main dependencies: libgcc-ng: '>=12' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 tomli: '' hash: - md5: f47f75517d1784806fbe4302c5e8997f - sha256: 9b82f40364484ddf2cc236021d286e15d4ed306e5f1ff145f0944e41035c6914 + md5: 05e8938cfb48c6570dae80243d801f42 + sha256: 92b317d2261420ae8ce79cb0cad614e123ab6da65a6628a65e8eda4758f13b30 manager: conda name: coverage optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.0.1-py311h2582759_0.conda - version: 7.0.1 + url: https://conda.anaconda.org/conda-forge/linux-64/coverage-7.0.5-py310h1fa729e_0.conda + version: 7.0.5 - category: main dependencies: krb5: '>=1.20.1,<1.21.0a0' @@ -2046,16 +2084,17 @@ package: brotli: '' libgcc-ng: '>=12' munkres: '' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + unicodedata2: '>=14.0.0' hash: - md5: 871b97970cf7420780f79a62fef8eb48 - sha256: 6af7716ceef638338ba93a4f0c325305da30e1f9bf8aad2c741c967ed4bac914 + md5: 12ebe92a8a578bc903bd844744f4d040 + sha256: 28e21fe765f07219c7f086b0d3bf66305ba2a457d5c248bcc92ee53d8b0f393d manager: conda name: fonttools optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.38.0-py311hd4cff14_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/fonttools-4.38.0-py310h5764c6d_1.tar.bz2 version: 4.38.0 - category: main dependencies: @@ -2079,19 +2118,19 @@ package: libprotobuf: '>=3.21.10,<3.22.0a0' libstdcxx-ng: '>=12' openssl: '>=3.0.7,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 re2: '>=2022.6.1,<2022.6.2.0a0' setuptools: '' six: '>=1.6.0' hash: - md5: 31ef25a48cffdb54768a342269f76405 - sha256: 9c9fd327784e48be409dbca8662be7bece6e937ed7e2a6e3c60a2c1a5bca22e2 + md5: 9f111b88852841a1b77055363b5db3bf + sha256: 64bb37e82655987d0d523aa2d9600a33995190fc6c988a863b93f68ba14508c7 manager: conda name: grpcio optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/grpcio-1.51.1-py311hf734370_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/grpcio-1.51.1-py310hc32fa93_0.conda version: 1.51.1 - category: main dependencies: @@ -2168,26 +2207,26 @@ package: - category: main dependencies: freetype: '>=2.12.1,<3.0a0' - jpeg: '>=9e,<10a' - lcms2: '>=2.12,<3.0a0' + lcms2: '>=2.14,<3.0a0' libgcc-ng: '>=12' - libtiff: '>=4.4.0,<4.5.0a0' + libjpeg-turbo: '>=2.1.4,<3.0a0' + libtiff: '>=4.5.0,<4.6.0a0' libwebp-base: '>=1.2.4,<2.0a0' libxcb: '>=1.13,<1.14.0a0' libzlib: '>=1.2.13,<1.3.0a0' openjpeg: '>=2.5.0,<3.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 tk: '>=8.6.12,<8.7.0a0' hash: - md5: 03ff0e369f200145f55f94a7a5be1cc4 - sha256: 0931e054b346139ca8ca5d0cea67f159fb68336470bdfc539f8ff2edfe3b7e37 + md5: 66366aceea767f174f4d0408f3a62812 + sha256: ab85b5203a2f052e2e70aaa83dd5aa0782758598ae9a06842ec1f65f03173202 manager: conda name: pillow optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pillow-9.2.0-py311h9461556_3.tar.bz2 - version: 9.2.0 + url: https://conda.anaconda.org/conda-forge/linux-64/pillow-9.4.0-py310h4927cde_0.conda + version: 9.4.0 - category: main dependencies: python: '>=3.7' @@ -2206,7 +2245,7 @@ package: dependencies: krb5: '>=1.20.1,<1.21.0a0' libgcc-ng: '>=12' - libpq: 15.1 hb675445_2 + libpq: 15.1 hb675445_3 libxml2: '>=2.10.3,<2.11.0a0' libzlib: '>=1.2.13,<1.3.0a0' openssl: '>=3.0.7,<4.0a0' @@ -2215,47 +2254,47 @@ package: tzdata: '' zlib: '' hash: - md5: 4d2f2c04f8bdb6a9cb0d6e8d90b1f907 - sha256: 6d24935e50d7af2ed7610e731217556a5862173d8d6f77f00c118df2952f1e54 + md5: 4f686d5d582a3e3b32a3cb010fa12103 + sha256: c44d0aec97d552bac0e0ad310fe55c6989d5ae9b6bec2ac448072ab6ed295511 manager: conda name: postgresql optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/postgresql-15.1-h3248436_2.conda + url: https://conda.anaconda.org/conda-forge/linux-64/postgresql-15.1-h3248436_3.conda version: '15.1' - category: main dependencies: - libcurl: '>=7.83.1,<8.0a0' + libcurl: '>=7.87.0,<8.0a0' libgcc-ng: '>=12' - libsqlite: '>=3.39.3,<4.0a0' + libsqlite: '>=3.40.0,<4.0a0' libstdcxx-ng: '>=12' - libtiff: '>=4.4.0,<4.5.0a0' - sqlite: '>=3.39.3,<4.0a0' + libtiff: '>=4.5.0,<4.6.0a0' + sqlite: '' hash: - md5: 255c7204dda39747c3ba380d28b026d7 - sha256: a381d3db5e344e101cd88304ec9eceaaa7a320ee35cc68fb10b247a7b46bcc3d + md5: ed901e1f5c504b144b31f015c6702634 + sha256: 8dcbb97ee78e8e0b34fc6a93904874108bed138bf046d5b91832c73abac802c1 manager: conda name: proj optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/proj-9.1.0-h93bde94_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/proj-9.1.0-h8ffa02c_1.conda version: 9.1.0 - category: main dependencies: libgcc-ng: '>=12' libprotobuf: '>=3.21.12,<3.22.0a0' libstdcxx-ng: '>=12' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '' hash: - md5: e50c8a6b26b30cc435a04391d654f572 - sha256: 500fd865e888422c252ecee543565085d132b6f2465813573ba7ba75667d47eb + md5: 90bb7e1b729c4b50272cf78be97ab912 + sha256: 38808ff5a9b724d00b12f14ca5c83b40a7b7ada4715a8e8c3b64bf73407bbe5f manager: conda name: protobuf optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/protobuf-4.21.12-py311hcafe171_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/protobuf-4.21.12-py310heca2aa9_0.conda version: 4.21.12 - category: main dependencies: @@ -2295,14 +2334,14 @@ package: python: '>=3.8' tomli: '>=1.0.0' hash: - md5: ac82c7aebc282e6ac0450fca012ca78c - sha256: 854233dc2d0d64219b7e951ccf49c1f32332c6fc7085ecb62cc18bc1f4e791b0 + md5: f0be05afc9c9ab45e273c088e00c258b + sha256: d298dfe6c53555c9fb5662f5f936e621cddd3b0a7031789375b82a1ee3b3a96b manager: conda name: pytest optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/pytest-7.2.0-pyhd8ed1ab_2.tar.bz2 - version: 7.2.0 + url: https://conda.anaconda.org/conda-forge/noarch/pytest-7.2.1-pyhd8ed1ab_0.conda + version: 7.2.1 - category: main dependencies: python: '>=3.6' @@ -2342,42 +2381,21 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/noarch/rsa-4.9-pyhd8ed1ab_0.tar.bz2 version: '4.9' -- category: main - dependencies: - libblas: '>=3.9.0,<4.0a0' - libcblas: '>=3.9.0,<4.0a0' - libgcc-ng: '>=12' - libgfortran-ng: '' - libgfortran5: '>=10.4.0' - liblapack: '>=3.9.0,<4.0a0' - libstdcxx-ng: '>=12' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 - hash: - md5: bb44baf80c9e22d4581dea2c030adb1c - sha256: 568bdbbcf87ab4cd2e309df58923d707388f15d48d1bc0eb3fbbc4f1a6be964d - manager: conda - name: scipy - optional: false - platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.9.3-py311h69910c8_2.tar.bz2 - version: 1.9.3 - category: main dependencies: geos: '>=3.11.1,<3.11.2.0a0' libgcc-ng: '>=12' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 069246afc942fd3530060b8f349afa9b - sha256: b0027fb4611229122ab5868f12b462eb340cac358e66a269ab28d1ff944b8982 + md5: c4a3707d6a630facb6cf7ed8e0d37326 + sha256: 31f71ea8786ce6a0cd649ffa270feace395cc7a8a758413f11e69d03c36a8efe manager: conda name: shapely optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/shapely-1.8.5-py311h2b60523_2.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/shapely-1.8.5-py310h5b266fc_2.tar.bz2 version: 1.8.5 - category: main dependencies: @@ -2426,17 +2444,17 @@ package: idna: '>=2.0' libgcc-ng: '>=12' multidict: '>=4.0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: fa1377ab82c07d7724a027158e793a7a - sha256: 1aec1f77d7ae7cff7e6475bbb653b899224192c89b09719dbffe3bfad2308848 + md5: a88cda17074955bdb5e93b8e3be59e7d + sha256: eb7fd99bf87e0d150ee6946479172688ded1c4fb51382ad27be5da217cd8815b manager: conda name: yarl optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.8.1-py311hd4cff14_0.tar.bz2 - version: 1.8.1 + url: https://conda.anaconda.org/conda-forge/linux-64/yarl-1.8.2-py310h5764c6d_0.conda + version: 1.8.2 - category: main dependencies: python: '>=3.6' @@ -2468,16 +2486,16 @@ package: dependencies: cffi: '>=1.0.0' libgcc-ng: '>=12' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 9bdac7084ecfc08338bae1b976535724 - sha256: 9bd71030fe4b03a28453c678bfc805993b7c6c6d6bdf910edef7040acf3091d6 + md5: 87669c3468dff637bbd0363bc0f895cf + sha256: a37f9a00170f48e71b67bb4547e8bf352dcee4e4a79a55f087b512022cc64a0d manager: conda name: brotlipy optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/brotlipy-0.7.0-py311hd4cff14_1005.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/brotlipy-0.7.0-py310h5764c6d_1005.tar.bz2 version: 0.7.0 - category: main dependencies: @@ -2510,64 +2528,64 @@ package: cffi: '>=1.12' libgcc-ng: '>=12' openssl: '>=3.0.7,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 34c95722eb879d7a9ee0546671084b2d - sha256: 4dde86f9fb9c78066517554899e7fa55f70d753349eb5ac51fc11df4ceb38cae + md5: af4b0c22dc4006ce3c095e840cb2efd7 + sha256: 11d745fc13a122aaba35984362411d0b65dc2b31552c8ff3c3bdf6c988dc288f manager: conda name: cryptography optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/cryptography-38.0.4-py311h42a1071_0.conda - version: 38.0.4 + url: https://conda.anaconda.org/conda-forge/linux-64/cryptography-39.0.0-py310h34c0648_0.conda + version: 39.0.0 - category: main dependencies: jpeg: '>=9e,<10a' libgcc-ng: '>=12' libstdcxx-ng: '>=12' - libtiff: '>=4.4.0,<4.5.0a0' - libzlib: '>=1.2.12,<1.3.0a0' + libtiff: '>=4.5.0,<4.6.0a0' + libzlib: '>=1.2.13,<1.3.0a0' proj: '>=9.1.0,<9.1.1.0a0' - zlib: '>=1.2.12,<1.3.0a0' + zlib: '' hash: - md5: 6a613710a0f19aba3a5dfe83bf1c1c0f - sha256: afc5ecf6b1892546cc497f0290a70333908aa388f750d614664c293f91468ee6 + md5: dfb1b96aee336c345c1833cf8f486acc + sha256: 1a148c74afa67d2647914621c9cf5e66153fbea4d81dbfdd1d9e860e4e971008 manager: conda name: geotiff optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/geotiff-1.7.1-ha76d385_4.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/geotiff-1.7.1-h7157cca_5.conda version: 1.7.1 - category: main dependencies: cffi: '>=1.0.0' libcrc32c: '>=1.1.2,<1.2.0a0' libgcc-ng: '>=12' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 30fc7e9e67651173963320d38fb3cb12 - sha256: 09a38cc70c92f891c630595e239f3e8138b141147e4e4897096d637021a5861c + md5: eacd2681883d37f27440cf5cd779bef2 + sha256: 1dcdac463e46799864c1006ca34959b3d443ae482b97eb17bb8d776cc7d99a19 manager: conda name: google-crc32c optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/google-crc32c-1.1.2-py311h98db957_4.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/google-crc32c-1.1.2-py310he8fe98e_4.tar.bz2 version: 1.1.2 - category: main dependencies: protobuf: '>=3.19.5,<5.0.0dev,!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5' python: '>=3.7' hash: - md5: 35947a7b1f5319de636d74ce38dcf131 - sha256: 88c2be80b3c4ca97f5259b6c6a814b730e6ab4d09c15dbbe60df779c3a7416f9 + md5: cbf8b4569c1d2a0a6077d34a2d38333e + sha256: 1b2a9ae4540e3056a7eaf126a4939360f521854c8a4aa04f10ed4c80da4edc7e manager: conda name: googleapis-common-protos optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/googleapis-common-protos-1.57.0-pyhd8ed1ab_3.conda - version: 1.57.0 + url: https://conda.anaconda.org/conda-forge/noarch/googleapis-common-protos-1.57.1-pyhd8ed1ab_0.conda + version: 1.57.1 - category: main dependencies: hdf5: '>=1.12.2,<1.12.3.0a0' @@ -2635,40 +2653,40 @@ package: kiwisolver: '>=1.0.1' libgcc-ng: '>=12' libstdcxx-ng: '>=12' - numpy: '>=1.23.4,<2.0a0' + numpy: '>=1.21.6,<2.0a0' packaging: '>=20.0' pillow: '>=6.2.0' pyparsing: '>=2.3.1' - python: '>=3.11,<3.12.0a0' + python: '>=3.10,<3.11.0a0' python-dateutil: '>=2.7' - python_abi: 3.11.* *_cp311 + python_abi: 3.10.* *_cp310 tk: '>=8.6.12,<8.7.0a0' hash: - md5: 96ec1bd38ecfc5ead0ac1eb8c4bf35ff - sha256: d4729943dc046222c77e0773a85da912c45346f8124c71ff80bacc04105b1000 + md5: da51ddb20c0f99d672eb756c3abf27e7 + sha256: 58b84a4607bfbc3375d8dc3ec83cf324ae1df0261f51b6ef65023b5a725b79f8 manager: conda name: matplotlib-base optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.6.2-py311he728205_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/matplotlib-base-3.6.2-py310h8d5ebf3_0.tar.bz2 version: 3.6.2 - category: main dependencies: libgcc-ng: '>=12' libstdcxx-ng: '>=12' - numpy: '>=1.23.5,<2.0a0' - python: '>=3.11,<3.12.0a0' + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' python-dateutil: '>=2.8.1' - python_abi: 3.11.* *_cp311 + python_abi: 3.10.* *_cp310 pytz: '>=2020.1' hash: - md5: d203d6938a0c1a76cb540a2972644af7 - sha256: f4e399718b1f7ce25464e0df94cc36251b312dea841adb8f76c5a02ac07562f3 + md5: 99e34b448c0510acaf98955668c0ac9e + sha256: d53cfeaa389e98b3cbe8ca05784fe5c39f8748066295466305eb9c2d140cd90e manager: conda name: pandas optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pandas-1.5.2-py311h8b32b4d_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/pandas-1.5.2-py310h9b08913_2.conda version: 1.5.2 - category: main dependencies: @@ -2686,35 +2704,35 @@ package: libiconv: '>=1.17,<2.0a0' libpng: '>=1.6.39,<1.7.0a0' libstdcxx-ng: '>=12' - libtiff: '>=4.4.0,<4.5.0a0' + libtiff: '>=4.5.0,<4.6.0a0' libzlib: '>=1.2.13,<1.3.0a0' nss: '>=3.82,<4.0a0' openjpeg: '>=2.5.0,<3.0a0' poppler-data: '' hash: - md5: 7ad6d858f5615f9b0e9e4bd60395ea75 - sha256: e722d8cd8c704fb8f62db08628e3af0d2802d69f26d168c52cca50ccb4d8acc6 + md5: 25cfe805ac16b3bed648f5376bc389f0 + sha256: 771f1338a9f8270447edabe6d34a2c613d778f1d065015a28ccf8dfcfaa38290 manager: conda name: poppler optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/poppler-22.12.0-h92391eb_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/poppler-22.12.0-h091648b_1.conda version: 22.12.0 - category: main dependencies: certifi: '' libgcc-ng: '>=12' proj: '>=9.1.0,<9.1.1.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 534c36b3d540acbe43e289958fbe30cb - sha256: 3b604d6ba8a3a14b4a9dc6a4e15176dc16bf2c3c2c4e19c6bddd2ce5877486a4 + md5: c126f81b5cea6b2d4a64d0744249a26f + sha256: f0d84cd82f2244c6f5f0ced0105c238d00f09df9bbe7e51aa2492cef45bb22a5 manager: conda name: pyproj optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/pyproj-3.4.1-py311h7c961c7_0.conda + url: https://conda.anaconda.org/conda-forge/linux-64/pyproj-3.4.1-py310hfc24d34_0.conda version: 3.4.1 - category: main dependencies: @@ -2731,26 +2749,6 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/noarch/pytest-cov-4.0.0-pyhd8ed1ab_0.tar.bz2 version: 4.0.0 -- category: main - dependencies: - joblib: '>=1.1.1' - libcblas: '>=3.9.0,<4.0a0' - libgcc-ng: '>=12' - libstdcxx-ng: '>=12' - numpy: '>=1.23.5,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 - scipy: '' - threadpoolctl: '>=2.0.0' - hash: - md5: aca888579184f85eadf57f9b40992046 - sha256: 3e786149c38445ffefd06ed49a465fad6a428536251a4b554e738aeb84d392dc - manager: conda - name: scikit-learn - optional: false - platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.2.0-py311h67c5ca5_0.conda - version: 1.2.0 - category: main dependencies: bzip2: '>=1.0.8,<2.0a0' @@ -2763,14 +2761,14 @@ package: zlib: '' zstd: '>=1.5.2,<1.6.0a0' hash: - md5: d7655c5bdd7a9b47a49d0029f72773da - sha256: a3df2f027f7f9ec604ab2e03facc69a1a167c20bd1ad91316102910fe771a310 + md5: 6d97164f19dbd27575ef1899b02dc1e0 + sha256: 406bf59089f80d553981a624c7c163b479f883f2f661a6aca3eb95aabebeb490 manager: conda name: tiledb optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/tiledb-2.13.0-hd532e3d_1.conda - version: 2.13.0 + url: https://conda.anaconda.org/conda-forge/linux-64/tiledb-2.13.2-hd532e3d_0.conda + version: 2.13.2 - category: main dependencies: aiosignal: '>=1.1.2' @@ -2780,17 +2778,17 @@ package: frozenlist: '>=1.1.1' libgcc-ng: '>=12' multidict: '>=4.5,<7.0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 yarl: '>=1.0,<2.0' hash: - md5: a20f1309428af51d85dc27c379b28339 - sha256: fe2a151c8d36c8636e43074aea1d62fa6e0e2bf3cf17a9f7e17f6551264c3750 + md5: 7212b99b48dcdb1d384078d772227130 + sha256: 9ae162c8562bed6fabf6b5ec55d0c00ed721a4b8411161a2b0cb3638bad200e0 manager: conda name: aiohttp optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.8.3-py311hd4cff14_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/aiohttp-3.8.3-py310h5764c6d_1.tar.bz2 version: 3.8.3 - category: main dependencies: @@ -2838,7 +2836,7 @@ package: json-c: '>=0.16,<0.17.0a0' kealib: '>=1.5.0,<1.6.0a0' lerc: '>=4.0.0,<5.0a0' - libcurl: '>=7.86.0,<8.0a0' + libcurl: '>=7.87.0,<8.0a0' libdeflate: '>=1.14,<1.15.0a0' libgcc-ng: '>=12' libiconv: '>=1.17,<2.0a0' @@ -2849,7 +2847,7 @@ package: libspatialite: '>=5.0.1,<5.1.0a0' libsqlite: '>=3.40.0,<4.0a0' libstdcxx-ng: '>=12' - libtiff: '>=4.4.0,<4.5.0a0' + libtiff: '>=4.5.0,<4.6.0a0' libuuid: '>=2.32.1,<3.0a0' libwebp-base: '>=1.2.4,<2.0a0' libxml2: '>=2.10.3,<2.11.0a0' @@ -2861,36 +2859,19 @@ package: poppler: '>=22.12.0,<22.13.0a0' postgresql: '' proj: '>=9.1.0,<9.1.1.0a0' - tiledb: '>=2.13.0,<2.14.0a0' + tiledb: '>=2.13.1,<2.14.0a0' xerces-c: '>=3.2.4,<3.3.0a0' xz: '>=5.2.6,<6.0a0' zstd: '>=1.5.2,<1.6.0a0' hash: - md5: fc4c5716fac9e7f242223dca042e1045 - sha256: cb6ffbf9e818030061b0c48e5a326f55bafa6e7904ff450e7d8b6b7b2423691b + md5: f16dc7517110a11910f7c1d9def32d38 + sha256: 84d5d701b0b739caa7a71eca47be2625079a2dd48c7638b9e5aedb72c916e593 manager: conda name: libgdal optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/libgdal-3.6.1-hf2b5f72_1.conda - version: 3.6.1 -- category: main - dependencies: - networkx: '' - numpy: '>=1.3' - pandas: '>=1.0' - python: '>=3.5' - scikit-learn: '' - scipy: '>=1.0' - hash: - md5: 908bbfb54da154042c5cbda77b37a3d1 - sha256: 1435305fb0a127b3154e76c0836d44526eeb93e80bd37596128d7ad8fb196d97 - manager: conda - name: mapclassify - optional: false - platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/mapclassify-2.4.3-pyhd8ed1ab_0.tar.bz2 - version: 2.4.3 + url: https://conda.anaconda.org/conda-forge/linux-64/libgdal-3.6.2-he31f7c0_1.conda + version: 3.6.2 - category: main dependencies: cftime: '' @@ -2898,51 +2879,51 @@ package: libgcc-ng: '>=12' libnetcdf: '>=4.8.1,<4.8.2.0a0' libzlib: '>=1.2.13,<1.3.0a0' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '' hash: - md5: 1ef39f477192bf05df04fb5ad594e82d - sha256: be3c05a42c3a967f80705a52e54c6a8bd5564f305111a273f83e7170b52a2d6e + md5: 4dd7aa28fb7d9a6de061c9579a30e7dd + sha256: 9a81799b1c22ae749037919a534b14b172924358e036c1e50c1d27ffca645272 manager: conda name: netcdf4 optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.6.2-nompi_py311hc6fcf29_100.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/netcdf4-1.6.2-nompi_py310h55e1e36_100.tar.bz2 version: 1.6.2 - category: main dependencies: - cryptography: '>=38.0.0,<39' + cryptography: '>=38.0.0,<40' python: '>=3.6' hash: - md5: fbfa0a180d48c800f922a10a114a8632 - sha256: 42f04dded77ac2597108378d62b121697d0e982aba7b20a462a7239030563628 + md5: d41957700e83bbb925928764cb7f8878 + sha256: adbf8951f22bfa950b9e24394df1ef1d2b2d7dfb194d91c7f42bc11900695785 manager: conda name: pyopenssl optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-22.1.0-pyhd8ed1ab_0.tar.bz2 - version: 22.1.0 + url: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-23.0.0-pyhd8ed1ab_0.conda + version: 23.0.0 - category: main dependencies: hdf5: '>=1.12.2,<1.12.3.0a0' libgcc-ng: '>=12' - libgdal: 3.6.1 hf2b5f72_1 + libgdal: 3.6.2 he31f7c0_1 libstdcxx-ng: '>=12' - numpy: '>=1.23.5,<2.0a0' + numpy: '>=1.21.6,<2.0a0' openssl: '>=3.0.7,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 654ec2d38113b75691bf8c5d499fae18 - sha256: 25854f4c9f07ceb7e16f2454f3abf021ce6f92e56d52d944a6026d9dc1e01418 + md5: d6855fd7042a21cba318f68874e5b3e6 + sha256: fca1260c69715a21f12a0d5421495909e5bf09ab2b3662eb12b4ec6da5d871c3 manager: conda name: gdal optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/gdal-3.6.1-py311hadb6153_1.conda - version: 3.6.1 + url: https://conda.anaconda.org/conda-forge/linux-64/gdal-3.6.2-py310hc1b7723_1.conda + version: 3.6.2 - category: main dependencies: affine: '' @@ -2954,20 +2935,20 @@ package: libgcc-ng: '>=12' libgdal: '>=3.6.0,<3.7.0a0' libstdcxx-ng: '>=12' - numpy: '>=1.23.4,<2.0a0' + numpy: '>=1.21.6,<2.0a0' proj: '>=9.1.0,<9.1.1.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '>=0.9.8' snuggs: '>=1.4.1' hash: - md5: ae9f6d01c505fb79519e1f106faa9e75 - sha256: c44eb273aa898bb6b7b059accc407b700348d02f15ab8d4092198e2417743518 + md5: e7d96b020ff846c1658afa1a08cee7bc + sha256: 1c798fd4a5b51f4e44dc634dc47c3e7ca6ff25edac78451e41b86c6a8289ace6 manager: conda name: rasterio optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/rasterio-1.3.4-py311hf3241e5_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/linux-64/rasterio-1.3.4-py310hfc14bbd_0.tar.bz2 version: 1.3.4 - category: main dependencies: @@ -2979,14 +2960,14 @@ package: pysocks: '>=1.5.6,<2.0,!=1.5.7' python: <4.0 hash: - md5: 3078ef2359efd6ecadbc7e085c5e0592 - sha256: 992f2d6ca50c98f865a4f2e4bada23f950e39f33ff7c64614a31ee152ec4d5ae + md5: 01f33ad2e0aaf6b5ba4add50dad5ad29 + sha256: f2f09c44e47946ce631dbc9a8a79bb463ac0f4122aaafdbcc51f200a1e420ca6 manager: conda name: urllib3 optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/urllib3-1.26.13-pyhd8ed1ab_0.conda - version: 1.26.13 + url: https://conda.anaconda.org/conda-forge/noarch/urllib3-1.26.14-pyhd8ed1ab_0.conda + version: 1.26.14 - category: main dependencies: attrs: '>=17' @@ -2998,20 +2979,20 @@ package: libgdal: '>=3.6.0,<3.7.0a0' libstdcxx-ng: '>=12' munch: '' - numpy: '>=1.23.5,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '' shapely: '' six: '>=1.7' hash: - md5: 6b0f1ce21a6254774177e78e00e1b966 - sha256: d0fa23c423b4d6b5636e75d46299b9edef87469949c737e8f2ed23e9013c639a + md5: 4dbdf48d4712e8906595291f38423eff + sha256: 4b16bdce243474428561646cd74573060e281cf3594e2bdc019ce61d9d9abfae manager: conda name: fiona optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/linux-64/fiona-1.8.22-py311h3f14cef_5.conda + url: https://conda.anaconda.org/conda-forge/linux-64/fiona-1.8.22-py310ha325b7b_5.conda version: 1.8.22 - category: main dependencies: @@ -3067,23 +3048,19 @@ package: version: 2.15.0 - category: main dependencies: - fiona: '' - folium: '' - geopandas-base: 0.12.2 pyha770c72_0 - mapclassify: '>=2.4.0' - matplotlib-base: '' - python: '>=3.8' - rtree: '' - xyzservices: '' + appdirs: '>=1.3.0' + packaging: '>=20.0' + python: '>=3.6' + requests: '>=2.19.0' hash: - md5: ee3b330f13297f5839d46e1ca3e57d56 - sha256: 51660094efee2a74b24ab535e03005a6ddedc9e160c0d573cfaf2724312d171c + md5: 6429e1d1091c51f626b5dcfdd38bf429 + sha256: 1f0548105de86fb2eb6fbb8d3d6cc2004079b8442d232258108687d6cc91eb73 manager: conda - name: geopandas + name: pooch optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/geopandas-0.12.2-pyhd8ed1ab_0.conda - version: 0.12.2 + url: https://conda.anaconda.org/conda-forge/noarch/pooch-1.6.0-pyhd8ed1ab_0.tar.bz2 + version: 1.6.0 - category: main dependencies: google-auth: '>=2.14.1,<3.0dev' @@ -3115,6 +3092,28 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/noarch/google-auth-httplib2-0.1.0-pyhd8ed1ab_1.tar.bz2 version: 0.1.0 +- category: main + dependencies: + libblas: '>=3.9.0,<4.0a0' + libcblas: '>=3.9.0,<4.0a0' + libgcc-ng: '>=12' + libgfortran-ng: '' + libgfortran5: '>=11.3.0' + liblapack: '>=3.9.0,<4.0a0' + libstdcxx-ng: '>=12' + numpy: '>=1.21.6,<2.0a0' + pooch: '' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + hash: + md5: ef72eeddf5316330730b11907c6c07d8 + sha256: 6183ada76df21014cb7aefdc3f7c850b4324bfccf77b0268dde09801f35dc349 + manager: conda + name: scipy + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/scipy-1.10.0-py310h8deb116_0.conda + version: 1.10.0 - category: main dependencies: google-api-core: '>=1.31.5,<3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0' @@ -3124,14 +3123,14 @@ package: python: '>=3.7' uritemplate: '>=3.0.1,<5' hash: - md5: 04241ec803212136585c4e7738de8543 - sha256: 59d5c1e9afce9be9042900e10ffa804bbe68fb1331fed2ace5d15ce461f83b87 + md5: d25bf20710e2622edfd16f1580d6f406 + sha256: 9c2b34998b23486e9c9f8e35e18735247ca7b07f3b09e29a369b4ea8a658c807 manager: conda name: google-api-python-client optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/google-api-python-client-2.70.0-pyhd8ed1ab_0.conda - version: 2.70.0 + url: https://conda.anaconda.org/conda-forge/noarch/google-api-python-client-2.72.0-pyhd8ed1ab_0.conda + version: 2.72.0 - category: main dependencies: google-api-core: '>=1.31.6,<3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0' @@ -3149,32 +3148,24 @@ package: version: 2.3.2 - category: main dependencies: - affine: '>=2.3.1' - gdal: '>=3.5.3' - geopandas: '>=0.12.2' - geopy: '>=2.2.0' - loguru: '>=0.6.0' - netcdf4: '>=1.6.1' - numpy: 1.23.5 - pandas: '>=1.4.4' - pip: '>=22.3.1' - pyproj: '>=3.4.0' - pytest: '>=7.2.0' - pytest-cov: 4.0.0 - python: '>=3.9,<3.15' - rasterio: '>=1.3.0' - requests: '>=2.28.1' - rtree: '>=1.0.0' - shapely: '>=1.8.4,<2' + joblib: '>=1.1.1' + libcblas: '>=3.9.0,<4.0a0' + libgcc-ng: '>=12' + libstdcxx-ng: '>=12' + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + scipy: '' + threadpoolctl: '>=2.0.0' hash: - md5: 668898d4e01567089bdfd74242b43dc5 - sha256: 58f56ebc6bbc4af8ca5c8a02aad3bf976c116a2ec0460fb3642c4d5a8670216b + md5: 5a08a1f004445ee9bf58261feb16cc18 + sha256: 00733203bf459b9ca33b8c19ba7a57fca460aa266a6d98a5b111e8b199ed896d manager: conda - name: pyramids + name: scikit-learn optional: false platform: linux-64 - url: https://conda.anaconda.org/conda-forge/noarch/pyramids-0.2.10-pyhd8ed1ab_0.conda - version: 0.2.10 + url: https://conda.anaconda.org/conda-forge/linux-64/scikit-learn-1.2.0-py310h209a8ca_0.conda + version: 1.2.0 - category: main dependencies: google-api-core: '>=1.31.5,<3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0' @@ -3193,6 +3184,23 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/noarch/google-cloud-storage-2.7.0-pyh1a96a4e_0.conda version: 2.7.0 +- category: main + dependencies: + networkx: '' + numpy: '>=1.3' + pandas: '>=1.0' + python: '>=3.5' + scikit-learn: '' + scipy: '>=1.0' + hash: + md5: 2b0aace000c60c7a6de29907e3df4c6e + sha256: 76db2b87e74d94ff0ab64e9d5809d853f5f2735ee205e135b982a93bed72978d + manager: conda + name: mapclassify + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/noarch/mapclassify-2.5.0-pyhd8ed1ab_0.conda + version: 2.5.0 - category: main dependencies: future: '' @@ -3214,6 +3222,51 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/noarch/earthengine-api-0.1.334-pyhd8ed1ab_1.conda version: 0.1.334 +- category: main + dependencies: + fiona: '' + folium: '' + geopandas-base: 0.12.2 pyha770c72_0 + mapclassify: '>=2.4.0' + matplotlib-base: '' + python: '>=3.8' + rtree: '' + xyzservices: '' + hash: + md5: ee3b330f13297f5839d46e1ca3e57d56 + sha256: 51660094efee2a74b24ab535e03005a6ddedc9e160c0d573cfaf2724312d171c + manager: conda + name: geopandas + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/noarch/geopandas-0.12.2-pyhd8ed1ab_0.conda + version: 0.12.2 +- category: main + dependencies: + affine: '>=2.3.1' + gdal: '>=3.5.3' + geopandas: '>=0.12.2' + geopy: '>=2.2.0' + loguru: '>=0.6.0' + netcdf4: '>=1.6.1' + numpy: 1.24.1 + pandas: '>=1.4.4' + pip: '>=22.3.1' + pyproj: '>=3.4.0' + python: '>=3.9,<3.11' + rasterio: '>=1.3.0' + requests: '>=2.28.1' + rtree: '>=1.0.0' + shapely: '>=1.8.4,<2' + hash: + md5: fd315a429db61ecd8ac4ba1890bf5382 + sha256: 06d6813e56b80e1b4306c33fc252dcecd4c4647e704b4f7dc0d7a2c300fa7f1a + manager: conda + name: pyramids + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/noarch/pyramids-0.2.12-pyhd8ed1ab_0.conda + version: 0.2.12 - category: main dependencies: {} hash: @@ -3401,6 +3454,17 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/osx-64/libiconv-1.17-hac89ed1_0.tar.bz2 version: '1.17' +- category: main + dependencies: {} + hash: + md5: a8adc43e4b09be9c2ddbf89900956db2 + sha256: a4c086d223fc82160cee1667d0a2a7da8b65f78f5bcda444cb5627c2232c83e3 + manager: conda + name: libjpeg-turbo + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/libjpeg-turbo-2.1.4-hb7f2c08_0.tar.bz2 + version: 2.1.4 - category: main dependencies: {} hash: @@ -3426,14 +3490,14 @@ package: - category: main dependencies: {} hash: - md5: 3a900993deb973d86d98361ceef49ab3 - sha256: d8b65c6bd88a6508bc0ed3c03edfdf4c05d55024b2bf43dd5f61bec69f3bb87e + md5: 3faa9933dff6e96333b5ca5274674b63 + sha256: cc1586b43b757890b7d1cd24e1582345a36c40acd6cb6f9d9affb91de3c62015 manager: conda name: llvm-openmp optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-15.0.6-h61d9ccf_0.conda - version: 15.0.6 + url: https://conda.anaconda.org/conda-forge/osx-64/llvm-openmp-15.0.7-h61d9ccf_0.conda + version: 15.0.7 - category: main dependencies: {} hash: @@ -3481,14 +3545,14 @@ package: - category: main dependencies: {} hash: - md5: 5e0a069a585445333868d2c6651c3b3f - sha256: 145edb385d464227aca8ce963b9e22f5f36cacac9085eb38f574961ebc69684e + md5: 42da9b0138e911cd5b2f75b0278e26dc + sha256: 0a66852c47be6b28b70bde29891a71d047730c723355d44b0da48db79fb99eb1 manager: conda name: python_abi optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.11-3_cp311.conda - version: '3.11' + url: https://conda.anaconda.org/conda-forge/osx-64/python_abi-3.10-3_cp310.conda + version: '3.10' - category: main dependencies: {} hash: @@ -4039,19 +4103,19 @@ package: - category: main dependencies: c-ares: '>=1.18.1,<2.0a0' - libcxx: '>=13.0.1' + libcxx: '>=14.0.6' libev: '>=4.33,<4.34.0a0' - libzlib: '>=1.2.12,<1.3.0a0' - openssl: '>=3.0.5,<4.0a0' + libzlib: '>=1.2.13,<1.3.0a0' + openssl: '>=3.0.7,<4.0a0' hash: - md5: 19d5ae4be3e4b3cfa5696f3667e8c631 - sha256: 9e14d62e4462e6be28bcaa266f69e96ead43f4d7ef566e9cd460dbc9ae999daf + md5: 910e7f012beecf5d845a993feb9259a9 + sha256: 6400779ed8bfee36c35a66d52ec4e374651b07fb0e1cd1d0d1b9ef39f86a21c0 manager: conda name: libnghttp2 optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.47.0-h5aae05b_1.tar.bz2 - version: 1.47.0 + url: https://conda.anaconda.org/conda-forge/osx-64/libnghttp2-1.51.0-he2ab024_0.conda + version: 1.51.0 - category: main dependencies: geos: '>=3.11.1,<3.11.2.0a0' @@ -4089,14 +4153,14 @@ package: xz: '>=5.2.6,<6.0a0' zstd: '>=1.5.2,<1.6.0a0' hash: - md5: 551fc78ba147767ea5905d0746e2fbb5 - sha256: 7ccfb5aba44657875ff18d27654d84a5c7f6daf8cd840b5524359c7926b02e7a + md5: f32f9708c8d6f13e20a524c6da9a881e + sha256: 6659b6b71e79976e1bdd4b730a92425954e88cad6a184e274d6523d34d85f10e manager: conda name: libtiff optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.4.0-h6268bbc_5.conda - version: 4.4.0 + url: https://conda.anaconda.org/conda-forge/osx-64/libtiff-4.5.0-h6268bbc_0.conda + version: 4.5.0 - category: main dependencies: icu: '>=70.1,<71.0a0' @@ -4129,24 +4193,24 @@ package: - category: main dependencies: bzip2: '>=1.0.8,<2.0a0' - libffi: '>=3.4.2,<3.5.0a0' - libsqlite: '>=3.39.4,<4.0a0' + libffi: '>=3.4,<4.0a0' + libsqlite: '>=3.40.0,<4.0a0' libzlib: '>=1.2.13,<1.3.0a0' ncurses: '>=6.3,<7.0a0' - openssl: '>=3.0.5,<4.0a0' + openssl: '>=3.0.7,<4.0a0' readline: '>=8.1.2,<9.0a0' tk: '>=8.6.12,<8.7.0a0' tzdata: '' - xz: '>=5.2.6,<5.3.0a0' + xz: '>=5.2.6,<6.0a0' hash: - md5: 9eac7bb07be3725945c23c4ae90f9faa - sha256: 7e79e880eb097ce12cf09c26486d6e385fcc746aceb21c03270ed18a1b0b3423 + md5: 4b6976686db5f16650df28332d84ce9e + sha256: b001073de81761dc30848a55e92fd2eb4cb9fc60c2809afa0987c2a7d7f621f9 manager: conda name: python optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/python-3.11.0-h559f36b_0_cpython.tar.bz2 - version: 3.11.0 + url: https://conda.anaconda.org/conda-forge/osx-64/python-3.10.8-he7542f4_0_cpython.conda + version: 3.10.8 - category: main dependencies: libsqlite: 3.40.0 ha978bb4_0 @@ -4174,6 +4238,18 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/noarch/affine-2.3.1-pyhd8ed1ab_0.tar.bz2 version: 2.3.1 +- category: main + dependencies: + python: '' + hash: + md5: 5f095bc6454094e96f146491fd03633b + sha256: ae9fb8f68281f84482f2c234379aa12405a9e365151d43af20b3ae1f17312111 + manager: conda + name: appdirs + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/noarch/appdirs-1.4.4-pyh9f0ad1d_0.tar.bz2 + version: 1.4.4 - category: main dependencies: python: '>=3.5' @@ -4300,29 +4376,29 @@ package: version: 2.14.1 - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: e5a486c298f9283c7cee302b74ba69f1 - sha256: c52d5e372d6d51b9f90e2aad8fc57f4fc201a0d0efe0f2758c4a53d6a55d352d + md5: a3236ddc60f49384eba9348391293038 + sha256: 741b1c53ac1dcb24a5685e61a1c88638ab52ecfaf097acc8c250594045529cb7 manager: conda name: frozenlist optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/frozenlist-1.3.3-py311h5547dcb_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/frozenlist-1.3.3-py310h90acd4f_0.tar.bz2 version: 1.3.3 - category: main dependencies: python: '>=3.8' hash: - md5: a6966947ba28bbe60f9904653da7fed5 - sha256: 286667d325d52cd866a410da18da5660eb8bcde10dd6eae90403fa462152eff6 + md5: fec8329fc739090f26a7d7803db254f1 + sha256: b3d34bf4924cb80363c1ab57ac821393f118ffaa94f05368bf4044941163b65e manager: conda name: future optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/future-0.18.2-pyhd8ed1ab_6.tar.bz2 - version: 0.18.2 + url: https://conda.anaconda.org/conda-forge/noarch/future-0.18.3-pyhd8ed1ab_0.conda + version: 0.18.3 - category: main dependencies: python: '>=3.6' @@ -4349,42 +4425,42 @@ package: version: '3.4' - category: main dependencies: - python: '' + python: '>=3.7' hash: - md5: 39161f81cc5e5ca45b8226fbb06c6905 - sha256: 9423ded508ebda87dae21d7876134e406ffeb88e6059f3fe1a909d180c351959 + md5: f800d2da156d08e289b14e87e43c1ae5 + sha256: 38740c939b668b36a50ef455b077e8015b8c9cf89860d421b3fff86048f49666 manager: conda name: iniconfig optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-1.1.1-pyh9f0ad1d_0.tar.bz2 - version: 1.1.1 + url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + version: 2.0.0 - category: main dependencies: libcxx: '>=14.0.4' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 5219e72a43e53e8f6af4fdf76a0f90ef - sha256: 49f91463ed78c6f4e31ddd12a9fe46b4d8ea85a7480620c1a39fd64971764654 + md5: cc358fb878ac593c60cea08b28ac7423 + sha256: 6b48d27a14c68978d7bfd4e676a366db64264edd7d7bb5545e9c54aee2a8aea4 manager: conda name: kiwisolver optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/kiwisolver-1.4.4-py311hd2070f0_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/kiwisolver-1.4.4-py310ha23aa8a_1.tar.bz2 version: 1.4.4 - category: main dependencies: jpeg: '>=9e,<10a' - libtiff: '>=4.4.0,<4.5.0a0' + libtiff: '>=4.5.0,<4.6.0a0' hash: - md5: e56c432e9a78c63692fa6bd076a15713 - sha256: c9cc9f806ae1cdc40597d2415b8ffe9448db434f109133938968b371f16580b8 + md5: 1e42174021ffc69545f0814b9478dee3 + sha256: 64efad232b892c2511ba56bbd821e0b1e2e80a7a8ccf3524c20b5f964793ce43 manager: conda name: lcms2 optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.14-h90f4b2a_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/lcms2-2.14-h29502cd_1.conda version: '2.14' - category: main dependencies: @@ -4438,53 +4514,53 @@ package: libzlib: '>=1.2.13,<1.3.0a0' openssl: '>=3.0.7,<4.0a0' hash: - md5: 9607f99f5d54d0bf8b2168d000a1ffa8 - sha256: 07f86d8962975563ff54a42279a728dab94cbc89ceddccede6c73c91c65690cc + md5: 60c31c2382d8e2334b1903a5e47bd85e + sha256: 482c06384d8f1817e7893be0a24c93bd9a114c8af7724add768a922647756636 manager: conda name: libpq optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libpq-15.1-h3640bf0_2.conda + url: https://conda.anaconda.org/conda-forge/osx-64/libpq-15.1-h3640bf0_3.conda version: '15.1' - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: fc9dde292b3ec1251e63aac5434cc47c - sha256: f74d200ffa50c455fbe631ca6564fe5b80c64ab314ec832528cfcdfad2a119d7 + md5: ba4c7857f20ba7ffa2ec04080935dae1 + sha256: 0cf33413ae709aad99d43351b580920a0543953cbf896784bf081a7ccd8252d2 manager: conda name: loguru optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/loguru-0.6.0-py311h6eed73b_2.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/loguru-0.6.0-py310h2ec42d9_2.tar.bz2 version: 0.6.0 - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: cd912231195461aa21aa4e8f1eff1276 - sha256: fd58b34fafe163b21909d1a2337605b8d30a3beaf692cc13bb37ffc427e234a2 + md5: 232c20719e4290fa284ae1e9a4661dfa + sha256: 45aa996770bb49fdd6bc68e24b301932c2bb592522e3798f0c80e0206c352b8b manager: conda name: markupsafe optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-2.1.1-py311h5547dcb_2.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/markupsafe-2.1.1-py310h90acd4f_2.tar.bz2 version: 2.1.1 - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: be2cbd18582a4f608ce9ae5a9535f3f4 - sha256: 3cac12d900db540347aecf1ad19dd68a728af760885d825fd1dd3a58f1a4272d + md5: 0324181c4442d94c865cf9ae3b6a7fea + sha256: 27d1eed1ba91e6e7ea6221ef7abe020924ac4d7c55d98f40c7841aa492744696 manager: conda name: multidict optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/multidict-6.0.2-py311h5547dcb_2.tar.bz2 - version: 6.0.2 + url: https://conda.anaconda.org/conda-forge/osx-64/multidict-6.0.4-py310h90acd4f_0.conda + version: 6.0.4 - category: main dependencies: python: '' @@ -4501,14 +4577,14 @@ package: dependencies: python: '>=3.8' hash: - md5: bb45ff9deddb045331fd039949f39650 - sha256: a8e3531fdb6f9acfde885dd94c8639c020013215dab98ff4ed82db7aa745277a + md5: 88e40007414ea9a13f8df20fcffa87e2 + sha256: edd149a40ea746ce17c1b135c72a1646810e99071bedb7d808914cc31b3c8a5d manager: conda name: networkx optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/networkx-2.8.8-pyhd8ed1ab_0.tar.bz2 - version: 2.8.8 + url: https://conda.anaconda.org/conda-forge/noarch/networkx-3.0-pyhd8ed1ab_0.conda + version: '3.0' - category: main dependencies: libcxx: '>=13.0.1' @@ -4526,31 +4602,31 @@ package: version: '3.78' - category: main dependencies: - libcxx: '>=13.0.1' - libpng: '>=1.6.37,<1.7.0a0' - libtiff: '>=4.4.0,<4.5.0a0' - libzlib: '>=1.2.12,<1.3.0a0' + libcxx: '>=14.0.6' + libpng: '>=1.6.39,<1.7.0a0' + libtiff: '>=4.5.0,<4.6.0a0' + libzlib: '>=1.2.13,<1.3.0a0' hash: - md5: be533cc782981a0ec5eed28aa618470a - sha256: 8e8851daf6eabf553e0bdf7cbdd3011b86e579d742852d2d757389f97a463b45 + md5: 299a29af9ac9f550ad459d655739280b + sha256: 2375eafbd5241d8249fb467e2a8e190646e8798c33059c72efa60f197cdf4944 manager: conda name: openjpeg optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/openjpeg-2.5.0-h5d0d7b0_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/openjpeg-2.5.0-h13ac156_2.conda version: 2.5.0 - category: main dependencies: python: '>=3.7' hash: - md5: 0e8e1bd93998978fc3125522266d12db - sha256: 163f26e55246c506a75551ca01f35c7d4d533aee6db5c4cf2d598ae253e956b8 + md5: 1ff2e3ca41f0ce16afec7190db28288b + sha256: 00288f5e5e841711e8b8fef1f1242c858d8ef99ccbe5d7e0df4789d5d8d40645 manager: conda name: packaging optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/packaging-22.0-pyhd8ed1ab_0.conda - version: '22.0' + url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.0-pyhd8ed1ab_0.conda + version: '23.0' - category: main dependencies: python: '>=3.8' @@ -4614,16 +4690,16 @@ package: - category: main dependencies: libspatialindex: '>=1.9.3,<1.9.4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 976a24c2adba8bb6b8ac6f7341cd411f - sha256: d9351807650e13fe9e50e5f46aeacc91f1e445f4053bc191508f20b56677e552 + md5: 621e20dd837cb895f3bccaa7ade9e1dd + sha256: 556c17bb30b4eee6e31ad4fdb6ae0dcb08bb78e6e0dc3d782dd2f856156b6727 manager: conda name: rtree optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/rtree-1.0.1-py311hbc1f44b_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/rtree-1.0.1-py310had9ce37_1.tar.bz2 version: 1.0.1 - category: main dependencies: @@ -4697,6 +4773,19 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.4.0-pyha770c72_0.tar.bz2 version: 4.4.0 +- category: main + dependencies: + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + hash: + md5: b62adca3645b3bbc46940d5b1833d59b + sha256: 69e8397a2ee493eef2ccde8d5d877886a89be887111a6fc276fb27b6a86c4131 + manager: conda + name: unicodedata2 + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/unicodedata2-15.0.0-py310h90acd4f_0.tar.bz2 + version: 15.0.0 - category: main dependencies: python: '>=3.6' @@ -4783,16 +4872,16 @@ package: dependencies: libffi: '>=3.4,<4.0a0' pycparser: '' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 5967be4da33261eada7cc79593f71088 - sha256: 436a99652d9b13ed4b945f05740b50c79447b581aa400f69607f56c4960b806d + md5: 652082e4a6cf9d26e43d0d362590c276 + sha256: 67aa2bf58a98ed9e5bd693233f1de3cf7d499e9520dec7cbea0ee71e4d8f6895 manager: conda name: cffi optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.15.1-py311ha86e640_3.conda + url: https://conda.anaconda.org/conda-forge/osx-64/cffi-1.15.1-py310ha78151a_3.conda version: 1.15.1 - category: main dependencies: @@ -4826,18 +4915,18 @@ package: version: 8.1.3 - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 tomli: '' hash: - md5: d131fe03d67d3251e0a049a5d9e0ae89 - sha256: 917eb8209b581d6a9b348da1d573c0fe0b1ffd74d1999f76b80122e870d24998 + md5: 477e36c5ed6fa39c9b6641827e95b195 + sha256: ff82df5a9d63068036a4b1ee86e667bdcc054dc73f18dac08297d19fb40dc214 manager: conda name: coverage optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/coverage-7.0.1-py311h5547dcb_0.conda - version: 7.0.1 + url: https://conda.anaconda.org/conda-forge/osx-64/coverage-7.0.5-py310h90acd4f_0.conda + version: 7.0.5 - category: main dependencies: krb5: '>=1.20.1,<1.21.0a0' @@ -4858,16 +4947,17 @@ package: dependencies: brotli: '' munkres: '' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + unicodedata2: '>=14.0.0' hash: - md5: 6fc564da4dd28e360f4cfee7bee95cf9 - sha256: 3fe3708186d18f427b59e7c586c6df2e14d6513f4a0c6e55c8b87918c358ecdd + md5: 0b05af0a10ea3a8db1847bc0e389a335 + sha256: a6187c79801684a572250205279e3a80ea76bbf0b03e98a7fa5b02f279fd480b manager: conda name: fonttools optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/fonttools-4.38.0-py311h5547dcb_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/fonttools-4.38.0-py310h90acd4f_1.tar.bz2 version: 4.38.0 - category: main dependencies: @@ -4891,19 +4981,19 @@ package: libgrpc: 1.51.1 h966d1d5_0 libprotobuf: '>=3.21.10,<3.22.0a0' openssl: '>=3.0.7,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 re2: '>=2022.6.1,<2022.6.2.0a0' setuptools: '' six: '>=1.6.0' hash: - md5: 790faa3d4193ef8e13e4e860acfefb46 - sha256: 690a4e0cc3e51d2017f3bdd279f22f945fb61e4899c3c21ff7a501a578cfa900 + md5: 099a6f3151830c2541a02ca8a5937e9c + sha256: ab0ca7fdaa0bcd0ca5afcca11cca2e5d1f1f75703d92d42e37eacf35831b196e manager: conda name: grpcio optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/grpcio-1.51.1-py311h25756fb_0.conda + url: https://conda.anaconda.org/conda-forge/osx-64/grpcio-1.51.1-py310h0f91fd3_0.conda version: 1.51.1 - category: main dependencies: @@ -4991,25 +5081,25 @@ package: - category: main dependencies: freetype: '>=2.12.1,<3.0a0' - jpeg: '>=9e,<10a' - lcms2: '>=2.12,<3.0a0' - libtiff: '>=4.4.0,<4.5.0a0' + lcms2: '>=2.14,<3.0a0' + libjpeg-turbo: '>=2.1.4,<3.0a0' + libtiff: '>=4.5.0,<4.6.0a0' libwebp-base: '>=1.2.4,<2.0a0' libxcb: '>=1.13,<1.14.0a0' libzlib: '>=1.2.13,<1.3.0a0' openjpeg: '>=2.5.0,<3.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 tk: '>=8.6.12,<8.7.0a0' hash: - md5: 98a9590d51ca20ae722ae5f850ddc6ca - sha256: 3f21179f5cc5a5eaf5dea88e13ce341a8532bcfd5c9f9efd811a07f87bc27939 + md5: f8c80978311bcc1dbf75229280b7556f + sha256: d5ba77adcded9344e888f751327fb85e99a66f94197a498522ad8514b3c172f0 manager: conda name: pillow optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/pillow-9.2.0-py311he7df5c9_3.tar.bz2 - version: 9.2.0 + url: https://conda.anaconda.org/conda-forge/osx-64/pillow-9.4.0-py310hab5364c_0.conda + version: 9.4.0 - category: main dependencies: python: '>=3.7' @@ -5027,7 +5117,7 @@ package: - category: main dependencies: krb5: '>=1.20.1,<1.21.0a0' - libpq: 15.1 h3640bf0_2 + libpq: 15.1 h3640bf0_3 libxml2: '>=2.10.3,<2.11.0a0' libzlib: '>=1.2.13,<1.3.0a0' openssl: '>=3.0.7,<4.0a0' @@ -5036,45 +5126,45 @@ package: tzdata: '' zlib: '' hash: - md5: 92e70337e0fdfa816d2a958f307220d9 - sha256: 1e5932a4df047eeadcd0945cfec7586984fb251f3c8f11199df59f5bddbac305 + md5: ac3e012d910a8d9688a6a82aaf2be8ce + sha256: 838e89e47cd33175236b1cc2f3d3104aac9d14553f69812b6d4593febb8319fe manager: conda name: postgresql optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/postgresql-15.1-hbea33b9_2.conda + url: https://conda.anaconda.org/conda-forge/osx-64/postgresql-15.1-hbea33b9_3.conda version: '15.1' - category: main dependencies: - libcurl: '>=7.83.1,<8.0a0' - libcxx: '>=14.0.4' - libsqlite: '>=3.39.3,<4.0a0' - libtiff: '>=4.4.0,<4.5.0a0' - sqlite: '>=3.39.3,<4.0a0' + libcurl: '>=7.87.0,<8.0a0' + libcxx: '>=14.0.6' + libsqlite: '>=3.40.0,<4.0a0' + libtiff: '>=4.5.0,<4.6.0a0' + sqlite: '' hash: - md5: 78ee95e87e5143d0e4a17d4aeef56411 - sha256: 4858f8a83f8a139a8bd38b76e6ebc51ba29b0c1a868caedaf4ea78c3cb9c718f + md5: 74cc94166836b8280877374856bb2b3b + sha256: c113521b0709a42e2bad22ebdbe3bda59979ce847e57d981a247bb112dc18a5c manager: conda name: proj optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/proj-9.1.0-hcbd9701_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/proj-9.1.0-hf909084_1.conda version: 9.1.0 - category: main dependencies: libcxx: '>=14.0.6' libprotobuf: '>=3.21.12,<3.22.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '' hash: - md5: 33cd90a68de87b897dfaa8544ecfc13b - sha256: f10f90d5a214e3ddab6cd798a273c65e9bc042907e025387cfe2f751b558f073 + md5: 589cb650d197ab61a0cd54553e063c21 + sha256: 581905fcabea7ad9df50898b91b9c896909657d0ce6dc1198cac55a52496180a manager: conda name: protobuf optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/protobuf-4.21.12-py311h814d153_0.conda + url: https://conda.anaconda.org/conda-forge/osx-64/protobuf-4.21.12-py310h7a76584_0.conda version: 4.21.12 - category: main dependencies: @@ -5114,14 +5204,14 @@ package: python: '>=3.8' tomli: '>=1.0.0' hash: - md5: ac82c7aebc282e6ac0450fca012ca78c - sha256: 854233dc2d0d64219b7e951ccf49c1f32332c6fc7085ecb62cc18bc1f4e791b0 + md5: f0be05afc9c9ab45e273c088e00c258b + sha256: d298dfe6c53555c9fb5662f5f936e621cddd3b0a7031789375b82a1ee3b3a96b manager: conda name: pytest optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/pytest-7.2.0-pyhd8ed1ab_2.tar.bz2 - version: 7.2.0 + url: https://conda.anaconda.org/conda-forge/noarch/pytest-7.2.1-pyhd8ed1ab_0.conda + version: 7.2.1 - category: main dependencies: python: '>=3.6' @@ -5191,17 +5281,17 @@ package: dependencies: idna: '>=2.0' multidict: '>=4.0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: a93e7e1dfa3323e5d2f4372260b7a9b8 - sha256: 59026a628271d86cd694344e2f7a5de95132571106cbf20c7ad231d207bf1694 + md5: 9e18f6b25b97c6078299f6d2ad6c1d07 + sha256: dd8e0e47b4b49dd0e74a429b638c052d054f2e27c637a06f1996df83a585fbf2 manager: conda name: yarl optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.8.1-py311h5547dcb_0.tar.bz2 - version: 1.8.1 + url: https://conda.anaconda.org/conda-forge/osx-64/yarl-1.8.2-py310h90acd4f_0.conda + version: 1.8.2 - category: main dependencies: python: '>=3.6' @@ -5232,16 +5322,16 @@ package: - category: main dependencies: cffi: '>=1.0.0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 5f97ac938a90d06eebea42c321abe0d7 - sha256: a203fc8595377e74ba47ef8e11d77346a8ad7ca9d92833002a8fd12d050f82e5 + md5: 63accc45f2b9ae1dad4db9cdfaa903b4 + sha256: de6e5b17631ef35c6acaeec0ba0143d0e77e0970704f0a3e947a5d59364f3c4a manager: conda name: brotlipy optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/brotlipy-0.7.0-py311h5547dcb_1005.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/brotlipy-0.7.0-py310h90acd4f_1005.tar.bz2 version: 0.7.0 - category: main dependencies: @@ -5273,62 +5363,62 @@ package: dependencies: cffi: '>=1.12' openssl: '>=3.0.7,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: d7415ad7ae6c27050886ab2b583f09ca - sha256: f0d17382398baf5828814bea1cb713444f0111f9090f1a9e42182078c4c66708 + md5: fa9ffedc2323bfec787a09e798bb93b7 + sha256: f3dfda5cf3abcdd94d3d7a3b2a88ee4c5a7c22999d00f57f875d8182086b7b8d manager: conda name: cryptography optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/cryptography-38.0.4-py311h61927ef_0.conda - version: 38.0.4 + url: https://conda.anaconda.org/conda-forge/osx-64/cryptography-39.0.0-py310hdd0c95c_0.conda + version: 39.0.0 - category: main dependencies: jpeg: '>=9e,<10a' - libcxx: '>=14.0.4' - libtiff: '>=4.4.0,<4.5.0a0' - libzlib: '>=1.2.12,<1.3.0a0' - proj: '>=9.1.0,<9.1.1.0a0' - zlib: '>=1.2.12,<1.3.0a0' + libcxx: '>=14.0.6' + libtiff: '>=4.5.0,<4.6.0a0' + libzlib: '>=1.2.13,<1.3.0a0' + proj: '>=9.1.0,<9.1.1.0a0' + zlib: '' hash: - md5: 7fab5b9379958e9d3f784842c00c8e66 - sha256: 828e0b381c31c3d188e1be9c2fda16a13442ff5d2a2634672187a28e86fc99b0 + md5: 23d4ce30c13a7f5e40d20a5a725c24dc + sha256: 7031efc72ab2f2ae6aa193748b402578ac73d89e5361e0cf4496e781e39e794f manager: conda name: geotiff optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/geotiff-1.7.1-he29fd1c_4.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/geotiff-1.7.1-h2039a76_5.conda version: 1.7.1 - category: main dependencies: cffi: '>=1.0.0' libcrc32c: '>=1.1.2,<1.2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: bb5f5a212cb6dd44784f785ef56bf5ee - sha256: 26c5a7314e99ead2d0b0a1db9855d718f47d4cbb49b287b26321cb920d63e3e1 + md5: d3575d879b46a8452503ca08b997e782 + sha256: e25401934633b8052fca25dcaed719a524e110c23c3b88b44ba6cc6e94068f9f manager: conda name: google-crc32c optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/google-crc32c-1.1.2-py311h0669569_4.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/google-crc32c-1.1.2-py310h6f7428f_4.tar.bz2 version: 1.1.2 - category: main dependencies: protobuf: '>=3.19.5,<5.0.0dev,!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5' python: '>=3.7' hash: - md5: 35947a7b1f5319de636d74ce38dcf131 - sha256: 88c2be80b3c4ca97f5259b6c6a814b730e6ab4d09c15dbbe60df779c3a7416f9 + md5: cbf8b4569c1d2a0a6077d34a2d38333e + sha256: 1b2a9ae4540e3056a7eaf126a4939360f521854c8a4aa04f10ed4c80da4edc7e manager: conda name: googleapis-common-protos optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/googleapis-common-protos-1.57.0-pyhd8ed1ab_3.conda - version: 1.57.0 + url: https://conda.anaconda.org/conda-forge/noarch/googleapis-common-protos-1.57.1-pyhd8ed1ab_0.conda + version: 1.57.1 - category: main dependencies: hdf5: '>=1.12.2,<1.12.3.0a0' @@ -5423,34 +5513,34 @@ package: libglib: '>=2.74.1,<3.0a0' libiconv: '>=1.17,<2.0a0' libpng: '>=1.6.39,<1.7.0a0' - libtiff: '>=4.4.0,<4.5.0a0' + libtiff: '>=4.5.0,<4.6.0a0' libzlib: '>=1.2.13,<1.3.0a0' nss: '>=3.78,<4.0a0' openjpeg: '>=2.5.0,<3.0a0' poppler-data: '' hash: - md5: ad1c9f970971bc448424cff37c99eddd - sha256: be972dca85c1d79917451f5036062bcd8864b4ca3a1ae843f731933343bf2627 + md5: 1d8cbcffea2c5ac4b315b06e0d48cbf7 + sha256: 10976a5f0a272a7e244cbcc1ce28928bb0110190697dcacf6bfa0fc96ac82865 manager: conda name: poppler optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/poppler-22.12.0-hf2ff1a1_0.conda + url: https://conda.anaconda.org/conda-forge/osx-64/poppler-22.12.0-h6e9091c_1.conda version: 22.12.0 - category: main dependencies: certifi: '' proj: '>=9.1.0,<9.1.1.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 8de8df18195c511f46c492bfa5a9f95d - sha256: f9fa2385f739d6ef3d2c34716881927355fb24a20aeee624efef1785f30ca986 + md5: 8f348c1e0d172fcd371df80d399b4500 + sha256: 7834d254bd0bbe3cd7eb3ac8a5734a6875a6d66d14f6add555ddfadb150611f3 manager: conda name: pyproj optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/pyproj-3.4.1-py311h871f4d8_0.conda + url: https://conda.anaconda.org/conda-forge/osx-64/pyproj-3.4.1-py310h8c678d5_0.conda version: 3.4.1 - category: main dependencies: @@ -5478,14 +5568,14 @@ package: zlib: '' zstd: '>=1.5.2,<1.6.0a0' hash: - md5: 8518a3ed8dfc2ff49bc5eced01d697b0 - sha256: f852dadc0a128ca7f9e629aa95287c247c8886ada566965a04c2c1ea672676c4 + md5: a10738d4788cf6b0b0d9bff2e324b942 + sha256: 0165e3597571c80b5d50af7917a048ffe70e7419cd91caf4bf69999de5a0e01d manager: conda name: tiledb optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/tiledb-2.13.0-h8b9cbf0_1.conda - version: 2.13.0 + url: https://conda.anaconda.org/conda-forge/osx-64/tiledb-2.13.2-h8b9cbf0_0.conda + version: 2.13.2 - category: main dependencies: aiosignal: '>=1.1.2' @@ -5494,17 +5584,17 @@ package: charset-normalizer: '>=2.0,<3.0' frozenlist: '>=1.1.1' multidict: '>=4.5,<7.0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 yarl: '>=1.0,<2.0' hash: - md5: 6e1df9c459203338c189b7fa5a1baf62 - sha256: 810964698ea96410595be608d843bef7fa92a8e4f5c1b84570926653c0de0cdc + md5: e3c525d42afb960af60873738cb1e43f + sha256: 871717adf765b8239b08a01f9ddb92220fb6e59aea700474aa3eaf8c60b2cfb4 manager: conda name: aiohttp optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.8.3-py311h5547dcb_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/aiohttp-3.8.3-py310h90acd4f_1.tar.bz2 version: 3.8.3 - category: main dependencies: @@ -5535,7 +5625,7 @@ package: json-c: '>=0.16,<0.17.0a0' kealib: '>=1.5.0,<1.6.0a0' lerc: '>=4.0.0,<5.0a0' - libcurl: '>=7.86.0,<8.0a0' + libcurl: '>=7.87.0,<8.0a0' libcxx: '>=14.0.6' libdeflate: '>=1.14,<1.15.0a0' libiconv: '>=1.17,<2.0a0' @@ -5545,7 +5635,7 @@ package: libpq: '>=15.1,<16.0a0' libspatialite: '>=5.0.1,<5.1.0a0' libsqlite: '>=3.40.0,<4.0a0' - libtiff: '>=4.4.0,<4.5.0a0' + libtiff: '>=4.5.0,<4.6.0a0' libwebp-base: '>=1.2.4,<2.0a0' libxml2: '>=2.10.3,<2.11.0a0' libzlib: '>=1.2.13,<1.3.0a0' @@ -5556,147 +5646,127 @@ package: poppler: '>=22.12.0,<22.13.0a0' postgresql: '' proj: '>=9.1.0,<9.1.1.0a0' - tiledb: '>=2.13.0,<2.14.0a0' + tiledb: '>=2.13.1,<2.14.0a0' xerces-c: '>=3.2.4,<3.3.0a0' xz: '>=5.2.6,<6.0a0' zstd: '>=1.5.2,<1.6.0a0' hash: - md5: bffc5ff040901eca6ddb545e2b6e043a - sha256: 582f6ec058f57019240c38070c27cc46bb8ac98aca7f799443e2c543391c2301 + md5: 1eb9593ce19fa949f7c32cb289271e82 + sha256: 61d2094cc01664cedcf23ab34616802b63ed31d65c520815977c8999f4f27ee6 manager: conda name: libgdal optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/libgdal-3.6.1-hd928027_1.conda - version: 3.6.1 + url: https://conda.anaconda.org/conda-forge/osx-64/libgdal-3.6.2-h44a409f_1.conda + version: 3.6.2 - category: main dependencies: libblas: '>=3.9.0,<4.0a0' libcblas: '>=3.9.0,<4.0a0' libcxx: '>=14.0.6' liblapack: '>=3.9.0,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: e8c8aa5d60b4d22153c1f0fdb8b1bb22 - sha256: e391fa253b52e25a285af61ae7b92eeef1ce510af84d496e338a6039fdaf9984 + md5: d35dc7ae4b3c80385c749332869aad0b + sha256: c5afcb11dbabab94bb1d6c8d0ccf10ac0f59f5b6edd1e686e0e284373f503bd6 manager: conda name: numpy optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.23.5-py311h62c7003_0.conda - version: 1.23.5 + url: https://conda.anaconda.org/conda-forge/osx-64/numpy-1.24.1-py310h1b7c290_0.conda + version: 1.24.1 - category: main dependencies: - cryptography: '>=38.0.0,<39' + cryptography: '>=38.0.0,<40' python: '>=3.6' hash: - md5: fbfa0a180d48c800f922a10a114a8632 - sha256: 42f04dded77ac2597108378d62b121697d0e982aba7b20a462a7239030563628 + md5: d41957700e83bbb925928764cb7f8878 + sha256: adbf8951f22bfa950b9e24394df1ef1d2b2d7dfb194d91c7f42bc11900695785 manager: conda name: pyopenssl optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-22.1.0-pyhd8ed1ab_0.tar.bz2 - version: 22.1.0 + url: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-23.0.0-pyhd8ed1ab_0.conda + version: 23.0.0 - category: main dependencies: - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 4838daf28fad712f5ac12b025b236983 - sha256: b475f5fc4a6e13982eb7d278d4f524922d606ae3f4b53eaa0b7d17144ab7067d + md5: fcc07bec2f8577cc1a8009cef81f78ff + sha256: 42d23b93b93fdda51aa90601bb948c49a0e574f3eb974b3c3c825adb0343a33a manager: conda name: cftime optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/cftime-1.6.2-py311hd5badaa_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/cftime-1.6.2-py310h936d966_1.tar.bz2 version: 1.6.2 - category: main dependencies: - libcxx: '>=14.0.4' + libcxx: '>=14.0.6' numpy: '>=1.16' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 7aff06dca8dc89b96ba3b8caeb6dc2c9 - sha256: 2f36deb9b78b04b3c260d8623741822e155a07fabc5ab214125ebc8688d09696 + md5: bc714cc57ec6422105ed991167987a9d + sha256: 81cc479e4411d5833ed5798145c64490ccee6ad998c0712e57686d369ce90ba7 manager: conda name: contourpy optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/contourpy-1.0.6-py311hd2070f0_0.tar.bz2 - version: 1.0.6 + url: https://conda.anaconda.org/conda-forge/osx-64/contourpy-1.0.7-py310ha23aa8a_0.conda + version: 1.0.7 - category: main dependencies: hdf5: '>=1.12.2,<1.12.3.0a0' libcxx: '>=14.0.6' - libgdal: 3.6.1 hd928027_1 - numpy: '>=1.23.5,<2.0a0' + libgdal: 3.6.2 h44a409f_1 + numpy: '>=1.21.6,<2.0a0' openssl: '>=3.0.7,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 6faccb7211fc87b880c0b51681be300f - sha256: 66c6bb2eff596b739a560868f3ba9d79fa22a26f8a4591b3989efa901a3a1bb1 + md5: 16d96cc0855982325700c8623af85ffb + sha256: ddebc8a3f9ad251ed8acbfbf0db0cf4af93fdc1264ad5757d64baa586a783e86 manager: conda name: gdal optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/gdal-3.6.1-py311h619941e_1.conda - version: 3.6.1 + url: https://conda.anaconda.org/conda-forge/osx-64/gdal-3.6.2-py310h5abc6fc_1.conda + version: 3.6.2 - category: main dependencies: libcxx: '>=14.0.6' - numpy: '>=1.23.5,<2.0a0' - python: '>=3.11,<3.12.0a0' + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' python-dateutil: '>=2.8.1' - python_abi: 3.11.* *_cp311 + python_abi: 3.10.* *_cp310 pytz: '>=2020.1' hash: - md5: c061bfc7a65e7b7a1757d2476056acc3 - sha256: 0ef797ccda8deac8865af8c5ce41d56c8e7f6c62efe44dc2a72dbc6438a1ec13 + md5: fb9dfbad0d66781143a6342c64ab9057 + sha256: 12f2c805fdfffc35bf5c6ff48218a31b92651804ad747e6ce68d313c9ccdc3f0 manager: conda name: pandas optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/pandas-1.5.2-py311hd84f3f5_0.conda + url: https://conda.anaconda.org/conda-forge/osx-64/pandas-1.5.2-py310hecf8f37_2.conda version: 1.5.2 -- category: main - dependencies: - libblas: '>=3.9.0,<4.0a0' - libcblas: '>=3.9.0,<4.0a0' - libcxx: '>=14.0.4' - libgfortran: 5.* - libgfortran5: '>=11.3.0' - liblapack: '>=3.9.0,<4.0a0' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 - hash: - md5: ad8a377dabefbd942989ff55e3c97e16 - sha256: 3fc3929503c72c0787cd5d03990f93e4a340687eceb402100763351337a56051 - manager: conda - name: scipy - optional: false - platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.9.3-py311h939689b_2.tar.bz2 - version: 1.9.3 - category: main dependencies: geos: '>=3.11.1,<3.11.2.0a0' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: be807d8e0b5cf5ceb33404261be5ccb1 - sha256: ff27237df8206871058eaf316a581cf64918056a0d6428c7f4db28547295c478 + md5: 08ce2573d824243bcfc93ac076056c49 + sha256: 8b06369ae97d612734a56fc6f4e0eae4e45c2d2483a76a01fab02e7bb98d8940 manager: conda name: shapely optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/shapely-1.8.5-py311h781b04c_2.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/shapely-1.8.5-py310h4e43f2a_2.tar.bz2 version: 1.8.5 - category: main dependencies: @@ -5722,14 +5792,14 @@ package: pysocks: '>=1.5.6,<2.0,!=1.5.7' python: <4.0 hash: - md5: 3078ef2359efd6ecadbc7e085c5e0592 - sha256: 992f2d6ca50c98f865a4f2e4bada23f950e39f33ff7c64614a31ee152ec4d5ae + md5: 01f33ad2e0aaf6b5ba4add50dad5ad29 + sha256: f2f09c44e47946ce631dbc9a8a79bb463ac0f4122aaafdbcc51f200a1e420ca6 manager: conda name: urllib3 optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/urllib3-1.26.13-pyhd8ed1ab_0.conda - version: 1.26.13 + url: https://conda.anaconda.org/conda-forge/noarch/urllib3-1.26.14-pyhd8ed1ab_0.conda + version: 1.26.14 - category: main dependencies: attrs: '>=17' @@ -5740,20 +5810,20 @@ package: libcxx: '>=14.0.6' libgdal: '>=3.6.0,<3.7.0a0' munch: '' - numpy: '>=1.23.5,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '' shapely: '' six: '>=1.7' hash: - md5: 7688a338b431a838c3acfb85df78b674 - sha256: dd454751d2df5f963629d08b5cd2cd3235ee3ae92fc6ed93c38f8b31fcf6d37e + md5: 34ccda7a32fb6a71ba13228219fd43f1 + sha256: 1782c30d290460df39229f9bfc30c76aeab9d5581fa45d40ad287c54c738e817 manager: conda name: fiona optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/fiona-1.8.22-py311h9687163_5.conda + url: https://conda.anaconda.org/conda-forge/osx-64/fiona-1.8.22-py310h3963e5c_5.conda version: 1.8.22 - category: main dependencies: @@ -5781,21 +5851,21 @@ package: freetype: '>=2.12.1,<3.0a0' kiwisolver: '>=1.0.1' libcxx: '>=14.0.4' - numpy: '>=1.23.4,<2.0a0' + numpy: '>=1.21.6,<2.0a0' packaging: '>=20.0' pillow: '>=6.2.0' pyparsing: '>=2.3.1' - python: '>=3.11,<3.12.0a0' + python: '>=3.10,<3.11.0a0' python-dateutil: '>=2.7' - python_abi: 3.11.* *_cp311 + python_abi: 3.10.* *_cp310 hash: - md5: 23cef32adc676da209c6c4874f29523f - sha256: 483ba99be2611486634572784619642984f7a6e5bc7a91ed61ba33a89a72807a + md5: 08b09d49effc05e5b8f7645497d451b8 + sha256: 7ad8ebb5181465d18c0a14759f2a482cadf343ebf26c95f0e39de5fbc0e6e19c manager: conda name: matplotlib-base optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/matplotlib-base-3.6.2-py311h2bf763f_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/matplotlib-base-3.6.2-py310he725631_0.tar.bz2 version: 3.6.2 - category: main dependencies: @@ -5803,18 +5873,18 @@ package: hdf5: '>=1.12.2,<1.12.3.0a0' libnetcdf: '>=4.8.1,<4.8.2.0a0' libzlib: '>=1.2.13,<1.3.0a0' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '' hash: - md5: f3e261e09dad04deaa0d061622874d1b - sha256: 60a76b80d51ed1e90e14739523a348c3172b0466f8baa7313bbd3a4c8c6b2a46 + md5: b4c85ff4b6cc1de70a50093380fd2c8a + sha256: e6cecd56beef04eb3abe6b9e8753bf101317fe183bc5d7c1b019891b574b5bea manager: conda name: netcdf4 optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/netcdf4-1.6.2-nompi_py311h41bc3eb_100.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/netcdf4-1.6.2-nompi_py310h6892ea4_100.tar.bz2 version: 1.6.2 - category: main dependencies: @@ -5826,20 +5896,20 @@ package: cligj: '>=0.5' libcxx: '>=14.0.6' libgdal: '>=3.6.0,<3.7.0a0' - numpy: '>=1.23.4,<2.0a0' + numpy: '>=1.21.6,<2.0a0' proj: '>=9.1.0,<9.1.1.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '>=0.9.8' snuggs: '>=1.4.1' hash: - md5: f8e4fc1a22c7aac89c74bf8298a93a30 - sha256: f85f7138945a38dec1c341e99cb34a0725c533d66a9b5382cdd14e395a4a037e + md5: 7da5ee6dc29cb2f9e255de55a73a12d7 + sha256: b06161cd5de30c24194698b886ad699f7c0fec9f615f959ed3ab8cfdf831d158 manager: conda name: rasterio optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/rasterio-1.3.4-py311h5bc4c5e_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/osx-64/rasterio-1.3.4-py310h3600f62_0.tar.bz2 version: 1.3.4 - category: main dependencies: @@ -5857,26 +5927,6 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/noarch/requests-2.28.1-pyhd8ed1ab_1.tar.bz2 version: 2.28.1 -- category: main - dependencies: - joblib: '>=1.1.1' - libcblas: '>=3.9.0,<4.0a0' - libcxx: '>=14.0.6' - llvm-openmp: '>=14.0.6' - numpy: '>=1.23.5,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 - scipy: '' - threadpoolctl: '>=2.0.0' - hash: - md5: 971d7cc90e31178dbd34ef0f0309309a - sha256: 9f74c97983bf73d5a465c8fde0ebdd6a29c0b70ede323a24917fe85262123b62 - manager: conda - name: scikit-learn - optional: false - platform: osx-64 - url: https://conda.anaconda.org/conda-forge/osx-64/scikit-learn-1.2.0-py311h087fafe_0.conda - version: 1.2.0 - category: main dependencies: branca: '>=0.6.0' @@ -5915,40 +5965,19 @@ package: version: 2.15.0 - category: main dependencies: - networkx: '' - numpy: '>=1.3' - pandas: '>=1.0' - python: '>=3.5' - scikit-learn: '' - scipy: '>=1.0' - hash: - md5: 908bbfb54da154042c5cbda77b37a3d1 - sha256: 1435305fb0a127b3154e76c0836d44526eeb93e80bd37596128d7ad8fb196d97 - manager: conda - name: mapclassify - optional: false - platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/mapclassify-2.4.3-pyhd8ed1ab_0.tar.bz2 - version: 2.4.3 -- category: main - dependencies: - fiona: '' - folium: '' - geopandas-base: 0.12.2 pyha770c72_0 - mapclassify: '>=2.4.0' - matplotlib-base: '' - python: '>=3.8' - rtree: '' - xyzservices: '' + appdirs: '>=1.3.0' + packaging: '>=20.0' + python: '>=3.6' + requests: '>=2.19.0' hash: - md5: ee3b330f13297f5839d46e1ca3e57d56 - sha256: 51660094efee2a74b24ab535e03005a6ddedc9e160c0d573cfaf2724312d171c + md5: 6429e1d1091c51f626b5dcfdd38bf429 + sha256: 1f0548105de86fb2eb6fbb8d3d6cc2004079b8442d232258108687d6cc91eb73 manager: conda - name: geopandas + name: pooch optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/geopandas-0.12.2-pyhd8ed1ab_0.conda - version: 0.12.2 + url: https://conda.anaconda.org/conda-forge/noarch/pooch-1.6.0-pyhd8ed1ab_0.tar.bz2 + version: 1.6.0 - category: main dependencies: google-auth: '>=2.14.1,<3.0dev' @@ -5980,6 +6009,27 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/noarch/google-auth-httplib2-0.1.0-pyhd8ed1ab_1.tar.bz2 version: 0.1.0 +- category: main + dependencies: + libblas: '>=3.9.0,<4.0a0' + libcblas: '>=3.9.0,<4.0a0' + libcxx: '>=14.0.6' + libgfortran: 5.* + libgfortran5: '>=11.3.0' + liblapack: '>=3.9.0,<4.0a0' + numpy: '>=1.21.6,<2.0a0' + pooch: '' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + hash: + md5: 0f05f17c0326731072325ed0f98cc60a + sha256: e5d350b012fa9386f2eec27630ab68a96da44ffdec2d43c745dea2ac5efa5a85 + manager: conda + name: scipy + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/scipy-1.10.0-py310h240c617_0.conda + version: 1.10.0 - category: main dependencies: google-api-core: '>=1.31.5,<3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0' @@ -5989,14 +6039,14 @@ package: python: '>=3.7' uritemplate: '>=3.0.1,<5' hash: - md5: 04241ec803212136585c4e7738de8543 - sha256: 59d5c1e9afce9be9042900e10ffa804bbe68fb1331fed2ace5d15ce461f83b87 + md5: d25bf20710e2622edfd16f1580d6f406 + sha256: 9c2b34998b23486e9c9f8e35e18735247ca7b07f3b09e29a369b4ea8a658c807 manager: conda name: google-api-python-client optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/google-api-python-client-2.70.0-pyhd8ed1ab_0.conda - version: 2.70.0 + url: https://conda.anaconda.org/conda-forge/noarch/google-api-python-client-2.72.0-pyhd8ed1ab_0.conda + version: 2.72.0 - category: main dependencies: google-api-core: '>=1.31.6,<3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0' @@ -6014,32 +6064,24 @@ package: version: 2.3.2 - category: main dependencies: - affine: '>=2.3.1' - gdal: '>=3.5.3' - geopandas: '>=0.12.2' - geopy: '>=2.2.0' - loguru: '>=0.6.0' - netcdf4: '>=1.6.1' - numpy: 1.23.5 - pandas: '>=1.4.4' - pip: '>=22.3.1' - pyproj: '>=3.4.0' - pytest: '>=7.2.0' - pytest-cov: 4.0.0 - python: '>=3.9,<3.15' - rasterio: '>=1.3.0' - requests: '>=2.28.1' - rtree: '>=1.0.0' - shapely: '>=1.8.4,<2' + joblib: '>=1.1.1' + libcblas: '>=3.9.0,<4.0a0' + libcxx: '>=14.0.6' + llvm-openmp: '>=14.0.6' + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + scipy: '' + threadpoolctl: '>=2.0.0' hash: - md5: 668898d4e01567089bdfd74242b43dc5 - sha256: 58f56ebc6bbc4af8ca5c8a02aad3bf976c116a2ec0460fb3642c4d5a8670216b + md5: 0bf9a20847233ba57ea31cba1d115696 + sha256: 6433f1b35613f02cfaad95df05e8eff69f31ca581897715a3685e5fdd8c2a19a manager: conda - name: pyramids + name: scikit-learn optional: false platform: osx-64 - url: https://conda.anaconda.org/conda-forge/noarch/pyramids-0.2.10-pyhd8ed1ab_0.conda - version: 0.2.10 + url: https://conda.anaconda.org/conda-forge/osx-64/scikit-learn-1.2.0-py310hcebe997_0.conda + version: 1.2.0 - category: main dependencies: google-api-core: '>=1.31.5,<3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0' @@ -6058,6 +6100,23 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/noarch/google-cloud-storage-2.7.0-pyh1a96a4e_0.conda version: 2.7.0 +- category: main + dependencies: + networkx: '' + numpy: '>=1.3' + pandas: '>=1.0' + python: '>=3.5' + scikit-learn: '' + scipy: '>=1.0' + hash: + md5: 2b0aace000c60c7a6de29907e3df4c6e + sha256: 76db2b87e74d94ff0ab64e9d5809d853f5f2735ee205e135b982a93bed72978d + manager: conda + name: mapclassify + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/noarch/mapclassify-2.5.0-pyhd8ed1ab_0.conda + version: 2.5.0 - category: main dependencies: future: '' @@ -6079,6 +6138,51 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/noarch/earthengine-api-0.1.334-pyhd8ed1ab_1.conda version: 0.1.334 +- category: main + dependencies: + fiona: '' + folium: '' + geopandas-base: 0.12.2 pyha770c72_0 + mapclassify: '>=2.4.0' + matplotlib-base: '' + python: '>=3.8' + rtree: '' + xyzservices: '' + hash: + md5: ee3b330f13297f5839d46e1ca3e57d56 + sha256: 51660094efee2a74b24ab535e03005a6ddedc9e160c0d573cfaf2724312d171c + manager: conda + name: geopandas + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/noarch/geopandas-0.12.2-pyhd8ed1ab_0.conda + version: 0.12.2 +- category: main + dependencies: + affine: '>=2.3.1' + gdal: '>=3.5.3' + geopandas: '>=0.12.2' + geopy: '>=2.2.0' + loguru: '>=0.6.0' + netcdf4: '>=1.6.1' + numpy: 1.24.1 + pandas: '>=1.4.4' + pip: '>=22.3.1' + pyproj: '>=3.4.0' + python: '>=3.9,<3.11' + rasterio: '>=1.3.0' + requests: '>=2.28.1' + rtree: '>=1.0.0' + shapely: '>=1.8.4,<2' + hash: + md5: fd315a429db61ecd8ac4ba1890bf5382 + sha256: 06d6813e56b80e1b4306c33fc252dcecd4c4647e704b4f7dc0d7a2c300fa7f1a + manager: conda + name: pyramids + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/noarch/pyramids-0.2.12-pyhd8ed1ab_0.conda + version: 0.2.12 - category: main dependencies: {} hash: @@ -6170,14 +6274,14 @@ package: - category: main dependencies: {} hash: - md5: fd1634ba85cfea9376e1fc02d6f592e9 - sha256: e042841d13274354d651a69a4f2589e9b46fd23b416368c9821bf3c6676f19d7 + md5: f4cfd883c0d91bb17164d8e34f4900d5 + sha256: 8212c6f1a68d5a494bcde5cd64196626024059dcbe8995469c8a5ed32694efa0 manager: conda name: python_abi optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.11-3_cp311.conda - version: '3.11' + url: https://conda.anaconda.org/conda-forge/win-64/python_abi-3.10-3_cp310.conda + version: '3.10' - category: main dependencies: {} hash: @@ -6243,14 +6347,14 @@ package: dependencies: ucrt: '>=10.0.20348.0' hash: - md5: c98b6e39006315599b793592bcc3c978 - sha256: 6b6feb349d3414655c2f9c549092689e5f99b487ff7ed9c1f1fda69a5dd4a624 + md5: 25640086ba777e79e5d233d079d7c5fc + sha256: 3a23d4c98bdb87b06bd8af9e42eea34c39a9da52c3dd96ace706234c55422f2d manager: conda name: vs2015_runtime optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.32.31332-h1d6e394_9.tar.bz2 - version: 14.32.31332 + url: https://conda.anaconda.org/conda-forge/win-64/vs2015_runtime-14.34.31931-h4c5c07a_10.conda + version: 14.34.31931 - category: main dependencies: fonts-conda-forge: '' @@ -6279,15 +6383,15 @@ package: version: 5.3.0 - category: main dependencies: - vs2015_runtime: '>=14.32.31332' + vs2015_runtime: '>=14.34.31931' hash: - md5: ba28983ef4f6d430827d0e7c5cdd7b48 - sha256: 1ca9e60e4e977be81dbee0ed236c6fb0a459c32957d2c2dc45a114d83f4c70d6 + md5: 52d246d8d14b83c516229be5bb03a163 + sha256: 05d5ae5859e8d097559f5445ffbaeac638c9875e4d2a0c5fd8c4bb1c010d35c1 manager: conda name: vc optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-h3d8a991_9.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/vc-14.3-hb6edc58_10.conda version: '14.3' - category: main dependencies: @@ -6475,6 +6579,19 @@ package: platform: win-64 url: https://conda.anaconda.org/conda-forge/win-64/libiconv-1.17-h8ffe710_0.tar.bz2 version: '1.17' +- category: main + dependencies: + vc: '>=14.2,<15' + vs2015_runtime: '>=14.29.30139' + hash: + md5: 24bf30c2957c1bf33b3e1131a88ae17d + sha256: ed081ab5e51b516723f30b49a84f1b5bb201d46d6da58de0ab435df3f01d4eb0 + manager: conda + name: libjpeg-turbo + optional: false + platform: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/libjpeg-turbo-2.1.4-hcfcfb64_0.tar.bz2 + version: 2.1.4 - category: main dependencies: vc: '>=14.1,<15.0a0' @@ -6860,24 +6977,24 @@ package: - category: main dependencies: bzip2: '>=1.0.8,<2.0a0' - libffi: '>=3.4.2,<3.5.0a0' - libsqlite: '>=3.39.4,<4.0a0' + libffi: '>=3.4,<4.0a0' + libsqlite: '>=3.40.0,<4.0a0' libzlib: '>=1.2.13,<1.3.0a0' - openssl: '>=3.0.5,<4.0a0' + openssl: '>=3.0.7,<4.0a0' tk: '>=8.6.12,<8.7.0a0' tzdata: '' vc: '>=14.1,<15' vs2015_runtime: '>=14.16.27033' - xz: '>=5.2.6,<5.3.0a0' + xz: '>=5.2.6,<6.0a0' hash: - md5: 13ee3577afc291dabd2d9edc59736688 - sha256: 20d1f1b5dc620b745c325844545fd5c0cdbfdb2385a0e27ef1507399844c8c6d + md5: 6a74ef0e5662397929214f2fb04c7d19 + sha256: 7c05da8180e62ebdf6e5af72fd1605df79395b11b0d0653788b828f6e1a6649e manager: conda name: python optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/python-3.11.0-hcf16a7b_0_cpython.tar.bz2 - version: 3.11.0 + url: https://conda.anaconda.org/conda-forge/win-64/python-3.10.8-h4de0772_0_cpython.conda + version: 3.10.8 - category: main dependencies: libsqlite: 3.40.0 hcfcfb64_0 @@ -6935,6 +7052,18 @@ package: platform: win-64 url: https://conda.anaconda.org/conda-forge/noarch/affine-2.3.1-pyhd8ed1ab_0.tar.bz2 version: 2.3.1 +- category: main + dependencies: + python: '' + hash: + md5: 5f095bc6454094e96f146491fd03633b + sha256: ae9fb8f68281f84482f2c234379aa12405a9e365151d43af20b3ae1f17312111 + manager: conda + name: appdirs + optional: false + platform: win-64 + url: https://conda.anaconda.org/conda-forge/noarch/appdirs-1.4.4-pyh9f0ad1d_0.tar.bz2 + version: 1.4.4 - category: main dependencies: python: '>=3.5' @@ -7098,32 +7227,32 @@ package: version: 2.12.1 - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: e4cc8c6ea80d6cf4e81e5050e6006536 - sha256: e9b4aa1fc3e09e669d06fccdfb0c80c0c1d8b3faf4599496c35fa0a88b388287 + md5: 550271ca005a4c805cd7391cef008dc6 + sha256: 1f88ceb482479902152030eaaa0a20e558d365e2968a94674770a7e8ff87486e manager: conda name: frozenlist optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/frozenlist-1.3.3-py311ha68e1ae_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/frozenlist-1.3.3-py310h8d17308_0.tar.bz2 version: 1.3.3 - category: main dependencies: python: '>=3.8' hash: - md5: a6966947ba28bbe60f9904653da7fed5 - sha256: 286667d325d52cd866a410da18da5660eb8bcde10dd6eae90403fa462152eff6 + md5: fec8329fc739090f26a7d7803db254f1 + sha256: b3d34bf4924cb80363c1ab57ac821393f118ffaa94f05368bf4044941163b65e manager: conda name: future optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/future-0.18.2-pyhd8ed1ab_6.tar.bz2 - version: 0.18.2 + url: https://conda.anaconda.org/conda-forge/noarch/future-0.18.3-pyhd8ed1ab_0.conda + version: 0.18.3 - category: main dependencies: python: '>=3.6' @@ -7167,31 +7296,31 @@ package: version: '3.4' - category: main dependencies: - python: '' + python: '>=3.7' hash: - md5: 39161f81cc5e5ca45b8226fbb06c6905 - sha256: 9423ded508ebda87dae21d7876134e406ffeb88e6059f3fe1a909d180c351959 + md5: f800d2da156d08e289b14e87e43c1ae5 + sha256: 38740c939b668b36a50ef455b077e8015b8c9cf89860d421b3fff86048f49666 manager: conda name: iniconfig optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-1.1.1-pyh9f0ad1d_0.tar.bz2 - version: 1.1.1 + url: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_0.conda + version: 2.0.0 - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 564530d9dd01d102b5ec76c34381f3b7 - sha256: 08cb19253d863d311f4b2d6f30a0a770ab0ce6365b238f3c5272c1fc6f6d5e5c + md5: c55fe943d5f212d49d27d08580f5a610 + sha256: 6e927eab8b735c7fcbd52dff8b7ecf9f98b9221cf0d21f8491f2aeaf5bcc49f3 manager: conda name: kiwisolver optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/kiwisolver-1.4.4-py311h005e61a_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/kiwisolver-1.4.4-py310h232114e_1.tar.bz2 version: 1.4.4 - category: main dependencies: @@ -7274,13 +7403,13 @@ package: vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: f8d4199ae61ff1648ab0477aef3a7030 - sha256: 5b05658f836a6700442b523119f899ac8386e67226caa09a6b3a0714d5e8fe70 + md5: df733c6a37616fc0adc225795ea80423 + sha256: b74030343e1d97666bcf55fdb97308fe30c2137b6517dda3b164fb2172869685 manager: conda name: libpq optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libpq-15.1-ha9684e8_2.conda + url: https://conda.anaconda.org/conda-forge/win-64/libpq-15.1-ha9684e8_3.conda version: '15.1' - category: main dependencies: @@ -7294,46 +7423,46 @@ package: xz: '>=5.2.6,<6.0a0' zstd: '>=1.5.2,<1.6.0a0' hash: - md5: fe00c2f95c1215e355c34094b00480d7 - sha256: dfa7f848f1e4bb24ed800968984638b2353728c439e4964f597aa9f31733370b + md5: d9b568beb74c97e53dbb9531b14f69c0 + sha256: dc13f42b392e05a1e705ceebcde82ed3e15663b511e78585d26fc4b9bf628b59 manager: conda name: libtiff optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libtiff-4.4.0-hc4f729c_5.conda - version: 4.4.0 + url: https://conda.anaconda.org/conda-forge/win-64/libtiff-4.5.0-hc4f729c_0.conda + version: 4.5.0 - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: d782a70b46000ea9a3c5c69c5fe0f767 - sha256: 957d424fda3b8da3d51d7252c2444e6bdf448df74e4b66611cd52cc6dc8fff9d + md5: 24e57be449c71b8edc52cc6a48ff846d + sha256: 76576c5fd2a6ad1e987b3df4bba55dab05c0f4f35e4f54c6ddbb9559aaf01537 manager: conda name: markupsafe optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.1-py311ha68e1ae_2.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/markupsafe-2.1.1-py310h8d17308_2.tar.bz2 version: 2.1.1 - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 179ecfa9dc80f41a059bbbe4c430c498 - sha256: 1d7c0a8948ec6a42da64490ea03f3292cb5cf53533fc78d881220bea0269f580 + md5: 23a55d74d8f91c7667555b81030034bf + sha256: 564e7e984814863a8f9fa31acbc50706dfe67d4e8601b3e74e4003a9c6ceba14 manager: conda name: multidict optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/multidict-6.0.2-py311ha68e1ae_2.tar.bz2 - version: 6.0.2 + url: https://conda.anaconda.org/conda-forge/win-64/multidict-6.0.4-py310h8d17308_0.conda + version: 6.0.4 - category: main dependencies: python: '' @@ -7350,26 +7479,26 @@ package: dependencies: python: '>=3.8' hash: - md5: bb45ff9deddb045331fd039949f39650 - sha256: a8e3531fdb6f9acfde885dd94c8639c020013215dab98ff4ed82db7aa745277a + md5: 88e40007414ea9a13f8df20fcffa87e2 + sha256: edd149a40ea746ce17c1b135c72a1646810e99071bedb7d808914cc31b3c8a5d manager: conda name: networkx optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/networkx-2.8.8-pyhd8ed1ab_0.tar.bz2 - version: 2.8.8 + url: https://conda.anaconda.org/conda-forge/noarch/networkx-3.0-pyhd8ed1ab_0.conda + version: '3.0' - category: main dependencies: python: '>=3.7' hash: - md5: 0e8e1bd93998978fc3125522266d12db - sha256: 163f26e55246c506a75551ca01f35c7d4d533aee6db5c4cf2d598ae253e956b8 + md5: 1ff2e3ca41f0ce16afec7190db28288b + sha256: 00288f5e5e841711e8b8fef1f1242c858d8ef99ccbe5d7e0df4789d5d8d40645 manager: conda name: packaging optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/packaging-22.0-pyhd8ed1ab_0.conda - version: '22.0' + url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.0-pyhd8ed1ab_0.conda + version: '23.0' - category: main dependencies: python: '>=3.8' @@ -7445,16 +7574,16 @@ package: - category: main dependencies: libspatialindex: '>=1.9.3,<1.9.4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 hash: - md5: 5196f6012592bfcfabc7d1c4bb5447a6 - sha256: 94d6733e10d3909a11aadfd04994729b50a7886c3a074145829dac4f6e191655 + md5: da35b972cbb9b41a4a73db959b810ad8 + sha256: 1b79e0198b44363959d3cb0127b88fa15004f3ac1db046bf854041f4155b536c manager: conda name: rtree optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/rtree-1.0.1-py311hcacb13a_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/rtree-1.0.1-py310h1cbd46b_1.tar.bz2 version: 1.0.1 - category: main dependencies: @@ -7528,6 +7657,22 @@ package: platform: win-64 url: https://conda.anaconda.org/conda-forge/noarch/typing_extensions-4.4.0-pyha770c72_0.tar.bz2 version: 4.4.0 +- category: main + dependencies: + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + ucrt: '>=10.0.20348.0' + vc: '>=14.2,<15' + vs2015_runtime: '>=14.29.30139' + hash: + md5: 5d14ba562f7740b64be9c8059498cfbf + sha256: 4b93fa5ecf66df2c8558c224bb7404d9fd73e956c3c5db059fb01c1e4bd61ffa + manager: conda + name: unicodedata2 + optional: false + platform: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/unicodedata2-15.0.0-py310h8d17308_0.tar.bz2 + version: 15.0.0 - category: main dependencies: python: '>=3.6' @@ -7646,19 +7791,19 @@ package: - category: main dependencies: pycparser: '' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: a8524727eb956b4741e25a64af79edb8 - sha256: 49ce08187365f97c67476d504411de0a17e69b972ab6b80521d01dc80dd657e6 + md5: b7ca236d34501eb6a70691c1e29a0234 + sha256: 53c4ef7d7c3e7487a700c89a28a3afbbdb38fe2efa61ba8157fbb69f0b9d5297 manager: conda name: cffi optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/cffi-1.15.1-py311h7d9ee11_3.conda + url: https://conda.anaconda.org/conda-forge/win-64/cffi-1.15.1-py310h628cb3f_3.conda version: 1.15.1 - category: main dependencies: @@ -7692,21 +7837,21 @@ package: version: 8.1.3 - category: main dependencies: - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 tomli: '' ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 11f200264d2b55fa2059aeecf72532da - sha256: 659d0e635da32fe0381826493817ea670aa7b910d94899736a19ab81ddecc868 + md5: bde65cf0a55cd33d535db1c2f2dbcaba + sha256: 3409d63b42b613038425b147260bf83b086972094c428f8c49b42decd6f4ce93 manager: conda name: coverage optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/coverage-7.0.1-py311ha68e1ae_0.conda - version: 7.0.1 + url: https://conda.anaconda.org/conda-forge/win-64/coverage-7.0.5-py310h8d17308_0.conda + version: 7.0.5 - category: main dependencies: krb5: '>=1.20.1,<1.21.0a0' @@ -7763,8 +7908,8 @@ package: libgrpc: 1.51.1 h6a6baca_0 libprotobuf: '>=3.21.10,<3.22.0a0' openssl: '>=3.0.7,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 re2: '>=2022.6.1,<2022.6.2.0a0' setuptools: '' six: '>=1.6.0' @@ -7772,13 +7917,13 @@ package: vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: bf6a0cc83273aa8a2696cdde5d517a5c - sha256: f8f39b56d4f58b7b97a71db4db5fe1dba112eeccce8cf2baf308fe54025bd8fd + md5: 7fe1e75b4b1bdcd6e869c356a735282c + sha256: f3d20f82f66ecd4e4940989b7a5f7fa1680075c783e9eaa1a8a7566fde6e9970 manager: conda name: grpcio optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/grpcio-1.51.1-py311hd5dd9ae_0.conda + url: https://conda.anaconda.org/conda-forge/win-64/grpcio-1.51.1-py310hf1f0be2_0.conda version: 1.51.1 - category: main dependencies: @@ -7839,18 +7984,18 @@ package: - category: main dependencies: jpeg: '>=9e,<10a' - libtiff: '>=4.4.0,<4.5.0a0' + libtiff: '>=4.5.0,<4.6.0a0' ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: a0deec92aa16fca7bf5a6717d05f88ee - sha256: 1e79c0c2ca28f00d2b171655ced23baf630aa87eca550ded775311c6dac04758 + md5: 135bd65be6768b2bc84e864e7141ab77 + sha256: 1827f99e49a66092b910a936df9f573bdd40ee8b79879032b0cb795d827e4877 manager: conda name: lcms2 optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/lcms2-2.14-h90d422f_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/lcms2-2.14-ha5c8aab_1.conda version: '2.14' - category: main dependencies: @@ -7887,17 +8032,17 @@ package: - category: main dependencies: colorama: '>=0.3.4' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 win32_setctime: '>=1.0.0' hash: - md5: 58ea91f88271092a08142ccd28208755 - sha256: f26456b7e3e08701b03b7729fa0a4b822240204cf383970215e61c819ea6bf13 + md5: 2082abb28ee725fd153833b6dbd0af38 + sha256: 328fc30578f2577277d5463e0bd8fb0e2a08986a5136b0a0a6092ad3dbfe9939 manager: conda name: loguru optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/loguru-0.6.0-py311h1ea47a8_2.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/loguru-0.6.0-py310h5588dad_2.tar.bz2 version: 0.6.0 - category: main dependencies: @@ -7915,19 +8060,20 @@ package: version: 2.5.0 - category: main dependencies: - libpng: '>=1.6.37,<1.7.0a0' - libtiff: '>=4.4.0,<4.5.0a0' - libzlib: '>=1.2.12,<1.3.0a0' - vc: '>=14.1,<15' - vs2015_runtime: '>=14.16.27033' + libpng: '>=1.6.39,<1.7.0a0' + libtiff: '>=4.5.0,<4.6.0a0' + libzlib: '>=1.2.13,<1.3.0a0' + ucrt: '>=10.0.20348.0' + vc: '>=14.2,<15' + vs2015_runtime: '>=14.29.30139' hash: - md5: a6834096f8d834339eca7ef4d23bcc44 - sha256: 20bca4de8475314dc20561435ca0f6186d03502ff9914ac27be69826885dde48 + md5: db0490689232e8e38c312281df6f31a2 + sha256: 1fb72db47e9b1cdb4980a1fd031e31fad2c6a4a632fc602e7d6fa74f4f491608 manager: conda name: openjpeg optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/openjpeg-2.5.0-hc9384bd_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/openjpeg-2.5.0-ha2aaf27_2.conda version: 2.5.0 - category: main dependencies: @@ -7946,7 +8092,7 @@ package: - category: main dependencies: krb5: '>=1.20.1,<1.21.0a0' - libpq: 15.1 ha9684e8_2 + libpq: 15.1 ha9684e8_3 libxml2: '>=2.10.3,<2.11.0a0' libzlib: '>=1.2.13,<1.3.0a0' openssl: '>=3.0.7,<4.0a0' @@ -7955,48 +8101,49 @@ package: vs2015_runtime: '>=14.29.30139' zlib: '' hash: - md5: 4a23e94d7ce726009beee93eddeba8ce - sha256: 3d5d960e0b54525c581ad30bcd6d0e68fe35868410b48bcbeeef938ba3be5393 + md5: 9e0c79de1528d73b4014e943ce342ab9 + sha256: c4cb0004287bb7032a8a7d6f8b2d19a4c93eddf79d224317169ca2e674d5a592 manager: conda name: postgresql optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/postgresql-15.1-hd87cd2b_2.conda + url: https://conda.anaconda.org/conda-forge/win-64/postgresql-15.1-hd87cd2b_3.conda version: '15.1' - category: main dependencies: - libcurl: '>=7.83.1,<8.0a0' - libsqlite: '>=3.39.3,<4.0a0' - libtiff: '>=4.4.0,<4.5.0a0' - sqlite: '>=3.39.3,<4.0a0' + libcurl: '>=7.87.0,<8.0a0' + libsqlite: '>=3.40.0,<4.0a0' + libtiff: '>=4.5.0,<4.6.0a0' + sqlite: '' + ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 40201019efe10a1373387506cffa8cb1 - sha256: 6b55081c4f422832d432d453cdde60570909b127b03e512568bb601ac304863d + md5: e7e92c4949982e63def48dc2ee6cbb59 + sha256: a8fe4fd0f8a9fe0e595f2185e3e4d42d6b272c0cfa8ebdb2fbab9f71143bf52c manager: conda name: proj optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/proj-9.1.0-h3863b3b_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/proj-9.1.0-heca977f_1.conda version: 9.1.0 - category: main dependencies: libprotobuf: 3.21.12.* - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '' ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: c01e81ea74ec35cf823ed5499743f372 - sha256: c6f56cb762b7a94b6dd24c5bf10d3a552bfb24a41a8961b4455d9bccb90f2f9f + md5: bc7af38de2d06a42df22de09b94eea75 + sha256: bfecaf7cfd6ad569b583ff9d1e9223f26eb4946702c2623f95ad9a413fa85402 manager: conda name: protobuf optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/protobuf-4.21.12-py311h12c1d0e_0.conda + url: https://conda.anaconda.org/conda-forge/win-64/protobuf-4.21.12-py310h00ffb61_0.conda version: 4.21.12 - category: main dependencies: @@ -8036,14 +8183,14 @@ package: python: '>=3.8' tomli: '>=1.0.0' hash: - md5: ac82c7aebc282e6ac0450fca012ca78c - sha256: 854233dc2d0d64219b7e951ccf49c1f32332c6fc7085ecb62cc18bc1f4e791b0 + md5: f0be05afc9c9ab45e273c088e00c258b + sha256: d298dfe6c53555c9fb5662f5f936e621cddd3b0a7031789375b82a1ee3b3a96b manager: conda name: pytest optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/pytest-7.2.0-pyhd8ed1ab_2.tar.bz2 - version: 7.2.0 + url: https://conda.anaconda.org/conda-forge/noarch/pytest-7.2.1-pyhd8ed1ab_0.conda + version: 7.2.1 - category: main dependencies: python: '>=3.6' @@ -8114,20 +8261,20 @@ package: dependencies: idna: '>=2.0' multidict: '>=4.0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: f4424979a70722f451fcefe9261af7f6 - sha256: 6457b0e3774d92605166b637356a408f62243b339e2ae6082cf1d124db31dc22 + md5: ca778392f9e76350e1bd0914823baeb5 + sha256: 8b30e998186b7fa1deccea70883aa309c54df154823ddb4e76d8635d647de1f8 manager: conda name: yarl optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/yarl-1.8.1-py311ha68e1ae_0.tar.bz2 - version: 1.8.1 + url: https://conda.anaconda.org/conda-forge/win-64/yarl-1.8.2-py310h8d17308_0.conda + version: 1.8.2 - category: main dependencies: python: '>=3.6' @@ -8158,19 +8305,19 @@ package: - category: main dependencies: cffi: '>=1.0.0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: dd9604ece454103e7210110c6d343e37 - sha256: 7165aa68df59f61e48a2a513374fa6551295bccd76cefaefd0b86665fd56601f + md5: 6cb010e0fa21d7b606a13038a89ccbc2 + sha256: 2631b26d291196d76694bf7d71ea77ba2abcfc46278c3a54730a2d5683ca6c2b manager: conda name: brotlipy optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/brotlipy-0.7.0-py311ha68e1ae_1005.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/brotlipy-0.7.0-py310h8d17308_1005.tar.bz2 version: 0.7.0 - category: main dependencies: @@ -8224,87 +8371,89 @@ package: dependencies: cffi: '>=1.12' openssl: '>=3.0.7,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 369bad555cfdd4094409411ac563de32 - sha256: 8758eeb490505d3fd3560a7da97c5c6bf76494e698ff9ab773b9ebc4f09b5c6e + md5: 925c5f114c9a7ff2c2889c6ff0a091d4 + sha256: 5271dcb16870025fc730798ad49fcfac7579a1ee02c7de86292e22c26915f247 manager: conda name: cryptography optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/cryptography-38.0.4-py311h28e9c30_0.conda - version: 38.0.4 + url: https://conda.anaconda.org/conda-forge/win-64/cryptography-39.0.0-py310h6e82f81_0.conda + version: 39.0.0 - category: main dependencies: brotli: '' munkres: '' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' + unicodedata2: '>=14.0.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: ce4de8eb02378d3fe73c80628be41ff8 - sha256: f023e89ae6bbd6e573d336acdfbff5bd5c506bb5458683610f1ab671dd90eece + md5: 278ceddad4295cdeb1a2c60537cd20a5 + sha256: 091dc74113779fe7a4f99648471e3810e03998bf79b00621035b92468c4a1951 manager: conda name: fonttools optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/fonttools-4.38.0-py311ha68e1ae_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/fonttools-4.38.0-py310h8d17308_1.tar.bz2 version: 4.38.0 - category: main dependencies: jpeg: '>=9e,<10a' - libtiff: '>=4.4.0,<4.5.0a0' - libzlib: '>=1.2.12,<1.3.0a0' + libtiff: '>=4.5.0,<4.6.0a0' + libzlib: '>=1.2.13,<1.3.0a0' proj: '>=9.1.0,<9.1.1.0a0' + ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' - zlib: '>=1.2.12,<1.3.0a0' + zlib: '' hash: - md5: 411fd346ad4b588b4f36db902abef917 - sha256: 86ce91110c05c49468d29340247105159153329b3d817127c7a8bb427f1dacfd + md5: b5925151b1abc9575ea4b7e8c3483c8e + sha256: bea3a2b4ab7f5af847e3a4152076cfcb3f922effcbc4f9b7f8f512c22115649c manager: conda name: geotiff optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/geotiff-1.7.1-h4ffd875_4.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/geotiff-1.7.1-h720ab47_5.conda version: 1.7.1 - category: main dependencies: cffi: '>=1.0.0' libcrc32c: '>=1.1.2,<1.2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 45d8a9fce4eb8e0c01571783d9c8e62f - sha256: 288069d99445afabb98ff2ede54500919c761ea16a313a1f5649ec7eddfa9bb7 + md5: a15b9bdf00b8b18c2af01fba0f2ab361 + sha256: 20e3d4a06b6b1bb011c5d75935c04fb6303dc1a9fa4fb44b48850481c4237819 manager: conda name: google-crc32c optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/google-crc32c-1.1.2-py311h48d9ab2_4.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/google-crc32c-1.1.2-py310ha7be474_4.tar.bz2 version: 1.1.2 - category: main dependencies: protobuf: '>=3.19.5,<5.0.0dev,!=3.20.0,!=3.20.1,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5' python: '>=3.7' hash: - md5: 35947a7b1f5319de636d74ce38dcf131 - sha256: 88c2be80b3c4ca97f5259b6c6a814b730e6ab4d09c15dbbe60df779c3a7416f9 + md5: cbf8b4569c1d2a0a6077d34a2d38333e + sha256: 1b2a9ae4540e3056a7eaf126a4939360f521854c8a4aa04f10ed4c80da4edc7e manager: conda name: googleapis-common-protos optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/googleapis-common-protos-1.57.0-pyhd8ed1ab_3.conda - version: 1.57.0 + url: https://conda.anaconda.org/conda-forge/noarch/googleapis-common-protos-1.57.1-pyhd8ed1ab_0.conda + version: 1.57.1 - category: main dependencies: hdf5: '>=1.12.2,<1.12.3.0a0' @@ -8381,45 +8530,45 @@ package: - category: main dependencies: freetype: '>=2.12.1,<3.0a0' - jpeg: '>=9e,<10a' - lcms2: '>=2.12,<3.0a0' - libtiff: '>=4.4.0,<4.5.0a0' + lcms2: '>=2.14,<3.0a0' + libjpeg-turbo: '>=2.1.4,<3.0a0' + libtiff: '>=4.5.0,<4.6.0a0' libwebp-base: '>=1.2.4,<2.0a0' libxcb: '>=1.13,<1.14.0a0' libzlib: '>=1.2.13,<1.3.0a0' openjpeg: '>=2.5.0,<3.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 tk: '>=8.6.12,<8.7.0a0' ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 4387c195c89548640148b908b8195c6f - sha256: e0fb789de5c94248167a2119860f0493744352b6864441141f5de6b1f76b9246 + md5: b5c8bb98f1d5af54621a77b2658a29eb + sha256: cacee1013eeae84f5bf085473b70033dd14f8f73d9bb6fb02c44bd1e62be00f2 manager: conda name: pillow optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/pillow-9.2.0-py311h97bb24d_3.tar.bz2 - version: 9.2.0 + url: https://conda.anaconda.org/conda-forge/win-64/pillow-9.4.0-py310h3d7015a_0.conda + version: 9.4.0 - category: main dependencies: certifi: '' proj: '>=9.1.0,<9.1.1.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 1f1ce84de1096f8c725e983d8b864df8 - sha256: 3785b2bfcf136ed874c83be079576170ba8285e779e102c58371e26afea4f9a9 + md5: d8ba2081e40c269060c305fe22b9b89e + sha256: 01abeba30cdd6e492c54c2840cef3ce5a47b2e9056b6c50ae1221d35a79ed1d7 manager: conda name: pyproj optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/pyproj-3.4.1-py311h5e9ada3_0.conda + url: https://conda.anaconda.org/conda-forge/win-64/pyproj-3.4.1-py310h0e9dbc5_0.conda version: 3.4.1 - category: main dependencies: @@ -8449,14 +8598,14 @@ package: zlib: '' zstd: '>=1.5.2,<1.6.0a0' hash: - md5: a060e132e648e696862c3aa05f09b515 - sha256: bf5fc73b24aed62b50d5075f70aac25fbd30e7a3eeb6be10d341de2f884322a0 + md5: 07426c5e1301448738f66686548d41ff + sha256: 96c2de92dce5de54c923d9242163196bff6bce8e0fbfdbcfd4d9c47ce2fb1123 manager: conda name: tiledb optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/tiledb-2.13.0-h3132609_1.conda - version: 2.13.0 + url: https://conda.anaconda.org/conda-forge/win-64/tiledb-2.13.2-h3132609_0.conda + version: 2.13.2 - category: main dependencies: aiosignal: '>=1.1.2' @@ -8465,20 +8614,20 @@ package: charset-normalizer: '>=2.0,<3.0' frozenlist: '>=1.1.1' multidict: '>=4.5,<7.0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' yarl: '>=1.0,<2.0' hash: - md5: 8a34ae5888fd5b5a5e1759d7053a2858 - sha256: a28cd88434181fb16f762cf43d8d13e83d84fec8cbd16e68393e1aea9ea987c3 + md5: 7846e8d0fad870608c934e42e05cc786 + sha256: 0087fbb93b4e7e7695dcf32f6ad1a67241baed84166723e6bc96e1af73194d42 manager: conda name: aiohttp optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.8.3-py311ha68e1ae_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/aiohttp-3.8.3-py310h8d17308_1.tar.bz2 version: 3.8.3 - category: main dependencies: @@ -8519,7 +8668,7 @@ package: libglib: '>=2.74.1,<3.0a0' libiconv: '>=1.17,<2.0a0' libpng: '>=1.6.39,<1.7.0a0' - libtiff: '>=4.4.0,<4.5.0a0' + libtiff: '>=4.5.0,<4.6.0a0' libzlib: '>=1.2.13,<1.3.0a0' openjpeg: '>=2.5.0,<3.0a0' poppler-data: '' @@ -8527,27 +8676,27 @@ package: vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 2525c54ec216b35a5ad4595c81b73864 - sha256: 62c3087eb6a8a44fd49450533b89c531b7d5509a4326a70680121ff76dcf79dc + md5: 52b2e8a302cf95041beb567977729c36 + sha256: 5fa2b0f16dd399e784d569fdde39a9cf6be6a1fe30c1b6b5e78c8e74ad55d8cc manager: conda name: poppler optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/poppler-22.12.0-ha6c1112_0.conda + url: https://conda.anaconda.org/conda-forge/win-64/poppler-22.12.0-h183ae7b_1.conda version: 22.12.0 - category: main dependencies: - cryptography: '>=38.0.0,<39' + cryptography: '>=38.0.0,<40' python: '>=3.6' hash: - md5: fbfa0a180d48c800f922a10a114a8632 - sha256: 42f04dded77ac2597108378d62b121697d0e982aba7b20a462a7239030563628 + md5: d41957700e83bbb925928764cb7f8878 + sha256: adbf8951f22bfa950b9e24394df1ef1d2b2d7dfb194d91c7f42bc11900695785 manager: conda name: pyopenssl optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-22.1.0-pyhd8ed1ab_0.tar.bz2 - version: 22.1.0 + url: https://conda.anaconda.org/conda-forge/noarch/pyopenssl-23.0.0-pyhd8ed1ab_0.conda + version: 23.0.0 - category: main dependencies: libblas: 3.9.0 16_win64_mkl @@ -8574,7 +8723,7 @@ package: jpeg: '>=9e,<10a' kealib: '>=1.5.0,<1.6.0a0' lerc: '>=4.0.0,<5.0a0' - libcurl: '>=7.86.0,<8.0a0' + libcurl: '>=7.87.0,<8.0a0' libdeflate: '>=1.14,<1.15.0a0' libiconv: '>=1.17,<2.0a0' libkml: '>=1.3.0,<1.4.0a0' @@ -8583,7 +8732,7 @@ package: libpq: '>=15.1,<16.0a0' libspatialite: '>=5.0.1,<5.1.0a0' libsqlite: '>=3.40.0,<4.0a0' - libtiff: '>=4.4.0,<4.5.0a0' + libtiff: '>=4.5.0,<4.6.0a0' libwebp-base: '>=1.2.4,<2.0a0' libxml2: '>=2.10.3,<2.11.0a0' libzlib: '>=1.2.13,<1.3.0a0' @@ -8594,7 +8743,7 @@ package: poppler: '>=22.12.0,<22.13.0a0' postgresql: '' proj: '>=9.1.0,<9.1.1.0a0' - tiledb: '>=2.13.0,<2.14.0a0' + tiledb: '>=2.13.1,<2.14.0a0' ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' @@ -8602,14 +8751,14 @@ package: xz: '>=5.2.6,<6.0a0' zstd: '>=1.5.2,<1.6.0a0' hash: - md5: c0143d3f0d67d7a5ccfaa8bd3e375f0a - sha256: 7e1788851dc4695efdcf30b5ced9f83ff7cfe2dca27ee8fc094933a6e83d27c4 + md5: 9a4ef5cd8e935b794df7aea0cc4ca70a + sha256: 140e1141816bd5e7a560fef469ca435394d07eea5f9f37d01c18be59cee1a603 manager: conda name: libgdal optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/libgdal-3.6.1-h9364c56_1.conda - version: 3.6.1 + url: https://conda.anaconda.org/conda-forge/win-64/libgdal-3.6.2-hffd0036_1.conda + version: 3.6.2 - category: main dependencies: libblas: 3.9.0 16_win64_mkl @@ -8632,33 +8781,33 @@ package: pysocks: '>=1.5.6,<2.0,!=1.5.7' python: <4.0 hash: - md5: 3078ef2359efd6ecadbc7e085c5e0592 - sha256: 992f2d6ca50c98f865a4f2e4bada23f950e39f33ff7c64614a31ee152ec4d5ae + md5: 01f33ad2e0aaf6b5ba4add50dad5ad29 + sha256: f2f09c44e47946ce631dbc9a8a79bb463ac0f4122aaafdbcc51f200a1e420ca6 manager: conda name: urllib3 optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/urllib3-1.26.13-pyhd8ed1ab_0.conda - version: 1.26.13 + url: https://conda.anaconda.org/conda-forge/noarch/urllib3-1.26.14-pyhd8ed1ab_0.conda + version: 1.26.14 - category: main dependencies: libblas: '>=3.9.0,<4.0a0' libcblas: '>=3.9.0,<4.0a0' liblapack: '>=3.9.0,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 4d593854ee9972ab30ade6c248d5ae4c - sha256: 9cd0945227620ddde7f0fdd3cb62653ed0270cd15f7fc8c280920b024f688bb0 + md5: 3a8fb4ff03b730acd3eea929d49cb01d + sha256: c063c4742244f9bb7d63eb88c1db2ad88c91e498251defba81221f30258bee01 manager: conda name: numpy optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/numpy-1.23.5-py311h95d790f_0.conda - version: 1.23.5 + url: https://conda.anaconda.org/conda-forge/win-64/numpy-1.24.1-py310h4a8f9c9_0.conda + version: 1.24.1 - category: main dependencies: certifi: '>=2017.4.17' @@ -8677,38 +8826,38 @@ package: version: 2.28.1 - category: main dependencies: - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 491ff9524ccc680e3302469ec9ea5909 - sha256: cd3681852a1000573d596fe769813fe54743e06a93e28977dfdb28fbab137e9f + md5: 6d26114b7e1313d82e85570789bd9ad0 + sha256: 7867e3bb3da6ae760236940d292425df91e941083c9a535c08ab70d0637a1387 manager: conda name: cftime optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/cftime-1.6.2-py311h59ca53f_1.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/cftime-1.6.2-py310h9b08ddd_1.tar.bz2 version: 1.6.2 - category: main dependencies: numpy: '>=1.16' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: c75187984ea6dbad6f1c2ea49f111363 - sha256: 266331f0b93275831e61ba44f6da4aac83d92e834040d14776d3e1ab28780f5b + md5: 357f1ccd3fa2bbf3661146467f7afd44 + sha256: c2d32b16fedb41b184729fd87c5b61f69f6a4e5f331955e231b83d30aac99a61 manager: conda name: contourpy optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/contourpy-1.0.6-py311h005e61a_0.tar.bz2 - version: 1.0.6 + url: https://conda.anaconda.org/conda-forge/win-64/contourpy-1.0.7-py310h232114e_0.conda + version: 1.0.7 - category: main dependencies: branca: '>=0.6.0' @@ -8728,23 +8877,23 @@ package: - category: main dependencies: hdf5: '>=1.12.2,<1.12.3.0a0' - libgdal: 3.6.1 h9364c56_1 - numpy: '>=1.23.5,<2.0a0' + libgdal: 3.6.2 hffd0036_1 + numpy: '>=1.21.6,<2.0a0' openssl: '>=3.0.7,<4.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: f5f5895643d7958d5a818ed10307dcbc - sha256: 22b25565b2352aa8b10588385c7ee633d452836c8d67e7740622c0a4cebc5b73 + md5: ed437558c068417a3fedd81f51aaa828 + sha256: 6c778b866106fe1cbe7560982705ad4f280fe42b1fb9dc290cd4b978c535a55c manager: conda name: gdal optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/gdal-3.6.1-py311h4bd9738_1.conda - version: 3.6.1 + url: https://conda.anaconda.org/conda-forge/win-64/gdal-3.6.2-py310h644bc08_1.conda + version: 3.6.2 - category: main dependencies: aiohttp: '>=3.6.2,<4.0.0dev' @@ -8767,61 +8916,55 @@ package: version: 2.15.0 - category: main dependencies: - numpy: '>=1.23.5,<2.0a0' - python: '>=3.11,<3.12.0a0' + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' python-dateutil: '>=2.8.1' - python_abi: 3.11.* *_cp311 + python_abi: 3.10.* *_cp310 pytz: '>=2020.1' ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 1122deeac8e1439e91f941cfcb977e3a - sha256: 1703bd52c4f887f1b6c8df92851083506b28c2a2b43137d51a8d84630b2c97ba + md5: e8bdd2f2676576f2b16285420b4c3a10 + sha256: 6115b85a156a60490c0e204ee7c6b565f61da1ba1d092fb67457ac3616a5297b manager: conda name: pandas optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/pandas-1.5.2-py311hf63dbb6_0.conda + url: https://conda.anaconda.org/conda-forge/win-64/pandas-1.5.2-py310h1c4a608_2.conda version: 1.5.2 - category: main dependencies: - libblas: '>=3.9.0,<4.0a0' - libcblas: '>=3.9.0,<4.0a0' - liblapack: '>=3.9.0,<4.0a0' - m2w64-gcc-libs: '' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 - ucrt: '>=10.0.20348.0' - vc: '>=14.2,<15' - vs2015_runtime: '>=14.29.30139' + appdirs: '>=1.3.0' + packaging: '>=20.0' + python: '>=3.6' + requests: '>=2.19.0' hash: - md5: 38e002f660c1b21a2806f862e6793217 - sha256: 6cec5d3fc535c7148015ccce7e9a63bc835648651da02e11bce74cad896dac41 + md5: 6429e1d1091c51f626b5dcfdd38bf429 + sha256: 1f0548105de86fb2eb6fbb8d3d6cc2004079b8442d232258108687d6cc91eb73 manager: conda - name: scipy + name: pooch optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/scipy-1.9.3-py311h37ff6ca_2.tar.bz2 - version: 1.9.3 + url: https://conda.anaconda.org/conda-forge/noarch/pooch-1.6.0-pyhd8ed1ab_0.tar.bz2 + version: 1.6.0 - category: main dependencies: geos: '>=3.11.1,<3.11.2.0a0' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 1446a03ee7e308ba21d165c5fca501fb - sha256: 894be16082d5de289c2a7fffc46fbfc305f7f40644785685137e31a6ddd8ee71 + md5: 76b4d1b25e5ba9d036700b6a0da8cdbc + sha256: f0ab8fde6ab31ea1d53a06287f1402264dce683a934ccf170fdd67683f8308bb manager: conda name: shapely optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/shapely-1.8.5-py311habfe8a2_2.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/shapely-1.8.5-py310h8c82734_2.tar.bz2 version: 1.8.5 - category: main dependencies: @@ -8846,9 +8989,9 @@ package: gdal: '' libgdal: '>=3.6.0,<3.7.0a0' munch: '' - numpy: '>=1.23.5,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '' shapely: '' six: '>=1.7' @@ -8856,13 +8999,13 @@ package: vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: c725455aa4f5ca54ebf17b7d120c76c5 - sha256: fe8d87cacbf2f83ec8953e5f4d8bd01655b6389be4ab8c63560677c5a4b798db + md5: 154fbd5cb756b259346cb860ec67f211 + sha256: f5a0d4733db5d20ad841b85e6ce086729a27f923438cecb1bb7575d5a6899e04 manager: conda name: fiona optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/fiona-1.8.22-py311ha4db88c_5.conda + url: https://conda.anaconda.org/conda-forge/win-64/fiona-1.8.22-py310h4a685fe_5.conda version: 1.8.22 - category: main dependencies: @@ -8919,24 +9062,24 @@ package: fonttools: '>=4.22.0' freetype: '>=2.12.1,<3.0a0' kiwisolver: '>=1.0.1' - numpy: '>=1.23.4,<2.0a0' + numpy: '>=1.21.6,<2.0a0' packaging: '>=20.0' pillow: '>=6.2.0' pyparsing: '>=2.3.1' - python: '>=3.11,<3.12.0a0' + python: '>=3.10,<3.11.0a0' python-dateutil: '>=2.7' - python_abi: 3.11.* *_cp311 + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 01e95ec628fd823e3baab49fc27cdc21 - sha256: 1596cb8cb84643bbe0c126e522c5f14939c44f7f716b706edfd50b61a9eecb11 + md5: 51a43b04e415da8dd0850c2ded044c6e + sha256: f1ef00bb3af1777bb16ccbab290f2b3e5e9abd5885bfdc619a213499399b9f65 manager: conda name: matplotlib-base optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/matplotlib-base-3.6.2-py311h6e989c2_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/matplotlib-base-3.6.2-py310h51140c5_0.tar.bz2 version: 3.6.2 - category: main dependencies: @@ -8944,21 +9087,21 @@ package: hdf5: '>=1.12.2,<1.12.3.0a0' libnetcdf: '>=4.8.1,<4.8.2.0a0' libzlib: '>=1.2.13,<1.3.0a0' - numpy: '>=1.23.4,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '' ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 34f677e6c466107dd9dbe3bbeca26789 - sha256: 5a3089b52628364d3e816263a4195cee99784925f02c40b61d11e5597fc30a6e + md5: 71f0444f4abebfd46c5a4a8f39c6a90c + sha256: db08130c28445b69e09da8202483389d2ce698b4ae97eea0cbae0fc9710605f8 manager: conda name: netcdf4 optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/netcdf4-1.6.2-nompi_py311h45b207f_100.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/netcdf4-1.6.2-nompi_py310h459bb5f_100.tar.bz2 version: 1.6.2 - category: main dependencies: @@ -8969,45 +9112,46 @@ package: click-plugins: '' cligj: '>=0.5' libgdal: '>=3.6.0,<3.7.0a0' - numpy: '>=1.23.4,<2.0a0' + numpy: '>=1.21.6,<2.0a0' proj: '>=9.1.0,<9.1.1.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 setuptools: '>=0.9.8' snuggs: '>=1.4.1' ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: 3c55605a40639983ea16d70df40390c1 - sha256: fe4416774b30430db37f367dd180844f1c314e996dcb90c958ec55a420df1d3c + md5: 18159e9495e5a1b79612d3ac6d8c7abb + sha256: 980591cfde14a92e33eb75d86d8d2c5f28193245e87afd1c781f60202f1de946 manager: conda name: rasterio optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/rasterio-1.3.4-py311hd28ea1e_0.tar.bz2 + url: https://conda.anaconda.org/conda-forge/win-64/rasterio-1.3.4-py310h1f46e14_0.tar.bz2 version: 1.3.4 - category: main dependencies: - joblib: '>=1.1.1' + libblas: '>=3.9.0,<4.0a0' libcblas: '>=3.9.0,<4.0a0' - numpy: '>=1.23.5,<2.0a0' - python: '>=3.11,<3.12.0a0' - python_abi: 3.11.* *_cp311 - scipy: '' - threadpoolctl: '>=2.0.0' + liblapack: '>=3.9.0,<4.0a0' + m2w64-gcc-libs: '' + numpy: '>=1.21.6,<2.0a0' + pooch: '' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 ucrt: '>=10.0.20348.0' vc: '>=14.2,<15' vs2015_runtime: '>=14.29.30139' hash: - md5: f8c5ee2304960728676b188473b067a4 - sha256: dd7678e1a50e5cc8a196192c739fc6c7527ad14eb76ab2e12605e5b26dd8f320 + md5: 87356a414020b1b468bb808d62c183c3 + sha256: f5e8f9f71dae19d89759814bdd5511a296854e68276dcd1ae3a2500d7c4f1890 manager: conda - name: scikit-learn + name: scipy optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/win-64/scikit-learn-1.2.0-py311h6619ee7_0.conda - version: 1.2.0 + url: https://conda.anaconda.org/conda-forge/win-64/scipy-1.10.0-py310h578b7cb_0.conda + version: 1.10.0 - category: main dependencies: google-api-core: '>=1.31.5,<3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0' @@ -9017,14 +9161,14 @@ package: python: '>=3.7' uritemplate: '>=3.0.1,<5' hash: - md5: 04241ec803212136585c4e7738de8543 - sha256: 59d5c1e9afce9be9042900e10ffa804bbe68fb1331fed2ace5d15ce461f83b87 + md5: d25bf20710e2622edfd16f1580d6f406 + sha256: 9c2b34998b23486e9c9f8e35e18735247ca7b07f3b09e29a369b4ea8a658c807 manager: conda name: google-api-python-client optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/google-api-python-client-2.70.0-pyhd8ed1ab_0.conda - version: 2.70.0 + url: https://conda.anaconda.org/conda-forge/noarch/google-api-python-client-2.72.0-pyhd8ed1ab_0.conda + version: 2.72.0 - category: main dependencies: google-api-core: '>=1.31.6,<3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0' @@ -9042,40 +9186,25 @@ package: version: 2.3.2 - category: main dependencies: - networkx: '' - numpy: '>=1.3' - pandas: '>=1.0' - python: '>=3.5' - scikit-learn: '' - scipy: '>=1.0' - hash: - md5: 908bbfb54da154042c5cbda77b37a3d1 - sha256: 1435305fb0a127b3154e76c0836d44526eeb93e80bd37596128d7ad8fb196d97 - manager: conda - name: mapclassify - optional: false - platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/mapclassify-2.4.3-pyhd8ed1ab_0.tar.bz2 - version: 2.4.3 -- category: main - dependencies: - fiona: '' - folium: '' - geopandas-base: 0.12.2 pyha770c72_0 - mapclassify: '>=2.4.0' - matplotlib-base: '' - python: '>=3.8' - rtree: '' - xyzservices: '' + joblib: '>=1.1.1' + libcblas: '>=3.9.0,<4.0a0' + numpy: '>=1.21.6,<2.0a0' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + scipy: '' + threadpoolctl: '>=2.0.0' + ucrt: '>=10.0.20348.0' + vc: '>=14.2,<15' + vs2015_runtime: '>=14.29.30139' hash: - md5: ee3b330f13297f5839d46e1ca3e57d56 - sha256: 51660094efee2a74b24ab535e03005a6ddedc9e160c0d573cfaf2724312d171c + md5: f5433a3e1971e7565a4a9bd00d1df2eb + sha256: da4c825912e4c388268611df0f3f99fae86e443bdbf17214fa2af1d9ef4bc80e manager: conda - name: geopandas + name: scikit-learn optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/geopandas-0.12.2-pyhd8ed1ab_0.conda - version: 0.12.2 + url: https://conda.anaconda.org/conda-forge/win-64/scikit-learn-1.2.0-py310had3394f_0.conda + version: 1.2.0 - category: main dependencies: google-api-core: '>=1.31.5,<3.0.0dev,!=2.0.*,!=2.1.*,!=2.2.*,!=2.3.0' @@ -9094,6 +9223,23 @@ package: platform: win-64 url: https://conda.anaconda.org/conda-forge/noarch/google-cloud-storage-2.7.0-pyh1a96a4e_0.conda version: 2.7.0 +- category: main + dependencies: + networkx: '' + numpy: '>=1.3' + pandas: '>=1.0' + python: '>=3.5' + scikit-learn: '' + scipy: '>=1.0' + hash: + md5: 2b0aace000c60c7a6de29907e3df4c6e + sha256: 76db2b87e74d94ff0ab64e9d5809d853f5f2735ee205e135b982a93bed72978d + manager: conda + name: mapclassify + optional: false + platform: win-64 + url: https://conda.anaconda.org/conda-forge/noarch/mapclassify-2.5.0-pyhd8ed1ab_0.conda + version: 2.5.0 - category: main dependencies: future: '' @@ -9115,6 +9261,25 @@ package: platform: win-64 url: https://conda.anaconda.org/conda-forge/noarch/earthengine-api-0.1.334-pyhd8ed1ab_1.conda version: 0.1.334 +- category: main + dependencies: + fiona: '' + folium: '' + geopandas-base: 0.12.2 pyha770c72_0 + mapclassify: '>=2.4.0' + matplotlib-base: '' + python: '>=3.8' + rtree: '' + xyzservices: '' + hash: + md5: ee3b330f13297f5839d46e1ca3e57d56 + sha256: 51660094efee2a74b24ab535e03005a6ddedc9e160c0d573cfaf2724312d171c + manager: conda + name: geopandas + optional: false + platform: win-64 + url: https://conda.anaconda.org/conda-forge/noarch/geopandas-0.12.2-pyhd8ed1ab_0.conda + version: 0.12.2 - category: main dependencies: affine: '>=2.3.1' @@ -9123,24 +9288,22 @@ package: geopy: '>=2.2.0' loguru: '>=0.6.0' netcdf4: '>=1.6.1' - numpy: 1.23.5 + numpy: 1.24.1 pandas: '>=1.4.4' pip: '>=22.3.1' pyproj: '>=3.4.0' - pytest: '>=7.2.0' - pytest-cov: 4.0.0 - python: '>=3.9,<3.15' + python: '>=3.9,<3.11' rasterio: '>=1.3.0' requests: '>=2.28.1' rtree: '>=1.0.0' shapely: '>=1.8.4,<2' hash: - md5: 668898d4e01567089bdfd74242b43dc5 - sha256: 58f56ebc6bbc4af8ca5c8a02aad3bf976c116a2ec0460fb3642c4d5a8670216b + md5: fd315a429db61ecd8ac4ba1890bf5382 + sha256: 06d6813e56b80e1b4306c33fc252dcecd4c4647e704b4f7dc0d7a2c300fa7f1a manager: conda name: pyramids optional: false platform: win-64 - url: https://conda.anaconda.org/conda-forge/noarch/pyramids-0.2.10-pyhd8ed1ab_0.conda - version: 0.2.10 + url: https://conda.anaconda.org/conda-forge/noarch/pyramids-0.2.12-pyhd8ed1ab_0.conda + version: 0.2.12 version: 1 diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index 07c70b6..25f4c9f 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -56,7 +56,7 @@ def __init__( # Define timestep for the timedates if temporal_resolution.lower() == "daily": self.time_freq = "D" - self.output_folder = os.path.join(path, "Precipitation", "CHIRPS", "Daily") + self.output_folder = os.path.join(path, "precipitation", "chirps", "daily") elif temporal_resolution.lower() == "monthly": self.time_freq = "MS" self.output_folder = os.path.join( diff --git a/tests/test_chirps.py b/tests/test_chirps.py index ebb9980..91d4dc1 100644 --- a/tests/test_chirps.py +++ b/tests/test_chirps.py @@ -36,7 +36,10 @@ def test_download( chirps_base_dir: str, ): test_download_chirps.download() - filelist = glob.glob(os.path.join(f"{chirps_base_dir}/Precipitation/CHIRPS/Daily", "chirps*.tif")) + print(os.listdir(os.path.join(f"{chirps_base_dir}/precipitation/chirps/daily"))) + filelist = glob.glob(os.path.join(f"{chirps_base_dir}/precipitation/chirps/daily", "chirps*.tif")) + assert len(filelist) == 10 # delete the files - [os.remove(i) for i in filelist] \ No newline at end of file + # [os.remove(i) for i in filelist] + shutil.rmtree(f"{chirps_base_dir}/precipitation") \ No newline at end of file From cb644fee94930f4bc9141d9140660e7c0ef8d244 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 22:47:20 +0100 Subject: [PATCH 12/36] update tests --- .coveralls.yml | 2 -- earth2observe/chirps.py | 24 +++++++++++++----------- tests/test_chirps.py | 4 ++-- 3 files changed, 15 insertions(+), 15 deletions(-) delete mode 100644 .coveralls.yml diff --git a/.coveralls.yml b/.coveralls.yml deleted file mode 100644 index 06e982e..0000000 --- a/.coveralls.yml +++ /dev/null @@ -1,2 +0,0 @@ -repo_token: hxJrvjqiH2xBI7eit7BAb7FidH0LeYpGq -service_name: github-action diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index 25f4c9f..2a72031 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -21,6 +21,8 @@ class CHIRPS(DataSource): temporal_resolution = ["daily", "monthly"] lat_bondaries = [-50, 50] lon_boundaries = [-180, 180] + globe_fname = "chirps-v2.0" + clipped_fname = "P_CHIRPS.v2.0" def __init__( self, @@ -203,36 +205,36 @@ def API(self, date, args): args: [list] """ - [output_folder, TimeCase, xID, yID, lon_lim, latlim] = args + [output_folder, temp_resolution, xID, yID, lon_lim, latlim] = args # Define FTP path to directory - if TimeCase.lower() == "daily": + if temp_resolution.lower() == "daily": pathFTP = f"pub/org/chg/products/CHIRPS-2.0/global_daily/tifs/p05/{date.strftime('%Y')}/" - elif TimeCase == "monthly": + elif temp_resolution == "monthly": pathFTP = "pub/org/chg/products/CHIRPS-2.0/global_monthly/tifs/" else: raise KeyError("The input temporal_resolution interval is not supported") # create all the input name (filename) and output (outfilename, filetif, DiFileEnd) names - if TimeCase.lower() == "daily": - filename = f"chirps-v2.0.{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif.gz" + if temp_resolution.lower() == "daily": + filename = f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif.gz" outfilename = os.path.join( output_folder, - f"chirps-v2.0.{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" + f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" ) DirFileEnd = os.path.join( output_folder, - f"P_CHIRPS.v2.0_mm-day-1_daily_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" + f"{self.clipped_fname}_mm-day-1_daily_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" ) - elif TimeCase == "monthly": - filename = f"chirps-v2.0.{date.strftime('%Y')}.{date.strftime('%m')}.tif.gz" + elif temp_resolution == "monthly": + filename = f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.tif.gz" outfilename = os.path.join( output_folder, - f"chirps-v2.0.{date.strftime('%Y')}.{date.strftime('%m')}.tif" + f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.tif" ) DirFileEnd = os.path.join( output_folder, - f"P_CHIRPS.v2.0_mm-month-1_monthly_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" + f"{self.clipped_fname}_mm-month-1_monthly_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" ) else: raise KeyError("The input temporal_resolution interval is not supported") diff --git a/tests/test_chirps.py b/tests/test_chirps.py index 91d4dc1..b5e6f16 100644 --- a/tests/test_chirps.py +++ b/tests/test_chirps.py @@ -35,10 +35,10 @@ def test_download( test_download_chirps: CHIRPS, chirps_base_dir: str, ): + fname = test_download_chirps.clipped_fname test_download_chirps.download() - print(os.listdir(os.path.join(f"{chirps_base_dir}/precipitation/chirps/daily"))) - filelist = glob.glob(os.path.join(f"{chirps_base_dir}/precipitation/chirps/daily", "chirps*.tif")) + filelist = glob.glob(os.path.join(f"{chirps_base_dir}/precipitation/chirps/daily", f"{fname}*.tif")) assert len(filelist) == 10 # delete the files # [os.remove(i) for i in filelist] From c850ef03f527228789dc3a4689cb01be0e7de83a Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 23:45:59 +0100 Subject: [PATCH 13/36] add patlib package --- conda-lock.yml | 88 ++++++++++++++++++++++++++++++++++++++++++++++-- requirements.txt | 1 + 2 files changed, 86 insertions(+), 3 deletions(-) diff --git a/conda-lock.yml b/conda-lock.yml index e72d391..9f9b856 100644 --- a/conda-lock.yml +++ b/conda-lock.yml @@ -15,9 +15,9 @@ metadata: - url: conda-forge used_env_vars: [] content_hash: - linux-64: c03a2ae4429c0be064cfc9bfe6ca40013bd6a76fa524e2a683875d8ddf92f8ec - osx-64: 2555d349819e4da12527af854a47a625c748a9bdee7617ac11c91db5e7cb2177 - win-64: 07e55835584bb9e19c718819833a15235fad3eed30776a83019f6058b52bb9d7 + linux-64: 325708bf05f854c0b78eb537ecc928f7cff57e17261dc6942378dcf91b5352ea + osx-64: c47df51583e2b16668de1e761099728753d342aa01140e6349997debacd7ffe4 + win-64: 4450a3d68bc233c59053d29dc7ac201816e729cbafc2d414282992263aea23ab platforms: - linux-64 - osx-64 @@ -778,6 +778,18 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/linux-64/xz-5.2.6-h166bdaf_0.tar.bz2 version: 5.2.6 +- category: main + dependencies: + libgcc-ng: '>=9.4.0' + hash: + md5: 4cb3ad778ec2d5a7acbdf254eb1c42ae + sha256: a4e34c710eeb26945bdbdaba82d3d74f60a78f54a874ec10d373811a5d217535 + manager: conda + name: yaml + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/yaml-0.2.5-h7f98852_2.tar.bz2 + version: 0.2.5 - category: main dependencies: libopenblas: '>=0.3.21,<1.0a0' @@ -1752,6 +1764,21 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/noarch/pytz-2022.7-pyhd8ed1ab_0.conda version: '2022.7' +- category: main + dependencies: + libgcc-ng: '>=12' + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + yaml: '>=0.2.5,<0.3.0a0' + hash: + md5: 9e68d2ff6d98737c855b65f48dd3c597 + sha256: 602d68ee4544274b12fb6d13b8d5fc61d0ebbee190292c21d8be10a4e68185bd + manager: conda + name: pyyaml + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pyyaml-6.0-py310h5764c6d_5.tar.bz2 + version: '6.0' - category: main dependencies: libspatialindex: '>=1.9.3,<1.9.4.0a0' @@ -3608,6 +3635,17 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/osx-64/xz-5.2.6-h775f41a_0.tar.bz2 version: 5.2.6 +- category: main + dependencies: {} + hash: + md5: d7e08fcf8259d742156188e8762b4d20 + sha256: 5301417e2c8dea45b401ffee8df3957d2447d4ce80c83c5ff151fc6bfe1c4148 + manager: conda + name: yaml + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/yaml-0.2.5-h0d85af4_2.tar.bz2 + version: 0.2.5 - category: main dependencies: libcxx: '>=14.0.4' @@ -4687,6 +4725,20 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/noarch/pytz-2022.7-pyhd8ed1ab_0.conda version: '2022.7' +- category: main + dependencies: + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + yaml: '>=0.2.5,<0.3.0a0' + hash: + md5: e0ba2009f52ccda088c63dedf0d1c5ec + sha256: ab7b2b8fef9adc4211834054d004f3e286161bb3e1dcb17d4b974fae4f87b31b + manager: conda + name: pyyaml + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pyyaml-6.0-py310h90acd4f_5.tar.bz2 + version: '6.0' - category: main dependencies: libspatialindex: '>=1.9.3,<1.9.4.0a0' @@ -6779,6 +6831,19 @@ package: platform: win-64 url: https://conda.anaconda.org/conda-forge/win-64/xz-5.2.6-h8d14728_0.tar.bz2 version: 5.2.6 +- category: main + dependencies: + vc: '>=14.1,<15.0a0' + vs2015_runtime: '>=14.16.27012' + hash: + md5: adbfb9f45d1004a26763652246a33764 + sha256: 4e2246383003acbad9682c7c63178e2e715ad0eb84f03a8df1fbfba455dfedc5 + manager: conda + name: yaml + optional: false + platform: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/yaml-0.2.5-h8ffe710_2.tar.bz2 + version: 0.2.5 - category: main dependencies: libiconv: '>=1.17,<2.0.0a0' @@ -7571,6 +7636,23 @@ package: platform: win-64 url: https://conda.anaconda.org/conda-forge/noarch/pytz-2022.7-pyhd8ed1ab_0.conda version: '2022.7' +- category: main + dependencies: + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + ucrt: '>=10.0.20348.0' + vc: '>=14.2,<15' + vs2015_runtime: '>=14.29.30139' + yaml: '>=0.2.5,<0.3.0a0' + hash: + md5: d0daf3eed98dd2bf4337ed08d8011eb8 + sha256: 7d948a99bf7af50c9823a248267fce75ac555e4f357de166f65a75fab8549f3c + manager: conda + name: pyyaml + optional: false + platform: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/pyyaml-6.0-py310h8d17308_5.tar.bz2 + version: '6.0' - category: main dependencies: libspatialindex: '>=1.9.3,<1.9.4.0a0' diff --git a/requirements.txt b/requirements.txt index 98739df..f7efbec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -8,4 +8,5 @@ numpy ==1.24.1 pandas >=1.4.4 pip >=22.3.1 pyramids-gis >=0.2.12 +PyYAML >=6.0 requests >=2.28.1 From 3d1ccbf40bb9d1f058d656cc6f4c609517385b97 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 23:46:40 +0100 Subject: [PATCH 14/36] add ecmwf test --- tests/conftest.py | 15 +++++++++++++-- tests/test_chirps.py | 19 +++++++++---------- tests/test_ecmwf.py | 37 +++++++++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 12 deletions(-) create mode 100644 tests/test_ecmwf.py diff --git a/tests/conftest.py b/tests/conftest.py index 7fc5007..4c746f8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,11 +1,12 @@ import pytest from typing import List +from pathlib import Path from tests.gee.conftest import * @pytest.fixture(scope="session") -def chirps_dates() -> list: +def dates() -> List: return ["2009-01-01", "2009-01-10"] @pytest.fixture(scope="session") @@ -23,4 +24,14 @@ def lon_bounds() -> List: @pytest.fixture(scope="session") def chirps_base_dir() -> str: - return "tests/data/chirps" \ No newline at end of file + return "tests/data/chirps" + + +@pytest.fixture(scope="session") +def ecmwf_base_dir() -> Path: + return Path("tests/data/ecmwf").absolute() + + +@pytest.fixture(scope="session") +def ecmwf_variables() -> List[str]: + return ["E"] # "T", \ No newline at end of file diff --git a/tests/test_chirps.py b/tests/test_chirps.py index b5e6f16..017d663 100644 --- a/tests/test_chirps.py +++ b/tests/test_chirps.py @@ -7,16 +7,16 @@ @pytest.fixture(scope="session") -def test_download_chirps( - chirps_dates: list, +def test_create_chirps_object( + dates: List, daily_temporal_resolution: str, lat_bounds: List, lon_bounds: List, chirps_base_dir: str, ): Coello = CHIRPS( - start=chirps_dates[0], - end=chirps_dates[1], + start=dates[0], + end=dates[1], lat_lim=lat_bounds, lon_lim=lon_bounds, temporal_resolution=daily_temporal_resolution, @@ -25,21 +25,20 @@ def test_download_chirps( assert Coello.api_url == "data.chc.ucsb.edu" assert Coello.lon_boundaries == [-180, 180] assert Coello.lat_bondaries == [-50, 50] - assert str(Coello.dates[0].date()) == chirps_dates[0] - assert str(Coello.dates[-1].date()) == chirps_dates[1] + assert str(Coello.dates[0].date()) == dates[0] + assert str(Coello.dates[-1].date()) == dates[1] return Coello def test_download( - test_download_chirps: CHIRPS, + test_create_chirps_object: CHIRPS, chirps_base_dir: str, ): - fname = test_download_chirps.clipped_fname - test_download_chirps.download() + fname = test_create_chirps_object.clipped_fname + test_create_chirps_object.download() filelist = glob.glob(os.path.join(f"{chirps_base_dir}/precipitation/chirps/daily", f"{fname}*.tif")) assert len(filelist) == 10 # delete the files - # [os.remove(i) for i in filelist] shutil.rmtree(f"{chirps_base_dir}/precipitation") \ No newline at end of file diff --git a/tests/test_ecmwf.py b/tests/test_ecmwf.py new file mode 100644 index 0000000..964913c --- /dev/null +++ b/tests/test_ecmwf.py @@ -0,0 +1,37 @@ +import pytest +import os +import glob +import shutil +from typing import List +from earth2observe.ecmwf import ECMWF + +@pytest.fixture(scope="session") +def test_create_ecmwf_object( + dates: List, + lat_bounds: List, + lon_bounds: List, + ecmwf_base_dir: str, + ecmwf_variables: List[str], +): + Coello = ECMWF( + start=dates[0], + end=dates[1], + lat_lim=lat_bounds, + lon_lim=lon_bounds, + path=ecmwf_base_dir, + variables=ecmwf_variables, + ) + assert isinstance(Coello, ECMWF) + return Coello + + +def test_download( + test_create_ecmwf_object: ECMWF, + ecmwf_base_dir: str, +): + + test_create_ecmwf_object.download() + filelist = glob.glob(os.path.join(f"{ecmwf_base_dir}/daily/Evaporation/", f"*.tif")) + assert len(filelist) == 10 + # delete the files + shutil.rmtree(f"{ecmwf_base_dir}") \ No newline at end of file From 6c44d07e2cf74a854314ccbc88071ecf2121ffd3 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 23:47:15 +0100 Subject: [PATCH 15/36] add pathlib package --- conda-lock.yml | 45 ++++++++++++++++++++++++++++++++++++++++++--- environment.yml | 2 ++ requirements.txt | 1 + 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/conda-lock.yml b/conda-lock.yml index 9f9b856..8d01e6f 100644 --- a/conda-lock.yml +++ b/conda-lock.yml @@ -15,9 +15,9 @@ metadata: - url: conda-forge used_env_vars: [] content_hash: - linux-64: 325708bf05f854c0b78eb537ecc928f7cff57e17261dc6942378dcf91b5352ea - osx-64: c47df51583e2b16668de1e761099728753d342aa01140e6349997debacd7ffe4 - win-64: 4450a3d68bc233c59053d29dc7ac201816e729cbafc2d414282992263aea23ab + linux-64: 254a8ec847efd0a02a050ea9fc62f1a75932bb3645fa638fc79971d4b8f35430 + osx-64: d8e507a190f5b7c996b48cd0a82bc6c4ed5fed5a8279ee8d4157cb3c39be60c3 + win-64: cc58bac7c0731eff5cf8ea05e67e60e4ddf69f70dfdf9d0080a8a7faa1a4d316 platforms: - linux-64 - osx-64 @@ -1704,6 +1704,19 @@ package: platform: linux-64 url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.0-pyhd8ed1ab_0.conda version: '23.0' +- category: main + dependencies: + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + hash: + md5: 8136eda9039ea7d038f5f567b3d36edc + sha256: 133a357c3d7f4e401a7fec91cba7a29d923ca27f7db1411144d07795fca6af71 + manager: conda + name: pathlib + optional: false + platform: linux-64 + url: https://conda.anaconda.org/conda-forge/linux-64/pathlib-1.0.1-py310hff52083_7.tar.bz2 + version: 1.0.1 - category: main dependencies: python: '>=3.8' @@ -4665,6 +4678,19 @@ package: platform: osx-64 url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.0-pyhd8ed1ab_0.conda version: '23.0' +- category: main + dependencies: + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + hash: + md5: 14854f5255d4f6b7e2b778c3bbae1bd3 + sha256: 980be3d027c0bb6840f1b0943971513c47899840344752ef7bc4602fa8329d75 + manager: conda + name: pathlib + optional: false + platform: osx-64 + url: https://conda.anaconda.org/conda-forge/osx-64/pathlib-1.0.1-py310h2ec42d9_7.tar.bz2 + version: 1.0.1 - category: main dependencies: python: '>=3.8' @@ -7564,6 +7590,19 @@ package: platform: win-64 url: https://conda.anaconda.org/conda-forge/noarch/packaging-23.0-pyhd8ed1ab_0.conda version: '23.0' +- category: main + dependencies: + python: '>=3.10,<3.11.0a0' + python_abi: 3.10.* *_cp310 + hash: + md5: 418ff71cea0e1072490e9b39b6766d2b + sha256: 4d28297d67b19cce3b8efc27b74958d17c07f777d323db2e654ea88787173bb8 + manager: conda + name: pathlib + optional: false + platform: win-64 + url: https://conda.anaconda.org/conda-forge/win-64/pathlib-1.0.1-py310h5588dad_7.tar.bz2 + version: 1.0.1 - category: main dependencies: python: '>=3.8' diff --git a/environment.yml b/environment.yml index 83c3bdc..0f5ecb0 100644 --- a/environment.yml +++ b/environment.yml @@ -12,6 +12,8 @@ dependencies: - joblib >=1.2.0 - pyramids >=0.2.12 - loguru >=0.6.0 + - PyYAML >=6.0 + - pathlib >=1.0.1 - pytest >=7.2.0 - pytest-cov ==4.0.0 - requests >=2.28.1 diff --git a/requirements.txt b/requirements.txt index f7efbec..1908cb8 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ pandas >=1.4.4 pip >=22.3.1 pyramids-gis >=0.2.12 PyYAML >=6.0 +pathlib >=1.0.1 requests >=2.28.1 From 28aac06c099853bec029c0713438adcb23456174 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sat, 14 Jan 2023 23:48:10 +0100 Subject: [PATCH 16/36] fix bug in time url_string name --- earth2observe/ecmwf.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/earth2observe/ecmwf.py b/earth2observe/ecmwf.py index 7b97d47..431304e 100644 --- a/earth2observe/ecmwf.py +++ b/earth2observe/ecmwf.py @@ -26,7 +26,7 @@ class ECMWF(DataSource): def __init__( self, - time: str = "daily", + temporal_resolution: str = "daily", start: str = None, end: str = None, path: str = "", @@ -59,16 +59,16 @@ def __init__( self.start = dt.datetime.strptime(start, fmt) self.end = dt.datetime.strptime(end, fmt) - if time == "six_hourly": + if temporal_resolution == "six_hourly": # Set required data for the three hourly option self.string1 = "oper" # Set required data for the daily option - elif time == "daily": + elif temporal_resolution == "daily": self.Dates = pd.date_range(self.start, self.end, freq="D") - elif time == "monthly": + elif temporal_resolution == "monthly": self.Dates = pd.date_range(self.start, self.end, freq="MS") - self.time = time + self.time = temporal_resolution self.path = path self.vars = variables @@ -303,7 +303,7 @@ def callAPI( "dataset": dataset, "step": step, "grid": grid, - "temporal_resolution": time_str, + "time": time_str, "date": date_str, "type": type_str, # http://apps.ecmwf.int/codes/grib/format/mars/type/ "class": class_str, # http://apps.ecmwf.int/codes/grib/format/mars/class/ @@ -323,7 +323,7 @@ def callAPI( "dataset": dataset, "step": step, "grid": grid, - "temporal_resolution": time_str, + "time": time_str, "date": date_str, "type": type_str, # http://apps.ecmwf.int/codes/grib/format/mars/type/ "class": class_str, # http://apps.ecmwf.int/codes/grib/format/mars/class/ @@ -371,7 +371,7 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres # Open the NC data Data = fh.variables[parameter_var][:] - Data_time = fh.variables["temporal_resolution"][:] + Data_time = fh.variables["time"][:] lons = fh.variables["longitude"][:] lats = fh.variables["latitude"][:] From 26447300dba13378e5eb6d3de309fe1d3c4fb9ba Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 00:13:06 +0100 Subject: [PATCH 17/36] add initialize server connection function --- earth2observe/ecmwf.py | 52 ++++++++++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/earth2observe/ecmwf.py b/earth2observe/ecmwf.py index 431304e..e5e96c7 100644 --- a/earth2observe/ecmwf.py +++ b/earth2observe/ecmwf.py @@ -56,6 +56,9 @@ def __init__( fmt (str, optional): [description]. Defaults to "%Y-%m-%d". """ + # initialize connection with ecmwf server + self.initialize() + self.start = dt.datetime.strptime(start, fmt) self.end = dt.datetime.strptime(end, fmt) @@ -75,6 +78,18 @@ def __init__( self.date_str = f"{self.start}/to/{self.end}" self.create_grid(lat_lim, lon_lim) + def initialize(self): + """Initialize connection with ECMWF server""" + try: + url = os.environ['ECMWF_API_URL'] + key = os.environ['ECMWF_API_KEY'] + email = os.environ['ECMWF_API_EMAIL'] + except KeyError: + raise AuthenticationError(f"Please define the following environment variables to successfully establish a " + f"connection with ecmwf server ECMWF_API_URL, ECMWF_API_KEY, ECMWF_API_EMAIL") + + self.server = ECMWFDataServer(url=url, key=key, email=email) + def create_grid(self, lat_lim: list, lon_lim: list): """Create_grid @@ -237,6 +252,7 @@ def API(self, var_info, dataset): # Download data by using the ECMWF API logger.info("Use API ECMWF to collect the data, please wait") self.callAPI( + self.server, self.path, download_type, stream, @@ -255,19 +271,20 @@ def API(self, var_info, dataset): @staticmethod def callAPI( - output_folder: str, - download_type: str, - stream: str, - levtype: str, - param: str, - step: str, - grid: str, - time_str: str, - date_str: str, - type_str: str, - class_str: str, - area_str: str, - dataset: str = "interim", + server, + output_folder: str, + download_type: str, + stream: str, + levtype: str, + param: str, + step: str, + grid: str, + time_str: str, + date_str: str, + type_str: str, + class_str: str, + area_str: str, + dataset: str = "interim", ): """send the request to the server. @@ -290,10 +307,7 @@ def callAPI( """ os.chdir(output_folder) - server = ECMWFDataServer() - # url = os.environ['ECMWF_API_URL'], - # key = os.environ['ECMWF_API_KEY'], - # email = os.environ['ECMWF_API_EMAIL'], + if download_type == 1 or download_type == 2: server.retrieve( { @@ -470,3 +484,7 @@ def get_catalog(self): def get_variable(self, var_name): """retrieve a variable form the datasource catalog""" return self.catalog.get(var_name) + +class AuthenticationError(Exception): + """Failed to establish connection with ECMWF server""" + pass \ No newline at end of file From 04d7f96d7d04975a6199e7422d194b18bd085707 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 00:25:37 +0100 Subject: [PATCH 18/36] add ecmwf credentials --- .github/workflows/ubuntu.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 7d5f4df..9c667dc 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -41,6 +41,10 @@ jobs: python setup.py install - name: Generate coverage report + env: + ECMWF_API_URL: ${{ secrets.ECMWF_API_URL }} + ECMWF_API_KEY: ${{ secrets.ECMWF_API_KEY }} + ECMWF_API_EMAIL: ${{ secrets.ECMWF_API_EMAIL }} run: | python -m pytest -vvv --cov=earth2observe --cov-report=xml From 5b3e81bb5831e97728a578458b2b3de08fc8a0ff Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 00:33:47 +0100 Subject: [PATCH 19/36] add initialize method to the abstract class --- earth2observe/chirps.py | 17 +++++++++++------ earth2observe/datasource.py | 6 ++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index 2a72031..ebfcfc2 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -88,6 +88,15 @@ def __init__( self.create_grid(lat_lim, lon_lim) + def initialize(self): + """Initialize connection with chirps ftp server""" + # open ftp server + # ftp = FTP("chg-ftpout.geog.ucsb.edu", "", "") + ftp = FTP(CHIRPS.api_url) + ftp.login() + self.server = ftp + + def create_grid(self, lat_lim: list, lon_lim: list): """Create_grid @@ -239,12 +248,12 @@ def API(self, date, args): else: raise KeyError("The input temporal_resolution interval is not supported") - self.callAPI(pathFTP, output_folder, filename) + self.callAPI(self.server, pathFTP, output_folder, filename) self.post_download(output_folder, filename, lon_lim, latlim, xID, yID, outfilename, DirFileEnd) @staticmethod - def callAPI(pathFTP: str, output_folder: str, filename: str): + def callAPI(ftp, pathFTP: str, output_folder: str, filename: str): """send the request to the server. RetrieveData method retrieves CHIRPS data for a given date from the @@ -267,10 +276,6 @@ def callAPI(pathFTP: str, output_folder: str, filename: str): bool DESCRIPTION. """ - # open ftp server - # ftp = FTP("chg-ftpout.geog.ucsb.edu", "", "") - ftp = FTP(CHIRPS.api_url) - ftp.login() # find the document name in this directory ftp.cwd(pathFTP) diff --git a/earth2observe/datasource.py b/earth2observe/datasource.py index 5e5ef4f..9808381 100644 --- a/earth2observe/datasource.py +++ b/earth2observe/datasource.py @@ -23,6 +23,12 @@ def API(self): """send/recieve request to the dataset server""" pass + + @abstractmethod + def initialize(self): + """Initialize connection with the data source server""" + pass + @abstractmethod def create_grid(self): """create a grid from the lat/lon boundaries""" From 8f6d1a97b69743d09b69fd845a5fa35d837bdbe2 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 00:52:55 +0100 Subject: [PATCH 20/36] initialize method for non ftp dataseources --- earth2observe/chirps.py | 16 ++++------------ earth2observe/datasource.py | 3 +-- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index ebfcfc2..62a34e2 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -88,15 +88,6 @@ def __init__( self.create_grid(lat_lim, lon_lim) - def initialize(self): - """Initialize connection with chirps ftp server""" - # open ftp server - # ftp = FTP("chg-ftpout.geog.ucsb.edu", "", "") - ftp = FTP(CHIRPS.api_url) - ftp.login() - self.server = ftp - - def create_grid(self, lat_lim: list, lon_lim: list): """Create_grid @@ -248,12 +239,12 @@ def API(self, date, args): else: raise KeyError("The input temporal_resolution interval is not supported") - self.callAPI(self.server, pathFTP, output_folder, filename) + self.callAPI(pathFTP, output_folder, filename) self.post_download(output_folder, filename, lon_lim, latlim, xID, yID, outfilename, DirFileEnd) @staticmethod - def callAPI(ftp, pathFTP: str, output_folder: str, filename: str): + def callAPI(pathFTP: str, output_folder: str, filename: str): """send the request to the server. RetrieveData method retrieves CHIRPS data for a given date from the @@ -276,7 +267,8 @@ def callAPI(ftp, pathFTP: str, output_folder: str, filename: str): bool DESCRIPTION. """ - + ftp = FTP(CHIRPS.api_url) + ftp.login() # find the document name in this directory ftp.cwd(pathFTP) listing = [] diff --git a/earth2observe/datasource.py b/earth2observe/datasource.py index 9808381..860fc3c 100644 --- a/earth2observe/datasource.py +++ b/earth2observe/datasource.py @@ -24,9 +24,8 @@ def API(self): pass - @abstractmethod def initialize(self): - """Initialize connection with the data source server""" + """Initialize connection with the data source server (for non ftp servers)""" pass @abstractmethod From 9752f96ce6d47fec04784706cd1f5d66a0cf2c03 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 00:56:30 +0100 Subject: [PATCH 21/36] fix removing test file at the end --- tests/test_ecmwf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_ecmwf.py b/tests/test_ecmwf.py index 964913c..a8d9ad6 100644 --- a/tests/test_ecmwf.py +++ b/tests/test_ecmwf.py @@ -34,4 +34,4 @@ def test_download( filelist = glob.glob(os.path.join(f"{ecmwf_base_dir}/daily/Evaporation/", f"*.tif")) assert len(filelist) == 10 # delete the files - shutil.rmtree(f"{ecmwf_base_dir}") \ No newline at end of file + shutil.rmtree(f"{ecmwf_base_dir}/daily") \ No newline at end of file From 5d6ff8ed3e1cacd424946a4ba2846f40ca6b7cc1 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 17:17:33 +0100 Subject: [PATCH 22/36] change name of abstract module and class --- earth2observe/abstractdatasource.py | 82 +++++++++++++++++++++++++++++ earth2observe/chirps.py | 10 ++-- earth2observe/datasource.py | 48 ----------------- earth2observe/ecmwf.py | 30 ++++++----- 4 files changed, 105 insertions(+), 65 deletions(-) create mode 100644 earth2observe/abstractdatasource.py delete mode 100644 earth2observe/datasource.py diff --git a/earth2observe/abstractdatasource.py b/earth2observe/abstractdatasource.py new file mode 100644 index 0000000..6f08135 --- /dev/null +++ b/earth2observe/abstractdatasource.py @@ -0,0 +1,82 @@ +from typing import Dict +from abc import ABC, abstractmethod + + +class AbstractDataSource(ABC): + """ + Bluebrint for all class for different datasources + """ + def __init__( + self, + temporal_resolution: str = "daily", + start: str = None, + end: str = None, + path: str = "", + variables: list = None, + lat_lim: list = None, + lon_lim: list = None, + fmt: str = "%Y-%m-%d", + ): + """ + + Parameters + ---------- + temporal_resolution (str, optional): + [description]. Defaults to 'daily'. + start (str, optional): + [description]. Defaults to ''. + end (str, optional): + [description]. Defaults to ''. + path (str, optional): + Path where you want to save the downloaded data. Defaults to ''. + variables (list, optional): + Variable code: VariablesInfo('day').descriptions.keys(). Defaults to []. + lat_lim (list, optional): + [ymin, ymax]. Defaults to None. + lon_lim (list, optional): + [xmin, xmax]. Defaults to None. + fmt (str, optional): + [description]. Defaults to "%Y-%m-%d". + """ + pass + + @abstractmethod + def download(self): + """Wrapper over all the given variables.""" + pass + + + # @abstractmethod + def downloadDataset(self): + """Download single variable/dataset""" + pass + + @abstractmethod + def API(self): + """send/recieve request to the dataset server""" + pass + + + @abstractmethod + def initialize(self): + """Initialize connection with the data source server (for non ftp servers)""" + pass + + @abstractmethod + def create_grid(self): + """create a grid from the lat/lon boundaries""" + pass + + +class AbstractCatalog(ABC): + """abstrach class for the datasource catalog""" + + @abstractmethod + def get_catalog(self): + """read the catalog of the datasource from disk or retrieve it from server""" + pass + + @abstractmethod + def get_variable(self, var_name) -> Dict[str, str]: + """get the details of a specific variable""" + pass diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index 62a34e2..d320684 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -9,11 +9,11 @@ from osgeo import gdal from pyramids.raster import Raster from pyramids.utils import extractFromGZ -from earth2observe.datasource import DataSource, CatalogTemplate +from earth2observe.abstractdatasource import AbstractDataSource, AbstractCatalog from earth2observe.utils import print_progress_bar -class CHIRPS(DataSource): +class CHIRPS(AbstractDataSource): """CHIRPS.""" api_url: str = "data.chc.ucsb.edu" start_date: str = "1981-01-01" @@ -87,6 +87,10 @@ def __init__( self.dates = pd.date_range(self.start, self.end, freq=self.time_freq) self.create_grid(lat_lim, lon_lim) + def initialize(self): + """Initialize FTP server""" + print("FTP server datasources does not need server initialization") + pass def create_grid(self, lat_lim: list, lon_lim: list): """Create_grid @@ -347,7 +351,7 @@ def listAttributes(self): print("\n") -class Catalog(CatalogTemplate): +class Catalog(AbstractCatalog): """ CHIRPS data catalog""" def __init__(self): diff --git a/earth2observe/datasource.py b/earth2observe/datasource.py deleted file mode 100644 index 860fc3c..0000000 --- a/earth2observe/datasource.py +++ /dev/null @@ -1,48 +0,0 @@ -from typing import Dict -from abc import ABC, abstractmethod - - -class DataSource(ABC): - """ - Bluebrint for all class for different datasources - """ - - @abstractmethod - def download(self): - """Wrapper over all the given variables.""" - pass - - - # @abstractmethod - def downloadDataset(self): - """Download single variable/dataset""" - pass - - @abstractmethod - def API(self): - """send/recieve request to the dataset server""" - pass - - - def initialize(self): - """Initialize connection with the data source server (for non ftp servers)""" - pass - - @abstractmethod - def create_grid(self): - """create a grid from the lat/lon boundaries""" - pass - - -class CatalogTemplate(ABC): - """abstrach class for the datasource catalog""" - - @abstractmethod - def get_catalog(self): - """read the catalog of the datasource from disk or retrieve it from server""" - pass - - @abstractmethod - def get_variable(self, var_name) -> Dict[str, str]: - """get the details of a specific variable""" - pass diff --git a/earth2observe/ecmwf.py b/earth2observe/ecmwf.py index e5e96c7..ff5ab38 100644 --- a/earth2observe/ecmwf.py +++ b/earth2observe/ecmwf.py @@ -16,14 +16,15 @@ from earth2observe import __path__ from earth2observe.utils import print_progress_bar -from earth2observe.datasource import DataSource, CatalogTemplate +from earth2observe.abstractdatasource import AbstractDataSource, AbstractCatalog -class ECMWF(DataSource): +class ECMWF(AbstractDataSource): """RemoteSensing. RemoteSensing class contains methods to download ECMWF data """ - + temporal_resolution = ["daily", "monthly"] + spatial_resolution = 0.125 def __init__( self, temporal_resolution: str = "daily", @@ -67,9 +68,9 @@ def __init__( self.string1 = "oper" # Set required data for the daily option elif temporal_resolution == "daily": - self.Dates = pd.date_range(self.start, self.end, freq="D") + self.dates = pd.date_range(self.start, self.end, freq="D") elif temporal_resolution == "monthly": - self.Dates = pd.date_range(self.start, self.end, freq="MS") + self.dates = pd.date_range(self.start, self.end, freq="MS") self.time = temporal_resolution self.path = path @@ -103,14 +104,15 @@ def create_grid(self, lat_lim: list, lon_lim: list): lon_lim: [] longitude boundaries """ + cell_size = self.spatial_resolution # correct latitude and longitude limits - latlim_corr_one = np.floor(lat_lim[0] / 0.125) * 0.125 - latlim_corr_two = np.ceil(lat_lim[1] / 0.125) * 0.125 + latlim_corr_one = np.floor(lat_lim[0] / cell_size) * cell_size + latlim_corr_two = np.ceil(lat_lim[1] / cell_size) * cell_size self.latlim_corr = [latlim_corr_one, latlim_corr_two] # correct latitude and longitude limits - lonlim_corr_one = np.floor(lon_lim[0] / 0.125) * 0.125 - lonlim_corr_two = np.ceil(lon_lim[1] / 0.125) * 0.125 + lonlim_corr_one = np.floor(lon_lim[0] / cell_size) * cell_size + lonlim_corr_two = np.ceil(lon_lim[1] / cell_size) * cell_size self.lonlim_corr = [lonlim_corr_one, lonlim_corr_two] @@ -244,7 +246,7 @@ def API(self, var_info, dataset): parameter_number = var_info.get("number_para") param = f"{parameter_number}.128" - grid = "0.125/0.125" + grid = f"{self.spatial_resolution}/{self.spatial_resolution}" class_str = "ei" # N, W, S, E area_str = f"{self.latlim_corr[1]}/{self.lonlim_corr[0]}/{self.latlim_corr[0]}/{self.lonlim_corr[1]}" @@ -392,17 +394,17 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres # Define the georeference information geo_four = np.nanmax(lats) geo_one = np.nanmin(lons) - geo = tuple([geo_one, 0.125, 0.0, geo_four, 0.0, -0.125]) + geo = tuple([geo_one, self.spatial_resolution, 0.0, geo_four, 0.0, -1 * self.spatial_resolution]) # Create Waitbar if progress_bar: - total_amount = len(self.Dates) + total_amount = len(self.dates) amount = 0 print_progress_bar( amount, total_amount, prefix="Progress:", suffix="Complete", length=50 ) - for date in self.Dates: + for date in self.dates: # Define the year, month and day year = date.year @@ -464,7 +466,7 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres fh.close() -class Catalog(CatalogTemplate): +class Catalog(AbstractCatalog): """ECMWF data catalog This class contains the information about the ECMWF variables http://rda.ucar.edu/cgi-bin/transform?xml=/metadata/ParameterTables/WMO_GRIB1.98-0.128.xml&view=gribdoc. From 17e675f706ed1bcb1589f1b1a67aaa0f47de494d Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 18:08:04 +0100 Subject: [PATCH 23/36] update ecmwf example --- examples/ecmwf_data.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/ecmwf_data.py b/examples/ecmwf_data.py index 2f26c26..9acb49d 100644 --- a/examples/ecmwf_data.py +++ b/examples/ecmwf_data.py @@ -31,11 +31,11 @@ # Temperature, Evapotranspiration variables = ["E"] # "T", -Coello = ECMWF(time=time, start=start, end=end, path=path, variables=variables, lat_lim=latlim, lon_lim=lonlim) +Coello = ECMWF(temporal_resolution=time, start=start, end=end, path=path, variables=variables, lat_lim=latlim, lon_lim=lonlim) Coello.download(dataset="interim") #%% variables = ["SRO"] -Coello = ECMWF(time=time, start=start, end=end, path=path, variables=variables, lat_lim=latlim, lon_lim=lonlim) +Coello = ECMWF(temporal_resolution=time, start=start, end=end, path=path, variables=variables, lat_lim=latlim, lon_lim=lonlim) Coello.download() From 2f1b3e2d91968792d1434283886bd7ffe61e156f Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 19:08:28 +0100 Subject: [PATCH 24/36] make move functions to the abstract class --- earth2observe/abstractdatasource.py | 15 ++++++-- earth2observe/chirps.py | 53 ++++++++++++++++++++-------- earth2observe/ecmwf.py | 45 +++++++++++++++-------- examples/data/ecmwf/data_interim.nc | Bin 17028 -> 0 bytes tests/test_chirps.py | 4 +-- 5 files changed, 84 insertions(+), 33 deletions(-) delete mode 100644 examples/data/ecmwf/data_interim.nc diff --git a/earth2observe/abstractdatasource.py b/earth2observe/abstractdatasource.py index 6f08135..dfb1e3c 100644 --- a/earth2observe/abstractdatasource.py +++ b/earth2observe/abstractdatasource.py @@ -11,8 +11,8 @@ def __init__( temporal_resolution: str = "daily", start: str = None, end: str = None, - path: str = "", - variables: list = None, + # path: str = "", + # variables: list = None, lat_lim: list = None, lon_lim: list = None, fmt: str = "%Y-%m-%d", @@ -38,6 +38,17 @@ def __init__( fmt (str, optional): [description]. Defaults to "%Y-%m-%d". """ + # initialize connection with ecmwf server + self.initialize() + self.temporal_resolution = temporal_resolution + + self.create_grid(lat_lim, lon_lim) + self.check_input_dates(start, end, temporal_resolution, fmt) + pass + + + @abstractmethod + def check_input_dates(self): pass @abstractmethod diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index d320684..b4f6c6f 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -55,24 +55,35 @@ def __init__( fmt (str, optional): [description]. Defaults to "%Y-%m-%d". """ - # Define timestep for the timedates - if temporal_resolution.lower() == "daily": - self.time_freq = "D" - self.output_folder = os.path.join(path, "precipitation", "chirps", "daily") - elif temporal_resolution.lower() == "monthly": - self.time_freq = "MS" - self.output_folder = os.path.join( - path, "Precipitation", "CHIRPS", "Monthly" - ) - else: - raise KeyError("The input temporal_resolution interval is not supported") - - self.time = temporal_resolution + super().__init__( + start=start, + end=end, + temporal_resolution=temporal_resolution, + lat_lim=lat_lim, + lon_lim=lon_lim, + fmt=fmt, + ) + self.output_folder = os.path.join(path, "chirps", "precipitation") # make directory if it not exists if not os.path.exists(self.output_folder): os.makedirs(self.output_folder) + + def check_input_dates(self, start: str, end: str, temporal_resolution: str, fmt: str): + """check validity of input dates + + Parameters + ---------- + temporal_resolution: (str, optional) + [description]. Defaults to 'daily'. + start: (str, optional) + [description]. Defaults to ''. + end: (str, optional) + [description]. Defaults to ''. + fmt: (str, optional) + [description]. Defaults to "%Y-%m-%d". + """ # check temporal_resolution variables if start is None: self.start = pd.Timestamp(self.start_date) @@ -83,9 +94,21 @@ def __init__( self.end = pd.Timestamp(self.end_date) else: self.end = dt.datetime.strptime(end, fmt) + + # Define timestep for the timedates + if temporal_resolution.lower() == "daily": + self.time_freq = "D" + # self.output_folder = os.path.join(path, "precipitation", "chirps", "daily") + elif temporal_resolution.lower() == "monthly": + self.time_freq = "MS" + # self.output_folder = os.path.join( + # path, "Precipitation", "CHIRPS", "Monthly" + # ) + else: + raise KeyError("The input temporal_resolution interval is not supported") + # Create days self.dates = pd.date_range(self.start, self.end, freq=self.time_freq) - self.create_grid(lat_lim, lon_lim) def initialize(self): """Initialize FTP server""" @@ -161,7 +184,7 @@ def download(self, progress_bar: bool = True, cores=None): # Pass variables to parallel function and run args = [ self.output_folder, - self.time, + self.temporal_resolution, self.xID, self.yID, self.lon_lim, diff --git a/earth2observe/ecmwf.py b/earth2observe/ecmwf.py index ff5ab38..fb59d45 100644 --- a/earth2observe/ecmwf.py +++ b/earth2observe/ecmwf.py @@ -57,9 +57,32 @@ def __init__( fmt (str, optional): [description]. Defaults to "%Y-%m-%d". """ - # initialize connection with ecmwf server - self.initialize() + super().__init__( + start=start, + end=end, + temporal_resolution=temporal_resolution, + lat_lim=lat_lim, + lon_lim=lon_lim, + fmt=fmt, + ) + self.path = path + self.vars = variables + + + def check_input_dates(self, start: str, end: str, temporal_resolution: str, fmt: str): + """check validity of input dates + Parameters + ---------- + temporal_resolution: (str, optional) + [description]. Defaults to 'daily'. + start: (str, optional) + [description]. Defaults to ''. + end: (str, optional) + [description]. Defaults to ''. + fmt: (str, optional) + [description]. Defaults to "%Y-%m-%d". + """ self.start = dt.datetime.strptime(start, fmt) self.end = dt.datetime.strptime(end, fmt) @@ -72,12 +95,8 @@ def __init__( elif temporal_resolution == "monthly": self.dates = pd.date_range(self.start, self.end, freq="MS") - self.time = temporal_resolution - self.path = path - self.vars = variables - self.date_str = f"{self.start}/to/{self.end}" - self.create_grid(lat_lim, lon_lim) + def initialize(self): """Initialize connection with ECMWF server""" @@ -178,10 +197,8 @@ def downloadDataset( progress_bar: [bool] True if you want to display a progress bar. """ - # Load factors / unit / type of variables / accounts - - # Create Out directory - out_dir = f"{self.path}/{self.time}/{var_info.get('file name')}" + # Create the directory + out_dir = f"{self.path}/{self.temporal_resolution}/{var_info.get('file name')}" if not os.path.exists(out_dir): os.makedirs(out_dir) @@ -419,9 +436,9 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres Date_good = np.zeros(len(Data_time)) - if self.time == "daily": + if self.temporal_resolution == "daily": days_later = 1 - if self.time == "monthly": + if self.temporal_resolution == "monthly": days_later = calendar.monthrange(year, month)[1] Date_good[ @@ -447,7 +464,7 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres # Define the out name name_out = os.path.join( out_dir, - f"%{var_output_name}_ECMWF_ERA-Interim_{Var_unit}_{self.time}_{year}.{month}.{day}.tif", + f"%{var_output_name}_ECMWF_ERA-Interim_{Var_unit}_{self.temporal_resolution}_{year}.{month}.{day}.tif", ) # Create Tiff files diff --git a/examples/data/ecmwf/data_interim.nc b/examples/data/ecmwf/data_interim.nc deleted file mode 100644 index 3d8fd13145d05ec38d27e979e9c651005ac3d7ec..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17028 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 Kj{K@3O#ch7*du%Z diff --git a/tests/test_chirps.py b/tests/test_chirps.py index 017d663..b64b12a 100644 --- a/tests/test_chirps.py +++ b/tests/test_chirps.py @@ -38,7 +38,7 @@ def test_download( fname = test_create_chirps_object.clipped_fname test_create_chirps_object.download() - filelist = glob.glob(os.path.join(f"{chirps_base_dir}/precipitation/chirps/daily", f"{fname}*.tif")) + filelist = glob.glob(os.path.join(f"{chirps_base_dir}/chirps/precipitation", f"{fname}*.tif")) assert len(filelist) == 10 # delete the files - shutil.rmtree(f"{chirps_base_dir}/precipitation") \ No newline at end of file + shutil.rmtree(f"{chirps_base_dir}/chirps/precipitation") \ No newline at end of file From 7c44cce818d785731070e9dfa23a262b678a37ae Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 20:42:32 +0100 Subject: [PATCH 25/36] add pathlib for paths and update modules to match the abstract class --- earth2observe/chirps.py | 9 +++++++-- earth2observe/ecmwf.py | 13 +++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index b4f6c6f..75e4e80 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -1,6 +1,7 @@ from typing import List import datetime as dt import os +from pathlib import Path from ftplib import FTP import numpy as np @@ -30,6 +31,7 @@ def __init__( start: str = None, end: str = None, path: str = "", + variables: list = None, lat_lim: list = None, lon_lim: list = None, fmt: str = "%Y-%m-%d", @@ -58,18 +60,20 @@ def __init__( super().__init__( start=start, end=end, + variables=variables, temporal_resolution=temporal_resolution, lat_lim=lat_lim, lon_lim=lon_lim, fmt=fmt, ) - self.output_folder = os.path.join(path, "chirps", "precipitation") + self.output_folder = os.path.join(Path(path).absolute(), "chirps", "precipitation") # make directory if it not exists if not os.path.exists(self.output_folder): os.makedirs(self.output_folder) + def check_input_dates(self, start: str, end: str, temporal_resolution: str, fmt: str): """check validity of input dates @@ -163,7 +167,7 @@ def create_grid(self, lat_lim: list, lon_lim: list): ) - def download(self, progress_bar: bool = True, cores=None): + def download(self, progress_bar: bool = True, cores=None, *args, **kwargs): """Download. downloads CHIRPS data @@ -206,6 +210,7 @@ def download(self, progress_bar: bool = True, cores=None): for date in self.dates: self.API(date, args) + if progress_bar: amount = amount + 1 print_progress_bar( diff --git a/earth2observe/ecmwf.py b/earth2observe/ecmwf.py index fb59d45..4f1170e 100644 --- a/earth2observe/ecmwf.py +++ b/earth2observe/ecmwf.py @@ -6,14 +6,15 @@ import datetime as dt import os from typing import Dict +from loguru import logger +import yaml import numpy as np import pandas as pd -import yaml +from pathlib import Path from ecmwfapi import ECMWFDataServer -from loguru import logger from netCDF4 import Dataset -from pyramids.raster import Raster +from pyramids.raster import Raster from earth2observe import __path__ from earth2observe.utils import print_progress_bar from earth2observe.abstractdatasource import AbstractDataSource, AbstractCatalog @@ -60,13 +61,13 @@ def __init__( super().__init__( start=start, end=end, + variables=variables, temporal_resolution=temporal_resolution, lat_lim=lat_lim, lon_lim=lon_lim, fmt=fmt, ) - self.path = path - self.vars = variables + self.path = Path(path).absolute() def check_input_dates(self, start: str, end: str, temporal_resolution: str, fmt: str): @@ -135,7 +136,7 @@ def create_grid(self, lat_lim: list, lon_lim: list): self.lonlim_corr = [lonlim_corr_one, lonlim_corr_two] - def download(self, dataset: str = "interim", progress_bar: bool = True): + def download(self, dataset: str = "interim", progress_bar: bool = True, *args, **kwargs): """Download wrapper over all given variables. ECMWF method downloads ECMWF daily data for a given variable, temporal_resolution From a27631a98c0fa0a6f357a8284b9469e9ebc1752e Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 20:43:31 +0100 Subject: [PATCH 26/36] add abstract module to call all data sources under the hood --- earth2observe/abstractdatasource.py | 33 +++++++++++--------- earth2observe/earth2observe.py | 48 +++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 14 deletions(-) create mode 100644 earth2observe/earth2observe.py diff --git a/earth2observe/abstractdatasource.py b/earth2observe/abstractdatasource.py index dfb1e3c..c501420 100644 --- a/earth2observe/abstractdatasource.py +++ b/earth2observe/abstractdatasource.py @@ -8,14 +8,14 @@ class AbstractDataSource(ABC): """ def __init__( self, - temporal_resolution: str = "daily", start: str = None, end: str = None, - # path: str = "", - # variables: list = None, + variables: list = None, + temporal_resolution: str = "daily", lat_lim: list = None, lon_lim: list = None, fmt: str = "%Y-%m-%d", + # path: str = "", ): """ @@ -41,25 +41,40 @@ def __init__( # initialize connection with ecmwf server self.initialize() self.temporal_resolution = temporal_resolution + # TODO: create a function to check if the given variable exists in the catalog + self.vars = variables self.create_grid(lat_lim, lon_lim) self.check_input_dates(start, end, temporal_resolution, fmt) pass - @abstractmethod def check_input_dates(self): + """Check validity of input dates""" + pass + + @abstractmethod + def initialize(self): + """Initialize connection with the data source server (for non ftp servers)""" + pass + + @abstractmethod + def create_grid(self): + """create a grid from the lat/lon boundaries""" pass @abstractmethod def download(self): """Wrapper over all the given variables.""" + # loop over dates if the downloaded rasters/netcdf are for a specific date out of the required + # list of dates pass # @abstractmethod def downloadDataset(self): """Download single variable/dataset""" + # used for non ftp servers pass @abstractmethod @@ -68,16 +83,6 @@ def API(self): pass - @abstractmethod - def initialize(self): - """Initialize connection with the data source server (for non ftp servers)""" - pass - - @abstractmethod - def create_grid(self): - """create a grid from the lat/lon boundaries""" - pass - class AbstractCatalog(ABC): """abstrach class for the datasource catalog""" diff --git a/earth2observe/earth2observe.py b/earth2observe/earth2observe.py new file mode 100644 index 0000000..9198000 --- /dev/null +++ b/earth2observe/earth2observe.py @@ -0,0 +1,48 @@ +from earth2observe.ecmwf import ECMWF +from earth2observe.chirps import CHIRPS + +class Earth2Observe: + """ + End user class to call all the data source classes abailable in earth2observe. + """ + + DataSources = { + "ecmwf": ECMWF, + "chirps": CHIRPS + } + + + def __init__( + self, + data_source: str = "chirps", + temporal_resolution: str = "daily", + start: str = None, + end: str = None, + path: str = "", + variables: list = None, + lat_lim: list = None, + lon_lim: list = None, + fmt: str = "%Y-%m-%d", + ): + if data_source not in self.DataSources: + raise ValueError(f'{data_source} not supported') + + self.datasource = self.DataSources[data_source]( + start=start, + end=end, + variables=variables, + lat_lim=lat_lim, + lon_lim=lon_lim, + temporal_resolution=temporal_resolution, + path=path, + fmt=fmt, + ) + + def download(self, progress_bar: bool = True, *args, **kwargs): + self.datasource.download( + progress_bar=progress_bar, + *args, + **kwargs + ) + + From 1b1e12f163c0eea2d4070e67d627d8d1c03ff751 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 21:35:24 +0100 Subject: [PATCH 27/36] add tests for the earth2observe module --- tests/conftest.py | 26 ++++++++++- tests/test_chirps.py | 5 +- tests/test_earth2observe.py | 93 +++++++++++++++++++++++++++++++++++++ tests/test_ecmwf.py | 4 +- 4 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 tests/test_earth2observe.py diff --git a/tests/conftest.py b/tests/conftest.py index 4c746f8..602c211 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,6 +9,10 @@ def dates() -> List: return ["2009-01-01", "2009-01-10"] +@pytest.fixture(scope="session") +def number_downloaded_files() -> int: + return 10 + @pytest.fixture(scope="session") def daily_temporal_resolution() -> str: return "daily" @@ -32,6 +36,26 @@ def ecmwf_base_dir() -> Path: return Path("tests/data/ecmwf").absolute() +@pytest.fixture(scope="session") +def chirps_variables() -> List[str]: + return ["precipitation"] # "T", + @pytest.fixture(scope="session") def ecmwf_variables() -> List[str]: - return ["E"] # "T", \ No newline at end of file + return ["E"] # "T", + +@pytest.fixture(scope="session") +def ecmwf_data_source() -> str: + return "ecmwf" + +@pytest.fixture(scope="session") +def ecmwf_data_source_output_dir() -> str: + return Path("tests/data/ecmwf-backend").absolute() + +@pytest.fixture(scope="session") +def chirps_data_source() -> str: + return "chirps" + +@pytest.fixture(scope="session") +def chirps_data_source_output_dir() -> str: + return Path("tests/data/chirps-backend").absolute() \ No newline at end of file diff --git a/tests/test_chirps.py b/tests/test_chirps.py index b64b12a..e65f500 100644 --- a/tests/test_chirps.py +++ b/tests/test_chirps.py @@ -10,6 +10,7 @@ def test_create_chirps_object( dates: List, daily_temporal_resolution: str, + chirps_variables: List[str], lat_bounds: List, lon_bounds: List, chirps_base_dir: str, @@ -19,6 +20,7 @@ def test_create_chirps_object( end=dates[1], lat_lim=lat_bounds, lon_lim=lon_bounds, + variables=chirps_variables, temporal_resolution=daily_temporal_resolution, path=chirps_base_dir ) @@ -34,11 +36,12 @@ def test_create_chirps_object( def test_download( test_create_chirps_object: CHIRPS, chirps_base_dir: str, + number_downloaded_files: int, ): fname = test_create_chirps_object.clipped_fname test_create_chirps_object.download() filelist = glob.glob(os.path.join(f"{chirps_base_dir}/chirps/precipitation", f"{fname}*.tif")) - assert len(filelist) == 10 + assert len(filelist) == number_downloaded_files # delete the files shutil.rmtree(f"{chirps_base_dir}/chirps/precipitation") \ No newline at end of file diff --git a/tests/test_earth2observe.py b/tests/test_earth2observe.py new file mode 100644 index 0000000..f97df8d --- /dev/null +++ b/tests/test_earth2observe.py @@ -0,0 +1,93 @@ +import os +import glob +from typing import List +import shutil +import pytest +from earth2observe.earth2observe import Earth2Observe +from earth2observe.chirps import CHIRPS + +class TestChirpsBackend: + + @pytest.fixture(scope="session") + def test_chirps_data_source_instantiate_object( + self, + chirps_data_source: str, + dates: List, + daily_temporal_resolution: str, + chirps_variables: List[str], + lat_bounds: List, + lon_bounds: List, + chirps_data_source_output_dir: str, + ): + e2o = Earth2Observe( + data_source=chirps_data_source, + start=dates[0], + end=dates[1], + variables=chirps_variables, + lat_lim=lat_bounds, + lon_lim=lon_bounds, + temporal_resolution=daily_temporal_resolution, + path=chirps_data_source_output_dir + ) + assert isinstance(e2o.DataSources, dict) + assert isinstance(e2o.datasource, CHIRPS) + assert e2o.datasource.vars == chirps_variables + assert isinstance(e2o.datasource.lat_lim, list) + return e2o + + def test_download_chirps_backend( + self, + test_chirps_data_source_instantiate_object: CHIRPS, + chirps_data_source_output_dir: str, + number_downloaded_files: int, + ): + test_chirps_data_source_instantiate_object.download() + fname = "P_CHIRPS" + filelist = glob.glob(os.path.join(f"{chirps_data_source_output_dir}/chirps/precipitation", f"{fname}*.tif")) + assert len(filelist) == number_downloaded_files + # delete the files + shutil.rmtree(f"{chirps_data_source_output_dir}/chirps/precipitation") + + + + +class TestECMWFBackend: + + @pytest.fixture(scope="session") + def test_ecmwf_data_source_instantiate_object( + self, + ecmwf_data_source: str, + dates: List, + daily_temporal_resolution: str, + ecmwf_variables: List[str], + lat_bounds: List, + lon_bounds: List, + ecmwf_data_source_output_dir: str, + ): + e2o = Earth2Observe( + data_source=ecmwf_data_source, + start=dates[0], + end=dates[1], + variables=ecmwf_variables, + lat_lim=lat_bounds, + lon_lim=lon_bounds, + temporal_resolution=daily_temporal_resolution, + path=ecmwf_data_source_output_dir + ) + assert isinstance(e2o.DataSources, dict) + assert isinstance(e2o.datasource, CHIRPS) + assert e2o.datasource.vars == ecmwf_variables + assert isinstance(e2o.datasource.lat_lim, list) + return e2o + + def test_download_chirps_backend( + self, + test_ecmwf_data_source_instantiate_object: CHIRPS, + chirps_data_source_output_dir: str, + number_downloaded_files: int, + ): + test_ecmwf_data_source_instantiate_object.download() + filelist = glob.glob(os.path.join(f"{chirps_data_source_output_dir}/daily/Evaporation/", f"*.tif")) + assert len(filelist) == number_downloaded_files + # delete the files + shutil.rmtree(f"{chirps_data_source_output_dir}/daily") \ No newline at end of file diff --git a/tests/test_ecmwf.py b/tests/test_ecmwf.py index a8d9ad6..6f4100f 100644 --- a/tests/test_ecmwf.py +++ b/tests/test_ecmwf.py @@ -28,10 +28,10 @@ def test_create_ecmwf_object( def test_download( test_create_ecmwf_object: ECMWF, ecmwf_base_dir: str, + number_downloaded_files: int, ): - test_create_ecmwf_object.download() filelist = glob.glob(os.path.join(f"{ecmwf_base_dir}/daily/Evaporation/", f"*.tif")) - assert len(filelist) == 10 + assert len(filelist) == number_downloaded_files # delete the files shutil.rmtree(f"{ecmwf_base_dir}/daily") \ No newline at end of file From 189fc5ec7ed7cd835043fdd5d2ac3975cf18f00e Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 21:37:50 +0100 Subject: [PATCH 28/36] reduce downloaded rasters to 5 in tests --- tests/conftest.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 602c211..8055cec 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -7,11 +7,11 @@ @pytest.fixture(scope="session") def dates() -> List: - return ["2009-01-01", "2009-01-10"] + return ["2009-01-01", "2009-01-05"] @pytest.fixture(scope="session") def number_downloaded_files() -> int: - return 10 + return 5 @pytest.fixture(scope="session") def daily_temporal_resolution() -> str: From 39903fa6a52d411b3123b3b0deab1c2508e41cbf Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 21:40:02 +0100 Subject: [PATCH 29/36] fix test check --- tests/test_earth2observe.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/test_earth2observe.py b/tests/test_earth2observe.py index f97df8d..bde40a2 100644 --- a/tests/test_earth2observe.py +++ b/tests/test_earth2observe.py @@ -5,6 +5,7 @@ import pytest from earth2observe.earth2observe import Earth2Observe from earth2observe.chirps import CHIRPS +from earth2observe.ecmwf import ECMWF class TestChirpsBackend: @@ -75,7 +76,7 @@ def test_ecmwf_data_source_instantiate_object( path=ecmwf_data_source_output_dir ) assert isinstance(e2o.DataSources, dict) - assert isinstance(e2o.datasource, CHIRPS) + assert isinstance(e2o.datasource, ECMWF) assert e2o.datasource.vars == ecmwf_variables assert isinstance(e2o.datasource.lat_lim, list) return e2o From 0912e3d98474f2a0981d606404018c14b5cb0b14 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 22:04:53 +0100 Subject: [PATCH 30/36] update tests --- tests/conftest.py | 8 ++++---- tests/test_earth2observe.py | 7 +++---- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 8055cec..fd95f6d 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -28,12 +28,12 @@ def lon_bounds() -> List: @pytest.fixture(scope="session") def chirps_base_dir() -> str: - return "tests/data/chirps" + return "tests/data/delete/chirps" @pytest.fixture(scope="session") def ecmwf_base_dir() -> Path: - return Path("tests/data/ecmwf").absolute() + return Path("tests/data/delete/ecmwf").absolute() @pytest.fixture(scope="session") @@ -50,7 +50,7 @@ def ecmwf_data_source() -> str: @pytest.fixture(scope="session") def ecmwf_data_source_output_dir() -> str: - return Path("tests/data/ecmwf-backend").absolute() + return Path("tests/data/delete/ecmwf-backend").absolute() @pytest.fixture(scope="session") def chirps_data_source() -> str: @@ -58,4 +58,4 @@ def chirps_data_source() -> str: @pytest.fixture(scope="session") def chirps_data_source_output_dir() -> str: - return Path("tests/data/chirps-backend").absolute() \ No newline at end of file + return Path("tests/data/delete/chirps-backend").absolute() \ No newline at end of file diff --git a/tests/test_earth2observe.py b/tests/test_earth2observe.py index bde40a2..8d10ee4 100644 --- a/tests/test_earth2observe.py +++ b/tests/test_earth2observe.py @@ -78,17 +78,16 @@ def test_ecmwf_data_source_instantiate_object( assert isinstance(e2o.DataSources, dict) assert isinstance(e2o.datasource, ECMWF) assert e2o.datasource.vars == ecmwf_variables - assert isinstance(e2o.datasource.lat_lim, list) return e2o def test_download_chirps_backend( self, test_ecmwf_data_source_instantiate_object: CHIRPS, - chirps_data_source_output_dir: str, + ecmwf_data_source_output_dir: str, number_downloaded_files: int, ): test_ecmwf_data_source_instantiate_object.download() - filelist = glob.glob(os.path.join(f"{chirps_data_source_output_dir}/daily/Evaporation/", f"*.tif")) + filelist = glob.glob(os.path.join(f"{ecmwf_data_source_output_dir}/daily/Evaporation/", f"*.tif")) assert len(filelist) == number_downloaded_files # delete the files - shutil.rmtree(f"{chirps_data_source_output_dir}/daily") \ No newline at end of file + shutil.rmtree(f"{ecmwf_data_source_output_dir}/daily") \ No newline at end of file From 4894285bd17c15db454a28c9acf60c9ce2a7a826 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 22:05:42 +0100 Subject: [PATCH 31/36] update examples --- examples/abstract_implementation.py | 51 +++++++++++++++++++++++++++++ examples/ecmwf_data.py | 20 +++++++++-- 2 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 examples/abstract_implementation.py diff --git a/examples/abstract_implementation.py b/examples/abstract_implementation.py new file mode 100644 index 0000000..46f2a6d --- /dev/null +++ b/examples/abstract_implementation.py @@ -0,0 +1,51 @@ +from earth2observe.earth2observe import Earth2Observe + +source = "chirps" +start = "2009-01-01" +end = "2009-01-10" +temporal_resolution = "daily" +latlim = [4.19, 4.64] +lonlim = [-75.65, -74.73] +path = r"examples\data\chirps" +variables = ["precipitation"] +e2o = Earth2Observe( + data_source=source, + start=start, + end=end, + variables=variables, + lat_lim=latlim, + lon_lim=lonlim, + temporal_resolution=temporal_resolution, + path=path +) +# e2o.download() +#%% +path = r"examples\data\chirps-cores" + +e2o = Earth2Observe( + data_source=source, + start=start, + end=end, + variables=variables, + lat_lim=latlim, + lon_lim=lonlim, + temporal_resolution=temporal_resolution, + path=path +) +# e2o.download(cores=4) +#%% + +path = r"examples\data\ecmwf" +source = "ecmwf" +variables = ["E"] +e2o = Earth2Observe( + data_source=source, + start=start, + end=end, + variables=variables, + lat_lim=latlim, + lon_lim=lonlim, + temporal_resolution=temporal_resolution, + path=path +) +e2o.download() \ No newline at end of file diff --git a/examples/ecmwf_data.py b/examples/ecmwf_data.py index 9acb49d..a1c5ce7 100644 --- a/examples/ecmwf_data.py +++ b/examples/ecmwf_data.py @@ -31,11 +31,27 @@ # Temperature, Evapotranspiration variables = ["E"] # "T", -Coello = ECMWF(temporal_resolution=time, start=start, end=end, path=path, variables=variables, lat_lim=latlim, lon_lim=lonlim) +Coello = ECMWF( + temporal_resolution=time, + start=start, + end=end, + path=path, + variables=variables, + lat_lim=latlim, + lon_lim=lonlim +) Coello.download(dataset="interim") #%% variables = ["SRO"] -Coello = ECMWF(temporal_resolution=time, start=start, end=end, path=path, variables=variables, lat_lim=latlim, lon_lim=lonlim) +Coello = ECMWF( + temporal_resolution=time, + start=start, + end=end, + path=path, + variables=variables, + lat_lim=latlim, + lon_lim=lonlim +) Coello.download() From 7e4cb292cd15871fda924c603a38342e1a49fbac Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 22:09:54 +0100 Subject: [PATCH 32/36] refactor --- .github/workflows/ubuntu.yml | 4 +- tests/test_chirps.py | 32 ++++++++------- tests/test_earth2observe.py | 77 +++++++++++++++++++----------------- tests/test_ecmwf.py | 25 ++++++------ 4 files changed, 75 insertions(+), 63 deletions(-) diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 9c667dc..13fd038 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -29,7 +29,7 @@ jobs: python -m pip install --upgrade pip pip install --no-cache-dir Cython pip install --find-links=https://girder.github.io/large_image_wheels --no-cache GDAL - + - name: Test GDAL installation run: | python -c "from osgeo import gdal" @@ -49,4 +49,4 @@ jobs: python -m pytest -vvv --cov=earth2observe --cov-report=xml - name: Upload coverage reports to Codecov with GitHub Action - uses: codecov/codecov-action@v3 \ No newline at end of file + uses: codecov/codecov-action@v3 diff --git a/tests/test_chirps.py b/tests/test_chirps.py index e65f500..ff09f81 100644 --- a/tests/test_chirps.py +++ b/tests/test_chirps.py @@ -1,19 +1,21 @@ -import os -from typing import List import glob +import os import shutil +from typing import List + import pytest + from earth2observe.chirps import CHIRPS @pytest.fixture(scope="session") def test_create_chirps_object( - dates: List, - daily_temporal_resolution: str, - chirps_variables: List[str], - lat_bounds: List, - lon_bounds: List, - chirps_base_dir: str, + dates: List, + daily_temporal_resolution: str, + chirps_variables: List[str], + lat_bounds: List, + lon_bounds: List, + chirps_base_dir: str, ): Coello = CHIRPS( start=dates[0], @@ -22,7 +24,7 @@ def test_create_chirps_object( lon_lim=lon_bounds, variables=chirps_variables, temporal_resolution=daily_temporal_resolution, - path=chirps_base_dir + path=chirps_base_dir, ) assert Coello.api_url == "data.chc.ucsb.edu" assert Coello.lon_boundaries == [-180, 180] @@ -34,14 +36,16 @@ def test_create_chirps_object( def test_download( - test_create_chirps_object: CHIRPS, - chirps_base_dir: str, - number_downloaded_files: int, + test_create_chirps_object: CHIRPS, + chirps_base_dir: str, + number_downloaded_files: int, ): fname = test_create_chirps_object.clipped_fname test_create_chirps_object.download() - filelist = glob.glob(os.path.join(f"{chirps_base_dir}/chirps/precipitation", f"{fname}*.tif")) + filelist = glob.glob( + os.path.join(f"{chirps_base_dir}/chirps/precipitation", f"{fname}*.tif") + ) assert len(filelist) == number_downloaded_files # delete the files - shutil.rmtree(f"{chirps_base_dir}/chirps/precipitation") \ No newline at end of file + shutil.rmtree(f"{chirps_base_dir}/chirps/precipitation") diff --git a/tests/test_earth2observe.py b/tests/test_earth2observe.py index 8d10ee4..44656c7 100644 --- a/tests/test_earth2observe.py +++ b/tests/test_earth2observe.py @@ -1,24 +1,26 @@ -import os import glob -from typing import List +import os import shutil +from typing import List + import pytest -from earth2observe.earth2observe import Earth2Observe + from earth2observe.chirps import CHIRPS +from earth2observe.earth2observe import Earth2Observe from earth2observe.ecmwf import ECMWF -class TestChirpsBackend: +class TestChirpsBackend: @pytest.fixture(scope="session") def test_chirps_data_source_instantiate_object( - self, - chirps_data_source: str, - dates: List, - daily_temporal_resolution: str, - chirps_variables: List[str], - lat_bounds: List, - lon_bounds: List, - chirps_data_source_output_dir: str, + self, + chirps_data_source: str, + dates: List, + daily_temporal_resolution: str, + chirps_variables: List[str], + lat_bounds: List, + lon_bounds: List, + chirps_data_source_output_dir: str, ): e2o = Earth2Observe( data_source=chirps_data_source, @@ -28,7 +30,7 @@ def test_chirps_data_source_instantiate_object( lat_lim=lat_bounds, lon_lim=lon_bounds, temporal_resolution=daily_temporal_resolution, - path=chirps_data_source_output_dir + path=chirps_data_source_output_dir, ) assert isinstance(e2o.DataSources, dict) assert isinstance(e2o.datasource, CHIRPS) @@ -37,33 +39,34 @@ def test_chirps_data_source_instantiate_object( return e2o def test_download_chirps_backend( - self, - test_chirps_data_source_instantiate_object: CHIRPS, - chirps_data_source_output_dir: str, - number_downloaded_files: int, + self, + test_chirps_data_source_instantiate_object: CHIRPS, + chirps_data_source_output_dir: str, + number_downloaded_files: int, ): test_chirps_data_source_instantiate_object.download() fname = "P_CHIRPS" - filelist = glob.glob(os.path.join(f"{chirps_data_source_output_dir}/chirps/precipitation", f"{fname}*.tif")) + filelist = glob.glob( + os.path.join( + f"{chirps_data_source_output_dir}/chirps/precipitation", f"{fname}*.tif" + ) + ) assert len(filelist) == number_downloaded_files # delete the files shutil.rmtree(f"{chirps_data_source_output_dir}/chirps/precipitation") - - class TestECMWFBackend: - @pytest.fixture(scope="session") def test_ecmwf_data_source_instantiate_object( - self, - ecmwf_data_source: str, - dates: List, - daily_temporal_resolution: str, - ecmwf_variables: List[str], - lat_bounds: List, - lon_bounds: List, - ecmwf_data_source_output_dir: str, + self, + ecmwf_data_source: str, + dates: List, + daily_temporal_resolution: str, + ecmwf_variables: List[str], + lat_bounds: List, + lon_bounds: List, + ecmwf_data_source_output_dir: str, ): e2o = Earth2Observe( data_source=ecmwf_data_source, @@ -73,7 +76,7 @@ def test_ecmwf_data_source_instantiate_object( lat_lim=lat_bounds, lon_lim=lon_bounds, temporal_resolution=daily_temporal_resolution, - path=ecmwf_data_source_output_dir + path=ecmwf_data_source_output_dir, ) assert isinstance(e2o.DataSources, dict) assert isinstance(e2o.datasource, ECMWF) @@ -81,13 +84,15 @@ def test_ecmwf_data_source_instantiate_object( return e2o def test_download_chirps_backend( - self, - test_ecmwf_data_source_instantiate_object: CHIRPS, - ecmwf_data_source_output_dir: str, - number_downloaded_files: int, + self, + test_ecmwf_data_source_instantiate_object: CHIRPS, + ecmwf_data_source_output_dir: str, + number_downloaded_files: int, ): test_ecmwf_data_source_instantiate_object.download() - filelist = glob.glob(os.path.join(f"{ecmwf_data_source_output_dir}/daily/Evaporation/", f"*.tif")) + filelist = glob.glob( + os.path.join(f"{ecmwf_data_source_output_dir}/daily/Evaporation/", f"*.tif") + ) assert len(filelist) == number_downloaded_files # delete the files - shutil.rmtree(f"{ecmwf_data_source_output_dir}/daily") \ No newline at end of file + shutil.rmtree(f"{ecmwf_data_source_output_dir}/daily") diff --git a/tests/test_ecmwf.py b/tests/test_ecmwf.py index 6f4100f..a1d1c95 100644 --- a/tests/test_ecmwf.py +++ b/tests/test_ecmwf.py @@ -1,17 +1,20 @@ -import pytest -import os import glob +import os import shutil from typing import List + +import pytest + from earth2observe.ecmwf import ECMWF + @pytest.fixture(scope="session") def test_create_ecmwf_object( - dates: List, - lat_bounds: List, - lon_bounds: List, - ecmwf_base_dir: str, - ecmwf_variables: List[str], + dates: List, + lat_bounds: List, + lon_bounds: List, + ecmwf_base_dir: str, + ecmwf_variables: List[str], ): Coello = ECMWF( start=dates[0], @@ -26,12 +29,12 @@ def test_create_ecmwf_object( def test_download( - test_create_ecmwf_object: ECMWF, - ecmwf_base_dir: str, - number_downloaded_files: int, + test_create_ecmwf_object: ECMWF, + ecmwf_base_dir: str, + number_downloaded_files: int, ): test_create_ecmwf_object.download() filelist = glob.glob(os.path.join(f"{ecmwf_base_dir}/daily/Evaporation/", f"*.tif")) assert len(filelist) == number_downloaded_files # delete the files - shutil.rmtree(f"{ecmwf_base_dir}/daily") \ No newline at end of file + shutil.rmtree(f"{ecmwf_base_dir}/daily") From bed731fad9a936e7b9ac05719146980a002a49dd Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 22:10:31 +0100 Subject: [PATCH 33/36] refactor --- earth2observe/utils.py | 2 +- examples/abstract_implementation.py | 8 ++++---- examples/chirps_data.py | 10 +++++++++- examples/ecmwf_data.py | 4 ++-- requirements.txt | 2 +- tests/conftest.py | 18 ++++++++++++++---- 6 files changed, 31 insertions(+), 13 deletions(-) diff --git a/earth2observe/utils.py b/earth2observe/utils.py index cc6d4c9..a3697a4 100644 --- a/earth2observe/utils.py +++ b/earth2observe/utils.py @@ -42,4 +42,4 @@ def print_progress_bar( sys.stdout.flush() if i == total: - print() \ No newline at end of file + print() diff --git a/examples/abstract_implementation.py b/examples/abstract_implementation.py index 46f2a6d..b260695 100644 --- a/examples/abstract_implementation.py +++ b/examples/abstract_implementation.py @@ -16,7 +16,7 @@ lat_lim=latlim, lon_lim=lonlim, temporal_resolution=temporal_resolution, - path=path + path=path, ) # e2o.download() #%% @@ -30,7 +30,7 @@ lat_lim=latlim, lon_lim=lonlim, temporal_resolution=temporal_resolution, - path=path + path=path, ) # e2o.download(cores=4) #%% @@ -46,6 +46,6 @@ lat_lim=latlim, lon_lim=lonlim, temporal_resolution=temporal_resolution, - path=path + path=path, ) -e2o.download() \ No newline at end of file +e2o.download() diff --git a/examples/chirps_data.py b/examples/chirps_data.py index d11026a..d717b82 100644 --- a/examples/chirps_data.py +++ b/examples/chirps_data.py @@ -1,4 +1,5 @@ from earth2observe.chirps import CHIRPS + # %% precipitation start = "2009-01-01" end = "2009-01-10" @@ -7,7 +8,14 @@ lonlim = [-75.65, -74.73] path = r"examples\data\chirps" -Coello = CHIRPS(start=start, end=end, lat_lim=latlim, lon_lim=lonlim, temporal_resolution=time, path=path) +Coello = CHIRPS( + start=start, + end=end, + lat_lim=latlim, + lon_lim=lonlim, + temporal_resolution=time, + path=path, +) #%% Coello.download() # cores=4 #%% diff --git a/examples/ecmwf_data.py b/examples/ecmwf_data.py index a1c5ce7..d9979e4 100644 --- a/examples/ecmwf_data.py +++ b/examples/ecmwf_data.py @@ -38,7 +38,7 @@ path=path, variables=variables, lat_lim=latlim, - lon_lim=lonlim + lon_lim=lonlim, ) Coello.download(dataset="interim") @@ -51,7 +51,7 @@ path=path, variables=variables, lat_lim=latlim, - lon_lim=lonlim + lon_lim=lonlim, ) Coello.download() diff --git a/requirements.txt b/requirements.txt index 1908cb8..6c4cffa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -6,8 +6,8 @@ loguru >=0.6.0 netCDF4 >=1.6.1 numpy ==1.24.1 pandas >=1.4.4 +pathlib >=1.0.1 pip >=22.3.1 pyramids-gis >=0.2.12 PyYAML >=6.0 -pathlib >=1.0.1 requests >=2.28.1 diff --git a/tests/conftest.py b/tests/conftest.py index fd95f6d..26b5b3c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,22 +1,26 @@ -import pytest -from typing import List from pathlib import Path -from tests.gee.conftest import * +from typing import List +import pytest + +from tests.gee.conftest import * @pytest.fixture(scope="session") def dates() -> List: return ["2009-01-01", "2009-01-05"] + @pytest.fixture(scope="session") def number_downloaded_files() -> int: return 5 + @pytest.fixture(scope="session") def daily_temporal_resolution() -> str: return "daily" + @pytest.fixture(scope="session") def lat_bounds() -> List: return [4.19, 4.64] @@ -26,6 +30,7 @@ def lat_bounds() -> List: def lon_bounds() -> List: return [-75.65, -74.73] + @pytest.fixture(scope="session") def chirps_base_dir() -> str: return "tests/data/delete/chirps" @@ -40,22 +45,27 @@ def ecmwf_base_dir() -> Path: def chirps_variables() -> List[str]: return ["precipitation"] # "T", + @pytest.fixture(scope="session") def ecmwf_variables() -> List[str]: return ["E"] # "T", + @pytest.fixture(scope="session") def ecmwf_data_source() -> str: return "ecmwf" + @pytest.fixture(scope="session") def ecmwf_data_source_output_dir() -> str: return Path("tests/data/delete/ecmwf-backend").absolute() + @pytest.fixture(scope="session") def chirps_data_source() -> str: return "chirps" + @pytest.fixture(scope="session") def chirps_data_source_output_dir() -> str: - return Path("tests/data/delete/chirps-backend").absolute() \ No newline at end of file + return Path("tests/data/delete/chirps-backend").absolute() From 778c1f7fad85aa211f1123c15e2a52f13a9bff31 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 22:10:57 +0100 Subject: [PATCH 34/36] refactor --- earth2observe/abstractdatasource.py | 41 +++++----- earth2observe/chirps.py | 86 +++++++++++--------- earth2observe/earth2observe.py | 44 ++++------- earth2observe/ecmwf.py | 117 ++++++++++++++++------------ 4 files changed, 153 insertions(+), 135 deletions(-) diff --git a/earth2observe/abstractdatasource.py b/earth2observe/abstractdatasource.py index c501420..f28ebea 100644 --- a/earth2observe/abstractdatasource.py +++ b/earth2observe/abstractdatasource.py @@ -1,21 +1,20 @@ -from typing import Dict from abc import ABC, abstractmethod +from typing import Dict class AbstractDataSource(ABC): - """ - Bluebrint for all class for different datasources - """ + """Bluebrint for all class for different datasources.""" + def __init__( - self, - start: str = None, - end: str = None, - variables: list = None, - temporal_resolution: str = "daily", - lat_lim: list = None, - lon_lim: list = None, - fmt: str = "%Y-%m-%d", - # path: str = "", + self, + start: str = None, + end: str = None, + variables: list = None, + temporal_resolution: str = "daily", + lat_lim: list = None, + lon_lim: list = None, + fmt: str = "%Y-%m-%d", + # path: str = "", ): """ @@ -50,7 +49,7 @@ def __init__( @abstractmethod def check_input_dates(self): - """Check validity of input dates""" + """Check validity of input dates.""" pass @abstractmethod @@ -60,7 +59,7 @@ def initialize(self): @abstractmethod def create_grid(self): - """create a grid from the lat/lon boundaries""" + """create a grid from the lat/lon boundaries.""" pass @abstractmethod @@ -70,29 +69,27 @@ def download(self): # list of dates pass - # @abstractmethod def downloadDataset(self): - """Download single variable/dataset""" + """Download single variable/dataset.""" # used for non ftp servers pass @abstractmethod def API(self): - """send/recieve request to the dataset server""" + """send/recieve request to the dataset server.""" pass - class AbstractCatalog(ABC): - """abstrach class for the datasource catalog""" + """abstrach class for the datasource catalog.""" @abstractmethod def get_catalog(self): - """read the catalog of the datasource from disk or retrieve it from server""" + """read the catalog of the datasource from disk or retrieve it from server.""" pass @abstractmethod def get_variable(self, var_name) -> Dict[str, str]: - """get the details of a specific variable""" + """get the details of a specific variable.""" pass diff --git a/earth2observe/chirps.py b/earth2observe/chirps.py index 75e4e80..29b554e 100644 --- a/earth2observe/chirps.py +++ b/earth2observe/chirps.py @@ -1,8 +1,7 @@ -from typing import List import datetime as dt import os -from pathlib import Path from ftplib import FTP +from pathlib import Path import numpy as np import pandas as pd @@ -10,12 +9,14 @@ from osgeo import gdal from pyramids.raster import Raster from pyramids.utils import extractFromGZ -from earth2observe.abstractdatasource import AbstractDataSource, AbstractCatalog + +from earth2observe.abstractdatasource import AbstractCatalog, AbstractDataSource from earth2observe.utils import print_progress_bar class CHIRPS(AbstractDataSource): """CHIRPS.""" + api_url: str = "data.chc.ucsb.edu" start_date: str = "1981-01-01" end_date: str = "Now" @@ -26,15 +27,15 @@ class CHIRPS(AbstractDataSource): clipped_fname = "P_CHIRPS.v2.0" def __init__( - self, - temporal_resolution: str = "daily", - start: str = None, - end: str = None, - path: str = "", - variables: list = None, - lat_lim: list = None, - lon_lim: list = None, - fmt: str = "%Y-%m-%d", + self, + temporal_resolution: str = "daily", + start: str = None, + end: str = None, + path: str = "", + variables: list = None, + lat_lim: list = None, + lon_lim: list = None, + fmt: str = "%Y-%m-%d", ): """CHIRPS. @@ -66,16 +67,18 @@ def __init__( lon_lim=lon_lim, fmt=fmt, ) - self.output_folder = os.path.join(Path(path).absolute(), "chirps", "precipitation") + self.output_folder = os.path.join( + Path(path).absolute(), "chirps", "precipitation" + ) # make directory if it not exists if not os.path.exists(self.output_folder): os.makedirs(self.output_folder) - - - def check_input_dates(self, start: str, end: str, temporal_resolution: str, fmt: str): - """check validity of input dates + def check_input_dates( + self, start: str, end: str, temporal_resolution: str, fmt: str + ): + """check validity of input dates. Parameters ---------- @@ -115,12 +118,12 @@ def check_input_dates(self, start: str, end: str, temporal_resolution: str, fmt: self.dates = pd.date_range(self.start, self.end, freq=self.time_freq) def initialize(self): - """Initialize FTP server""" + """Initialize FTP server.""" print("FTP server datasources does not need server initialization") pass def create_grid(self, lat_lim: list, lon_lim: list): - """Create_grid + """Create_grid. create grid from the lat/lon boundaries @@ -166,7 +169,6 @@ def create_grid(self, lat_lim: list, lon_lim: list): ) ) - def download(self, progress_bar: bool = True, cores=None, *args, **kwargs): """Download. @@ -228,14 +230,13 @@ def download(self, progress_bar: bool = True, cores=None, *args, **kwargs): return results def API(self, date, args): - """form the request url abd trigger the request + """form the request url abd trigger the request. Parameters ---------- date: args: [list] - """ [output_folder, temp_resolution, xID, yID, lon_lim, latlim] = args @@ -252,28 +253,31 @@ def API(self, date, args): filename = f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif.gz" outfilename = os.path.join( output_folder, - f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" + f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif", ) DirFileEnd = os.path.join( output_folder, - f"{self.clipped_fname}_mm-day-1_daily_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" + f"{self.clipped_fname}_mm-day-1_daily_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif", ) elif temp_resolution == "monthly": - filename = f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.tif.gz" + filename = ( + f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.tif.gz" + ) outfilename = os.path.join( output_folder, - f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.tif" + f"{self.globe_fname}.{date.strftime('%Y')}.{date.strftime('%m')}.tif", ) DirFileEnd = os.path.join( output_folder, - f"{self.clipped_fname}_mm-month-1_monthly_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif" + f"{self.clipped_fname}_mm-month-1_monthly_{date.strftime('%Y')}.{date.strftime('%m')}.{date.strftime('%d')}.tif", ) else: raise KeyError("The input temporal_resolution interval is not supported") self.callAPI(pathFTP, output_folder, filename) - self.post_download(output_folder, filename, lon_lim, latlim, xID, yID, outfilename, DirFileEnd) - + self.post_download( + output_folder, filename, lon_lim, latlim, xID, yID, outfilename, DirFileEnd + ) @staticmethod def callAPI(pathFTP: str, output_folder: str, filename: str): @@ -314,9 +318,18 @@ def callAPI(pathFTP: str, output_folder: str, filename: str): ftp.retrbinary("RETR " + filename, lf.write, 8192) lf.close() - - def post_download(self, output_folder, filename, lon_lim, latlim, xID, yID, outfilename, DirFileEnd): - """clip the downloaded data to the extent we want + def post_download( + self, + output_folder, + filename, + lon_lim, + latlim, + xID, + yID, + outfilename, + DirFileEnd, + ): + """clip the downloaded data to the extent we want. Parameters ---------- @@ -379,14 +392,15 @@ def listAttributes(self): print("\n") + class Catalog(AbstractCatalog): - """ CHIRPS data catalog""" + """CHIRPS data catalog.""" def __init__(self): self.catalog = self.get_catalog() def get_catalog(self): - """return the catalog""" + """return the catalog.""" return { "Precipitation": { "descriptions": "rainfall [mm/temporal_resolution step]", @@ -394,9 +408,9 @@ def get_catalog(self): "temporal resolution": ["daily", "monthly"], "file name": "rainfall", "var_name": "R", - } + } } def get_variable(self, var_name): - """get the details of a specific variable""" + """get the details of a specific variable.""" return self.catalog.get(var_name) diff --git a/earth2observe/earth2observe.py b/earth2observe/earth2observe.py index 9198000..6ed6ab4 100644 --- a/earth2observe/earth2observe.py +++ b/earth2observe/earth2observe.py @@ -1,31 +1,27 @@ -from earth2observe.ecmwf import ECMWF +"""Front end module that runs each data source backend.""" from earth2observe.chirps import CHIRPS +from earth2observe.ecmwf import ECMWF -class Earth2Observe: - """ - End user class to call all the data source classes abailable in earth2observe. - """ - DataSources = { - "ecmwf": ECMWF, - "chirps": CHIRPS - } +class Earth2Observe: + """End user class to call all the data source classes abailable in earth2observe.""" + DataSources = {"ecmwf": ECMWF, "chirps": CHIRPS} def __init__( - self, - data_source: str = "chirps", - temporal_resolution: str = "daily", - start: str = None, - end: str = None, - path: str = "", - variables: list = None, - lat_lim: list = None, - lon_lim: list = None, - fmt: str = "%Y-%m-%d", + self, + data_source: str = "chirps", + temporal_resolution: str = "daily", + start: str = None, + end: str = None, + path: str = "", + variables: list = None, + lat_lim: list = None, + lon_lim: list = None, + fmt: str = "%Y-%m-%d", ): if data_source not in self.DataSources: - raise ValueError(f'{data_source} not supported') + raise ValueError(f"{data_source} not supported") self.datasource = self.DataSources[data_source]( start=start, @@ -39,10 +35,4 @@ def __init__( ) def download(self, progress_bar: bool = True, *args, **kwargs): - self.datasource.download( - progress_bar=progress_bar, - *args, - **kwargs - ) - - + self.datasource.download(progress_bar=progress_bar, *args, **kwargs) diff --git a/earth2observe/ecmwf.py b/earth2observe/ecmwf.py index 4f1170e..8c2dce4 100644 --- a/earth2observe/ecmwf.py +++ b/earth2observe/ecmwf.py @@ -5,27 +5,31 @@ import calendar import datetime as dt import os +from pathlib import Path from typing import Dict -from loguru import logger -import yaml + import numpy as np import pandas as pd -from pathlib import Path +import yaml from ecmwfapi import ECMWFDataServer +from loguru import logger from netCDF4 import Dataset - from pyramids.raster import Raster + from earth2observe import __path__ +from earth2observe.abstractdatasource import AbstractCatalog, AbstractDataSource from earth2observe.utils import print_progress_bar -from earth2observe.abstractdatasource import AbstractDataSource, AbstractCatalog + class ECMWF(AbstractDataSource): """RemoteSensing. RemoteSensing class contains methods to download ECMWF data """ + temporal_resolution = ["daily", "monthly"] spatial_resolution = 0.125 + def __init__( self, temporal_resolution: str = "daily", @@ -69,9 +73,10 @@ def __init__( ) self.path = Path(path).absolute() - - def check_input_dates(self, start: str, end: str, temporal_resolution: str, fmt: str): - """check validity of input dates + def check_input_dates( + self, start: str, end: str, temporal_resolution: str, fmt: str + ): + """check validity of input dates. Parameters ---------- @@ -98,22 +103,22 @@ def check_input_dates(self, start: str, end: str, temporal_resolution: str, fmt: self.date_str = f"{self.start}/to/{self.end}" - def initialize(self): - """Initialize connection with ECMWF server""" + """Initialize connection with ECMWF server.""" try: - url = os.environ['ECMWF_API_URL'] - key = os.environ['ECMWF_API_KEY'] - email = os.environ['ECMWF_API_EMAIL'] + url = os.environ["ECMWF_API_URL"] + key = os.environ["ECMWF_API_KEY"] + email = os.environ["ECMWF_API_EMAIL"] except KeyError: - raise AuthenticationError(f"Please define the following environment variables to successfully establish a " - f"connection with ecmwf server ECMWF_API_URL, ECMWF_API_KEY, ECMWF_API_EMAIL") + raise AuthenticationError( + "Please define the following environment variables to successfully establish a " + "connection with ecmwf server ECMWF_API_URL, ECMWF_API_KEY, ECMWF_API_EMAIL" + ) self.server = ECMWFDataServer(url=url, key=key, email=email) - def create_grid(self, lat_lim: list, lon_lim: list): - """Create_grid + """Create_grid. create grid from the lat/lon boundaries @@ -135,8 +140,9 @@ def create_grid(self, lat_lim: list, lon_lim: list): lonlim_corr_two = np.ceil(lon_lim[1] / cell_size) * cell_size self.lonlim_corr = [lonlim_corr_one, lonlim_corr_two] - - def download(self, dataset: str = "interim", progress_bar: bool = True, *args, **kwargs): + def download( + self, dataset: str = "interim", progress_bar: bool = True, *args, **kwargs + ): """Download wrapper over all given variables. ECMWF method downloads ECMWF daily data for a given variable, temporal_resolution @@ -171,7 +177,10 @@ def download(self, dataset: str = "interim", progress_bar: bool = True, *args, * os.remove(del_ecmwf_dataset) def downloadDataset( - self, var_info: Dict[str, str], dataset: str = "interim", progress_bar: bool = True + self, + var_info: Dict[str, str], + dataset: str = "interim", + progress_bar: bool = True, ): """Download a climate variable. @@ -209,10 +218,8 @@ def downloadDataset( # process the downloaded data self.post_download(var_info, out_dir, dataset, progress_bar) - - def API(self, var_info, dataset): - """form the request url abd trigger the request + """form the request url abd trigger the request. Parameters ---------- @@ -288,23 +295,22 @@ def API(self, var_info, dataset): dataset=dataset, ) - @staticmethod def callAPI( - server, - output_folder: str, - download_type: str, - stream: str, - levtype: str, - param: str, - step: str, - grid: str, - time_str: str, - date_str: str, - type_str: str, - class_str: str, - area_str: str, - dataset: str = "interim", + server, + output_folder: str, + download_type: str, + stream: str, + levtype: str, + param: str, + step: str, + grid: str, + time_str: str, + date_str: str, + type_str: str, + class_str: str, + area_str: str, + dataset: str = "interim", ): """send the request to the server. @@ -367,8 +373,10 @@ def callAPI( } ) - def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progress_bar: bool=True): - """ clip the downloaded data to the extent we want + def post_download( + self, var_info: Dict[str, str], out_dir, dataset: str, progress_bar: bool = True + ): + """clip the downloaded data to the extent we want. Parameters ---------- @@ -412,7 +420,16 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres # Define the georeference information geo_four = np.nanmax(lats) geo_one = np.nanmin(lons) - geo = tuple([geo_one, self.spatial_resolution, 0.0, geo_four, 0.0, -1 * self.spatial_resolution]) + geo = tuple( + [ + geo_one, + self.spatial_resolution, + 0.0, + geo_four, + 0.0, + -1 * self.spatial_resolution, + ] + ) # Create Waitbar if progress_bar: @@ -484,27 +501,27 @@ def post_download(self, var_info: Dict[str, str], out_dir, dataset: str, progres fh.close() + class Catalog(AbstractCatalog): - """ECMWF data catalog - This class contains the information about the ECMWF variables - http://rda.ucar.edu/cgi-bin/transform?xml=/metadata/ParameterTables/WMO_GRIB1.98-0.128.xml&view=gribdoc. - """ + """ECMWF data catalog This class contains the information about the ECMWF variables http://rda.ucar.edu/cgi-bin/transform?xml=/metadata/ParameterTables/WMO_GRIB1.98-0.128.xml&view=gribdoc.""" + def __init__(self, version: int = 1): # get the catalog self.catalog = self.get_catalog() self.version = version - def get_catalog(self): - """readthe data catalog from disk""" + """readthe data catalog from disk.""" with open(f"{__path__[0]}/ecmwf_data_catalog.yaml", "r") as stream: catalog = yaml.safe_load(stream) return catalog def get_variable(self, var_name): - """retrieve a variable form the datasource catalog""" + """retrieve a variable form the datasource catalog.""" return self.catalog.get(var_name) + class AuthenticationError(Exception): - """Failed to establish connection with ECMWF server""" - pass \ No newline at end of file + """Failed to establish connection with ECMWF server.""" + + pass From 7e77edb10e7f204166ea4f5fda626cd8e3d69875 Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 22:13:12 +0100 Subject: [PATCH 35/36] remove un-necessary files --- .gitignore | 1 + earth2observe/mswep.py | 2 -- tests/mo/mswep.py | 2 ++ 3 files changed, 3 insertions(+), 2 deletions(-) delete mode 100644 earth2observe/mswep.py create mode 100644 tests/mo/mswep.py diff --git a/.gitignore b/.gitignore index af2d68c..60465f6 100644 --- a/.gitignore +++ b/.gitignore @@ -150,3 +150,4 @@ conda/ .idea/* examples/data/chirps/* *.xml +tests/mo/* \ No newline at end of file diff --git a/earth2observe/mswep.py b/earth2observe/mswep.py deleted file mode 100644 index d2b779e..0000000 --- a/earth2observe/mswep.py +++ /dev/null @@ -1,2 +0,0 @@ -# class MSWEP(): -"http://www.gloh2o.org/mswx/" \ No newline at end of file diff --git a/tests/mo/mswep.py b/tests/mo/mswep.py new file mode 100644 index 0000000..9f96b1a --- /dev/null +++ b/tests/mo/mswep.py @@ -0,0 +1,2 @@ +# class MSWEP(): +"""http://www.gloh2o.org/mswx/""" From 0c9ce550e38221f6e0f06a8da99eecce559237af Mon Sep 17 00:00:00 2001 From: Mostafa Farrag Date: Sun, 15 Jan 2023 22:16:08 +0100 Subject: [PATCH 36/36] update necessities --- HISTORY.rst | 4 +++- README.md | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index a53ac67..fc87258 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -19,8 +19,10 @@ History * fix pypi package names in the requirements.txt file * fix python version in requirement.txt -0.2.0 (2023-01-14) +0.2.0 (2023-01-15) ------------------ * bump up numpy and pyramids versions * create an abstract class for datasource and catalog as a bluebrint for all data sources +* test all classes in CI +* use pathlib to deal with paths diff --git a/README.md b/README.md index 27fa90b..03e7a4f 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ pip install git+https://github.com/MAfarrag/earthobserve ## pip to install the last release you can easly use pip ``` -pip install earthobserve==0.1.7 +pip install earthobserve==0.2.0 ``` Quick start