Repository: OuyangWenyu/hydrodataset (language: python)

Issue:
Dev
DAYMET, ERA5-LAND, PMLV2, MOD16A2V105, NLDAS


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 5ec9723..b142843 100644
--- a/.gitignore
+++ b/.gitignore
@@ -128,12 +128,12 @@ dmypy.json
 # Pyre type checker
 .pyre/
 .idea
-/hydrobench/app/download/dask-worker-space/
+/hydrodataset/app/download/dask-worker-space/
 /test/test_data/01013500_2000_01-02_nomask.nc
 /test/cache/
 /test/test_data/
-/hydrobench/app/download/cache/
-/hydrobench/app/daymet4basins/cache/
-/hydrobench/nldas4basins/earth_data
-/hydrobench/nldas4basins/subset_NLDAS_FORA0125_*.txt
-/hydrobench/modis4basins/*download.txt
+/hydrodataset/app/download/cache/
+/hydrodataset/app/daymet4basins/cache/
+/hydrodataset/nldas4basins/earth_data
+/hydrodataset/nldas4basins/subset_NLDAS_FORA0125_*.txt
+/hydrodataset/modis4basins/*download.txt
diff --git a/README.md b/README.md
index a725cfe..5cd48f8 100644
--- a/README.md
+++ b/README.md
@@ -1,13 +1,13 @@
-# HydroBench
+# HydroDataset
 
-Data downloader and processor for Hydrologic Modeling
+Dataset downloader and processor for Watershed Hydrologic Modeling
 
-## Data source zoo list
+## Datasets zoo list
 
 - CAMELS/MOPEX/LAMAH
 - Daymet
-- ECMWF
-- MODIS
+- ECMWF ERA5-Land
+- MODIS ET
 - NLDAS
 
 More details are shown in the following sections.
@@ -56,7 +56,7 @@ You can also use the following code to download CAMELS-US (notice: the unzipped
 ```Python
 import os
 import definitions
-from hydrobench.data.data_camels import Camels
+from hydrodataset.data.data_camels import Camels
 
 # DATASET_DIR is defined in the definitions.py file
 camels_path = os.path.join(definitions.DATASET_DIR, "camels", "camels_us")
@@ -90,6 +90,7 @@ camels
     └── ... 
 canopex
     └── Boundaries.zip
+    └── HYSETS_watershed_properties.txt
     └── ...   
 lamah_ce
     └── 2_LamaH-CE_daily.tar.gz
@@ -119,7 +120,7 @@ We provided some scripts to process the Daymet grid data for basins:
 - If you want to get P (precipitation), PE (potential evapotranspiration), Q (streamflow) and Basin areas, please use
   hydrobench/app/daymet4basins/pbm_p_pe_q_basin_area.py
 
-## ECMWF
+## ECMWF ERA5-Land
 
 ### Download ERA5-Land data
 
@@ -131,7 +132,7 @@ from https://cds.climate.copernicus.eu/cdsapp#!/dataset/reanalysis-era5-land?tab
 
 TODO: Regrid the raw data to the required resolutions (src/regrid.py from https://github.com/pangeo-data/WeatherBench)
 
-## MODIS
+## MODIS ET
 
 ### Download basin mean ET data from GEE
 
diff --git a/docs/source/conf.py b/docs/source/conf.py
index e44c7ce..819c913 100644
--- a/docs/source/conf.py
+++ b/docs/source/conf.py
@@ -18,7 +18,7 @@
 
 # -- Project information -----------------------------------------------------
 
-project = 'HydroBench'
+project = 'HydroDataset'
 copyright = '2021, OuyangWenyu'
 author = 'OuyangWenyu'
 
diff --git a/docs/source/develop.rst b/docs/source/develop.rst
index a7c4c90..7184087 100644
--- a/docs/source/develop.rst
+++ b/docs/source/develop.rst
@@ -6,30 +6,24 @@ Design strategy
 --------------------
 The whole structure:
 
-* docs: the document for HydroBench
-* hydrobench: the directory of core code
+* docs: the document for HydroDatasets
+* hydrodatasets: the directory of core code
 * test: all testing code and data
 
-Let's dive into the "hydrobench" directory.
-
-We could set three individual parts for three datasets respectively.
-However, these parts share many common code, hence, we think it's a better way to design the structure
-according to the concrete data processing at first. We'll see if it is still good when nearly finishing.
-
-Now the directories in "hydrobench" are:
+Now the directories in "hydrodatasets" include:
 
 * app: scripts for downloading and preprocessing source data
 * data: this directory contains the data-source classes for source data;
 * daymet4basins: this is the directory for downloading and processing daymet data for camels-basins' boundaries;
-* ecmwf4basins: this is the directory for downloading and processing ERA5 data;
-* modis4basins: this is the directory for downloading and processing MODIS products data;
-* nldas4basins: this is the directory for downloading and processing NLDAS data;
+* ecmwf4basins: this is the directory for downloading and processing ERA5-Land data;
+* modis4basins: this is the directory for downloading and processing MODIS ET products data;
+* nldas4basins: this is the directory for downloading and processing NLDAS forcing data;
 * pet: all methods for calculating potential evapotranspiration are here;
 * utils: all utility functions.
 
 Conventions
 ----------------------
-* Please write unittest code for all functions.
+* Please write pytest code for all your defined functions.
 * Please write comments by English, and note we use the the same format in `this example <https://sphinxcontrib-napoleon.readthedocs.io/en/latest/example_numpy.html#example-numpy>`_.
 
 Update documents
@@ -39,6 +33,6 @@ After adding new features or modifying existed code, please update the document:
 .. code-block:: shell
 
     cd docs
-    sphinx-apidoc -o source/ ../hydrobench
+    sphinx-apidoc -o source/ ../hydrodatasets
     make html
 
diff --git a/docs/source/hydrobench.app.daymet4basins.rst b/docs/source/hydrobench.app.daymet4basins.rst
deleted file mode 100644
index 0f954ea..0000000
--- a/docs/source/hydrobench.app.daymet4basins.rst
+++ /dev/null
@@ -1,53 +0,0 @@
-hydrobench.app.daymet4basins package
-====================================
-
-Submodules
-----------
-
-hydrobench.app.daymet4basins.calculate\_basin\_mean\_forcing\_include\_pet module
----------------------------------------------------------------------------------
-
-.. automodule:: hydrobench.app.daymet4basins.calculate_basin_mean_forcing_include_pet
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.app.daymet4basins.calculate\_basin\_mean\_values module
-------------------------------------------------------------------
-
-.. automodule:: hydrobench.app.daymet4basins.calculate_basin_mean_values
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.app.daymet4basins.cut\_nc\_to\_bounds\_add\_pet module
------------------------------------------------------------------
-
-.. automodule:: hydrobench.app.daymet4basins.cut_nc_to_bounds_add_pet
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.app.daymet4basins.pbm\_p\_pe\_q\_basin\_area module
---------------------------------------------------------------
-
-.. automodule:: hydrobench.app.daymet4basins.pbm_p_pe_q_basin_area
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.app.daymet4basins.regrid\_daymet\_nc module
-------------------------------------------------------
-
-.. automodule:: hydrobench.app.daymet4basins.regrid_daymet_nc
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.app.daymet4basins
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.app.download.rst b/docs/source/hydrobench.app.download.rst
deleted file mode 100644
index 52aec2b..0000000
--- a/docs/source/hydrobench.app.download.rst
+++ /dev/null
@@ -1,53 +0,0 @@
-hydrobench.app.download package
-===============================
-
-Submodules
-----------
-
-hydrobench.app.download.download\_daymet\_camels\_basin module
---------------------------------------------------------------
-
-.. automodule:: hydrobench.app.download.download_daymet_camels_basin
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.app.download.download\_daymet\_camels\_outside\_nldi module
-----------------------------------------------------------------------
-
-.. automodule:: hydrobench.app.download.download_daymet_camels_outside_nldi
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.app.download.download\_daymet\_nldi\_camels\_basin module
---------------------------------------------------------------------
-
-.. automodule:: hydrobench.app.download.download_daymet_nldi_camels_basin
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.app.download.download\_nldas\_hourly module
-------------------------------------------------------
-
-.. automodule:: hydrobench.app.download.download_nldas_hourly
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.app.download.download\_nldi module
----------------------------------------------
-
-.. automodule:: hydrobench.app.download.download_nldi
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.app.download
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.app.modis4basins.rst b/docs/source/hydrobench.app.modis4basins.rst
deleted file mode 100644
index 5871f58..0000000
--- a/docs/source/hydrobench.app.modis4basins.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-hydrobench.app.modis4basins package
-===================================
-
-Submodules
-----------
-
-hydrobench.app.modis4basins.trans\_modis\_et\_to\_camels\_format module
------------------------------------------------------------------------
-
-.. automodule:: hydrobench.app.modis4basins.trans_modis_et_to_camels_format
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.app.modis4basins
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.app.nldas4basins.rst b/docs/source/hydrobench.app.nldas4basins.rst
deleted file mode 100644
index e6f0c37..0000000
--- a/docs/source/hydrobench.app.nldas4basins.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-hydrobench.app.nldas4basins package
-===================================
-
-Submodules
-----------
-
-hydrobench.app.nldas4basins.trans\_nldas\_to\_camels\_format module
--------------------------------------------------------------------
-
-.. automodule:: hydrobench.app.nldas4basins.trans_nldas_to_camels_format
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.app.nldas4basins
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.app.rst b/docs/source/hydrobench.app.rst
deleted file mode 100644
index 3e53e5f..0000000
--- a/docs/source/hydrobench.app.rst
+++ /dev/null
@@ -1,32 +0,0 @@
-hydrobench.app package
-======================
-
-Subpackages
------------
-
-.. toctree::
-   :maxdepth: 4
-
-   hydrobench.app.daymet4basins
-   hydrobench.app.download
-   hydrobench.app.modis4basins
-   hydrobench.app.nldas4basins
-
-Submodules
-----------
-
-hydrobench.app.script\_args module
-----------------------------------
-
-.. automodule:: hydrobench.app.script_args
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.app
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.data.rst b/docs/source/hydrobench.data.rst
deleted file mode 100644
index 68db710..0000000
--- a/docs/source/hydrobench.data.rst
+++ /dev/null
@@ -1,45 +0,0 @@
-hydrobench.data package
-=======================
-
-Submodules
-----------
-
-hydrobench.data.data\_base module
----------------------------------
-
-.. automodule:: hydrobench.data.data_base
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.data.data\_camels module
------------------------------------
-
-.. automodule:: hydrobench.data.data_camels
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.data.data\_daymet4camels module
-------------------------------------------
-
-.. automodule:: hydrobench.data.data_daymet4camels
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.data.stat module
----------------------------
-
-.. automodule:: hydrobench.data.stat
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.data
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.daymet4basins.rst b/docs/source/hydrobench.daymet4basins.rst
deleted file mode 100644
index 10ffad6..0000000
--- a/docs/source/hydrobench.daymet4basins.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-hydrobench.daymet4basins package
-================================
-
-Submodules
-----------
-
-hydrobench.daymet4basins.basin\_daymet\_process module
-------------------------------------------------------
-
-.. automodule:: hydrobench.daymet4basins.basin_daymet_process
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.daymet4basins
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.ecmwf4basins.rst b/docs/source/hydrobench.ecmwf4basins.rst
deleted file mode 100644
index 979fdf2..0000000
--- a/docs/source/hydrobench.ecmwf4basins.rst
+++ /dev/null
@@ -1,21 +0,0 @@
-hydrobench.ecmwf4basins package
-===============================
-
-Submodules
-----------
-
-hydrobench.ecmwf4basins.download\_era5\_land module
----------------------------------------------------
-
-.. automodule:: hydrobench.ecmwf4basins.download_era5_land
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.ecmwf4basins
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.modis4basins.rst b/docs/source/hydrobench.modis4basins.rst
deleted file mode 100644
index d329eb7..0000000
--- a/docs/source/hydrobench.modis4basins.rst
+++ /dev/null
@@ -1,53 +0,0 @@
-hydrobench.modis4basins package
-===============================
-
-Submodules
-----------
-
-hydrobench.modis4basins.DAACDataDownload module
------------------------------------------------
-
-.. automodule:: hydrobench.modis4basins.DAACDataDownload
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.modis4basins.EarthdataLoginSetup module
---------------------------------------------------
-
-.. automodule:: hydrobench.modis4basins.EarthdataLoginSetup
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.modis4basins.basin\_mod16a2v105\_process module
-----------------------------------------------------------
-
-.. automodule:: hydrobench.modis4basins.basin_mod16a2v105_process
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.modis4basins.basin\_pmlv2\_process module
-----------------------------------------------------
-
-.. automodule:: hydrobench.modis4basins.basin_pmlv2_process
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.modis4basins.get\_modis module
------------------------------------------
-
-.. automodule:: hydrobench.modis4basins.get_modis
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.modis4basins
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.nldas4basins.rst b/docs/source/hydrobench.nldas4basins.rst
deleted file mode 100644
index b6d241b..0000000
--- a/docs/source/hydrobench.nldas4basins.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-hydrobench.nldas4basins package
-===============================
-
-Submodules
-----------
-
-hydrobench.nldas4basins.basin\_nldas\_process module
-----------------------------------------------------
-
-.. automodule:: hydrobench.nldas4basins.basin_nldas_process
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.nldas4basins.download\_nldas module
-----------------------------------------------
-
-.. automodule:: hydrobench.nldas4basins.download_nldas
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.nldas4basins
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.pet.rst b/docs/source/hydrobench.pet.rst
deleted file mode 100644
index 13817c8..0000000
--- a/docs/source/hydrobench.pet.rst
+++ /dev/null
@@ -1,37 +0,0 @@
-hydrobench.pet package
-======================
-
-Submodules
-----------
-
-hydrobench.pet.meteo\_utils module
-----------------------------------
-
-.. automodule:: hydrobench.pet.meteo_utils
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.pet.pet4daymet module
---------------------------------
-
-.. automodule:: hydrobench.pet.pet4daymet
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.pet.rad\_utils module
---------------------------------
-
-.. automodule:: hydrobench.pet.rad_utils
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.pet
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.rst b/docs/source/hydrobench.rst
deleted file mode 100644
index 5844016..0000000
--- a/docs/source/hydrobench.rst
+++ /dev/null
@@ -1,25 +0,0 @@
-hydrobench package
-==================
-
-Subpackages
------------
-
-.. toctree::
-   :maxdepth: 4
-
-   hydrobench.app
-   hydrobench.data
-   hydrobench.daymet4basins
-   hydrobench.ecmwf4basins
-   hydrobench.modis4basins
-   hydrobench.nldas4basins
-   hydrobench.pet
-   hydrobench.utils
-
-Module contents
----------------
-
-.. automodule:: hydrobench
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/hydrobench.utils.rst b/docs/source/hydrobench.utils.rst
deleted file mode 100644
index 2fd4b9a..0000000
--- a/docs/source/hydrobench.utils.rst
+++ /dev/null
@@ -1,29 +0,0 @@
-hydrobench.utils package
-========================
-
-Submodules
-----------
-
-hydrobench.utils.hydro\_geo module
-----------------------------------
-
-.. automodule:: hydrobench.utils.hydro_geo
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-hydrobench.utils.hydro\_utils module
-------------------------------------
-
-.. automodule:: hydrobench.utils.hydro_utils
-   :members:
-   :undoc-members:
-   :show-inheritance:
-
-Module contents
----------------
-
-.. automodule:: hydrobench.utils
-   :members:
-   :undoc-members:
-   :show-inheritance:
diff --git a/docs/source/index.rst b/docs/source/index.rst
index 782a274..ecf0da0 100644
--- a/docs/source/index.rst
+++ b/docs/source/index.rst
@@ -1,9 +1,9 @@
-.. HydroBench documentation master file, created by
+.. HydroDataset documentation master file, created by
    sphinx-quickstart on Mon Jul 26 15:57:56 2021.
    You can adapt this file completely to your liking, but it should at least
    contain the root `toctree` directive.
 
-Welcome to HydroBench's documentation!
+Welcome to HydroDataset's documentation!
 ======================================
 
 .. toctree::
diff --git a/docs/source/intro.rst b/docs/source/intro.rst
index ab410ed..ef63541 100644
--- a/docs/source/intro.rst
+++ b/docs/source/intro.rst
@@ -1,31 +1,20 @@
 Introduction
 ============================
-This is a dataset zoo for hydrological modeling, especially with data-driven methods.
+This is a dataset zoo for watershed hydrological modeling, especially with data-driven methods.
 
 Overview
 --------------------
-Now we are making three datasets. After finishing the preparation of datasets, we will provide deep-learning benchmark experiments for each dataset.
 
-* GHS: Geospatial attributes and Hydrometeorological forcings of gages for Streamflow modeling
-* CAMELS-grid: a grid-version CAMELS dataset
-* HFlowDB: a DataBase for Hourly streamflow modeling of gages, especially for High flow (Flood) modeling.
+Now we mainly download and process the following datasets
 
-The "GHS" is an extension for `the CAMELS dataset <https://ral.ucar.edu/solutions/products/camels>`_ .
-It contains geospatial attributes, hydrometeorological forcings and streamflow data of 9067 gages over the Contiguous United States (CONUS)
-in `the GAGES-II dataset <https://water.usgs.gov/GIS/metadata/usgswrd/XML/gagesII_Sept2011.xml>`_ .
-
-CAMELS-grid include all basins in the CAMELS dataset. We create boundary masks for each basin
-and download the gridded data of `the Daymet dataset <https://daymet.ornl.gov/>`_ for all of them.
-
-HFlowDB is mainly created for flood forecasting in basins. It origins from `the FlowDB dataset <https://arxiv.org/abs/2012.11154>`_ .
-But HFlowDB is for gages and its basins, while FlowDB only include streamflow data of gages and precipitation data of its nearest rainfall gage.
-
-Download
--------------------
-Now we have not provided an online way to download the data.
-If you need the dataset, please contact with `Ouyang, Wenyu <https://github.com/OuyangWenyu>`_
+- CAMELS/MOPEX/LAMAH
+- Daymet
+- ECMWF
+- MODIS
+- NLDAS
 
 Contributor
 -------------------
-Wenyu Ouyang: hust2014owen@gmail.com
-Tianqi Xin: 2034687001@qq.com
+`Ouyang, Wenyu <https://github.com/OuyangWenyu>`_
+
+If you have any problems, please contact with hust2014owe@gmail.com
diff --git a/docs/source/modules.rst b/docs/source/modules.rst
deleted file mode 100644
index b68661b..0000000
--- a/docs/source/modules.rst
+++ /dev/null
@@ -1,7 +0,0 @@
-hydrobench
-==========
-
-.. toctree::
-   :maxdepth: 4
-
-   hydrobench
diff --git a/environment.yml b/environment.yml
index 94b4bc1..b145b58 100644
--- a/environment.yml
+++ b/environment.yml
@@ -1,4 +1,4 @@
-name: HydroBench
+name: HydroDatasets
 channels:
   - conda-forge
   - defaults
@@ -13,4 +13,5 @@ dependencies:
   - cdsapi
   - cfgrib
   - tqdm
-  - sphinx
\ No newline at end of file
+  - sphinx
+  - pytest
\ No newline at end of file
diff --git a/hydrobench/__init__.py b/hydrodataset/__init__.py
similarity index 100%
rename from hydrobench/__init__.py
rename to hydrodataset/__init__.py
diff --git a/hydrobench/app/__init__.py b/hydrodataset/app/__init__.py
similarity index 100%
rename from hydrobench/app/__init__.py
rename to hydrodataset/app/__init__.py
diff --git a/hydrobench/app/daymet4basins/__init__.py b/hydrodataset/app/daymet4basins/__init__.py
similarity index 100%
rename from hydrobench/app/daymet4basins/__init__.py
rename to hydrodataset/app/daymet4basins/__init__.py
diff --git a/hydrobench/app/daymet4basins/calculate_basin_mean_forcing_include_pet.py b/hydrodataset/app/daymet4basins/calculate_basin_mean_forcing_include_pet.py
similarity index 94%
rename from hydrobench/app/daymet4basins/calculate_basin_mean_forcing_include_pet.py
rename to hydrodataset/app/daymet4basins/calculate_basin_mean_forcing_include_pet.py
index dbea988..b6ba443 100644
--- a/hydrobench/app/daymet4basins/calculate_basin_mean_forcing_include_pet.py
+++ b/hydrodataset/app/daymet4basins/calculate_basin_mean_forcing_include_pet.py
@@ -12,9 +12,9 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.utils.hydro_utils import unserialize_geopandas, hydro_logger, t_range_days
-from hydrobench.daymet4basins.basin_daymet_process import calculate_basin_mean
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.utils.hydro_utils import unserialize_geopandas, hydro_logger, t_range_days
+from hydrodataset.daymet4basins.basin_daymet_process import calculate_basin_mean
 
 
 def main(args):
diff --git a/hydrobench/app/daymet4basins/calculate_basin_mean_values.py b/hydrodataset/app/daymet4basins/calculate_basin_mean_values.py
similarity index 95%
rename from hydrobench/app/daymet4basins/calculate_basin_mean_values.py
rename to hydrodataset/app/daymet4basins/calculate_basin_mean_values.py
index c0ca0be..124e3bd 100644
--- a/hydrobench/app/daymet4basins/calculate_basin_mean_values.py
+++ b/hydrodataset/app/daymet4basins/calculate_basin_mean_values.py
@@ -12,9 +12,9 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.utils.hydro_utils import unserialize_geopandas, hydro_logger, t_range_days
-from hydrobench.daymet4basins.basin_daymet_process import calculate_basin_mean
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.utils.hydro_utils import unserialize_geopandas, hydro_logger, t_range_days
+from hydrodataset.daymet4basins.basin_daymet_process import calculate_basin_mean
 
 
 def main(args):
diff --git a/hydrobench/app/daymet4basins/cut_nc_to_bounds_add_pet.py b/hydrodataset/app/daymet4basins/cut_nc_to_bounds_add_pet.py
similarity index 92%
rename from hydrobench/app/daymet4basins/cut_nc_to_bounds_add_pet.py
rename to hydrodataset/app/daymet4basins/cut_nc_to_bounds_add_pet.py
index e843f96..b7ad21c 100644
--- a/hydrobench/app/daymet4basins/cut_nc_to_bounds_add_pet.py
+++ b/hydrodataset/app/daymet4basins/cut_nc_to_bounds_add_pet.py
@@ -10,9 +10,9 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.utils.hydro_utils import unserialize_geopandas, hydro_logger
-from hydrobench.daymet4basins.basin_daymet_process import generate_boundary_dataset, calculate_basin_grids_pet
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.utils.hydro_utils import unserialize_geopandas, hydro_logger
+from hydrodataset.daymet4basins.basin_daymet_process import generate_boundary_dataset, calculate_basin_grids_pet
 
 
 def main(args):
diff --git a/hydrobench/app/daymet4basins/pbm_p_pe_q_basin_area.py b/hydrodataset/app/daymet4basins/pbm_p_pe_q_basin_area.py
similarity index 95%
rename from hydrobench/app/daymet4basins/pbm_p_pe_q_basin_area.py
rename to hydrodataset/app/daymet4basins/pbm_p_pe_q_basin_area.py
index 1159bc3..cf32410 100644
--- a/hydrobench/app/daymet4basins/pbm_p_pe_q_basin_area.py
+++ b/hydrodataset/app/daymet4basins/pbm_p_pe_q_basin_area.py
@@ -11,8 +11,8 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.utils.hydro_utils import hydro_logger, t_range_days
-from hydrobench.data.data_daymet4camels import Daymet4Camels
+from hydrodataset.utils.hydro_utils import hydro_logger, t_range_days
+from hydrodataset.data.data_daymet4camels import Daymet4Camels
 
 
 def main(args):
diff --git a/hydrobench/app/daymet4basins/regrid_daymet_nc.py b/hydrodataset/app/daymet4basins/regrid_daymet_nc.py
similarity index 95%
rename from hydrobench/app/daymet4basins/regrid_daymet_nc.py
rename to hydrodataset/app/daymet4basins/regrid_daymet_nc.py
index b05aa91..e11f07c 100644
--- a/hydrobench/app/daymet4basins/regrid_daymet_nc.py
+++ b/hydrodataset/app/daymet4basins/regrid_daymet_nc.py
@@ -10,9 +10,9 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.utils.hydro_utils import unserialize_geopandas, hydro_logger
-from hydrobench.daymet4basins.basin_daymet_process import resample_nc
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.utils.hydro_utils import unserialize_geopandas, hydro_logger
+from hydrodataset.daymet4basins.basin_daymet_process import resample_nc
 
 
 def main(args):
diff --git a/hydrobench/app/download/__init__.py b/hydrodataset/app/download/__init__.py
similarity index 100%
rename from hydrobench/app/download/__init__.py
rename to hydrodataset/app/download/__init__.py
diff --git a/hydrobench/app/download/download_daymet_camels_basin.py b/hydrodataset/app/download/download_daymet_camels_basin.py
similarity index 91%
rename from hydrobench/app/download/download_daymet_camels_basin.py
rename to hydrodataset/app/download/download_daymet_camels_basin.py
index 8a198d6..e40ce7b 100644
--- a/hydrobench/app/download/download_daymet_camels_basin.py
+++ b/hydrodataset/app/download/download_daymet_camels_basin.py
@@ -10,9 +10,9 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.daymet4basins.basin_daymet_process import download_daymet_by_geom_bound
-from hydrobench.utils.hydro_utils import unserialize_geopandas, hydro_logger
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.daymet4basins.basin_daymet_process import download_daymet_by_geom_bound
+from hydrodataset.utils.hydro_utils import unserialize_geopandas, hydro_logger
 
 
 def main(args):
diff --git a/hydrobench/app/download/download_daymet_camels_outside_nldi.py b/hydrodataset/app/download/download_daymet_camels_outside_nldi.py
similarity index 95%
rename from hydrobench/app/download/download_daymet_camels_outside_nldi.py
rename to hydrodataset/app/download/download_daymet_camels_outside_nldi.py
index 83e84e1..eb30751 100644
--- a/hydrobench/app/download/download_daymet_camels_outside_nldi.py
+++ b/hydrodataset/app/download/download_daymet_camels_outside_nldi.py
@@ -14,9 +14,9 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.daymet4basins.basin_daymet_process import download_daymet_by_geom_bound
-from hydrobench.utils.hydro_utils import unserialize_geopandas, hydro_logger, serialize_json, unserialize_json
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.daymet4basins.basin_daymet_process import download_daymet_by_geom_bound
+from hydrodataset.utils.hydro_utils import unserialize_geopandas, hydro_logger, serialize_json, unserialize_json
 
 
 def do_we_need_redownload(geometry, basin_id, previous_download_data_dir, download_year):
diff --git a/hydrobench/app/download/download_daymet_nldi_camels_basin.py b/hydrodataset/app/download/download_daymet_nldi_camels_basin.py
similarity index 92%
rename from hydrobench/app/download/download_daymet_nldi_camels_basin.py
rename to hydrodataset/app/download/download_daymet_nldi_camels_basin.py
index 0f27ac7..82f0c1d 100644
--- a/hydrobench/app/download/download_daymet_nldi_camels_basin.py
+++ b/hydrodataset/app/download/download_daymet_nldi_camels_basin.py
@@ -10,9 +10,9 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.daymet4basins.basin_daymet_process import download_daymet_by_geom_bound
-from hydrobench.utils.hydro_utils import unserialize_geopandas, hydro_logger
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.daymet4basins.basin_daymet_process import download_daymet_by_geom_bound
+from hydrodataset.utils.hydro_utils import unserialize_geopandas, hydro_logger
 
 
 def main(args):
diff --git a/hydrobench/app/download/download_nldas_hourly.py b/hydrodataset/app/download/download_nldas_hourly.py
similarity index 87%
rename from hydrobench/app/download/download_nldas_hourly.py
rename to hydrodataset/app/download/download_nldas_hourly.py
index d8996fc..006826b 100644
--- a/hydrobench/app/download/download_nldas_hourly.py
+++ b/hydrodataset/app/download/download_nldas_hourly.py
@@ -4,8 +4,8 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.utils.hydro_utils import hydro_logger
-from hydrobench.nldas4basins.download_nldas import download_nldas_with_url_lst
+from hydrodataset.utils.hydro_utils import hydro_logger
+from hydrodataset.nldas4basins.download_nldas import download_nldas_with_url_lst
 
 
 def main(args):
diff --git a/hydrobench/app/download/download_nldi.py b/hydrodataset/app/download/download_nldi.py
similarity index 86%
rename from hydrobench/app/download/download_nldi.py
rename to hydrodataset/app/download/download_nldi.py
index 1de9ae7..11dd714 100644
--- a/hydrobench/app/download/download_nldi.py
+++ b/hydrodataset/app/download/download_nldi.py
@@ -5,8 +5,8 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.utils.hydro_utils import progress_wrapped, hydro_logger
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.utils.hydro_utils import progress_wrapped, hydro_logger
 
 
 @progress_wrapped(estimated_time=1000)
diff --git a/hydrobench/app/modis4basins/__init__.py b/hydrodataset/app/modis4basins/__init__.py
similarity index 100%
rename from hydrobench/app/modis4basins/__init__.py
rename to hydrodataset/app/modis4basins/__init__.py
diff --git a/hydrobench/app/modis4basins/trans_modis_et_to_camels_format.py b/hydrodataset/app/modis4basins/trans_modis_et_to_camels_format.py
similarity index 91%
rename from hydrobench/app/modis4basins/trans_modis_et_to_camels_format.py
rename to hydrodataset/app/modis4basins/trans_modis_et_to_camels_format.py
index c647685..d7b28c5 100644
--- a/hydrobench/app/modis4basins/trans_modis_et_to_camels_format.py
+++ b/hydrodataset/app/modis4basins/trans_modis_et_to_camels_format.py
@@ -9,9 +9,9 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.modis4basins.basin_pmlv2_process import trans_8day_pmlv2_to_camels_format
-from hydrobench.modis4basins.basin_mod16a2v105_process import trans_8day_modis16a2v105_to_camels_format
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.modis4basins.basin_pmlv2_process import trans_8day_pmlv2_to_camels_format
+from hydrodataset.modis4basins.basin_mod16a2v105_process import trans_8day_modis16a2v105_to_camels_format
 
 
 def main(args):
diff --git a/hydrobench/app/nldas4basins/__init__.py b/hydrodataset/app/nldas4basins/__init__.py
similarity index 100%
rename from hydrobench/app/nldas4basins/__init__.py
rename to hydrodataset/app/nldas4basins/__init__.py
diff --git a/hydrobench/app/nldas4basins/trans_nldas_to_camels_format.py b/hydrodataset/app/nldas4basins/trans_nldas_to_camels_format.py
similarity index 95%
rename from hydrobench/app/nldas4basins/trans_nldas_to_camels_format.py
rename to hydrodataset/app/nldas4basins/trans_nldas_to_camels_format.py
index 7225968..7a3721c 100644
--- a/hydrobench/app/nldas4basins/trans_nldas_to_camels_format.py
+++ b/hydrodataset/app/nldas4basins/trans_nldas_to_camels_format.py
@@ -10,8 +10,8 @@
 
 sys.path.append(os.path.join("..", "..", ".."))
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.nldas4basins.basin_nldas_process import trans_daily_nldas_to_camels_format
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.nldas4basins.basin_nldas_process import trans_daily_nldas_to_camels_format
 
 
 def main(args):
diff --git a/hydrobench/app/script_args.py b/hydrodataset/app/script_args.py
similarity index 100%
rename from hydrobench/app/script_args.py
rename to hydrodataset/app/script_args.py
diff --git a/hydrobench/data/__init__.py b/hydrodataset/data/__init__.py
similarity index 100%
rename from hydrobench/data/__init__.py
rename to hydrodataset/data/__init__.py
diff --git a/hydrobench/data/data_base.py b/hydrodataset/data/data_base.py
similarity index 100%
rename from hydrobench/data/data_base.py
rename to hydrodataset/data/data_base.py
diff --git a/hydrobench/data/data_camels.py b/hydrodataset/data/data_camels.py
similarity index 99%
rename from hydrobench/data/data_camels.py
rename to hydrodataset/data/data_camels.py
index b117d4d..8526f83 100644
--- a/hydrobench/data/data_camels.py
+++ b/hydrodataset/data/data_camels.py
@@ -7,10 +7,10 @@
 import numpy as np
 from pandas.core.dtypes.common import is_string_dtype, is_numeric_dtype
 
-from hydrobench.data.data_base import DataSourceBase
-from hydrobench.data.stat import cal_fdc
-from hydrobench.utils import hydro_utils
-from hydrobench.utils.hydro_utils import download_one_zip, unzip_nested_zip
+from hydrodataset.data.data_base import DataSourceBase
+from hydrodataset.data.stat import cal_fdc
+from hydrodataset.utils import hydro_utils
+from hydrodataset.utils.hydro_utils import download_one_zip, unzip_nested_zip
 
 CAMELS_NO_DATASET_ERROR_LOG = "We cannot read this dataset now. Please check if you choose the correct dataset:\n" \
                               " [\"AUS\", \"BR\", \"CA\", \"CL\", \"GB\", \"US\", \"YR\"]"
@@ -523,6 +523,10 @@ def read_object_ids(self, **kwargs) -> np.array:
             # although there are 698 sites, there are only 611 sites with attributes data.
             # Hence we only use 611 sites now
             attr_all_file = os.path.join(self.data_source_description["CAMELS_DIR"], "HYSETS_watershed_properties.txt")
+            if not os.path.isfile(attr_all_file):
+                raise FileNotFoundError(
+                    "Please download HYSETS_watershed_properties.txt from https://osf.io/7fn4c/ and put it in the "
+                    "root directory of CANOPEX")
             canopex_attr_data = pd.read_csv(attr_all_file, sep=';')
             return np.intersect1d(id_strs, canopex_attr_data["Official_ID"].values)
         elif self.region == "CE":
diff --git a/hydrobench/data/data_daymet4camels.py b/hydrodataset/data/data_daymet4camels.py
similarity index 98%
rename from hydrobench/data/data_daymet4camels.py
rename to hydrodataset/data/data_daymet4camels.py
index 19c4c36..e8d8c50 100644
--- a/hydrobench/data/data_daymet4camels.py
+++ b/hydrodataset/data/data_daymet4camels.py
@@ -8,9 +8,9 @@
 import numpy as np
 import xarray as xr
 
-from hydrobench.data.data_base import DataSourceBase
-from hydrobench.data.data_camels import Camels
-from hydrobench.utils import hydro_utils
+from hydrodataset.data.data_base import DataSourceBase
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.utils import hydro_utils
 
 
 class Daymet4Camels(DataSourceBase):
diff --git a/hydrobench/data/stat.py b/hydrodataset/data/stat.py
similarity index 99%
rename from hydrobench/data/stat.py
rename to hydrodataset/data/stat.py
index f942643..c31c480 100644
--- a/hydrobench/data/stat.py
+++ b/hydrodataset/data/stat.py
@@ -4,7 +4,7 @@
 import scipy.stats
 from scipy.stats import wilcoxon
 
-from hydrobench.utils.hydro_utils import hydro_logger
+from hydrodataset.utils.hydro_utils import hydro_logger
 
 
 def KGE(xs, xo):
diff --git a/hydrobench/daymet4basins/__init__.py b/hydrodataset/daymet4basins/__init__.py
similarity index 100%
rename from hydrobench/daymet4basins/__init__.py
rename to hydrodataset/daymet4basins/__init__.py
diff --git a/hydrobench/daymet4basins/basin_daymet_process.py b/hydrodataset/daymet4basins/basin_daymet_process.py
similarity index 99%
rename from hydrobench/daymet4basins/basin_daymet_process.py
rename to hydrodataset/daymet4basins/basin_daymet_process.py
index a233742..84da9a2 100644
--- a/hydrobench/daymet4basins/basin_daymet_process.py
+++ b/hydrodataset/daymet4basins/basin_daymet_process.py
@@ -13,8 +13,8 @@
 import xarray as xr
 import numpy as np
 import pandas as pd
-from hydrobench.pet.pet4daymet import priestley_taylor, pm_fao56
-from hydrobench.utils.hydro_utils import t_range_days
+from hydrodataset.pet.pet4daymet import priestley_taylor, pm_fao56
+from hydrodataset.utils.hydro_utils import t_range_days
 
 DEF_CRS = "epsg:4326"
 
diff --git a/hydrobench/ecmwf4basins/__init__.py b/hydrodataset/ecmwf4basins/__init__.py
similarity index 100%
rename from hydrobench/ecmwf4basins/__init__.py
rename to hydrodataset/ecmwf4basins/__init__.py
diff --git a/hydrodataset/ecmwf4basins/basin_era5_process.py b/hydrodataset/ecmwf4basins/basin_era5_process.py
new file mode 100644
index 0000000..c08889b
--- /dev/null
+++ b/hydrodataset/ecmwf4basins/basin_era5_process.py
@@ -0,0 +1,132 @@
+"""
+Process ERA5 land data for basins
+"""
+import fnmatch
+import os
+import numpy as np
+import pandas as pd
+
+from hydrodataset.utils.hydro_utils import utc_to_local
+
+
+def trans_era5_land_to_camels_format(era5_land_dir, output_dir, gage_dict, region, year, time_zone="Asia/Hong_Kong"):
+    """
+    Transform hourly forcing data of ERA5-LAND downloaded from GEE to the format in CAMELS.
+
+    ERA5-LAND's forcing data is hourly, so we resample it to daily in GEE,
+    In addition, we will use them for basins in China, so we chose the time zone "Asia/Hong_Kong"
+    The GEE code: https://code.earthengine.google.com/b40bfe7529ec9df928f5abfc029f4e4e
+
+    Parameters
+    ----------
+    era5_land_dir
+        the original data's directory
+    output_dir
+        the transformed data's directory
+    gage_dict
+        a dict containing gage's ids and the correspond HUC02 ids
+    region
+        we named the file downloaded from GEE as era5_land_<region>_mean_<year>.csv,
+        because we use GEE code to generate data for each year for each shape file (region) containing some basins.
+        For example, if we use the basins' shpfile in MinRiverBasins, the region is "camels_mr".
+    year
+        we use GEE code to generate data for each year, so each year for each region has one data file.
+    time_zone
+        local time zone and the default is Asia/Hong_Kong (UTC+8)
+        Generally our data's time zone is UTC; when we need local time, we need to transform it
+
+    Returns
+    -------
+    None
+    """
+    # you can add features or delete features, or change the order, which depends on your txt content
+    avg_dataset = ["gage_id", "time_start", "dewpoint_temperature_2m_mean", "temperature_2m_mean",
+                   "skin_temperature_mean", "soil_temperature_level_1_mean", "soil_temperature_level_2_mean",
+                   "soil_temperature_level_3_mean", "soil_temperature_level_4_mean", "lake_bottom_temperature_mean",
+                   "lake_ice_depth_mean", "lake_ice_temperature_mean", "lake_mix_layer_depth_mean",
+                   "lake_shape_factor_mean", "lake_total_layer_temperature_mean", "snow_albedo_mean", "snow_cover_mean",
+                   "snow_density_mean", "snow_depth_mean", "snow_depth_water_equivalent_mean",
+                   "temperature_of_snow_layer_mean", "skin_reservoir_content_mean",
+                   "volumetric_soil_water_layer_1_mean", "volumetric_soil_water_layer_2_mean",
+                   "volumetric_soil_water_layer_3_mean", "volumetric_soil_water_layer_4_mean", "forecast_albedo_mean",
+                   "u_component_of_wind_10m_mean", "v_component_of_wind_10m_mean", "surface_pressure_mean",
+                   "leaf_area_index_high_vegetation_mean", "leaf_area_index_low_vegetation_mean"]
+    sum_dataset = ["gage_id", "time_start", "snowfall_hourly_sum", "snowmelt_hourly_sum",
+                   "surface_latent_heat_flux_hourly_sum", "surface_net_solar_radiation_hourly_sum",
+                   "surface_net_thermal_radiation_hourly_sum", "surface_sensible_heat_flux_hourly_sum",
+                   "surface_solar_radiation_downwards_hourly_sum", "surface_thermal_radiation_downwards_hourly_sum",
+                   "evaporation_from_bare_soil_hourly_sum",
+                   "evaporation_from_open_water_surfaces_excluding_oceans_hourly_sum",
+                   "evaporation_from_the_top_of_canopy_hourly_sum",
+                   "evaporation_from_vegetation_transpiration_hourly_sum", "potential_evaporation_hourly_sum",
+                   "runoff_hourly_sum", "snow_evaporation_hourly_sum", "sub_surface_runoff_hourly_sum",
+                   "surface_runoff_hourly_sum", "total_evaporation_hourly_sum", "total_precipitation_hourly_sum"]
+    camels_format_index = ['Year', 'Mnth', 'Day', 'Hr', 'dewpoint_temperature_2m', 'temperature_2m', 'skin_temperature',
+                           'soil_temperature_level_1', 'soil_temperature_level_2', 'soil_temperature_level_3',
+                           'soil_temperature_level_4', 'lake_bottom_temperature', 'lake_ice_depth',
+                           'lake_ice_temperature', 'lake_mix_layer_depth', 'lake_shape_factor',
+                           'lake_total_layer_temperature', 'snow_albedo', 'snow_cover', 'snow_density', 'snow_depth',
+                           'snow_depth_water_equivalent', 'temperature_of_snow_layer', 'skin_reservoir_content',
+                           'volumetric_soil_water_layer_1', 'volumetric_soil_water_layer_2',
+                           'volumetric_soil_water_layer_3', 'volumetric_soil_water_layer_4', 'forecast_albedo',
+                           'u_component_of_wind_10m', 'v_component_of_wind_10m', 'surface_pressure',
+                           'leaf_area_index_high_vegetation', 'leaf_area_index_low_vegetation', 'snowfall_hourly',
+                           'snowmelt_hourly', 'surface_latent_heat_flux_hourly', 'surface_net_solar_radiation_hourly',
+                           'surface_net_thermal_radiation_hourly', 'surface_sensible_heat_flux_hourly',
+                           'surface_solar_radiation_downwards_hourly', 'surface_thermal_radiation_downwards_hourly',
+                           'evaporation_from_bare_soil_hourly',
+                           'evaporation_from_open_water_surfaces_excluding_oceans_hourly',
+                           'evaporation_from_the_top_of_canopy_hourly',
+                           'evaporation_from_vegetation_transpiration_hourly', 'potential_evaporation_hourly',
+                           'runoff_hourly', 'snow_evaporation_hourly', 'sub_surface_runoff_hourly',
+                           'surface_runoff_hourly', 'total_evaporation_hourly', 'total_precipitation_hourly']
+
+    gage_id_key = "gage_id"
+
+    # because this function only work for one year and one region, it's better to chose avg and sum files at first
+    for f_name in os.listdir(era5_land_dir):
+        if fnmatch.fnmatch(f_name, 'era5_land_' + region + '_avg_mean_' + str(year) + '.csv'):
+            avg_data_file = os.path.join(era5_land_dir, f_name)
+        if fnmatch.fnmatch(f_name, 'era5_land_' + region + '_sum_mean_' + str(year) + '.csv'):
+            sum_data_file = os.path.join(era5_land_dir, f_name)
+
+    avg_data_temp = pd.read_csv(avg_data_file, sep=',', dtype={avg_dataset[0]: str})
+    sum_data_temp = pd.read_csv(sum_data_file, sep=',', dtype={sum_dataset[0]: str})
+    # transform UTC time to local
+    # refer to: https://stackoverflow.com/questions/33204763/how-to-pass-multiple-arguments-to-the-apply-function
+    avg_data_temp[avg_dataset[1]] = avg_data_temp[avg_dataset[1]].apply(
+        lambda dt_tmp: utc_to_local(dt_tmp, local_tz=time_zone))
+    sum_data_temp[sum_dataset[1]] = sum_data_temp[sum_dataset[1]].apply(
+        lambda dt_tmp: utc_to_local(dt_tmp, local_tz=time_zone))
+    for i_basin in range(len(gage_dict[gage_id_key])):
+        avg_basin_data = avg_data_temp[
+            avg_data_temp[avg_dataset[0]].values.astype(int) == int(gage_dict[gage_id_key][i_basin])]
+        sum_basin_data = sum_data_temp[
+            sum_data_temp[avg_dataset[0]].values.astype(int) == int(gage_dict[gage_id_key][i_basin])]
+        if avg_basin_data.shape[0] == 0 or sum_basin_data.shape[0] == 0:
+            raise ArithmeticError("chosen basins' number is zero")
+        # get Year,Month,Day,Hour info
+        csv_date = pd.to_datetime(avg_basin_data[avg_dataset[1]])
+        # the hour is set to 12, as 12 is the average hour of a day
+        year_month_day_hour = pd.DataFrame([[dt.year, dt.month, dt.day, 12] for dt in csv_date],
+                                           columns=camels_format_index[0:4])
+        avg_data_df = pd.DataFrame(avg_basin_data.iloc[:, 2:].values,
+                                   columns=camels_format_index[4:4 + len(avg_dataset) - 2])
+        sum_data_df = pd.DataFrame(sum_basin_data.iloc[:, 2:].values,
+                                   columns=camels_format_index[-(len(sum_dataset) - 2):])
+        # concat
+        new_data_df = pd.concat([year_month_day_hour, avg_data_df, sum_data_df], axis=1)
+        # output the result
+        if not os.path.isdir(output_dir):
+            os.makedirs(output_dir)
+        output_file = os.path.join(output_dir, gage_dict[gage_id_key][i_basin] + '_lump_era5_land_forcing.txt')
+        print("output forcing data of", gage_dict[gage_id_key][i_basin], "year", str(year))
+        if os.path.isfile(output_file):
+            data_old = pd.read_csv(output_file, sep=' ')
+            years = np.unique(data_old[camels_format_index[0]].values)
+            if year in years:
+                continue
+            else:
+                os.remove(output_file)
+                new_data_df = pd.concat([data_old, new_data_df]).sort_values(by=camels_format_index[0:3])
+        new_data_df.to_csv(output_file, header=True, index=False, sep=' ')
diff --git a/hydrobench/ecmwf4basins/download_era5_land.py b/hydrodataset/ecmwf4basins/download_era5_land.py
similarity index 99%
rename from hydrobench/ecmwf4basins/download_era5_land.py
rename to hydrodataset/ecmwf4basins/download_era5_land.py
index 057f635..9e1e22d 100644
--- a/hydrobench/ecmwf4basins/download_era5_land.py
+++ b/hydrodataset/ecmwf4basins/download_era5_land.py
@@ -30,7 +30,7 @@
 import pygeoutils as geoutils
 from shapely.geometry import MultiPolygon, Polygon
 
-from hydrobench.utils import hydro_utils
+from hydrodataset.utils import hydro_utils
 
 DEF_CRS = "epsg:4326"
 
diff --git a/hydrobench/modis4basins/DAACDataDownload.py b/hydrodataset/modis4basins/DAACDataDownload.py
similarity index 100%
rename from hydrobench/modis4basins/DAACDataDownload.py
rename to hydrodataset/modis4basins/DAACDataDownload.py
diff --git a/hydrobench/modis4basins/EarthdataLoginSetup.py b/hydrodataset/modis4basins/EarthdataLoginSetup.py
similarity index 100%
rename from hydrobench/modis4basins/EarthdataLoginSetup.py
rename to hydrodataset/modis4basins/EarthdataLoginSetup.py
diff --git a/hydrobench/modis4basins/__init__.py b/hydrodataset/modis4basins/__init__.py
similarity index 100%
rename from hydrobench/modis4basins/__init__.py
rename to hydrodataset/modis4basins/__init__.py
diff --git a/hydrobench/modis4basins/basin_mod16a2v105_process.py b/hydrodataset/modis4basins/basin_mod16a2v105_process.py
similarity index 100%
rename from hydrobench/modis4basins/basin_mod16a2v105_process.py
rename to hydrodataset/modis4basins/basin_mod16a2v105_process.py
diff --git a/hydrobench/modis4basins/basin_pmlv2_process.py b/hydrodataset/modis4basins/basin_pmlv2_process.py
similarity index 100%
rename from hydrobench/modis4basins/basin_pmlv2_process.py
rename to hydrodataset/modis4basins/basin_pmlv2_process.py
diff --git a/hydrobench/modis4basins/get_modis.py b/hydrodataset/modis4basins/get_modis.py
similarity index 100%
rename from hydrobench/modis4basins/get_modis.py
rename to hydrodataset/modis4basins/get_modis.py
diff --git a/hydrobench/modis4basins/readme.md b/hydrodataset/modis4basins/readme.md
similarity index 100%
rename from hydrobench/modis4basins/readme.md
rename to hydrodataset/modis4basins/readme.md
diff --git a/hydrobench/nldas4basins/__init__.py b/hydrodataset/nldas4basins/__init__.py
similarity index 100%
rename from hydrobench/nldas4basins/__init__.py
rename to hydrodataset/nldas4basins/__init__.py
diff --git a/hydrobench/nldas4basins/basin_nldas_process.py b/hydrodataset/nldas4basins/basin_nldas_process.py
similarity index 100%
rename from hydrobench/nldas4basins/basin_nldas_process.py
rename to hydrodataset/nldas4basins/basin_nldas_process.py
diff --git a/hydrobench/nldas4basins/download_nldas.py b/hydrodataset/nldas4basins/download_nldas.py
similarity index 98%
rename from hydrobench/nldas4basins/download_nldas.py
rename to hydrodataset/nldas4basins/download_nldas.py
index 50379a4..5c2fabe 100644
--- a/hydrobench/nldas4basins/download_nldas.py
+++ b/hydrodataset/nldas4basins/download_nldas.py
@@ -18,7 +18,7 @@
 import requests
 from tqdm import tqdm
 
-from hydrobench.utils.hydro_utils import hydro_logger
+from hydrodataset.utils.hydro_utils import hydro_logger
 
 
 # overriding requests.Session.rebuild_auth to mantain headers when redirected
diff --git a/hydrobench/pet/__init__.py b/hydrodataset/pet/__init__.py
similarity index 100%
rename from hydrobench/pet/__init__.py
rename to hydrodataset/pet/__init__.py
diff --git a/hydrobench/pet/meteo_utils.py b/hydrodataset/pet/meteo_utils.py
similarity index 100%
rename from hydrobench/pet/meteo_utils.py
rename to hydrodataset/pet/meteo_utils.py
diff --git a/hydrobench/pet/pet4daymet.py b/hydrodataset/pet/pet4daymet.py
similarity index 96%
rename from hydrobench/pet/pet4daymet.py
rename to hydrodataset/pet/pet4daymet.py
index 131e36a..959b3c9 100644
--- a/hydrobench/pet/pet4daymet.py
+++ b/hydrodataset/pet/pet4daymet.py
@@ -3,8 +3,8 @@
 
 import numpy as np
 import xarray as xr
-from hydrobench.pet.meteo_utils import calc_press, calc_psy, calc_vpc, calc_lambda_, calc_ea, calc_es
-from hydrobench.pet.rad_utils import calc_rad_short, calc_rad_long
+from hydrodataset.pet.meteo_utils import calc_press, calc_psy, calc_vpc, calc_lambda_, calc_ea, calc_es
+from hydrodataset.pet.rad_utils import calc_rad_short, calc_rad_long
 
 
 def priestley_taylor(t_min: Union[np.ndarray, xr.DataArray],
diff --git a/hydrobench/pet/rad_utils.py b/hydrodataset/pet/rad_utils.py
similarity index 99%
rename from hydrobench/pet/rad_utils.py
rename to hydrodataset/pet/rad_utils.py
index f8c44fc..d2dd0f4 100644
--- a/hydrobench/pet/rad_utils.py
+++ b/hydrodataset/pet/rad_utils.py
@@ -2,7 +2,7 @@
 
 import numpy as np
 import xarray as xr
-from hydrobench.pet.meteo_utils import calc_ea
+from hydrodataset.pet.meteo_utils import calc_ea
 
 
 def calc_rad_short(s_rad: Union[np.ndarray, xr.DataArray] = None,
diff --git a/hydrobench/utils/__init__.py b/hydrodataset/utils/__init__.py
similarity index 100%
rename from hydrobench/utils/__init__.py
rename to hydrodataset/utils/__init__.py
diff --git a/hydrobench/utils/hydro_geo.py b/hydrodataset/utils/hydro_geo.py
similarity index 100%
rename from hydrobench/utils/hydro_geo.py
rename to hydrodataset/utils/hydro_geo.py
diff --git a/hydrobench/utils/hydro_utils.py b/hydrodataset/utils/hydro_utils.py
similarity index 93%
rename from hydrobench/utils/hydro_utils.py
rename to hydrodataset/utils/hydro_utils.py
index 7095936..76af7b6 100644
--- a/hydrobench/utils/hydro_utils.py
+++ b/hydrodataset/utils/hydro_utils.py
@@ -3,7 +3,7 @@
 import re
 import zipfile
 import datetime as dt, datetime
-from typing import List
+from typing import List, Union
 import geopandas as gpd
 import pickle
 import smtplib
@@ -12,6 +12,7 @@
 import numpy as np
 import urllib
 from urllib import parse
+from dateutil import tz
 
 import requests
 import matplotlib.pyplot as plt
@@ -398,6 +399,41 @@ def t_range_to_julian(t_range):
     return julian_dates
 
 
+def utc_to_local(utc_time: Union[str, np.datetime64], local_tz: str = "Asia/Hong_Kong",
+                 time_format="%Y-%m-%dT%H:%M:%S"):
+    """
+    Transform UTC time to local time.
+
+    Code comes from: https://stackoverflow.com/questions/4770297/convert-utc-datetime-string-to-local-datetime
+
+    Parameters
+    ----------
+    utc_time
+        the UTC time
+    local_tz
+        the local time zone; default is "Asia/Hong_Kong"
+    time_format
+        the format of utc_time_str and return value; default is "%Y-%m-%dT%H:%M:%S"
+
+    Returns
+    -------
+    str
+        return local time string; its format is time_format
+    """
+    from_zone = tz.gettz('UTC')
+    to_zone = tz.gettz(local_tz)
+    if type(utc_time) is np.datetime64:
+        utc_time = np.datetime_as_string(utc_time)
+    utc = datetime.datetime.strptime(utc_time, time_format)
+    # Tell the datetime object that it's in UTC time zone since
+    # datetime objects are 'naive' by default
+    utc = utc.replace(tzinfo=from_zone)
+    # Convert time zone
+    central = utc.astimezone(to_zone)
+    result_str = central.strftime(time_format)
+    return result_str
+
+
 # --------------------------------------------------MATH CALCULATION---------------------------------------------------
 def subset_of_dict(dict, chosen_keys):
     """make a new dict from key-values of chosen keys in a list"""


Test patch:
diff --git a/test/__init__.py b/test/__init__.py
index d22bcc8..4f9e278 100644
--- a/test/__init__.py
+++ b/test/__init__.py
@@ -1,1 +1,1 @@
-from test import test_download_daymet
+from test import test_download_dataset
diff --git a/test/example_data/era5_land_camels_mr_avg_mean_2010.csv b/test/example_data/era5_land_camels_mr_avg_mean_2010.csv
new file mode 100644
index 0000000..87975dc
--- /dev/null
+++ b/test/example_data/era5_land_camels_mr_avg_mean_2010.csv
@@ -0,0 +1,55 @@
+gage_id,time_start,dewpoint_temperature_2m_mean,temperature_2m_mean,skin_temperature_mean,soil_temperature_level_1_mean,soil_temperature_level_2_mean,soil_temperature_level_3_mean,soil_temperature_level_4_mean,lake_bottom_temperature_mean,lake_ice_depth_mean,lake_ice_temperature_mean,lake_mix_layer_depth_mean,lake_shape_factor_mean,lake_total_layer_temperature_mean,snow_albedo_mean,snow_cover_mean,snow_density_mean,snow_depth_mean,snow_depth_water_equivalent_mean,temperature_of_snow_layer_mean,skin_reservoir_content_mean,volumetric_soil_water_layer_1_mean,volumetric_soil_water_layer_2_mean,volumetric_soil_water_layer_3_mean,volumetric_soil_water_layer_4_mean,forecast_albedo_mean,u_component_of_wind_10m_mean,v_component_of_wind_10m_mean,surface_pressure_mean,leaf_area_index_high_vegetation_mean,leaf_area_index_low_vegetation_mean
+61019,2010-07-16T16:00:00,283.48582415467735,285.1410260357693,286.6763681482346,286.8825664210263,286.43931239452536,284.7340475537649,280.07871916626397,278.01212181288923,-273.15,2.450307210513832E-4,3.962560146370876,-272.351568635374,8.552235504184146,0.8799581823110084,0.0,100.01177793181795,-7.3453647229951E-24,-7.345364920210326E-25,273.15736700119857,3.5307701903132316E-4,0.4279281294472999,0.42873191595298304,0.42139814755839,0.4167172093254793,0.14198110360937513,-0.5614164737465382,-0.5086371134993655,68047.45226633629,2.9472924783899317,2.2105814966001924
+61019,2010-07-17T16:00:00,280.2127828510094,282.99879146235253,283.87890968821927,284.99703910534475,285.48258481235524,284.68414626918604,280.1786082707315,278.0164616296804,-273.15,4.539489748367487E-5,4.22972708650772,-272.35126941207466,8.494033835814736,0.8799749888897519,0.0,100.00713060185328,-7.3453647229951E-24,-7.345364920210326E-25,273.1592391104226,2.6012438847683786E-4,0.41865411425458837,0.4212638576665186,0.4238110046213482,0.41777969944562887,0.14182502260121785,-0.11304181947930649,-0.2579186547130539,68132.55055198199,2.946105717693784,2.2026002677909946
+61019,2010-07-18T16:00:00,280.1504700116299,283.69529286821904,286.0970743777834,286.09346633542526,285.19947785398045,284.5027686106397,280.2735567888577,278.021433511093,-273.15,1.3567606610346653E-4,3.725544347304612,-272.3510370272272,8.425431770255656,0.8799556867506687,0.0,100.01201633782614,-7.3453647229951E-24,-7.345364920210326E-25,273.14544370824,1.3168822810468288E-4,0.40932619796278324,0.4136274574655657,0.42194422559198763,0.41834884591812205,0.14166893109640313,0.1954216121035236,-0.04655923049367504,68025.85340570877,2.9449106209421463,2.1946189249203996
+96001,2010-07-16T16:00:00,283.3878095859716,285.056259568432,286.6024884432538,286.8088544369551,286.36330801166173,284.6565390329015,279.9962581920828,278.01038780079637,-273.15,2.450307210513832E-4,3.990215428644758,-272.3515942530189,8.536762385931011,0.8799583605164047,0.0,100.01172632707764,-7.3453647229951E-24,-7.345364920210326E-25,273.15731859561873,3.5191724047916527E-4,0.4275456143177963,0.42835035546697714,0.42073121164727256,0.4160595322019032,0.14210549914352155,-0.5657164683950497,-0.5172467115656771,67880.47659437233,2.941248978069007,2.2063900583398257
+96001,2010-07-17T16:00:00,280.0982993428457,282.8967808322111,283.7923424667711,284.91560256122807,285.4048220754355,284.6066312810133,280.0963632631775,278.01476709207105,-273.15,4.539489748367487E-5,4.260001629976721,-272.3512900849544,8.478675873916178,0.8799746439132314,0.0,100.00722700292445,-7.3453647229951E-24,-7.345364920210326E-25,273.15922514481196,2.5846748754208273E-4,0.41823403189721736,0.42092449464667775,0.4232446574691556,0.4170984357379495,0.14195065189619996,-0.11841795807858801,-0.2585532680182535,67964.90463676756,2.9400505957990335,2.198534770561105
+96001,2010-07-18T16:00:00,280.0399133532658,283.600148521197,286.0087322495808,286.0074449334723,285.115778139691,284.42424937425716,280.19152023736314,278.0197838109798,-273.15,1.3567606610346653E-4,3.7435525413733672,-272.3510534929783,8.40941385048234,0.879955664182317,0.0,100.01201302693732,-7.3453647229951E-24,-7.345364920210326E-25,273.1451979491338,1.2979419511219167E-4,0.4088151818266858,0.4132201609144035,0.4214283339083484,0.41767178208638145,0.14179579328423475,0.1967647821001659,-0.050736855630958096,67857.76058529317,2.938843572507481,2.190679289826723
+92352,2010-07-16T16:00:00,282.7812609023925,284.60513467602954,286.3362103150822,286.53289153670727,286.03754139076057,284.2781025366163,279.5224260377569,278.02893611086694,-273.15,2.450307210513832E-4,4.12346388938258,-272.3516059361772,8.490831784394413,0.8799550784345682,0.0,100.01262462628956,-7.3453647229951E-24,-7.345364920210326E-25,273.1567334329602,3.438983053990942E-4,0.42788222320415414,0.4286274197001615,0.4193893147303886,0.4150004884579187,0.1430781405939637,-0.6258337755243352,-0.6121674465370959,66916.62012397932,2.725343276170559,2.264924484558496
+92352,2010-07-17T16:00:00,279.41750589348436,282.34116516611454,283.40754343808,284.57923221971174,285.0888338907563,284.2340243577561,279.6243314430006,278.03365955977745,-273.15,4.539489748367487E-5,4.4234696351717995,-272.35126154485556,8.435851721029247,0.8799740536669427,0.0,100.00738743721648,-7.3453647229951E-24,-7.345364920210326E-25,273.1590621541734,2.500167649706367E-4,0.4188092175163025,0.42151964828558663,0.4224929038307256,0.4158903335039619,0.14294431970626495,-0.17397091909672077,-0.27297211405464994,66994.71242742933,2.724346648584053,2.2574257900625967
+92352,2010-07-18T16:00:00,279.3046086684786,283.09176420935637,285.5386846163347,285.582536160205,284.71890988564326,284.04828277439833,279.72132884849873,278.0389965859502,-273.15,1.3567606610346653E-4,3.7749090957306266,-272.35100673253106,8.362409302501746,0.8799576745653027,0.0,100.01132872126232,-7.3453647229951E-24,-7.345364920210326E-25,273.1422270302365,1.1917764015568446E-4,0.4086997285205475,0.4136824014231483,0.42105903324020977,0.4164988820676283,0.1428104789100875,0.21989709476003408,-0.08521916980461053,66883.50271153507,2.723339202090171,2.2499284737820484
+96012,2010-07-16T16:00:00,281.25322769858093,283.73827629544127,285.5340645131009,285.7285053320076,285.21118641026874,283.49249032078745,278.65230336279643,277.9585156160226,-273.15,2.450307210513832E-4,5.0864581673469145,-272.3736900687966,8.11309686350086,0.8784669021430608,0.0,100.37093165562554,-7.3453647229951E-24,-7.345364920210326E-25,273.15843874826135,3.135710213883278E-4,0.42410063013893884,0.4257492028819575,0.42581852697751005,0.42198707865200424,0.15103726366267037,-0.6984597997549414,-1.0076173181268309,64641.73241705674,2.9252317621196653,2.1243039474644547
+96012,2010-07-17T16:00:00,278.5552677116316,281.03708726270486,282.47956924147144,283.85131263350644,284.37115578121364,283.4480865152805,278.7465751048007,277.976095714609,-273.15,4.539489748367487E-5,5.712104627985608,-272.3711682951766,8.0908435634244,0.8711295359114548,1.404369027547059,117.11482403794088,0.0014366312374195628,2.3106049252369538E-4,272.8915986606819,2.970052389274098E-4,0.4234494605064205,0.4249167047780312,0.42589827444392836,0.42284045464323855,0.16078842920354872,-0.44581493040564174,-0.4165445591428722,64722.034847484676,2.924160540559134,2.1157562533325547
+96012,2010-07-18T16:00:00,277.6170561458398,281.7425854529432,284.6131557230296,284.7684318591035,283.9081483965573,283.25624659621457,278.83667641114596,277.9914558044697,-273.15,1.3567606610346653E-4,4.685421383344759,-272.3696040309098,8.05066361914613,0.8461838832777114,1.492287930911607,128.78786335007652,0.0014303050089562626,2.2502138084096876E-4,272.12201391630066,1.0754017470724471E-4,0.4099132584587133,0.41589915391223237,0.4244529585002652,0.4233826118521959,0.16096175833328127,0.16684481255111303,-0.1313183580479797,64637.623323214575,2.9230882624074583,2.107198422899364
+92355,2010-07-16T16:00:00,283.54231756616036,284.219791882157,285.0673831339706,285.45702235852906,285.368660465922,284.0392578288481,279.8710501481802,277.8978102075457,-273.15,2.450307210513832E-4,3.92647607161901,-272.3535940569389,8.364506112699956,0.8799787669726211,0.0,100.00610988577321,-7.3453647229951E-24,-7.345364920210326E-25,273.16030565897626,3.7730426803209117E-4,0.4258374317971952,0.42659271854874437,0.42770041047647556,0.4238437781775509,0.13745344417636937,-0.31144698256960174,-0.043197541750048626,67572.5096758276,4.710924222975635,1.6097417822930478
+92355,2010-07-17T16:00:00,280.4064235837087,282.10680900993924,282.8050503212609,283.8144468688899,284.30658193370004,283.94113710840793,279.9609519120774,277.90193242727895,-273.15,4.539489748367487E-5,4.131618508079799,-272.3533550956387,8.278972541094578,0.879989153174317,0.0,100.00317261216318,-7.3453647229951E-24,-7.345364920210326E-25,273.1600168207673,2.9322286526226835E-4,0.41806151320237783,0.41993411536032366,0.4265658771574492,0.42530195028606876,0.13710608960778736,0.09078652111452015,-0.14408793103541964,67663.18949983497,4.708764650834796,1.6029257063904367
+92355,2010-07-18T16:00:00,280.72467632698243,282.87470972607707,285.83550991745244,285.5536793789294,284.44843119597726,283.7530468841431,280.04529609673517,277.9074697974799,-273.15,1.3567606610346653E-4,4.212652898473635,-272.3530020491025,8.221218803614216,0.8799540316225127,0.0,100.01308842509414,-7.3453647229951E-24,-7.345364920210326E-25,273.1603635152181,1.7461736700428066E-4,0.41337834351805897,0.4152926459740706,0.4230205468964159,0.4254029953137444,0.13675830002986802,0.10251797128953558,0.08351366256891335,67584.16307890545,4.706601266993313,1.5960854138026972
+61566,2010-07-16T16:00:00,290.3869018035454,291.36680823229244,291.34484026336384,291.76360786105874,291.81778572641855,290.34326911372534,286.2427588174766,279.8303298159874,-273.15,2.450307210513832E-4,2.799432117289046,-272.35274383682116,10.919362859376069,0.879962916456691,0.0,100.01056327633711,-7.3453647229951E-24,-7.345364920210326E-25,273.16030565897626,4.875729960806265E-4,0.4405444446310391,0.4447904128873655,0.444985781958997,0.439465797721069,0.14574302460976257,-0.00493559879512964,-0.18267329853103495,81561.18734459278,3.4337089404474708,2.737580630610845
+61566,2010-07-17T16:00:00,287.4685229172471,290.9004313269164,290.5685123904708,290.9624831792749,290.9006021795747,290.2642068477315,286.3263368528172,279.8213906735465,-273.15,4.539489748367487E-5,2.917738739280843,-272.3539755690562,10.794035420019137,0.8799646321632912,0.0,100.0100718732373,-7.3453647229951E-24,-7.345364920210326E-25,273.1599015884705,2.3120435003684434E-4,0.425622445072323,0.4321101615538812,0.436924394058866,0.4418788671243897,0.14559405455461627,0.42846178399278717,0.17239647206504008,81722.92092138909,3.4298837456897266,2.7241973627109948
+61566,2010-07-18T16:00:00,287.0707662878088,291.3529339414963,292.41109602755483,292.23309376935083,291.20224747541664,290.1558599141259,286.40560888267316,279.8439618710854,-273.15,1.3567606610346653E-4,3.2562528178230195,-272.3542170494889,10.813790258919067,0.8799232721565087,0.0,100.02168181534795,-7.3453647229951E-24,-7.345364920210326E-25,273.15985452859763,7.328523998511297E-5,0.4121120116102467,0.42179689496790757,0.43084862309275107,0.4417646860560627,0.1454452906838189,-0.06514047389281263,0.025289827019434982,81631.3140928287,3.426064410009207,2.7108185272328966
+61561,2010-07-16T16:00:00,288.84486577104036,289.84886795933414,289.8640749999801,290.246398276789,290.2440608994281,288.76190778022016,284.7518851443517,278.1617729146469,-273.15,2.450307210513832E-4,3.088135996710532,-272.35000232436,9.344156072006873,0.8799633050626132,0.0,100.0104537368047,-7.3453647229951E-24,-7.345364920210326E-25,273.16030565897626,4.7134448501555355E-4,0.4335213707350424,0.4353835507517565,0.43803724669728394,0.434057159596706,0.1463404437089465,-0.12805696639881944,-0.08396608474877908,78123.06054188055,3.463077941628641,2.5623680551932417
+61561,2010-07-17T16:00:00,285.53420373673526,288.9678749047219,288.66317687703514,289.2121469151408,289.27092038652404,288.68586853246865,284.8360761514349,278.16279377090353,-273.15,4.539489748367487E-5,3.1398948201810946,-272.35004244824336,9.266570186181298,0.8799697822623713,0.0,100.00862373594197,-7.3453647229951E-24,-7.345364920210326E-25,273.15982298700567,2.7001518830161223E-4,0.4212392993915861,0.4248041504218888,0.4321218639403424,0.436141874547196,0.1461538892600064,0.44520169320101094,0.08040106940456271,78279.94607960655,3.4597696449228303,2.547591594049762
+61561,2010-07-18T16:00:00,285.4377780619195,289.2840323572893,290.6845148282162,290.50229536388855,289.4993415500885,288.56340485051936,284.91570232435254,278.1651178695059,-273.15,1.3567606610346653E-4,3.3879543508183563,-272.3500221076807,9.2206312105149,0.8799323416542624,0.0,100.01913237560683,-7.3453647229951E-24,-7.345364920210326E-25,273.1596343307863,9.959895463203017E-5,0.4087199481805414,0.41561008412401934,0.426790475073017,0.43604882008812484,0.1459677173947597,0.006330107741665057,-0.05857331650206931,78187.50203109634,3.4564663994174745,2.5328197458247037
+61141,2010-07-16T16:00:00,286.31058500421824,287.98944378453126,289.07977070027175,289.3111663472494,288.9631302031825,287.3755709592428,282.8102197030163,278.74558097111804,-273.15,2.450307210513832E-4,3.573782304150719,-272.3511947020081,9.692245068415769,0.8799486868450394,0.0,100.01447961419602,-7.3453647229951E-24,-7.345364920210326E-25,273.1580877102789,3.5814234954509744E-4,0.4256590835613817,0.42365141075256196,0.39973910979069865,0.40270344625326376,0.14597163568884378,-0.5543644221721797,-0.6967074632618847,73971.20281433001,2.5637246439603762,2.3642458215344564
+61141,2010-07-17T16:00:00,283.56541118180695,286.3879773321315,286.95228864327964,287.83096361103486,288.1250531920907,287.31675339674086,282.9072710700539,278.7500390110152,-273.15,4.539489748367487E-5,3.721871932166974,-272.3509690494853,9.63873759244703,0.8799710995720782,0.0,100.00823635873826,-7.3453647229951E-24,-7.345364920210326E-25,273.15944669490705,2.1152007122545816E-4,0.41273384825054815,0.4166709866647437,0.40479632255236814,0.4036766720630132,0.1458295162812835,-0.04405745781443869,-0.1343765783160263,74074.83227569886,2.562734307839196,2.353536567436124
+61141,2010-07-18T16:00:00,283.47071346770565,287.1056851350104,288.9874894582258,288.96516332293595,288.04266286693655,287.16477203954065,282.9997650554831,278.75476577064563,-273.15,1.3567606610346653E-4,3.391773244108594,-272.35079692141716,9.595672275567866,0.8799581529666888,0.0,100.01146413791605,-7.3453647229951E-24,-7.345364920210326E-25,273.1491028074538,1.0809317915902137E-4,0.4011103186328827,0.4069237615542867,0.40348181058934085,0.4041807837148557,0.14568776630768568,0.07875365349372228,0.12003080712065974,73976.24237517036,2.561735971960517,2.342822427189133
+92200,2010-07-16T16:00:00,281.66784271024926,284.06701366045326,285.75390183293297,285.9828712396037,285.51854391651943,283.82558287876583,279.05700565542213,277.9654518744303,-273.15,2.450307210513832E-4,4.955496931562382,-272.37230708243027,8.169399134646834,0.8785545654597725,0.0,100.34980271328875,-7.3453647229951E-24,-7.345364920210326E-25,273.1585477617559,3.220092602304781E-4,0.4252627899118366,0.4268080597186837,0.42696440838091165,0.4231192901323527,0.1512016640418371,-0.6583011337513293,-0.9440319128303558,65315.254898937965,2.940990530013244,2.1364627965740577
+92200,2010-07-17T16:00:00,278.9164150879835,281.44364808639597,282.83606083038626,284.17248857494275,284.6733607326923,283.7789065038599,279.150119602412,277.9820561858948,-273.15,4.539489748367487E-5,5.558721161946791,-272.3699327312294,8.144354502680843,0.8716461572735721,1.3223644757732886,116.11583399983712,0.0013527428160873423,2.1756830368275534E-4,272.9072761613116,2.9764166500842964E-4,0.42393026697323677,0.42547325927809393,0.4273578825058146,0.4240840203744827,0.16038019087612984,-0.4213675276766245,-0.41719800913162,65403.39927116368,2.9398231388125615,2.127763254172714
+92200,2010-07-18T16:00:00,278.01983656775354,282.2051178994314,284.9939705461475,285.1213199909006,284.2464777344602,283.59056871750175,279.23905597226326,277.9965914894795,-273.15,1.3567606610346653E-4,4.60096851170658,-272.3684600670641,8.104979359967876,0.8481574441065959,1.4051495787467498,127.1071700431915,0.001346785991619271,2.118818305422776E-4,272.1826456959634,1.1028568257262168E-4,0.41047612398798916,0.416404542364649,0.4257084616328241,0.4246360095609887,0.16054005929579762,0.138215262799422,-0.13194537549891805,65316.886932912326,2.938654556159892,2.1190527437247786
+92199,2010-07-16T16:00:00,282.12100426182917,284.43791659010253,286.0612323014234,286.3034193002113,285.86847303868836,284.18090607095894,279.44145595074406,278.25787337500805,-273.15,2.450307210513832E-4,4.823341499894936,-272.371425577009,8.48045232167887,0.8786185966432145,0.0,100.33438312850618,-7.3453647229951E-24,-7.345364920210326E-25,273.15862781808687,3.316308408475844E-4,0.42657111728636665,0.4283800746441718,0.42885971451350857,0.42523374035090594,0.15101012541871042,-0.6215620421020863,-0.9156928354028357,66120.88831899881,2.933481930375931,2.1729215171458174
+92199,2010-07-17T16:00:00,279.35752528214084,281.9400303047538,283.28777157318734,284.5708432147448,285.03150418256286,284.1338455370051,279.53398736433445,278.2739119796733,-273.15,4.539489748367487E-5,5.401976589476744,-272.36918996935015,8.445995843674732,0.8720255638877735,1.2621427249658916,115.3822013624083,0.0012911376064273733,2.0766003375565447E-4,272.91878910866717,2.9637040607092543E-4,0.4244181737363939,0.42616804334099756,0.4287303722830374,0.4263082636578447,0.15976629440886736,-0.3773403820717206,-0.392402693513809,66215.2909735701,2.9322686247766394,2.1640092852110806
+92199,2010-07-18T16:00:00,278.4606202490756,282.6977472093046,285.41997373017244,285.5326990864055,284.64295821626604,283.9517658260268,279.6223872923778,278.28865968035933,-273.15,1.3567606610346653E-4,4.499207465401313,-272.36780376607777,8.412515033777844,0.8496048265552735,1.3411577146814955,125.87346543415183,0.0012854520614781425,2.022325280743854E-4,272.2271719063612,1.0852464141950318E-4,0.4107870341662954,0.4169887529785292,0.42673646142232424,0.4268121730218162,0.15991448902795216,0.12308188016185201,-0.11764326878083796,66127.86625574002,2.931054431351236,2.155086163545965
+61417,2010-07-16T16:00:00,282.16751304312226,284.4794283166518,286.0961254276697,286.33878266182506,285.9056925293328,284.21878099798863,279.48025757265424,278.3161003850747,-273.15,2.450307210513832E-4,4.811063281374418,-272.3714255437991,8.533553537072175,0.878623087739749,0.0,100.3333018699907,-7.3453647229951E-24,-7.345364920210326E-25,273.1586334476612,3.3244698266540084E-4,0.4266861194675583,0.4285295073397914,0.4290657817211657,0.4254503701737812,0.15101352979555338,-0.6186659668260747,-0.9145535213897551,66212.25896127099,2.93244202146611,2.1758491497017953
+61417,2010-07-17T16:00:00,279.4084924441792,281.9945008524909,283.3351941325103,284.61325502596964,285.06998585330456,284.1716592225045,279.5727502116889,278.3323104818611,-273.15,4.539489748367487E-5,5.3883360657155,-272.3692245068574,8.498349685864637,0.8720522546978878,1.2579079215627083,115.33060909875506,0.0012868055179705593,2.0696328258777258E-4,272.9195987230618,2.9615499837341646E-4,0.424422008201941,0.42622847916287704,0.4288155946263036,0.4265325792712538,0.15973959366425644,-0.3760398081001975,-0.39059218380869926,66307.04781271498,2.931221114464225,2.1669233048647385
+61417,2010-07-18T16:00:00,278.5070192709638,282.7499356693177,285.462749757852,285.57509829252433,284.6847437237167,283.99011696152974,279.66111470968275,278.3473155958295,-273.15,1.3567606610346653E-4,4.48894061839305,-272.3678632898776,8.466044779853235,0.8497065441795815,1.3366577962950925,125.78672878473584,0.0012811390494416282,2.0155398754074892E-4,272.2303029967861,1.0822071657875264E-4,0.41079822614199946,0.4170479776969027,0.4267932526190036,0.4270303527707655,0.1598865606394971,0.12200622414032535,-0.11535881426055278,66219.61028024848,2.929999371409697,2.1579865671532135
+92198,2010-07-16T16:00:00,282.0747466130631,284.39789012459426,286.0276597771334,286.2694902935246,285.83267274151416,284.14466682941077,279.4044896711926,278.19928335250864,-273.15,2.450307210513832E-4,4.836382476526025,-272.37145129203384,8.42673668982435,0.8786137640224894,0.0,100.33554978268012,-7.3453647229951E-24,-7.345364920210326E-25,273.158621865174,3.3065133543742247E-4,0.42640159418606044,0.42817841419447367,0.4286089757561033,0.42494272983704584,0.15102830119577548,-0.6245442433321667,-0.9172965455947545,66032.18133900187,2.9303416145790093,2.169855514257599
+92198,2010-07-17T16:00:00,279.30732669350624,281.88655018038804,283.2407033283905,284.52917948378575,284.9942125438461,284.0976342229225,279.49706514947945,278.2150907432615,-273.15,4.539489748367487E-5,5.416405637119234,-272.36918169330386,8.393236801027331,0.8719973205266223,1.2666207572884272,115.43676222526167,0.0012957185114391891,2.0839680331813146E-4,272.9179329934989,2.964040297472519E-4,0.42432491399337285,0.4260497370509797,0.4285918912939951,0.4260111244659538,0.1598161648288534,-0.37958750582271217,-0.3942589680806514,66126.14971041984,2.9291372767684614,2.160951746157755
+92198,2010-07-18T16:00:00,278.41496419478284,282.64622744595044,285.3780075414317,285.49122223668957,284.60222025682583,283.91495525082047,279.58550495855167,278.22958240611973,-273.15,1.3567606610346653E-4,4.510066522049582,-272.36777140786444,8.358717099060495,0.8494973261995974,1.3459160890532402,125.96516696012915,0.0012900127944020078,2.0295004106199912E-4,272.2238609795501,1.088080340342281E-4,0.41069642964719666,0.41686918068316614,0.42663048011985344,0.4265224121951608,0.15996551603986742,0.1238900351802323,-0.11963664282701322,66038.73692584921,2.9279320828501008,2.1520371855773557
+92354,2010-07-16T16:00:00,282.1108467621827,283.40675620565173,284.59687786309723,284.893630996042,284.5427078285702,283.0132516122013,278.13270698638223,278.1052694506705,-273.15,2.450307210513832E-4,3.7713016101958496,-272.3580930818263,8.302264347753598,0.8799747041052495,0.0,100.00719767150754,-7.3453647229951E-24,-7.345364920210326E-25,273.1589615018082,3.666832686839028E-4,0.44264732737063506,0.4433738574161854,0.44052306900186844,0.4353249193890965,0.14365912894614652,-0.6356906052377653,-0.24246311485441538,64670.02248524059,3.826788005568748,2.0313402067579873
+92354,2010-07-17T16:00:00,278.1654246947221,280.7751652404637,281.5150764673199,282.81761546875487,283.5121831071342,282.92172963839147,278.23384470791194,278.1173469731787,-273.15,4.539489748367487E-5,4.233229355472115,-272.3567383434227,8.220326460927181,0.87999648825676,0.0,100.00112268742112,-7.3453647229951E-24,-7.345364920210326E-25,273.1600392285257,2.926163295208566E-4,0.4353755561534042,0.43803840855390414,0.44138293785140426,0.4364160801888444,0.1433765461386869,-0.27424767099814334,-0.08800833976627512,64751.07704622407,3.825975636383956,2.0244279726786707
+92354,2010-07-18T16:00:00,278.5429096779454,281.6608296868523,284.4939502339839,284.3603248406322,283.3194752910536,282.7012418428343,278.3290499506052,278.1279695136505,-273.15,1.3567606610346653E-4,3.780585795333981,-272.3556708674832,8.144640802117522,0.8799692626357235,0.0,100.0080422949575,-7.3453647229951E-24,-7.345364920210326E-25,273.1412950493028,1.3891404227877355E-4,0.4269755328508918,0.43060821666220356,0.43925649841701936,0.4369617201830741,0.1430918436159678,0.14937973900462492,0.05868538937529428,64667.49693671577,3.8251442417834216,2.0175389915925934
+61277,2010-07-16T16:00:00,296.90932107407986,297.7920389981144,297.63258186255354,298.1757210266428,298.3869960265967,297.076079337485,292.7867829868314,288.4539462506059,-273.15,2.450307210513832E-4,2.052844529618504,-272.399456195909,18.845852862641102,0.8799378723119492,0.0,100.01757584043031,-7.3453647229951E-24,-7.345364920210326E-25,273.16030565897626,4.953968908427343E-4,0.4345581798204469,0.4391818972931272,0.41841414230820106,0.3528087770739718,0.15343805374177552,0.17524338405854947,-1.156257838603515,95235.53585460484,2.520281334196468,2.921661220359347
+61277,2010-07-17T16:00:00,295.76608412354915,298.738943638646,298.8886026760274,298.61668847356407,297.9866364044335,296.9993424266126,292.8723292827986,288.2295744125863,-273.15,4.539489748367487E-5,2.227414205061026,-272.3999145413449,18.605948155174797,0.8799485135571578,0.0,100.01458058262402,-7.3453647229951E-24,-7.345364920210326E-25,273.1600801129519,2.0849842996045336E-4,0.41878140221158,0.425713737293568,0.42710156421767576,0.35505060819566675,0.153372551525025,-0.2384704969189142,0.027160594154181865,95467.361343663,2.5169486070874196,2.913700444260189
+61277,2010-07-18T16:00:00,295.51589195749165,299.3642300116419,299.7934371423228,299.60708154664684,298.65625702911836,296.9845362943226,292.9551156525774,288.4254322765172,-273.15,1.3567606610346653E-4,2.984689838467078,-272.39986722566994,18.826847456975333,0.8798908148953716,0.0,100.03084217396255,-7.3453647229951E-24,-7.345364920210326E-25,273.1603635152181,1.468137914260036E-5,0.40206429383635234,0.4126585003679104,0.42338090879915236,0.35683603430894406,0.15330692139300817,-1.2776831949335672,1.3022932920744232,95388.49377152012,2.5136158799783708,2.905734879304799
+92353,2010-07-16T16:00:00,282.2538401107124,284.2993100089816,286.32758492719586,286.4938920219826,285.92493595706526,284.063166758197,279.2146916487462,278.0106545021027,-273.15,2.450307210513832E-4,4.387460606477576,-272.35073273382716,8.432222276877514,0.8799521725439455,0.0,100.01343066997107,-7.3453647229951E-24,-7.345364920210326E-25,273.15656174183545,3.304023155099546E-4,0.42578462247039184,0.426419849712074,0.4153220104498115,0.4136242891467714,0.14491232058103148,-0.6939067224030174,-0.7921081832145727,66384.39672168501,2.378792357212352,2.31560972585363
+92353,2010-07-17T16:00:00,279.17017045387087,282.0777932027929,283.34426706469196,284.5284700379592,285.0114931810125,284.0338864795528,279.3190548680234,278.01451350825954,-273.15,4.539489748367487E-5,4.69860596831259,-272.3505180822306,8.390669014752019,0.8799734038607793,0.0,100.00757213978397,-7.3453647229951E-24,-7.345364920210326E-25,273.1591097252242,2.4980992055514755E-4,0.4171485467244235,0.41970119904117575,0.41896993053378484,0.41419108350523337,0.14481384505890713,-0.2476373520280589,-0.34421154198809734,66455.5801659855,2.3782617293938695,2.3082896115614173
+92353,2010-07-18T16:00:00,278.7656278722513,282.82335425205974,285.2231540208266,285.35378539228697,284.54415175093476,283.8534646648978,279.41873208280316,278.0195022790992,-273.15,1.3567606610346653E-4,3.8546015225156203,-272.3503717890353,8.320908216209322,0.8799552047871916,0.0,100.01187335011655,-7.3453647229951E-24,-7.345364920210326E-25,273.1383791268864,1.1613613166141075E-4,0.406719421341323,0.4120997841883276,0.4180605303774848,0.41467572447770384,0.14471571761160923,0.2876094860452466,-0.18244569524559845,66339.56142508895,2.377719122392495,2.3009657110650568
+61205,2010-07-16T16:00:00,284.69416939664995,286.66470844842326,287.8968335514511,288.16543848084115,287.8312764097664,286.2141346134873,281.60175235177627,279.0858491956381,-273.15,2.450307210513832E-4,4.170590683585243,-272.36474409299575,9.585534635215161,0.8791428147698548,0.0,100.20832894012976,-7.3453647229951E-24,-7.345364920210326E-25,273.15874875172403,3.601336929681622E-4,0.4280791473730128,0.4291913029675026,0.42014002931182326,0.418308856809304,0.1494458081184114,-0.5131969014798852,-0.8097859238072072,71042.88443547573,2.876887887993545,2.3165157803025402
+61205,2010-07-17T16:00:00,282.0148320288602,284.75785998265536,285.6698137906605,286.6915288701005,287.00742838831974,286.1585937726235,281.6940988116875,279.09502625085395,-273.15,4.539489748367487E-5,4.563961931771959,-272.3637413371715,9.529097924520832,0.8751590077041091,0.7643499101513358,109.31875059306738,7.819091248118895E-4,1.2575830371913546E-4,273.01378313690316,2.5965295622921926E-4,0.42079967382824696,0.42396593257471965,0.42099088618098857,0.41950270740565426,0.15469307213531958,-0.20968008994246518,-0.24776189179570088,71151.65307992938,2.875413062483411,2.306460288900486
+61205,2010-07-18T16:00:00,281.35268382292196,285.4687086550261,287.69477347536304,287.73677383480566,286.81704761861494,285.99865335824666,281.78224967140864,279.11387123489857,-273.15,1.3567606610346653E-4,3.983933106360074,-272.3629770225226,9.512387781201925,0.8615712010962634,0.8122011547808706,115.67490298471274,7.784659755664477E-4,1.2247142229299883E-4,272.59242920310095,1.0009660847177309E-4,0.4074014280549451,0.414196205447064,0.4188039846827142,0.4199328531508129,0.15472748612482676,0.04830716982415242,0.009397038333042455,71061.17037081772,2.8739362261036403,2.2963971657379907
+61215,2010-07-16T16:00:00,285.3838434247554,287.27282164488116,288.41784332118044,288.70218063232045,288.40080792376995,286.7940090688852,282.2056416144436,279.60327150031816,-273.15,2.450307210513832E-4,4.051894233857036,-272.36636661508237,10.096112406043975,0.8791955795342806,0.0,100.19561811105777,-7.3453647229951E-24,-7.345364920210326E-25,273.1588496147906,3.717951947576824E-4,0.4288792330794098,0.430277513736782,0.4212618436680026,0.4174090212127811,0.14939945185246192,-0.4627174035950513,-0.8002118072319143,72371.61034638922,2.890398945815088,2.3608563716489517
+61215,2010-07-17T16:00:00,282.77438914474715,285.547003559361,286.4035062991037,287.34537564883857,287.5997304502595,286.7379410207384,282.29752038701605,279.60400212722953,-273.15,4.539489748367487E-5,4.423154346377722,-272.36548668534033,10.028990642326997,0.8754692601059071,0.7148320760846644,108.71599774273729,7.312537302296025E-4,1.1761114659467493E-4,273.0232609623444,2.5870824137611855E-4,0.42097533814422594,0.42446000836469555,0.42230466087684443,0.41870878719734134,0.15429957752765636,-0.19097863974370854,-0.21823274079578422,72488.35594880884,2.8887378057718927,2.3508210920567993
+61215,2010-07-18T16:00:00,282.08651700382677,286.2507668595796,288.35522273907634,288.3836102224429,287.4619689497918,286.5875373076057,282.38530000447275,279.6307753681294,-273.15,1.3567606610346653E-4,3.9027659689912086,-272.36478106116505,10.02432641563743,0.8627595845890232,0.7595833138194775,114.66097480629458,7.280336428184571E-4,1.1453720330968891E-4,272.6292224003717,9.549327886031304E-5,0.40737961694433555,0.414456906720008,0.4198997862458676,0.41918611698615676,0.15432456068390055,0.00420615783907692,0.05599370784116995,72398.16036451193,2.887074228348496,2.34077867804086
+61239,2010-07-16T16:00:00,293.02821773671155,293.5835080633416,293.5298288118791,294.01925474186265,294.15409073845007,292.5288659187507,288.25111478933684,281.87797092878077,-273.15,2.450307210513832E-4,2.6940155150504634,-272.36022469321625,13.091560255894594,0.8799655847467902,0.0,100.00981671154572,-7.3453647229951E-24,-7.345364920210326E-25,273.16030565897626,5.582276848694809E-4,0.4569940011613649,0.46870551019006157,0.4706766759378914,0.47374306831916474,0.14505737335947372,0.08853382013469961,-0.33706374133309513,86086.86587984367,3.399613816182227,2.9635446247754884
+61239,2010-07-17T16:00:00,290.87125345813257,294.2541044970372,294.3548584973974,294.2684506014779,293.6550346951684,292.4856331996423,288.33246083524523,281.854782672893,-273.15,4.539489748367487E-5,2.6707175188755468,-272.36047336290716,12.990685027217529,0.8799520828332275,0.0,100.01359717079102,-7.3453647229951E-24,-7.345364920210326E-25,273.16007764090546,2.7610249532356056E-4,0.4410380871380955,0.4496432926808418,0.4724528637512098,0.47651129878530685,0.14495362128337494,0.3375880737668311,0.022147167286668937,86318.1681584364,3.396053027616277,2.9517720278810864
+61239,2010-07-18T16:00:00,289.3009334764202,294.7803850807499,295.3796649309918,295.2387583454424,294.1647736912084,292.4697620938556,288.4114188037143,281.87055680189525,-273.15,1.3567606610346653E-4,2.8507448294732938,-272.3605386546111,13.015424661585739,0.8799466661991464,0.0,100.01513577013932,-7.3453647229951E-24,-7.345364920210326E-25,273.1603635152181,4.4330541045875336E-5,0.42631679719754045,0.4377484912681734,0.4644594612346455,0.4763678364881509,0.1448493625266786,-0.12171649267015724,0.23660213340060898,86227.64385283322,3.392480465305147,2.939997166952136
diff --git a/test/example_data/era5_land_camels_mr_sum_mean_2010.csv b/test/example_data/era5_land_camels_mr_sum_mean_2010.csv
new file mode 100644
index 0000000..29f3ede
--- /dev/null
+++ b/test/example_data/era5_land_camels_mr_sum_mean_2010.csv
@@ -0,0 +1,55 @@
+gage_id,time_start,snowfall_hourly_sum,snowmelt_hourly_sum,surface_latent_heat_flux_hourly_sum,surface_net_solar_radiation_hourly_sum,surface_net_thermal_radiation_hourly_sum,surface_sensible_heat_flux_hourly_sum,surface_solar_radiation_downwards_hourly_sum,surface_thermal_radiation_downwards_hourly_sum,evaporation_from_bare_soil_hourly_sum,evaporation_from_open_water_surfaces_excluding_oceans_hourly_sum,evaporation_from_the_top_of_canopy_hourly_sum,evaporation_from_vegetation_transpiration_hourly_sum,potential_evaporation_hourly_sum,runoff_hourly_sum,snow_evaporation_hourly_sum,sub_surface_runoff_hourly_sum,surface_runoff_hourly_sum,total_evaporation_hourly_sum,total_precipitation_hourly_sum
+61019,2010-07-16T16:00:00,0.0,2.090196044489699E-11,-6634397.875952309,1.2163804180371067E7,-3354775.8262973893,-1960236.4949000617,1.4201370247091502E7,2.9725465252989125E7,-5.988518379734166E-4,-1.7811528886930896E-4,-0.0018750035313761996,-9.395496997716142E-7,-0.00300015278211992,0.010873260318116381,1.1519451043912876E-12,0.0029737157482202076,0.00789954226440326,-0.002652910009742402,0.020023423239006924
+61019,2010-07-17T16:00:00,0.0,0.0,-4890764.649565292,8912656.333315404,-3714938.068172446,-1051904.7219144925,1.0392646256950788E7,2.8052732720498316E7,-3.900341739337309E-4,-1.069047388937793E-4,-0.0014573019994590566,-1.4393548236169335E-6,-0.0023217916128038542,0.003373529320016623,0.0,0.0027037448750352566,6.697857915217205E-4,-0.001955679950750999,0.004093792646874787
+61019,2010-07-18T16:00:00,0.0,1.0157150746545788E-10,-9680517.85401093,2.1406524473890822E7,-6690047.428466429,-3932020.055104415,2.4945569393600404E7,2.6055149260231216E7,-0.0025733153065293415,-5.927193692015617E-4,-7.035590892566981E-4,-1.374912426774514E-6,-0.005367733653879531,0.003461905105722796,1.0642971073180376E-12,0.0027524741455155284,7.094312971762517E-4,-0.003870968277664382,0.0037060865156302116
+96001,2010-07-16T16:00:00,0.0,2.124625760132976E-11,-6668054.120333077,1.2234306046391284E7,-3376276.773236637,-1972915.787248774,1.428536888030465E7,2.966861503015613E7,-6.072332501033754E-4,-1.8054258596392417E-4,-0.001877638788833779,-9.537748288533525E-7,-0.0030186405069976023,0.01059000015115427,1.1709199476771193E-12,0.002860408786026047,0.007729588975229704,-0.002666368204780245,0.019726420918638254
+96001,2010-07-17T16:00:00,0.0,0.0,-4906737.531568299,8931569.139228508,-3716313.0160711342,-1058594.6238588942,1.0416044411800072E7,2.801137421346183E7,-3.93965323198623E-4,-1.079450121884181E-4,-0.0014586951276299813,-1.4618493482043954E-6,-0.0023327054373165268,0.003308779102403444,0.0,0.002652322069000253,6.56458413391744E-4,-0.0019620670721399694,0.004068157945872741
+96001,2010-07-18T16:00:00,0.0,8.016559178009726E-11,-9681125.665166447,2.1438516772434894E7,-6719524.26508263,-3936455.969971389,2.4986271184052747E7,2.5984074213880915E7,-0.002583107615953037,-5.939096176394022E-4,-6.927980624117041E-4,-1.3964127414762737E-6,-0.005375713736021957,0.0034107911198708405,1.0818282125277732E-12,0.002706985527849458,7.0380584724799E-4,-0.0038712113175650227,0.003678564982522958
+92352,2010-07-16T16:00:00,0.0,4.7082616920701415E-12,-7102466.318755307,1.3154629810768992E7,-3630767.642478914,-2153694.7114684787,1.537338833152469E7,2.928348407491663E7,-7.129965631878135E-4,-2.0494133734723312E-4,-0.0019210030724086682,-1.1362591218746779E-6,-0.0032452176604089128,0.00948333207681271,1.0654471501451829E-13,0.0025147160634965706,0.0069686132807384666,-0.0028400774977170784,0.018839316062866377
+92352,2010-07-17T16:00:00,0.0,0.0,-5034055.420452808,9192922.143078156,-3769145.830206357,-1171301.975550761,1.0732123500512075E7,2.7780023003965896E7,-4.385488716891249E-4,-1.0195006478311341E-4,-0.001470736620846206,-1.7425623147824447E-6,-0.0023765519242851816,0.0028265650541591026,0.0,0.002226413360849368,6.001537927073864E-4,-0.002012977959897331,0.004075111413378123
+92352,2010-07-18T16:00:00,0.0,6.494154058027782E-13,-9846445.63051578,2.167375002536444E7,-6981649.499400748,-3787926.326294912,2.528964789797561E7,2.5502681828637406E7,-0.002748487639814819,-5.674702579790406E-4,-6.196960515096744E-4,-1.6644862664428793E-6,-0.005362544722614967,0.0028226809769233046,0.0,0.002292921069613082,5.29759753236419E-4,-0.003937318129715616,0.0031224149927492405
+96012,2010-07-16T16:00:00,0.0,2.100641025978373E-10,-7468117.58031277,1.410839236602013E7,-3758006.101885078,-2476084.3257606993,1.6637625357025113E7,2.8763955996375337E7,-0.001184530937226786,-2.8248817740017957E-4,-0.0015183363026618805,-9.354975845419526E-7,-0.0037927685264605945,0.013353743568082665,1.4112658725534547E-15,0.004429838111686671,0.008923904831058432,-0.0029862914229149906,0.017449432698251964
+96012,2010-07-17T16:00:00,5.332970574673405E-4,2.126757378418645E-4,-5600552.811177117,1.0082627101685062E7,-3579422.7633228274,-1717410.2384289019,1.2194917856455334E7,2.7601613862892494E7,-5.411217390071994E-4,-1.2782407148449575E-4,-0.0015704526905971183,-1.0318254051891043E-6,-0.002683604454807058,0.006015358622568512,8.168177327945255E-7,0.0040514416750152445,0.0019639179100591738,-0.0022396134466979682,0.009698480277790491
+96012,2010-07-18T16:00:00,5.510054548583854E-6,2.180620156348672E-4,-9584111.487052979,2.117395530927386E7,-6573942.266492914,-3900468.39632683,2.5213882559655726E7,2.5505232033846546E7,-0.0026946386698255675,-5.733773573696328E-4,-5.641547173165904E-4,-1.2294459927243201E-6,-0.00569560491582787,0.0041883074513983515,8.66355850560108E-7,0.003939864335899817,2.484428524385731E-4,-0.0038325337287328067,0.0019064185094030447
+92355,2010-07-16T16:00:00,0.0,2.4776740921951457E-10,-4811548.560879813,7460880.001571092,-1498872.987169416,-1282018.0497512438,8648598.275988478,3.087335353233831E7,-4.764444675880847E-5,-6.040337740102966E-5,-0.0018159022213831157,-5.3220000542343274E-8,-0.0020091611258909944,0.014116212218398979,1.548546307621966E-11,0.004447356543402985,0.009668858021958148,-0.0019240032364015618,0.02023498676033981
+92355,2010-07-17T16:00:00,0.0,0.0,-4742496.1958627915,7506706.776119402,-2704289.2367111817,-782100.0157109189,8697717.336475516,2.8607619524744704E7,-1.2980059348193098E-4,-1.366288050263925E-4,-0.0016298945266465669,-6.756466052768805E-8,-0.0023141200921241445,0.0061483588728114364,0.0,0.005099648186894542,0.0010487111326786009,-0.0018963912942352387,0.004725465783965694
+92355,2010-07-18T16:00:00,0.0,2.6532572955790537E-10,-8455139.65435978,2.0531577214977738E7,-5041657.169939774,-5633649.258968316,2.3781442881382566E7,2.7590429454831112E7,-0.0016416236721652282,-7.128082384053217E-4,-0.0010264776614169063,-6.540742578166853E-8,-0.0057060883028574655,0.007004668568871852,1.548546307621966E-11,0.005047872299672297,0.0019567936315496547,-0.0033809739765161204,0.00758037807890881
+61566,2010-07-16T16:00:00,0.0,5.7635815283962634E-11,-2833302.744235781,4282456.596270801,-1661283.227394239,-192350.98990844077,5011553.4450310785,3.36913305076522E7,-2.1774288806408264E-5,-8.623257660564238E-6,-0.0011000297234457705,-2.5310697948829862E-6,-0.0011692225354476094,0.06417466519227567,0.0,0.02048718144771472,0.04368748385236359,-0.0011329586198264019,0.07320641542069502
+61566,2010-07-17T16:00:00,0.0,1.4079072804786555E-10,-5012306.901423511,8932918.156385753,-3423716.4218071233,-522935.385818352,1.0456403361224351E7,3.1485885609236103E7,-9.455241447677237E-4,-2.1185599628048923E-4,-8.450251927908402E-4,-1.8768194829593854E-6,-0.0027491145362762708,0.006840593502904406,3.960128236978535E-12,0.006506676372798666,3.3392000617026826E-4,-0.002004281582939063,0.001732738524502758
+61566,2010-07-18T16:00:00,0.0,7.025843228135748E-10,-1.1384026595335161E7,2.1444951934906095E7,-5663592.508988836,-3190485.158123371,2.508787930709082E7,3.0083269576288167E7,-0.0034480078925532283,-7.580964551592637E-4,-3.43499890955784E-4,-2.5503038809829746E-6,-0.0071394111128830285,0.005688796885083052,3.975688662271181E-12,0.005464653669692356,2.24141928730248E-4,-0.00455215389504884,0.0012850181605994432
+61561,2010-07-16T16:00:00,0.0,0.0,-2788492.1899564364,4713764.824165828,-1815905.4806357415,-448569.29943989654,5517285.208578678,3.281407453769926E7,-9.125295492882724E-6,-6.874318590093536E-6,-0.001099014785298581,-2.513924478326078E-8,-0.0011300455205125732,0.04728453330336459,0.0,0.01191711058691511,0.0353674219959663,-0.0011150400774951378,0.05324089226856752
+61561,2010-07-17T16:00:00,0.0,7.133496669944782E-12,-4945228.116712144,8870633.465173058,-3542964.206759537,-569231.6763847,1.039104573957585E7,3.0451077851357173E7,-7.397371166020072E-4,-1.7608286061387624E-4,-0.001061613837112485,-2.5493378308569355E-8,-0.002439598483554001,0.0064087092991996965,0.0,0.005934701507984294,4.7400907346143E-4,-0.0019774586075093944,0.0023910677409562566
+61561,2010-07-18T16:00:00,0.0,4.140994816902946E-10,-1.0451680773612902E7,2.0679803224950932E7,-5650856.866197521,-3341026.70324094,2.4208961011632916E7,2.9246673634257257E7,-0.003018811845381441,-6.837775894024783E-4,-4.7671964543741967E-4,-2.626147756250566E-8,-0.005961689840528026,0.005662786644730574,4.235513647779714E-13,0.0053427448101472635,3.2004098676723244E-4,-0.004179334916720837,0.0018202277585909047
+61141,2010-07-16T16:00:00,0.0,4.0810254825530507E-10,-6101250.044864159,1.0680956238175128E7,-3023794.492206948,-1433790.092326009,1.2501235006981269E7,3.1226312376582947E7,-5.737828994023159E-4,-1.551929064909914E-4,-0.001708791525566242,-1.952202174849247E-6,-0.0027458028678229553,0.011340107889738101,9.919684176670025E-12,0.0029734370975780036,0.008366669598647888,-0.0024397191832732958,0.02562562614557816
+61141,2010-07-17T16:00:00,0.0,4.5663938337570255E-11,-4893534.283255757,8968913.260444852,-3702649.6303441906,-867241.4191470935,1.0507420924071873E7,2.9530866596303698E7,-6.765840498400205E-4,-1.3206662141412233E-4,-0.0011455388346823842,-2.5983797894337747E-6,-0.002337410583894968,0.002802557025569665,0.0,0.0022890140565676926,5.135444486950209E-4,-0.0019567874570217184,0.0031785511621395266
+61141,2010-07-18T16:00:00,0.0,1.7262581545935774E-10,-1.0447197042861778E7,2.12078338214904E7,-6242039.270267343,-3416349.3191633276,2.482718141933649E7,2.7911883618248712E7,-0.0030039857758187116,-5.952232870151722E-4,-5.759701835197613E-4,-2.3631429309187694E-6,-0.005579366850987153,0.002881187742586284,8.032770609878873E-13,0.0023305717355102226,5.506161759217482E-4,-0.004177541924977822,0.0029553635986559967
+92200,2010-07-16T16:00:00,0.0,1.9779794445891627E-10,-7167210.030374806,1.3498794481122758E7,-3645236.9581019436,-2342004.389884196,1.5919237162666734E7,2.8981216122275427E7,-0.0011153655391580222,-2.653232956635054E-4,-0.0014843891711728149,-8.88403376049414E-7,-0.0036263289458678427,0.014028861478742716,1.3288585970850508E-15,0.00451894921305672,0.009509911560986956,-0.0028659669064219784,0.018927254777330475
+92200,2010-07-17T16:00:00,5.021565343555016E-4,2.0025707991593443E-4,-5592665.77634966,1.0028802330846813E7,-3560310.198891621,-1665862.4689317467,1.211457943206762E7,2.7782327838977013E7,-5.65503450272856E-4,-1.3170793505817873E-4,-0.0015390269492812343,-9.841356888728873E-7,-0.0027106189832467502,0.005949362450954468,7.691217421077486E-7,0.004075945760145839,0.0018734177609118822,-0.0022364532696660293,0.009288375439297962
+92200,2010-07-18T16:00:00,5.188308949925312E-6,2.05328839738603E-4,-9673016.267300567,2.116220596150927E7,-6536445.371546311,-3828682.7606029315,2.518807519099829E7,2.5718941379536677E7,-0.002731020019793731,-5.802148134184358E-4,-5.564878671495297E-4,-1.1707108324662029E-6,-0.00575371666976967,0.00421240209889167,8.157672076833448E-7,0.003965467700542624,2.4693413597920037E-4,-0.003868077514768269,0.0018608176458204384
+92199,2010-07-16T16:00:00,0.0,1.9396486739571593E-10,-6945571.154517872,1.3030781099367546E7,-3532230.677770452,-2249881.0717597,1.5366182196414476E7,2.924343132764979E7,-0.0010646998101995037,-2.531129487807401E-4,-0.0014579951367156682,-1.5313482700691662E-6,-0.003503253962858308,0.016290366336377888,1.2683410977434825E-15,0.005487317669252079,0.010803048157272965,-0.002777339730889741,0.021578986352442743
+92199,2010-07-17T16:00:00,4.7928784252938535E-4,1.9113718426352715E-4,-5649871.18123233,1.0082822425361307E7,-3538643.6457664873,-1633064.250649614,1.2161527067924675E7,2.801363546473572E7,-6.156970031359211E-4,-1.3958419327298645E-4,-0.0015031598892584178,-1.6165487078811195E-6,-0.002753332135834764,0.006104459609433941,7.340951978059756E-7,0.004310560155186043,0.001793900202914136,-0.0022593234411257567,0.00891083519557384
+92199,2010-07-18T16:00:00,4.952028367363929E-6,1.959779783251742E-4,-9848718.637050511,2.125085744080493E7,-6497969.106901422,-3775794.053134756,2.5274544890750725E7,2.5959552675313637E7,-0.0028063899247361417,-5.901068463941152E-4,-5.403871696220699E-4,-2.2258461391069723E-6,-0.005828097315912126,0.004371129352464007,7.786164816521459E-7,0.004134696767707154,2.3643231473210454E-4,-0.003938331014374657,0.001781183040439255
+61417,2010-07-16T16:00:00,0.0,1.933140669241864E-10,-6929279.21440477,1.2996086340020303E7,-3525219.584524589,-2241236.703842248,1.5325268999549383E7,2.926750005423776E7,-0.0010611479556515407,-2.522321508749756E-4,-0.0014558068174687975,-1.63762944617774E-6,-0.003494312613179095,0.01654232516748486,1.2640854972548242E-15,0.005653545079857299,0.0108887795739841,-0.0027708250381474923,0.021794357532371765
+61417,2010-07-17T16:00:00,4.776797123658948E-4,1.9049587363888424E-4,-5653938.757439369,1.0088280188936366E7,-3538277.8871702426,-1629579.464636869,1.2167034252284337E7,2.803640267809153E7,-6.200327293611182E-4,-1.400699058423139E-4,-0.0014998838564307473,-1.6948641177304315E-6,-0.002759417542748271,0.006124084271087968,7.31632125460482E-7,0.004336169710664529,0.0017879152901142646,-0.0022609496237927704,0.008881593531335556
+61417,2010-07-18T16:00:00,4.9354130780088045E-6,1.9532042587269894E-4,-9862309.741244044,2.125413726357166E7,-6495377.196949876,-3768895.4496522606,2.5277644306142066E7,2.598285457027292E7,-0.0028128526382004966,-5.905519212163707E-4,-5.387285670452447E-4,-2.4084086422721173E-6,-0.005840732380328324,0.004383080582936003,7.760041696169018E-7,0.00414744061075538,2.3563971879721237E-4,-0.003943765369172276,0.0017752313472354298
+92198,2010-07-16T16:00:00,0.0,1.946530470511965E-10,-6962473.711461718,1.3067337746613309E7,-3540039.526787372,-2258715.8894173466,1.5409373275833422E7,2.9219259205661424E7,-0.001068474890745091,-2.5404060972028405E-4,-0.0014602312390505153,-1.3513613565036594E-6,-0.0035125872188302184,0.016091325656608438,1.2728411216467611E-15,0.005317875031204708,0.010773450091543605,-0.0027840985893633615,0.021389563719538433
+92198,2010-07-17T16:00:00,4.809883367826822E-4,1.9181533141142095E-4,-5643434.01675031,1.0074529115284113E7,-3538867.188900186,-1636655.3779206455,1.2153098315303791E7,2.7991266843485206E7,-6.110855382247996E-4,-1.3905890630949458E-4,-0.0015058767802112276,-1.465316464822937E-6,-0.0027446979709663893,0.00607991713862978,7.366997384483044E-7,0.00427974920173131,0.001800168700032911,-0.002256749744790704,0.008940636201953765
+92198,2010-07-18T16:00:00,4.969597967578332E-6,1.9667329624345917E-4,-9834976.660795309,2.124721720326697E7,-6501159.01348116,-3782027.54688884,2.527172757694537E7,2.593613733279758E7,-0.0028000280667972123,-5.896544118589458E-4,-5.420210585407475E-4,-1.914346265259239E-6,-0.005813118853700977,0.004354235886490621,7.813788840347609E-7,0.004116966848493077,2.3726871716011792E-4,-0.003932836353542804,0.001787435124872572
+92354,2010-07-16T16:00:00,0.0,0.0,-6251773.908510268,1.1148565463145174E7,-3176175.466942862,-1625576.0863110647,1.3035001161746934E7,2.8950244852408078E7,-3.401783873575782E-4,-1.0789703689007563E-4,-0.00205103557874543,-7.98346977324019E-7,-0.0027718336282668695,0.00776563301083133,0.0,0.0028794284401297177,0.004886204123126602,-0.0024999092633170546,0.01412985240839043
+92354,2010-07-17T16:00:00,0.0,0.0,-4737636.703607801,7735738.657345069,-3108600.906266182,-798685.634386328,9035864.643880544,2.759348845244259E7,-1.8520072734682082E-4,-4.202931660862345E-5,-0.0016660459113580434,-1.1727028013037084E-6,-0.0022592603235577695,0.003847567135962966,0.0,0.0030773482585270207,7.702194484799261E-4,-0.001894448342368626,0.004104020650300386
+92354,2010-07-18T16:00:00,0.0,0.0,-9212959.761436213,2.107285824615915E7,-6358200.699464868,-4297989.200069048,2.4587802398066625E7,2.566743309546004E7,-0.0023150196751997947,-4.913637315863753E-4,-8.765995542985177E-4,-1.0222253168923607E-6,-0.00553567660530367,0.00425800616550215,0.0,0.0031855862536888015,0.0010724223155998385,-0.003684004973224689,0.004689309567856515
+61277,2010-07-16T16:00:00,0.0,8.144071392341559E-10,-2969084.000477326,3162271.3479713593,-811617.3023866348,170552.93269689733,3735018.3565632445,3.764300071121717E7,-1.0247956761347933E-5,-8.97135812264638E-7,-0.001173330846115911,-2.778396855035089E-6,-0.0011970598579591099,0.00781840503855935,3.0562494990364745E-12,0.0021745494253453315,0.005643852314687286,-0.0011872538069800998,0.03207393817077683
+61277,2010-07-17T16:00:00,0.0,6.490362572499277E-10,-6533326.675894989,1.000458246396181E7,-2252148.8114558477,-499477.28878281615,1.181855922673031E7,3.677782966014319E7,-0.001754483534467711,-2.78355737010057E-4,-5.77980242136128E-4,-1.6760009925519082E-6,-0.0033446845031723485,1.2887316558127758E-4,5.0011355438778675E-12,1.1894109176565182E-4,9.928647259823745E-6,-0.002612494587284781,4.695071880118454E-4
+61277,2010-07-18T16:00:00,0.0,2.3080796216723455E-9,-1.228986377661098E7,1.90421589699284E7,-4468951.837231503,-1435449.892601432,2.248558541813842E7,3.50363426038186E7,-0.004194098642109259,-6.78142710746686E-4,-4.0380443781969936E-5,-1.7522634195968468E-6,-0.006743321702915614,1.28123971471354E-4,2.083806476615778E-11,1.2729486943998316E-4,8.271815953220556E-7,-0.004914372519707765,5.289650322054923E-5
+92353,2010-07-16T16:00:00,0.0,0.0,-7564581.470819095,1.4399604197999747E7,-3995945.148974555,-2476603.183440942,1.6857973962526906E7,2.8900856763894174E7,-9.097407620105669E-4,-2.576527925290036E-4,-0.001856123441549666,-1.3470612166859498E-6,-0.0035044653567549554,0.007023536035766749,1.5474881367044127E-13,0.002366219619285503,0.004657312256597331,-0.0030248644097352925,0.016037129342514046
+92353,2010-07-17T16:00:00,0.0,0.0,-5179842.488606155,9723853.378782125,-3994506.361691355,-1334692.951639448,1.1373356018230155E7,2.7524374207368024E7,-4.7018447808227126E-4,-1.0860535140610417E-4,-0.0014903949315898226,-2.089493557459902E-6,-0.002339410546547832,0.0027356895436922483,0.0,0.0021422419261745225,5.934512508430124E-4,-0.0020712741788529534,0.004412277645027712
+92353,2010-07-18T16:00:00,0.0,0.0,-1.0036611628560578E7,2.2058975619761996E7,-7446530.945404485,-3594102.261552095,2.5796857508292187E7,2.4888021266616035E7,-0.002858085481136691,-5.784883381372525E-4,-5.747617271239864E-4,-2.024839355728569E-6,-0.0052430391863907185,0.002599944796916397,0.0,0.002192469506159827,4.074739313250872E-4,-0.004013360140307303,0.0028493983181251312
+61205,2010-07-16T16:00:00,0.0,3.321894563525999E-10,-6146784.097346294,1.1107944452488082E7,-3105347.786872696,-1707083.4188252972,1.3072845733561173E7,3.0567345181496702E7,-7.963210489753456E-4,-1.932147267529432E-4,-0.0014651072106683636,-3.283929499438283E-6,-0.002980627427360231,0.020663442859117583,4.6024769294875564E-12,0.006671302329732984,0.013992139972687667,-0.0024579270957921042,0.029804084240380183
+61205,2010-07-17T16:00:00,2.9025530324541023E-4,1.1575215827538042E-4,-5412391.980720758,9680810.926076457,-3533265.401479259,-1271682.6556260807,1.155747086677399E7,2.9126612026259873E7,-7.246042871257964E-4,-1.5056269291891417E-4,-0.0012863545770089332,-3.2468010015894122E-6,-0.002676598414058732,0.005150433645285327,4.4456647336364997E-7,0.0039056670875835097,0.0012447676045103102,-0.0021643235231757364,0.006348982896597342
+61205,2010-07-18T16:00:00,2.9989337677826995E-6,1.186838358695925E-4,-1.0381763265284164E7,2.1307993145583976E7,-6293272.485042421,-3508071.956420474,2.5196713675340783E7,2.7251281049742E7,-0.00303089102105367,-6.137687747770477E-4,-5.028664210045705E-4,-4.385337244972776E-6,-0.006012992111853461,0.003979191450188718,4.715292372367531E-7,0.0036795515266164294,2.9963984821210535E-4,-0.00415143969728293,0.0019269722233958507
+61215,2010-07-16T16:00:00,0.0,3.3125363811148514E-10,-5929050.976897582,1.0603644594671138E7,-2973578.4304706226,-1592933.6974349152,1.2478805947964031E7,3.0953943166789077E7,-7.449666607424832E-4,-1.8045668569082056E-4,-0.0014415360810640797,-3.902120871599812E-6,-0.0028599463850896047,0.02054325880777612,4.613196245688816E-12,0.006616242682643766,0.013927015628521984,-0.002370861721286979,0.030356872262653593
+61215,2010-07-17T16:00:00,2.714513317237391E-4,1.0825325863036937E-4,-5512636.828694132,9771830.595312873,-3485491.8458759356,-1229572.3054652268,1.1652083372051263E7,2.952426776930291E7,-7.926718134061979E-4,-1.6007137852708876E-4,-0.001248459093580803,-3.618583287943628E-6,-0.002761514197800467,0.005050060049584557,4.157659659857369E-7,0.0038830261638218844,0.0011670348449397013,-0.0022044048006989877,0.005977954605811343
+61215,2010-07-18T16:00:00,2.8046500991150346E-6,1.1099509847218884E-4,-1.0482906791973386E7,2.116681905254811E7,-6193827.558724799,-3384216.6665391424,2.5019354313912667E7,2.767338556653357E7,-0.0030918943913062855,-6.184891066432839E-4,-4.7671083079055737E-4,-5.227109830935225E-6,-0.006103178077485294,0.0038961065007158966,4.409830959960777E-7,0.0036153777433958773,2.8072879032929756E-4,-0.004191880085545146,0.0018094426636561041
+61239,2010-07-16T16:00:00,0.0,1.3923698845373767E-10,-2390635.2381788543,3481520.2087043766,-1309163.9016681304,-216945.87833939545,4070059.931017183,3.508333699636272E7,-1.3110330558460123E-7,7.939559232201076E-6,-9.600910703069544E-4,-3.665097050343555E-6,-9.561549962336933E-4,0.03638389547563745,1.2557027062732216E-12,0.01189767025251333,0.024486229006819186,-9.559482901636174E-4,0.05652655899873296
+61239,2010-07-17T16:00:00,0.0,1.588609935378215E-11,-7020981.184999375,1.1791674062460806E7,-3307378.319829425,-878311.7566787911,1.3793299240436476E7,3.3420663359964874E7,-0.0017240126631269974,-2.833769129789879E-4,-7.971362004641321E-4,-2.9690967839798544E-6,-0.004160240236013309,0.008699654798338438,0.0,0.008607582142769313,9.207257426967734E-5,-0.0028074943025642118,7.876747791868056E-4
+61239,2010-07-18T16:00:00,0.0,7.363674288694315E-10,-1.2475584447008654E7,2.101927481073624E7,-5402334.902671516,-2197948.625862285,2.458036216831807E7,3.1819508410385054E7,-0.004138825349364873,-7.018812867945624E-4,-1.414081845799302E-4,-6.523103276018843E-6,-0.007823793496714623,0.006302912071838773,1.0396050312401556E-11,0.006285431790266645,1.7482153328422265E-5,-0.004988637509399871,1.5118705785560903E-4
diff --git a/test/test_camels.py b/test/test_camels.py
index e6b40d3..e05785b 100644
--- a/test/test_camels.py
+++ b/test/test_camels.py
@@ -1,278 +1,344 @@
 import os
-import unittest
+import pytest
 
 import numpy as np
 
 import definitions
-from hydrobench.data.data_camels import Camels
-
-
-class CamelsTestCase(unittest.TestCase):
-    def setUp(self) -> None:
-        self.camels_aus_path = os.path.join(definitions.DATASET_DIR, "camels", "camels_aus")
-        self.camels_br_path = os.path.join(definitions.DATASET_DIR, "camels", "camels_br")
-        self.camels_cl_path = os.path.join(definitions.DATASET_DIR, "camels", "camels_cl")
-        self.camels_gb_path = os.path.join(definitions.DATASET_DIR, "camels", "camels_gb")
-        self.camels_us_path = os.path.join(definitions.DATASET_DIR, "camels", "camels_us")
-        self.camels_yr_path = os.path.join(definitions.DATASET_DIR, "camels", "camels_yr")
-        self.canopex_path = os.path.join(definitions.DATASET_DIR, "canopex")
-        self.lamah_ce_path = os.path.join(definitions.DATASET_DIR, "lamah_ce")
-        self.aus_region = "AUS"
-        self.br_region = "BR"
-        self.cl_region = "CL"
-        self.gb_region = "GB"
-        self.us_region = "US"
-        self.yr_region = "YR"
-        self.ca_region = "CA"
-        self.lamah_ce_region = "CE"
-
-    def test_download_camels(self):
-        camels_us = Camels(self.camels_us_path, download=True)
-        self.assertTrue(
-            os.path.isfile(os.path.join(self.camels_us_path, "basin_set_full_res", "HCDN_nhru_final_671.shp")))
-
-    def test_read_camels_us(self):
-        camels_us = Camels(self.camels_us_path, download=False, region=self.us_region)
-        gage_ids = camels_us.read_object_ids()
-        self.assertEqual(gage_ids.size, 671)
-        attrs = camels_us.read_constant_cols(gage_ids[:5], var_lst=["soil_conductivity", "elev_mean", "geol_1st_class"])
-        np.testing.assert_almost_equal(attrs, np.array(
-            [[1.10652248, 250.31, 10.], [2.37500506, 92.68, 0.], [1.28980735, 143.8, 10.],
-             [1.37329168, 247.8, 10.], [2.61515428, 310.38, 7.]]))
-        forcings = camels_us.read_relevant_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
-                                                var_lst=["dayl", "prcp", "srad"])
-        np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
-        flows = camels_us.read_target_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"], target_cols=["usgsFlow"])
-        np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 1]))
-        streamflow_types = camels_us.get_target_cols()
-        np.testing.assert_array_equal(streamflow_types, np.array(["usgsFlow"]))
-        focing_types = camels_us.get_relevant_cols()
-        np.testing.assert_array_equal(focing_types, np.array(['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']))
-        attr_types = camels_us.get_constant_cols()
-        np.testing.assert_array_equal(attr_types[:3], np.array(['gauge_lat', 'gauge_lon', 'elev_mean']))
-
-    def test_download_camels_aus(self):
-        camels_aus = Camels(self.camels_aus_path, download=True, region="AUS")
-        self.assertTrue(os.path.isfile(os.path.join(self.camels_aus_path, "05_hydrometeorology", "05_hydrometeorology",
-                                                    "01_precipitation_timeseries", "precipitation_AWAP.csv")))
-
-    def test_read_camels_aus(self):
-        camels_aus = Camels(self.camels_aus_path, download=False, region=self.aus_region)
-        gage_ids = camels_aus.read_object_ids()
-        self.assertEqual(gage_ids.size, 222)
-        attrs = camels_aus.read_constant_cols(gage_ids[:5], var_lst=["catchment_area", "slope_fdc", "geol_sec"])
-        np.testing.assert_array_equal(attrs, np.array(
-            [[1.25773e+04, 3.66793e-01, 6.00000e+00], [1.13929e+04, 3.29998e-01, 6.00000e+00],
-             [5.65300e+02, 1.78540e-02, 6.00000e+00], [4.58300e+02, 5.00234e-01, 6.00000e+00],
-             [7.73170e+03, 3.74751e-01, 1.00000e+00]]))
-        forcings = camels_aus.read_relevant_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
-                                                 var_lst=["precipitation_AWAP", "et_morton_actual_SILO", "tmin_SILO"])
-        np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
-        flows = camels_aus.read_target_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
-                                            target_cols=["streamflow_MLd", "streamflow_mmd"])
-        np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 2]))
-        streamflow_types = camels_aus.get_target_cols()
-        np.testing.assert_array_equal(streamflow_types, np.array(
-            ["streamflow_MLd", "streamflow_MLd_inclInfilled", "streamflow_mmd", "streamflow_QualityCodes"]))
-        focing_types = camels_aus.get_relevant_cols()
-        np.testing.assert_array_equal(focing_types, np.array(
-            ['precipitation_AWAP', 'precipitation_SILO', 'precipitation_var_AWAP', 'et_morton_actual_SILO',
-             'et_morton_point_SILO', 'et_morton_wet_SILO', 'et_short_crop_SILO', 'et_tall_crop_SILO',
-             'evap_morton_lake_SILO', 'evap_pan_SILO', 'evap_syn_SILO', 'solarrad_AWAP', 'tmax_AWAP', 'tmin_AWAP',
-             'vprp_AWAP', 'mslp_SILO', 'radiation_SILO', 'rh_tmax_SILO', 'rh_tmin_SILO', 'tmax_SILO', 'tmin_SILO',
-             'vp_deficit_SILO', 'vp_SILO']))
-        attr_types = camels_aus.get_constant_cols()
-        np.testing.assert_array_equal(attr_types[:3],
-                                      np.array(['station_name', 'drainage_division', 'river_region']))
-
-    def test_download_camels_br(self):
-        camels_br = Camels(self.camels_br_path, download=True, region="BR")
-        self.assertTrue(
-            os.path.isfile(os.path.join(self.camels_br_path, "01_CAMELS_BR_attributes", "01_CAMELS_BR_attributes",
-                                        "CAMELS_BR_attributes_description.xlsx")))
-
-    def test_read_camels_br(self):
-        camels_br = Camels(self.camels_br_path, download=False, region=self.br_region)
-        gage_ids = camels_br.read_object_ids()
-        self.assertEqual(gage_ids.size, 897)
-        attrs = camels_br.read_constant_cols(gage_ids[:5], var_lst=["geol_class_1st", "p_mean", "runoff_ratio"])
-        np.testing.assert_array_equal(attrs, np.array(
-            [[8., 6.51179, 0.55336], [6., 5.38941, 0.72594], [6., 5.70191, 0.759], [6., 5.19877, 0.39463],
-             [8., 5.49805, 0.38579]]))
-        forcings = camels_br.read_relevant_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
-                                                var_lst=["precipitation_chirps", "evapotransp_gleam",
-                                                         "potential_evapotransp_gleam", "temperature_min_cpc"])
-        np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 4]))
-        # start from 1995/01/01 end with 2017/04/30
-        flows = camels_br.read_target_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
-                                           target_cols=["streamflow_m3s", "streamflow_mm_selected_catchments"])
-        np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 2]))
-        streamflow_types = camels_br.get_target_cols()
-        np.testing.assert_array_equal(streamflow_types, np.array(
-            ['streamflow_m3s', 'streamflow_mm_selected_catchments', 'streamflow_simulated']))
-        focing_types = camels_br.get_relevant_cols()
-        np.testing.assert_array_equal(focing_types, np.array(
-            ['precipitation_chirps', 'precipitation_mswep', 'precipitation_cpc', 'evapotransp_gleam', 'evapotransp_mgb',
-             'potential_evapotransp_gleam', 'temperature_min_cpc', 'temperature_mean_cpc', 'temperature_max_cpc']))
-        attr_types = camels_br.get_constant_cols()
-        np.testing.assert_array_equal(attr_types[:3], np.array(['p_mean', 'pet_mean', 'et_mean']))
-
-    def test_download_camels_cl(self):
-        camels_cl = Camels(self.camels_cl_path, download=True, region="CL")
-        self.assertTrue(
-            os.path.isfile(os.path.join(self.camels_cl_path, "1_CAMELScl_attributes", "1_CAMELScl_attributes.txt")))
-
-    def test_read_camels_cl(self):
-        camels_cl = Camels(self.camels_cl_path, download=False, region=self.cl_region)
-        gage_ids = camels_cl.read_object_ids()
-        self.assertEqual(gage_ids.size, 516)
-        # TODO: NaN value
-        attrs = camels_cl.read_constant_cols(gage_ids[:5], var_lst=["geol_class_1st", "crop_frac"])
-        np.testing.assert_array_equal(attrs, np.array([[9., 0.], [9., 53.], [9., 64.], [10., 144.], [10., 104.]]))
-        # TODO: NaN value, mainly for pet_8d_modis
-        forcings = camels_cl.read_relevant_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
-                                                var_lst=["pet_8d_modis", "precip_cr2met", "swe"])
-        np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
-        flows = camels_cl.read_target_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
-                                           target_cols=["streamflow_m3s", "streamflow_mm"])
-        np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 2]))
-        streamflow_types = camels_cl.get_target_cols()
-        np.testing.assert_array_equal(streamflow_types, np.array(['streamflow_m3s', 'streamflow_mm']))
-        focing_types = camels_cl.get_relevant_cols()
-        np.testing.assert_array_equal(focing_types, np.array(
-            ['precip_cr2met', 'precip_chirps', 'precip_mswep', 'precip_tmpa', 'tmin_cr2met', 'tmax_cr2met',
-             'tmean_cr2met', 'pet_8d_modis', 'pet_hargreaves', 'swe']))
-        attr_types = camels_cl.get_constant_cols()
-        np.testing.assert_array_equal(attr_types[:3], np.array(['gauge_name', 'gauge_lat', 'gauge_lon']))
-
-    def test_download_camels_gb(self):
-        camels_gb = Camels(self.camels_gb_path, download=True, region=self.gb_region)
-        self.assertTrue(
-            os.path.isfile(os.path.join(self.camels_gb_path, "8344e4f3-d2ea-44f5-8afa-86d2987543a9",
-                                        "8344e4f3-d2ea-44f5-8afa-86d2987543a9", "data",
-                                        "CAMELS_GB_climatic_attributes.csv")))
-
-    def test_read_camels_gb(self):
-        camels_gb = Camels(self.camels_gb_path, download=False, region=self.gb_region)
-        gage_ids = camels_gb.read_object_ids()
-        self.assertEqual(gage_ids.size, 671)
-        attrs = camels_gb.read_constant_cols(gage_ids[:5], var_lst=["p_mean", "slope_fdc", "gauge_name"])
-        np.testing.assert_array_equal(attrs, np.array(
-            [[2.29, 1.94, 596.], [2.31, 1.95, 670.], [2.65, 4.01, 647.], [2.31, 1.54, 393.], [2.29, 1.47, 217.]]))
-        forcings = camels_gb.read_relevant_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
-                                                var_lst=["precipitation", "pet", "temperature", "peti"])
-        np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 4]))
-        flows = camels_gb.read_target_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
-                                           target_cols=["discharge_spec", "discharge_vol"])
-        np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 2]))
-        streamflow_types = camels_gb.get_target_cols()
-        np.testing.assert_array_equal(streamflow_types, np.array(["discharge_spec", "discharge_vol"]))
-        focing_types = camels_gb.get_relevant_cols()
-        np.testing.assert_array_equal(focing_types, np.array(
-            ["precipitation", "pet", "temperature", "peti", "humidity", "shortwave_rad", "longwave_rad", "windspeed"]))
-        attr_types = camels_gb.get_constant_cols()
-        np.testing.assert_array_equal(attr_types[:3], np.array(["p_mean", "pet_mean", "aridity"]))
-
-    def test_download_camels_yr(self):
-        camels_yr = Camels(self.camels_yr_path, download=True, region=self.yr_region)
-        self.assertTrue(
-            os.path.isfile(os.path.join(self.camels_yr_path, "8344e4f3-d2ea-44f5-8afa-86d2987543a9",
-                                        "8344e4f3-d2ea-44f5-8afa-86d2987543a9", "data",
-                                        "CAMELS_GB_climatic_attributes.csv")))
-
-    def test_read_camels_yr(self):
-        camels_yr = Camels(self.camels_yr_path, download=False, region=self.yr_region)
-        gage_ids = camels_yr.read_object_ids()
-        self.assertEqual(gage_ids.size, 102)
-        attrs = camels_yr.read_constant_cols(gage_ids[:5], var_lst=["area", "barren", "bdticm"])
-        np.testing.assert_almost_equal(attrs, np.array(
-            [[3.11520000e+04, 2.98706264e-03, 3.33904449e+03], [4.27056000e+05, 2.30162622e-02, 1.80570119e+03],
-             [3.80128000e+05, 2.47549979e-02, 1.77874628e+03], [7.33561000e+05, 1.41340180e-02, 2.01143843e+03],
-             [2.04213000e+05, 7.75394506e-03, 1.53321208e+03]]), decimal=3)
-        forcings = camels_yr.read_relevant_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
-                                                var_lst=["pre", "evp", "gst_mean", "prs_mean"])
-        np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 4]))
-        flows = camels_yr.read_target_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"], target_cols=["normalized_q"])
-        np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 1]))
-        streamflow_types = camels_yr.get_target_cols()
-        np.testing.assert_array_equal(streamflow_types, np.array(["normalized_q"]))
-        focing_types = camels_yr.get_relevant_cols()
-        np.testing.assert_array_equal(focing_types, np.array(
-            ["pre", "evp", "gst_mean", "prs_mean", "tem_mean", "rhu", "win_mean", "gst_min", "prs_min", "tem_min",
-             "gst_max", "prs_max", "tem_max", "ssd", "win_max"]))
-        attr_types = camels_yr.get_constant_cols()
-        np.testing.assert_array_equal(attr_types[:3], np.array(["area", "barren", "bdticm"]))
-
-    def test_download_canopex(self):
-        canopex = Camels(self.canopex_path, download=True, region=self.ca_region)
-        self.assertTrue(
-            os.path.isfile(os.path.join(self.canopex_path, "CANOPEX_NRCAN_ASCII", "CANOPEX_NRCAN_ASCII", "1.dly")))
-
-    def test_read_canopex_data(self):
-        canopex = Camels(self.canopex_path, download=False, region=self.ca_region)
-        gage_ids = canopex.read_object_ids()
-        self.assertEqual(gage_ids.size, 611)
-        attrs = canopex.read_constant_cols(gage_ids[:5],
-                                           var_lst=["Drainage_Area_km2", "Land_Use_Grass_frac", "Permeability_logk_m2"])
-        np.testing.assert_almost_equal(attrs, np.array(
-            [[3.28438700e+02, 6.94000000e-02, - 1.35251586e+01], [3.43515600e+02, 6.16000000e-02, - 1.42367348e+01],
-             [1.45554950e+03, 3.59000000e-02, - 1.50071080e+01], [5.64820300e+02, 3.05000000e-02, - 1.51002546e+01],
-             [1.05383090e+03, 3.27000000e-02, - 1.51999998e+01]]), decimal=3)
-        forcings = canopex.read_relevant_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
-                                              var_lst=["prcp", "tmax", "tmin"])
-        np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
-        flows = canopex.read_target_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"], target_cols=["discharge"])
-        np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 1]))
-        streamflow_types = canopex.get_target_cols()
-        np.testing.assert_array_equal(streamflow_types, np.array(["discharge"]))
-        focing_types = canopex.get_relevant_cols()
-        np.testing.assert_array_equal(focing_types, np.array(["prcp", "tmax", "tmin"]))
-        attr_types = canopex.get_constant_cols()
-        np.testing.assert_array_equal(attr_types[:3], np.array(["Source", "Name", "Official_ID"]))
-
-    def test_download_lamah_ce(self):
-        lamah_ce = Camels(self.lamah_ce_path, download=True, region=self.lamah_ce_region)
-        self.assertTrue(
-            os.path.isfile(os.path.join(self.lamah_ce_path, "CANOPEX_NRCAN_ASCII", "CANOPEX_NRCAN_ASCII", "1.dly")))
-
-    def test_read_lamah_ce(self):
-        lamah_ce = Camels(self.lamah_ce_path, download=False, region=self.lamah_ce_region)
-        gage_ids = lamah_ce.read_object_ids()
-        self.assertEqual(gage_ids.size, 859)
-        attrs = lamah_ce.read_constant_cols(gage_ids[:5], var_lst=['area_calc', 'elev_mean', 'elev_med'])
-        np.testing.assert_almost_equal(attrs, np.array(
-            [[4668.379, 1875., 1963.], [102.287, 1775., 1827.], [536.299, 1844., 1916.], [66.286, 1894., 1907.],
-             [72.448, 1774., 1796.]]), decimal=3)
-        forcings = lamah_ce.read_relevant_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
-                                               var_lst=["2m_temp_max", "prec", "volsw_4"])
-        np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
-        flows = lamah_ce.read_target_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"], target_cols=["qobs"])
-        np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 1]))
-        streamflow_types = lamah_ce.get_target_cols()
-        np.testing.assert_array_equal(streamflow_types, np.array(["qobs"]))
-        focing_types = lamah_ce.get_relevant_cols()
-        np.testing.assert_array_equal(focing_types, np.array(
-            ["2m_temp_max", "2m_temp_mean", "2m_temp_min", "2m_dp_temp_max", "2m_dp_temp_mean",
-             "2m_dp_temp_min", "10m_wind_u", "10m_wind_v", "fcst_alb", "lai_high_veg", "lai_low_veg",
-             "swe", "surf_net_solar_rad_max", "surf_net_solar_rad_mean", "surf_net_therm_rad_max",
-             "surf_net_therm_rad_mean", "surf_press", "total_et", "prec", "volsw_123", "volsw_4"]))
-        attr_types = lamah_ce.get_constant_cols()
-        np.testing.assert_array_equal(attr_types, np.array(
-            ['area_calc', 'elev_mean', 'elev_med', 'elev_std', 'elev_ran', 'slope_mean', 'mvert_dist', 'mvert_ang',
-             'elon_ratio', 'strm_dens', 'p_mean', 'et0_mean', 'eta_mean', 'arid_1', 'arid_2', 'p_season', 'frac_snow',
-             'hi_prec_fr', 'hi_prec_du', 'hi_prec_ti', 'lo_prec_fr', 'lo_prec_du', 'lo_prec_ti', 'lc_dom', 'agr_fra',
-             'bare_fra', 'forest_fra', 'glac_fra', 'lake_fra', 'urban_fra', 'lai_max', 'lai_diff', 'ndvi_max',
-             'ndvi_min', 'gvf_max', 'gvf_diff', 'bedrk_dep', 'root_dep', 'soil_poros', 'soil_condu', 'soil_tawc',
-             'sand_fra', 'silt_fra', 'clay_fra', 'grav_fra', 'oc_fra', 'gc_dom', 'gc_ig_fra', 'gc_mt_fra', 'gc_pa_fra',
-             'gc_pb_fra', 'gc_pi_fra', 'gc_py_fra', 'gc_sc_fra', 'gc_sm_fra', 'gc_ss_fra', 'gc_su_fra', 'gc_va_fra',
-             'gc_vb_fra', 'gc_wb_fra', 'geol_perme', 'geol_poros']))
-
-    def test_ca_p_mean(self):
-        canopex = Camels(self.canopex_path, download=False, region=self.ca_region)
-        gage_ids = canopex.read_object_ids()
-        p_mean = canopex.read_mean_prep(gage_ids[:5])
-        np.testing.assert_almost_equal(p_mean, np.array([2.91712073, 3.14145935, 3.12958083, 3.09248435, 3.04431583]))
-
-
-if __name__ == '__main__':
-    unittest.main()
+from hydrodataset.data.data_camels import Camels
+
+
+@pytest.fixture
+def camels_aus_path():
+    return os.path.join(definitions.DATASET_DIR, "camels", "camels_aus")
+
+
+@pytest.fixture
+def camels_br_path():
+    return os.path.join(definitions.DATASET_DIR, "camels", "camels_br")
+
+
+@pytest.fixture
+def camels_cl_path():
+    return os.path.join(definitions.DATASET_DIR, "camels", "camels_cl")
+
+
+@pytest.fixture
+def camels_gb_path():
+    return os.path.join(definitions.DATASET_DIR, "camels", "camels_gb")
+
+
+@pytest.fixture
+def camels_us_path():
+    return os.path.join(definitions.DATASET_DIR, "camels", "camels_us")
+
+
+@pytest.fixture
+def camels_yr_path():
+    return os.path.join(definitions.DATASET_DIR, "camels", "camels_yr")
+
+
+@pytest.fixture
+def canopex_path():
+    return os.path.join(definitions.DATASET_DIR, "canopex")
+
+
+@pytest.fixture
+def lamah_ce_path():
+    return os.path.join(definitions.DATASET_DIR, "lamah_ce")
+
+
+@pytest.fixture
+def aus_region():
+    return "AUS"
+
+
+@pytest.fixture
+def br_region():
+    return "BR"
+
+
+@pytest.fixture
+def cl_region():
+    return "CL"
+
+
+@pytest.fixture
+def gb_region():
+    return "GB"
+
+
+@pytest.fixture
+def us_region():
+    return "US"
+
+
+@pytest.fixture
+def yr_region():
+    return "YR"
+
+
+@pytest.fixture
+def ca_region():
+    return "CA"
+
+
+@pytest.fixture
+def lamah_ce_region():
+    return "CE"
+
+
+def test_download_camels(camels_us_path):
+    camels_us = Camels(camels_us_path, download=True)
+    assert os.path.isfile(os.path.join(camels_us_path, "basin_set_full_res", "HCDN_nhru_final_671.shp"))
+
+
+def test_read_camels_us(camels_us_path, us_region):
+    camels_us = Camels(camels_us_path, download=False, region=us_region)
+    gage_ids = camels_us.read_object_ids()
+    assert gage_ids.size == 671
+    attrs = camels_us.read_constant_cols(gage_ids[:5], var_lst=["soil_conductivity", "elev_mean", "geol_1st_class"])
+    np.testing.assert_almost_equal(attrs, np.array(
+        [[1.10652248, 250.31, 10.], [2.37500506, 92.68, 0.], [1.28980735, 143.8, 10.],
+         [1.37329168, 247.8, 10.], [2.61515428, 310.38, 7.]]))
+    forcings = camels_us.read_relevant_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
+                                            var_lst=["dayl", "prcp", "srad"])
+    np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
+    flows = camels_us.read_target_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"], target_cols=["usgsFlow"])
+    np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 1]))
+    streamflow_types = camels_us.get_target_cols()
+    np.testing.assert_array_equal(streamflow_types, np.array(["usgsFlow"]))
+    focing_types = camels_us.get_relevant_cols()
+    np.testing.assert_array_equal(focing_types, np.array(['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']))
+    attr_types = camels_us.get_constant_cols()
+    np.testing.assert_array_equal(attr_types[:3], np.array(['gauge_lat', 'gauge_lon', 'elev_mean']))
+
+
+def test_download_camels_aus(camels_aus_path):
+    camels_aus = Camels(camels_aus_path, download=True, region="AUS")
+    assert os.path.isfile(os.path.join(camels_aus_path, "05_hydrometeorology", "05_hydrometeorology",
+                                       "01_precipitation_timeseries", "precipitation_AWAP.csv"))
+
+
+def test_read_camels_aus(camels_aus_path, aus_region):
+    camels_aus = Camels(camels_aus_path, download=False, region=aus_region)
+    gage_ids = camels_aus.read_object_ids()
+    assert gage_ids.size == 222
+    attrs = camels_aus.read_constant_cols(gage_ids[:5], var_lst=["catchment_area", "slope_fdc", "geol_sec"])
+    np.testing.assert_array_equal(attrs, np.array(
+        [[1.25773e+04, 3.66793e-01, 6.00000e+00], [1.13929e+04, 3.29998e-01, 6.00000e+00],
+         [5.65300e+02, 1.78540e-02, 6.00000e+00], [4.58300e+02, 5.00234e-01, 6.00000e+00],
+         [7.73170e+03, 3.74751e-01, 1.00000e+00]]))
+    forcings = camels_aus.read_relevant_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
+                                             var_lst=["precipitation_AWAP", "et_morton_actual_SILO", "tmin_SILO"])
+    np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
+    flows = camels_aus.read_target_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
+                                        target_cols=["streamflow_MLd", "streamflow_mmd"])
+    np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 2]))
+    streamflow_types = camels_aus.get_target_cols()
+    np.testing.assert_array_equal(streamflow_types, np.array(
+        ["streamflow_MLd", "streamflow_MLd_inclInfilled", "streamflow_mmd", "streamflow_QualityCodes"]))
+    focing_types = camels_aus.get_relevant_cols()
+    np.testing.assert_array_equal(focing_types, np.array(
+        ['precipitation_AWAP', 'precipitation_SILO', 'precipitation_var_AWAP', 'et_morton_actual_SILO',
+         'et_morton_point_SILO', 'et_morton_wet_SILO', 'et_short_crop_SILO', 'et_tall_crop_SILO',
+         'evap_morton_lake_SILO', 'evap_pan_SILO', 'evap_syn_SILO', 'solarrad_AWAP', 'tmax_AWAP', 'tmin_AWAP',
+         'vprp_AWAP', 'mslp_SILO', 'radiation_SILO', 'rh_tmax_SILO', 'rh_tmin_SILO', 'tmax_SILO', 'tmin_SILO',
+         'vp_deficit_SILO', 'vp_SILO']))
+    attr_types = camels_aus.get_constant_cols()
+    np.testing.assert_array_equal(attr_types[:3],
+                                  np.array(['station_name', 'drainage_division', 'river_region']))
+
+
+def test_download_camels_br(camels_br_path):
+    camels_br = Camels(camels_br_path, download=True, region="BR")
+    assert os.path.isfile(os.path.join(camels_br_path, "01_CAMELS_BR_attributes", "01_CAMELS_BR_attributes",
+                                       "CAMELS_BR_attributes_description.xlsx"))
+
+
+def test_read_camels_br(camels_br_path, br_region):
+    camels_br = Camels(camels_br_path, download=False, region=br_region)
+    gage_ids = camels_br.read_object_ids()
+    assert gage_ids.size == 897
+    attrs = camels_br.read_constant_cols(gage_ids[:5], var_lst=["geol_class_1st", "p_mean", "runoff_ratio"])
+    np.testing.assert_array_equal(attrs, np.array(
+        [[8., 6.51179, 0.55336], [6., 5.38941, 0.72594], [6., 5.70191, 0.759], [6., 5.19877, 0.39463],
+         [8., 5.49805, 0.38579]]))
+    forcings = camels_br.read_relevant_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
+                                            var_lst=["precipitation_chirps", "evapotransp_gleam",
+                                                     "potential_evapotransp_gleam", "temperature_min_cpc"])
+    np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 4]))
+    # start from 1995/01/01 end with 2017/04/30
+    flows = camels_br.read_target_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
+                                       target_cols=["streamflow_m3s", "streamflow_mm_selected_catchments"])
+    np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 2]))
+    streamflow_types = camels_br.get_target_cols()
+    np.testing.assert_array_equal(streamflow_types, np.array(
+        ['streamflow_m3s', 'streamflow_mm_selected_catchments', 'streamflow_simulated']))
+    focing_types = camels_br.get_relevant_cols()
+    np.testing.assert_array_equal(focing_types, np.array(
+        ['precipitation_chirps', 'precipitation_mswep', 'precipitation_cpc', 'evapotransp_gleam', 'evapotransp_mgb',
+         'potential_evapotransp_gleam', 'temperature_min_cpc', 'temperature_mean_cpc', 'temperature_max_cpc']))
+    attr_types = camels_br.get_constant_cols()
+    np.testing.assert_array_equal(attr_types[:3], np.array(['p_mean', 'pet_mean', 'et_mean']))
+
+
+def test_download_camels_cl(camels_cl_path):
+    camels_cl = Camels(camels_cl_path, download=True, region="CL")
+    assert os.path.isfile(os.path.join(camels_cl_path, "1_CAMELScl_attributes", "1_CAMELScl_attributes.txt"))
+
+
+def test_read_camels_cl(camels_cl_path, cl_region):
+    camels_cl = Camels(camels_cl_path, download=False, region=cl_region)
+    gage_ids = camels_cl.read_object_ids()
+    assert gage_ids.size == 516
+    # TODO: NaN value
+    attrs = camels_cl.read_constant_cols(gage_ids[:5], var_lst=["geol_class_1st", "crop_frac"])
+    np.testing.assert_array_equal(attrs, np.array([[9., 0.], [9., 53.], [9., 64.], [10., 144.], [10., 104.]]))
+    # TODO: NaN value, mainly for pet_8d_modis
+    forcings = camels_cl.read_relevant_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
+                                            var_lst=["pet_8d_modis", "precip_cr2met", "swe"])
+    np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
+    flows = camels_cl.read_target_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
+                                       target_cols=["streamflow_m3s", "streamflow_mm"])
+    np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 2]))
+    streamflow_types = camels_cl.get_target_cols()
+    np.testing.assert_array_equal(streamflow_types, np.array(['streamflow_m3s', 'streamflow_mm']))
+    focing_types = camels_cl.get_relevant_cols()
+    np.testing.assert_array_equal(focing_types, np.array(
+        ['precip_cr2met', 'precip_chirps', 'precip_mswep', 'precip_tmpa', 'tmin_cr2met', 'tmax_cr2met',
+         'tmean_cr2met', 'pet_8d_modis', 'pet_hargreaves', 'swe']))
+    attr_types = camels_cl.get_constant_cols()
+    np.testing.assert_array_equal(attr_types[:3], np.array(['gauge_name', 'gauge_lat', 'gauge_lon']))
+
+
+def test_download_camels_gb(camels_gb_path, gb_region):
+    camels_gb = Camels(camels_gb_path, download=True, region=gb_region)
+    assert os.path.isfile(os.path.join(camels_gb_path, "8344e4f3-d2ea-44f5-8afa-86d2987543a9",
+                                       "8344e4f3-d2ea-44f5-8afa-86d2987543a9", "data",
+                                       "CAMELS_GB_climatic_attributes.csv"))
+
+
+def test_read_camels_gb(camels_gb_path, gb_region):
+    camels_gb = Camels(camels_gb_path, download=False, region=gb_region)
+    gage_ids = camels_gb.read_object_ids()
+    assert gage_ids.size == 671
+    attrs = camels_gb.read_constant_cols(gage_ids[:5], var_lst=["p_mean", "slope_fdc", "gauge_name"])
+    np.testing.assert_array_equal(attrs, np.array(
+        [[2.29, 1.94, 596.], [2.31, 1.95, 670.], [2.65, 4.01, 647.], [2.31, 1.54, 393.], [2.29, 1.47, 217.]]))
+    forcings = camels_gb.read_relevant_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
+                                            var_lst=["precipitation", "pet", "temperature", "peti"])
+    np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 4]))
+    flows = camels_gb.read_target_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
+                                       target_cols=["discharge_spec", "discharge_vol"])
+    np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 2]))
+    streamflow_types = camels_gb.get_target_cols()
+    np.testing.assert_array_equal(streamflow_types, np.array(["discharge_spec", "discharge_vol"]))
+    focing_types = camels_gb.get_relevant_cols()
+    np.testing.assert_array_equal(focing_types, np.array(
+        ["precipitation", "pet", "temperature", "peti", "humidity", "shortwave_rad", "longwave_rad", "windspeed"]))
+    attr_types = camels_gb.get_constant_cols()
+    np.testing.assert_array_equal(attr_types[:3], np.array(["p_mean", "pet_mean", "aridity"]))
+
+
+def test_download_camels_yr(camels_yr_path, yr_region):
+    camels_yr = Camels(camels_yr_path, download=True, region=yr_region)
+    assert os.path.isfile(
+        os.path.join(camels_yr_path, "9_Normal_Camels_YR", "1_Normal_Camels_YR_basin_data", "0146", "attributes.json"))
+
+
+def test_read_camels_yr(camels_yr_path, yr_region):
+    camels_yr = Camels(camels_yr_path, download=False, region=yr_region)
+    gage_ids = camels_yr.read_object_ids()
+    assert gage_ids.size == 102
+    attrs = camels_yr.read_constant_cols(gage_ids[:5], var_lst=["area", "barren", "bdticm"])
+    np.testing.assert_almost_equal(attrs, np.array(
+        [[3.11520000e+04, 2.98706264e-03, 3.33904449e+03], [4.27056000e+05, 2.30162622e-02, 1.80570119e+03],
+         [3.80128000e+05, 2.47549979e-02, 1.77874628e+03], [7.33561000e+05, 1.41340180e-02, 2.01143843e+03],
+         [2.04213000e+05, 7.75394506e-03, 1.53321208e+03]]), decimal=3)
+    forcings = camels_yr.read_relevant_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"],
+                                            var_lst=["pre", "evp", "gst_mean", "prs_mean"])
+    np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 4]))
+    flows = camels_yr.read_target_cols(gage_ids[:5], ["1995-01-01", "2015-01-01"], target_cols=["normalized_q"])
+    np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 1]))
+    streamflow_types = camels_yr.get_target_cols()
+    np.testing.assert_array_equal(streamflow_types, np.array(["normalized_q"]))
+    focing_types = camels_yr.get_relevant_cols()
+    np.testing.assert_array_equal(focing_types, np.array(
+        ["pre", "evp", "gst_mean", "prs_mean", "tem_mean", "rhu", "win_mean", "gst_min", "prs_min", "tem_min",
+         "gst_max", "prs_max", "tem_max", "ssd", "win_max"]))
+    attr_types = camels_yr.get_constant_cols()
+    np.testing.assert_array_equal(attr_types[:3], np.array(["area", "barren", "bdticm"]))
+
+
+def test_download_canopex(canopex_path, ca_region):
+    canopex = Camels(canopex_path, download=True, region=ca_region)
+    assert os.path.isfile(os.path.join(canopex_path, "CANOPEX_NRCAN_ASCII", "CANOPEX_NRCAN_ASCII", "1.dly"))
+
+
+def test_read_canopex_data(canopex_path, ca_region):
+    canopex = Camels(canopex_path, download=False, region=ca_region)
+    gage_ids = canopex.read_object_ids()
+    assert gage_ids.size == 611
+    attrs = canopex.read_constant_cols(gage_ids[:5],
+                                       var_lst=["Drainage_Area_km2", "Land_Use_Grass_frac", "Permeability_logk_m2"])
+    np.testing.assert_almost_equal(attrs, np.array(
+        [[3.28438700e+02, 6.94000000e-02, - 1.35251586e+01], [3.43515600e+02, 6.16000000e-02, - 1.42367348e+01],
+         [1.45554950e+03, 3.59000000e-02, - 1.50071080e+01], [5.64820300e+02, 3.05000000e-02, - 1.51002546e+01],
+         [1.05383090e+03, 3.27000000e-02, - 1.51999998e+01]]), decimal=3)
+    forcings = canopex.read_relevant_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
+                                          var_lst=["prcp", "tmax", "tmin"])
+    np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
+    flows = canopex.read_target_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"], target_cols=["discharge"])
+    np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 1]))
+    streamflow_types = canopex.get_target_cols()
+    np.testing.assert_array_equal(streamflow_types, np.array(["discharge"]))
+    focing_types = canopex.get_relevant_cols()
+    np.testing.assert_array_equal(focing_types, np.array(["prcp", "tmax", "tmin"]))
+    attr_types = canopex.get_constant_cols()
+    np.testing.assert_array_equal(attr_types[:3], np.array(["Source", "Name", "Official_ID"]))
+
+
+def test_download_lamah_ce(lamah_ce_path, lamah_ce_region):
+    lamah_ce = Camels(lamah_ce_path, download=True, region=lamah_ce_region)
+    assert os.path.isfile(
+        os.path.join(lamah_ce_path, "2_LamaH-CE_daily", "A_basins_total_upstrm", "2_timeseries", "daily", "ID_882.csv"))
+
+
+def test_read_lamah_ce(lamah_ce_path, lamah_ce_region):
+    lamah_ce = Camels(lamah_ce_path, download=False, region=lamah_ce_region)
+    gage_ids = lamah_ce.read_object_ids()
+    assert gage_ids.size == 859
+    attrs = lamah_ce.read_constant_cols(gage_ids[:5], var_lst=['area_calc', 'elev_mean', 'elev_med'])
+    np.testing.assert_almost_equal(attrs, np.array(
+        [[4668.379, 1875., 1963.], [102.287, 1775., 1827.], [536.299, 1844., 1916.], [66.286, 1894., 1907.],
+         [72.448, 1774., 1796.]]), decimal=3)
+    forcings = lamah_ce.read_relevant_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"],
+                                           var_lst=["2m_temp_max", "prec", "volsw_4"])
+    np.testing.assert_array_equal(forcings.shape, np.array([5, 7305, 3]))
+    flows = lamah_ce.read_target_cols(gage_ids[:5], ["1990-01-01", "2010-01-01"], target_cols=["qobs"])
+    np.testing.assert_array_equal(flows.shape, np.array([5, 7305, 1]))
+    streamflow_types = lamah_ce.get_target_cols()
+    np.testing.assert_array_equal(streamflow_types, np.array(["qobs"]))
+    focing_types = lamah_ce.get_relevant_cols()
+    np.testing.assert_array_equal(focing_types, np.array(
+        ["2m_temp_max", "2m_temp_mean", "2m_temp_min", "2m_dp_temp_max", "2m_dp_temp_mean",
+         "2m_dp_temp_min", "10m_wind_u", "10m_wind_v", "fcst_alb", "lai_high_veg", "lai_low_veg",
+         "swe", "surf_net_solar_rad_max", "surf_net_solar_rad_mean", "surf_net_therm_rad_max",
+         "surf_net_therm_rad_mean", "surf_press", "total_et", "prec", "volsw_123", "volsw_4"]))
+    attr_types = lamah_ce.get_constant_cols()
+    np.testing.assert_array_equal(attr_types, np.array(
+        ['area_calc', 'elev_mean', 'elev_med', 'elev_std', 'elev_ran', 'slope_mean', 'mvert_dist', 'mvert_ang',
+         'elon_ratio', 'strm_dens', 'p_mean', 'et0_mean', 'eta_mean', 'arid_1', 'arid_2', 'p_season', 'frac_snow',
+         'hi_prec_fr', 'hi_prec_du', 'hi_prec_ti', 'lo_prec_fr', 'lo_prec_du', 'lo_prec_ti', 'lc_dom', 'agr_fra',
+         'bare_fra', 'forest_fra', 'glac_fra', 'lake_fra', 'urban_fra', 'lai_max', 'lai_diff', 'ndvi_max',
+         'ndvi_min', 'gvf_max', 'gvf_diff', 'bedrk_dep', 'root_dep', 'soil_poros', 'soil_condu', 'soil_tawc',
+         'sand_fra', 'silt_fra', 'clay_fra', 'grav_fra', 'oc_fra', 'gc_dom', 'gc_ig_fra', 'gc_mt_fra', 'gc_pa_fra',
+         'gc_pb_fra', 'gc_pi_fra', 'gc_py_fra', 'gc_sc_fra', 'gc_sm_fra', 'gc_ss_fra', 'gc_su_fra', 'gc_va_fra',
+         'gc_vb_fra', 'gc_wb_fra', 'geol_perme', 'geol_poros']))
+
+
+def test_ca_p_mean(canopex_path, ca_region):
+    canopex = Camels(canopex_path, download=False, region=ca_region)
+    gage_ids = canopex.read_object_ids()
+    p_mean = canopex.read_mean_prep(gage_ids[:5])
+    np.testing.assert_almost_equal(p_mean, np.array([2.91712073, 3.14145935, 3.12958083, 3.09248435, 3.04431583]))
diff --git a/test/test_download_dataset.py b/test/test_download_dataset.py
new file mode 100644
index 0000000..dbc7266
--- /dev/null
+++ b/test/test_download_dataset.py
@@ -0,0 +1,212 @@
+import os
+import pytest
+import geopandas as gpd
+from pynhd import NLDI
+import xarray as xr
+import pydaymet as daymet
+
+import definitions
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.daymet4basins.basin_daymet_process import download_daymet_by_geom_bound, calculate_basin_grids_pet, \
+    calculate_basin_mean
+from hydrodataset.utils.hydro_utils import unserialize_geopandas
+from hydrodataset.ecmwf4basins.download_era5_land import download_era5
+from hydrodataset.nldas4basins.download_nldas import download_nldas_with_url_lst
+
+
+@pytest.fixture()
+def save_dir():
+    save_dir_ = os.path.join(definitions.ROOT_DIR, "test", "test_data")
+    if not os.path.isdir(save_dir_):
+        os.makedirs(save_dir_)
+    return save_dir_
+
+
+@pytest.fixture()
+def var():
+    return ['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']
+
+
+@pytest.fixture()
+def camels():
+    camels_dir = os.path.join(definitions.DATASET_DIR, "camels", "camels_us")
+    return Camels(camels_dir, True)
+
+
+def test_read_daymet_1basin_3days(save_dir):
+    basin_id = "01013500"
+    dates = ("2000-01-01", "2000-01-03")
+    geometry = NLDI().get_basins(basin_id).geometry[0]
+    # ``tmin``, ``tmax``, ``prcp``, ``srad``, ``vp``, ``swe``, ``dayl``
+    var = ['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']
+    daily = daymet.get_bygeom(geometry, dates, variables=var, pet=True)
+    save_path = os.path.join(save_dir, basin_id + "_2000_01_01-03.nc")
+    daily.to_netcdf(save_path)
+
+
+def test_read_daymet_1basin_in_camels_2days(camels, save_dir):
+    basin_id = "01013500"
+    dates = ("2000-01-01", "2000-01-02")
+    camels_shp_file = camels.dataset_description["CAMELS_BASINS_SHP_FILE"]
+    camels_shp = gpd.read_file(camels_shp_file)
+    # transform the geographic coordinates to wgs84 i.e. epsg4326  it seems NAD83 is equal to WGS1984 in geopandas
+    camels_shp_epsg4326 = camels_shp.to_crs(epsg=4326)
+    geometry = camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry[0]
+    # ``tmin``, ``tmax``, ``prcp``, ``srad``, ``vp``, ``swe``, ``dayl``
+    var = ['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']
+    daily = daymet.get_bygeom(geometry, dates, variables=var, pet=True)
+    save_path = os.path.join(save_dir, basin_id + "_in_camels_2000_01_01-02.nc")
+    daily.to_netcdf(save_path)
+
+
+def test_read_daymet_basins_3days(var, save_dir):
+    basin_id = ["01013500", "01031500"]
+    dates = ("2000-01-01", "2000-01-03")
+    basins = NLDI().get_basins(basin_id)
+    for i in range(len(basin_id)):
+        # ``tmin``, ``tmax``, ``prcp``, ``srad``, ``vp``, ``swe``, ``dayl``
+        daily = daymet.get_bygeom(basins.geometry[i], dates, variables=var)
+        save_path = os.path.join(save_dir, basin_id[i] + "_2000_01_01-03.nc")
+        daily.to_netcdf(save_path)
+
+
+def test_download_nldi_shpfile(save_dir):
+    basin_id = "01013500"
+    basin = NLDI().get_basins(basin_id)
+    # geometry = basin.geometry[0]
+    save_path = os.path.join(save_dir, basin_id + ".shp")
+    basin.to_file(save_path)
+
+
+def test_download_daymet_without_dask(var, save_dir):
+    basin_id = "01013500"
+    dates = ("2000-01-01", "2000-01-03")
+    geometry = NLDI().get_basins(basin_id).geometry[0]
+    daily = download_daymet_by_geom_bound(geometry, dates, variables=var)
+    save_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_nomask.nc")
+    daily.to_netcdf(save_path)
+
+
+def test_download_daymet_without_dask_local_shpfile(save_dir, var):
+    # Notice the projection, otherwise it will occur many NaN values since the locations are wrong
+    basin_id = "01013500"
+    dates = ("2000-01-01", "2000-01-03")
+    basin_shp_dir = os.path.join(definitions.ROOT_DIR, "test", "test_data")
+    basin_shp_file = os.path.join(basin_shp_dir, "01013500.shp")
+    if not os.path.isfile(basin_shp_file):
+        basin = NLDI().get_basins(basin_id)
+        save_path = os.path.join(save_dir, basin_id + ".shp")
+        basin.to_file(save_path)
+    basins = unserialize_geopandas(basin_shp_file)
+    geometry = basins.geometry[0]
+    daily = download_daymet_by_geom_bound(geometry, dates, variables=var)
+    save_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_nomask_local_shp.nc")
+    daily.to_netcdf(save_path)
+
+
+def test_equal_local_shp_download_shp_nc(save_dir):
+    basin_id = "01013500"
+    read_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_nomask.nc")
+    read_path_local = os.path.join(save_dir, basin_id + "_2000_01_01-03_nomask_local_shp.nc")
+    daily = xr.open_dataset(read_path)
+    daily_local = xr.open_dataset(read_path_local)
+    print(daily.equals(daily_local))
+
+
+def test_download_from_url_directly(var, save_dir):
+    basin_id = "01013500"
+    dates = ("2000-01-01", "2000-01-03")
+    geometry = NLDI().get_basins(basin_id).geometry[0]
+    daily = download_daymet_by_geom_bound(geometry, dates, variables=var, boundary=False)
+    save_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_from_urls.nc")
+    daily.to_netcdf(save_path)
+
+
+def test_basin_bound_pet_fao56(save_dir):
+    basin_id = "01013500"
+    read_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_nomask.nc")
+    daily = xr.open_dataset(read_path)
+    include_pet = calculate_basin_grids_pet(daily, pet_method="pm_fao56")
+    save_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_pet_fao56.nc")
+    include_pet.to_netcdf(save_path)
+
+
+def test_basin_bound_pet_pt(save_dir):
+    basin_id = "01013500"
+    read_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_nomask.nc")
+    daily = xr.open_dataset(read_path)
+    include_pet = calculate_basin_grids_pet(daily, pet_method="priestley_taylor")
+    save_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_pet_pt.nc")
+    include_pet.to_netcdf(save_path)
+
+
+def test_basin_mean(save_dir):
+    basin_id = "01013500"
+    read_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_pet_pt.nc")
+    daily = xr.open_dataset(read_path)
+    basins = NLDI().get_basins(basin_id)
+    mean_daily = calculate_basin_mean(daily, basins.geometry[0])
+    print(mean_daily)
+
+
+def test_batch_download_nldi_shpfile(save_dir):
+    basin_id = ["01013500", "01031500"]
+    basins = NLDI().get_basins(basin_id)
+    # geometry = basin.geometry[0]
+    save_path = os.path.join(save_dir, "two_test_basins.shp")
+    basins.to_file(save_path)
+
+
+def test_batch_download_daymet_without_dask(save_dir, var):
+    basins_id = ["01013500", "01031500"]
+    dates = ("2000-01-01", "2000-01-03")
+    basins = NLDI().get_basins(basins_id)
+    save_dir = save_dir
+    if not os.path.isdir(save_dir):
+        os.makedirs(save_dir)
+    for i in range(len(basins_id)):
+        # ``tmin``, ``tmax``, ``prcp``, ``srad``, ``vp``, ``swe``, ``dayl``
+        daily = download_daymet_by_geom_bound(basins.geometry[i], dates, variables=var)
+        save_path = os.path.join(save_dir, basins_id[i] + "_2000_01_01-03_nomask.nc")
+        daily.to_netcdf(save_path)
+
+
+def test_batch_basins_pet(save_dir):
+    basin_id = ["01013500", "01031500"]
+    for i in range(len(basin_id)):
+        read_path = os.path.join(save_dir, basin_id[i] + "_2000_01_01-03_nomask.nc")
+        daily = xr.open_dataset(read_path)
+        include_pet = calculate_basin_grids_pet(daily, pet_method=["pm_fao56", "priestley_taylor"])
+        save_path = os.path.join(save_dir, basin_id[i] + "_2000_01_01-03_pet.nc")
+        include_pet.to_netcdf(save_path)
+
+
+def test_batch_basins_mean(save_dir):
+    basins_id = ["01013500", "01031500"]
+    basins = NLDI().get_basins(basins_id)
+    for i in range(len(basins_id)):
+        read_path = os.path.join(save_dir, basins_id[i] + "_2000_01_01-03_pet.nc")
+        daily = xr.open_dataset(read_path)
+        mean_daily = calculate_basin_mean(daily, basins.geometry[i])
+        print(mean_daily)
+        save_path = os.path.join(save_dir, basins_id[i] + "_2000_01_01-03_mean.nc")
+        mean_daily.to_netcdf(save_path)
+
+
+def test_download_era5(save_dir):
+    downloaded_file = os.path.join(save_dir, "a_test_range.nc")
+    date_range = ["2000-01-01", "2000-01-03"]
+    lat_lon_range = (31, 108, 30, 109)  # lat_max, lon_min, lat_min, lon_max
+    variables_list = 'total_precipitation'
+    download_era5(downloaded_file, date_range, lat_lon_range, variables_list, file_format="netcdf")
+    print("Downloading ERA5 hourly data is finished!")
+
+
+def test_download_nldas_hourly():
+    download_lst_dir = os.path.join(definitions.ROOT_DIR, "hydrobench", "nldas4basins")
+    save_dir = os.path.join(definitions.DATASET_DIR, "nldas_hourly")
+    for file in os.listdir(download_lst_dir):
+        if "NLDAS" in file and ".txt" in file:
+            url_lst_file = os.path.join(definitions.ROOT_DIR, "hydrobench", "nldas4basins", file)
+            download_nldas_with_url_lst(url_lst_file, save_dir)
+    print("Downloading NLDAS hourly data is finished!")
diff --git a/test/test_download_daymet.py b/test/test_download_daymet.py
deleted file mode 100644
index 2504295..0000000
--- a/test/test_download_daymet.py
+++ /dev/null
@@ -1,205 +0,0 @@
-import os
-import unittest
-import geopandas as gpd
-from pynhd import NLDI
-import xarray as xr
-import pydaymet as daymet
-
-import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.daymet4basins.basin_daymet_process import download_daymet_by_geom_bound, calculate_basin_grids_pet, \
-    calculate_basin_mean
-from hydrobench.utils.hydro_utils import unserialize_geopandas
-
-
-class TestDaymet4Basin(unittest.TestCase):
-    def setUp(self) -> None:
-        save_dir = os.path.join(definitions.ROOT_DIR, "test", "test_data")
-        if not os.path.isdir(save_dir):
-            os.makedirs(save_dir)
-        self.save_dir = save_dir
-        self.var = ['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']
-        camels_dir = os.path.join(definitions.DATASET_DIR, "camels")
-        self.camels = Camels(camels_dir, True)
-
-    def test_read_daymet_1basin_3days(self):
-        basin_id = "01013500"
-        dates = ("2000-01-01", "2000-01-03")
-        geometry = NLDI().get_basins(basin_id).geometry[0]
-        # ``tmin``, ``tmax``, ``prcp``, ``srad``, ``vp``, ``swe``, ``dayl``
-        var = ['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']
-        daily = daymet.get_bygeom(geometry, dates, variables=var, pet=True)
-        save_dir = self.save_dir
-        save_path = os.path.join(save_dir, basin_id + "_2000_01_01-03.nc")
-        daily.to_netcdf(save_path)
-
-    def test_read_daymet_1basin_in_camels_2days(self):
-        basin_id = "01013500"
-        dates = ("2000-01-01", "2000-01-02")
-        camels_shp_file = self.camels.dataset_description["CAMELS_BASINS_SHP_FILE"]
-        camels_shp = gpd.read_file(camels_shp_file)
-        # transform the geographic coordinates to wgs84 i.e. epsg4326  it seems NAD83 is equal to WGS1984 in geopandas
-        camels_shp_epsg4326 = camels_shp.to_crs(epsg=4326)
-        geometry = camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry[0]
-        # ``tmin``, ``tmax``, ``prcp``, ``srad``, ``vp``, ``swe``, ``dayl``
-        var = ['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']
-        daily = daymet.get_bygeom(geometry, dates, variables=var, pet=True)
-        save_dir = self.save_dir
-        save_path = os.path.join(save_dir, basin_id + "_in_camels_2000_01_01-02.nc")
-        daily.to_netcdf(save_path)
-
-    def test_read_daymet_basins_3days(self):
-        basin_id = ["01013500", "01031500"]
-        dates = ("2000-01-01", "2000-01-03")
-        basins = NLDI().get_basins(basin_id)
-        for i in range(len(basin_id)):
-            # ``tmin``, ``tmax``, ``prcp``, ``srad``, ``vp``, ``swe``, ``dayl``
-            var = self.var
-            daily = daymet.get_bygeom(basins.geometry[i], dates, variables=var)
-            save_path = os.path.join(self.save_dir, basin_id[i] + "_2000_01_01-03.nc")
-            daily.to_netcdf(save_path)
-
-    def test_download_nldi_shpfile(self):
-        basin_id = "01013500"
-        basin = NLDI().get_basins(basin_id)
-        # geometry = basin.geometry[0]
-        save_path = os.path.join(self.save_dir, basin_id + ".shp")
-        basin.to_file(save_path)
-
-    def test_download_daymet_without_dask(self):
-        basin_id = "01013500"
-        dates = ("2000-01-01", "2000-01-03")
-        geometry = NLDI().get_basins(basin_id).geometry[0]
-        var = self.var
-        daily = download_daymet_by_geom_bound(geometry, dates, variables=var)
-        save_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_nomask.nc")
-        daily.to_netcdf(save_path)
-
-    def test_download_daymet_without_dask_local_shpfile(self):
-        # Notice the projection, otherwise it will occur many NaN values since the locations are wrong
-        basin_id = "01013500"
-        dates = ("2000-01-01", "2000-01-03")
-        basin_shp_dir = os.path.join(definitions.ROOT_DIR, "test", "test_data")
-        basin_shp_file = os.path.join(basin_shp_dir, "01013500.shp")
-        if not os.path.isfile(basin_shp_file):
-            basin = NLDI().get_basins(basin_id)
-            save_path = os.path.join(self.save_dir, basin_id + ".shp")
-            basin.to_file(save_path)
-        basins = unserialize_geopandas(basin_shp_file)
-        geometry = basins.geometry[0]
-        var = self.var
-        daily = download_daymet_by_geom_bound(geometry, dates, variables=var)
-        save_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_nomask_local_shp.nc")
-        daily.to_netcdf(save_path)
-
-    def test_equal_local_shp_download_shp_nc(self):
-        basin_id = "01013500"
-        read_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_nomask.nc")
-        read_path_local = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_nomask_local_shp.nc")
-        daily = xr.open_dataset(read_path)
-        daily_local = xr.open_dataset(read_path_local)
-        print(daily.equals(daily_local))
-
-    def test_download_from_url_directly(self):
-        basin_id = "01013500"
-        dates = ("2000-01-01", "2000-01-03")
-        geometry = NLDI().get_basins(basin_id).geometry[0]
-        var = self.var
-        daily = download_daymet_by_geom_bound(geometry, dates, variables=var, boundary=False)
-        save_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_from_urls.nc")
-        daily.to_netcdf(save_path)
-
-    def test_basin_bound_pet_fao56(self):
-        basin_id = "01013500"
-        read_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_nomask.nc")
-        daily = xr.open_dataset(read_path)
-        include_pet = calculate_basin_grids_pet(daily, pet_method="pm_fao56")
-        save_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_pet_fao56.nc")
-        include_pet.to_netcdf(save_path)
-
-    def test_basin_bound_pet_pt(self):
-        basin_id = "01013500"
-        read_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_nomask.nc")
-        daily = xr.open_dataset(read_path)
-        include_pet = calculate_basin_grids_pet(daily, pet_method="priestley_taylor")
-        save_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_pet_pt.nc")
-        include_pet.to_netcdf(save_path)
-
-    def test_basin_mean(self):
-        basin_id = "01013500"
-        read_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_pet_pt.nc")
-        daily = xr.open_dataset(read_path)
-        basins = NLDI().get_basins(basin_id)
-        mean_daily = calculate_basin_mean(daily, basins.geometry[0])
-        print(mean_daily)
-
-    def test_batch_download_nldi_shpfile(self):
-        basin_id = ["01013500", "01031500"]
-        basins = NLDI().get_basins(basin_id)
-        # geometry = basin.geometry[0]
-        save_path = os.path.join(self.save_dir, "two_test_basins.shp")
-        basins.to_file(save_path)
-
-    def test_batch_download_daymet_without_dask(self):
-        basins_id = ["01013500", "01031500"]
-        dates = ("2000-01-01", "2000-01-03")
-        basins = NLDI().get_basins(basins_id)
-        save_dir = self.save_dir
-        if not os.path.isdir(save_dir):
-            os.makedirs(save_dir)
-        for i in range(len(basins_id)):
-            # ``tmin``, ``tmax``, ``prcp``, ``srad``, ``vp``, ``swe``, ``dayl``
-            var = self.var
-            daily = download_daymet_by_geom_bound(basins.geometry[i], dates, variables=var)
-            save_path = os.path.join(save_dir, basins_id[i] + "_2000_01_01-03_nomask.nc")
-            daily.to_netcdf(save_path)
-
-    def test_batch_basins_pet(self):
-        basin_id = ["01013500", "01031500"]
-        save_dir = os.path.join(definitions.ROOT_DIR, "test", "test_data")
-        if not os.path.isdir(save_dir):
-            os.makedirs(save_dir)
-        for i in range(len(basin_id)):
-            read_path = os.path.join(save_dir, basin_id[i] + "_2000_01_01-03_nomask.nc")
-            daily = xr.open_dataset(read_path)
-            include_pet = calculate_basin_grids_pet(daily, pet_method=["pm_fao56", "priestley_taylor"])
-            save_path = os.path.join(save_dir, basin_id[i] + "_2000_01_01-03_pet.nc")
-            include_pet.to_netcdf(save_path)
-
-    def test_batch_basins_mean(self):
-        basins_id = ["01013500", "01031500"]
-        basins = NLDI().get_basins(basins_id)
-        save_dir = os.path.join(definitions.ROOT_DIR, "test", "test_data")
-        if not os.path.isdir(save_dir):
-            os.makedirs(save_dir)
-        for i in range(len(basins_id)):
-            read_path = os.path.join(save_dir, basins_id[i] + "_2000_01_01-03_pet.nc")
-            daily = xr.open_dataset(read_path)
-            mean_daily = calculate_basin_mean(daily, basins.geometry[i])
-            print(mean_daily)
-            save_path = os.path.join(save_dir, basins_id[i] + "_2000_01_01-03_mean.nc")
-            mean_daily.to_netcdf(save_path)
-
-
-if __name__ == "__main__":
-    unittest.main()
-    # suite = unittest.TestSuite()
-    # suite.addTest(TestDaymet4Basin("test_read_daymet_1basin_3days"))
-    # suite.addTest(TestDaymet4Basin("test_read_daymet_1basin_in_camels_2days"))
-    # suite.addTest(TestDaymet4Basin("test_read_daymet_basins_3days"))
-    # suite.addTest(TestDaymet4Basin("test_download_nldi_shpfile"))
-    # suite.addTest(TestDaymet4Basin("test_download_daymet_without_dask"))
-    # suite.addTest(TestDaymet4Basin("test_download_daymet_without_dask_local_shpfile"))
-    # suite.addTest(TestDaymet4Basin("test_trans_to_csv_load_to_gis"))
-    # suite.addTest(TestDaymet4Basin("test_equal_local_shp_download_shp_nc"))
-    # suite.addTest(TestDaymet4Basin("test_download_from_url_directly"))
-    # suite.addTest(TestDaymet4Basin("test_basin_bound_pet_fao56"))
-    # suite.addTest(TestDaymet4Basin("test_basin_bound_pet_pt"))
-    # suite.addTest(TestDaymet4Basin("test_basin_mean"))
-    # suite.addTest(TestDaymet4Basin("test_batch_download_nldi_shpfile"))
-    # suite.addTest(TestDaymet4Basin("test_batch_download_daymet_without_dask"))
-    # suite.addTest(TestDaymet4Basin("test_batch_basins_pet"))
-    # suite.addTest(TestDaymet4Basin("test_batch_basins_mean"))
-    #
-    # runner = unittest.TextTestRunner()
-    # runner.run(suite)
diff --git a/test/test_download_era5_land.py b/test/test_download_era5_land.py
deleted file mode 100644
index 79a3c95..0000000
--- a/test/test_download_era5_land.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import os
-import unittest
-
-import definitions
-from hydrobench.ecmwf4basins.download_era5_land import download_era5
-
-
-class MyTestCase(unittest.TestCase):
-    def test_download_era5(self):
-        save_dir = os.path.join(definitions.ROOT_DIR, "test", "test_data")
-        downloaded_file = os.path.join(save_dir, "a_test_range.nc")
-        date_range = ["2000-01-01", "2000-01-03"]
-        lat_lon_range = (31, 108, 30, 109)  # lat_max, lon_min, lat_min, lon_max
-        variables_list = 'total_precipitation'
-        download_era5(downloaded_file, date_range, lat_lon_range, variables_list, file_format="netcdf")
-        print("Downloading ERA5 hourly data is finished!")
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/test/test_download_nldas.py b/test/test_download_nldas.py
deleted file mode 100644
index ddd750f..0000000
--- a/test/test_download_nldas.py
+++ /dev/null
@@ -1,20 +0,0 @@
-import os.path
-import unittest
-
-import definitions
-from hydrobench.nldas4basins.download_nldas import download_nldas_with_url_lst
-
-
-class MyTestCase(unittest.TestCase):
-    def test_download_nldas_hourly(self):
-        download_lst_dir = os.path.join(definitions.ROOT_DIR, "hydrobench", "nldas4basins")
-        save_dir = os.path.join(definitions.DATASET_DIR, "nldas_hourly")
-        for file in os.listdir(download_lst_dir):
-            if "NLDAS" in file and ".txt" in file:
-                url_lst_file = os.path.join(definitions.ROOT_DIR, "hydrobench", "nldas4basins", file)
-                download_nldas_with_url_lst(url_lst_file, save_dir)
-        print("Downloading NLDAS hourly data is finished!")
-
-
-if __name__ == '__main__':
-    unittest.main()
diff --git a/test/test_downloaded_data.py b/test/test_downloaded_data.py
index 9f5ea43..a7ebc9b 100644
--- a/test/test_downloaded_data.py
+++ b/test/test_downloaded_data.py
@@ -1,229 +1,254 @@
 import os
-import unittest
+import pytest
 import numpy as np
 import pandas as pd
 import geopandas as gpd
 import xarray as xr
 import rasterio.features as rio_features
 import pygeoutils as geoutils
-import cfgrib
 import definitions
-from hydrobench.data.data_camels import Camels
-from hydrobench.daymet4basins.basin_daymet_process import generate_boundary_dataset, resample_nc, \
+from hydrodataset.data.data_camels import Camels
+from hydrodataset.daymet4basins.basin_daymet_process import generate_boundary_dataset, resample_nc, \
     trans_daymet_to_camels_format, insert_daymet_value_in_leap_year
-from hydrobench.modis4basins.basin_mod16a2v105_process import trans_8day_modis16a2v105_to_camels_format
-from hydrobench.modis4basins.basin_pmlv2_process import trans_8day_pmlv2_to_camels_format
-from hydrobench.nldas4basins.basin_nldas_process import trans_daily_nldas_to_camels_format
-
-
-class MyTestCase(unittest.TestCase):
-    def setUp(self) -> None:
-        save_dir = os.path.join(definitions.ROOT_DIR, "test", "test_data")
-        if not os.path.isdir(save_dir):
-            os.makedirs(save_dir)
-        self.save_dir = save_dir
-        self.var = ['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']
-        camels_dir = os.path.join(definitions.DATASET_DIR, "camels")
-        self.camels = Camels(camels_dir, True)
-
-    def test1_trans_to_csv_load_to_gis(self):
-        basin_id = "01013500"
-        read_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_nomask.nc")
-        daily = xr.open_dataset(read_path)
-
-        arr_lat = daily['lat'].values.flatten()
-        arr_lon = daily['lon'].values.flatten()
-        arr_data = daily['prcp'].values[0, :, :].flatten()
-
-        arr_all = np.c_[arr_lat, arr_lon, arr_data]
-        # remove the rows with nan value
-        arr = arr_all[~np.isnan(arr_all).any(axis=1)]
-        df = pd.DataFrame(data=arr, columns=['lat', 'lon', 'prcp'])
-        df.to_csv(os.path.join(self.save_dir, 'load_to_qgis.csv'), index=False)
-        # after getting the csv file, please use "Layer -> Add Layer -> Add Delimited Text Layer" in QGIS to import it.
-
-    def test2_which_basin_boundary_out_of_camels(self):
-        basin_id = "01013500"
-        camels_shp_file = self.camels.dataset_description["CAMELS_BASINS_SHP_FILE"]
-        camels_shp = gpd.read_file(camels_shp_file)
-        # transform the geographic coordinates to wgs84 i.e. epsg4326  it seems NAD83 is equal to WGS1984 in geopandas
-        camels_shp_epsg4326 = camels_shp.to_crs(epsg=4326)
-        geometry = camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry.item()
-        gb = geometry.bounds
-        gb_west = gb[0]
-        gb_south = gb[1]
-        gb_east = gb[2]
-        gb_north = gb[3]
-
-        read_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_nomask.nc")
-        daily = xr.open_dataset(read_path)
-
-        arr_lat = daily['lat'].values.flatten()
-        arr_lon = daily['lon'].values.flatten()
-        arr_data = daily['prcp'].values[0, :, :].flatten()
-
-        arr_all = np.c_[arr_lat, arr_lon, arr_data]
-        # remove the rows with nan value
-        arr = arr_all[~np.isnan(arr_all).any(axis=1)]
-        df = pd.DataFrame(data=arr, columns=['lat', 'lon', 'prcp'])
-
-        df_east = df["lon"].max()
-        df_west = df["lon"].min()
-        df_north = df["lat"].max()
-        df_south = df["lat"].min()
-        # if boundary is in the
-        print(gb_west > df_west)
-        print(gb_east < df_east)
-        print(gb_north < df_north)
-        print(gb_south > df_south)
-
-    def test3_trans_to_rectangle(self):
-        basin_id = "01013500"
-        camels_shp_file = self.camels.dataset_description["CAMELS_BASINS_SHP_FILE"]
-        camels_shp = gpd.read_file(camels_shp_file)
-        # transform the geographic coordinates to wgs84 i.e. epsg4326  it seems NAD83 is equal to WGS1984 in geopandas
-        camels_shp_epsg4326 = camels_shp.to_crs(epsg=4326)
-        geometry = camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry.item()
-        save_path = os.path.join(self.save_dir, basin_id + "_camels.shp")
-        camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry.to_file(save_path)
-
-        read_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_from_urls.nc")
-        ds = xr.open_dataset(read_path)
-        ds_dims = ("y", "x")
-        transform, width, height = geoutils.pygeoutils._get_transform(ds, ds_dims)
-        _geometry = geoutils.pygeoutils._geo2polygon(geometry, "epsg:4326", ds.crs)
-
-        _mask = rio_features.geometry_mask([_geometry], (height, width), transform, invert=True)
-        # x - column, y - row
-        y_idx, x_idx = np.where(_mask)
-        y_idx_min = y_idx.min()
-        y_idx_max = y_idx.max()
-        x_idx_min = x_idx.min()
-        x_idx_max = x_idx.max()
-        _mask_bound = np.full(_mask.shape, False)
-        _mask_bound[y_idx_min:y_idx_max + 1, x_idx_min:x_idx_max + 1] = True
-
-        coords = {ds_dims[0]: ds.coords[ds_dims[0]], ds_dims[1]: ds.coords[ds_dims[1]]}
-        mask = xr.DataArray(_mask, coords, dims=ds_dims)
-        mask_bound = xr.DataArray(_mask_bound, coords, dims=ds_dims)
-
-        ds_masked = ds.where(mask, drop=True)
-        ds_masked.attrs["transform"] = transform
-        ds_masked.attrs["bounds"] = _geometry.bounds
-
-        ds_bound_masked = ds.where(mask_bound, drop=True)
-        ds_bound_masked.attrs["transform"] = transform
-        ds_bound_masked.attrs["bounds"] = _geometry.bounds
-
-        arr_lat = ds_masked['lat'].values.flatten()
-        arr_lon = ds_masked['lon'].values.flatten()
-        arr_data = ds_masked['prcp'].values[0, :, :].flatten()
-
-        arr_all = np.c_[arr_lat, arr_lon, arr_data]
-        # remove the rows with nan value
-        arr = arr_all[~np.isnan(arr_all).any(axis=1)]
-        df = pd.DataFrame(data=arr, columns=['lat', 'lon', 'prcp'])
-        df.to_csv(os.path.join(self.save_dir, 'geometry_load_to_qgis.csv'), index=False)
-
-        arr_bound_lat = ds_bound_masked['lat'].values.flatten()
-        arr_bound_lon = ds_bound_masked['lon'].values.flatten()
-        arr_bound_data = ds_bound_masked['prcp'].values[0, :, :].flatten()
-
-        arr_bound_all = np.c_[arr_bound_lat, arr_bound_lon, arr_bound_data]
-        # remove the rows with nan value
-        arr_bound = arr_bound_all[~np.isnan(arr_bound_all).any(axis=1)]
-        df_bound = pd.DataFrame(data=arr_bound, columns=['lat', 'lon', 'prcp'])
-        df_bound.to_csv(os.path.join(self.save_dir, 'bound_load_to_qgis.csv'), index=False)
-        # after getting the csv file, please use "Layer -> Add Layer -> Add Delimited Text Layer" in QGIS to import it.
-
-    def test4_read_nc_write_boundary(self):
-        basin_id = "01013500"
-        camels_shp_file = self.camels.dataset_description["CAMELS_BASINS_SHP_FILE"]
-        camels_shp = gpd.read_file(camels_shp_file)
-        # transform the geographic coordinates to wgs84 i.e. epsg4326  it seems NAD83 is equal to WGS1984 in geopandas
-        camels_shp_epsg4326 = camels_shp.to_crs(epsg=4326)
-        geometry = camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry.item()
-
-        read_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_from_urls.nc")
-        ds = xr.open_dataset(read_path)
-        ds_masked = generate_boundary_dataset(ds, geometry)
-
-        save_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_bound.nc")
-        ds_masked.to_netcdf(save_path)
-
-    def test_resample_nc(self):
-        basin_id = "01013500"
-        nc_path = os.path.join(self.save_dir, basin_id + "_2000_01_01-03_bound.nc")
-        ds = xr.open_dataset(nc_path)
-        ds_high_res = resample_nc(ds, 0.5)
-        ds_low_res = resample_nc(ds, 2)
-        # the direction of exploration is to the first row (y-axis in this example), so we chose [0, 1, 0]
-        self.assertAlmostEqual(ds_high_res["swe"].values[0, 1, 0].item(), ds["swe"].values[0, 0, 0].item())
-        self.assertAlmostEqual(ds_low_res["swe"].values[0, 0, 0].item(), np.mean(ds["swe"].values[0, 0:2, 0:2]))
-
-    def test_gee_daymet_to_camels_format(self):
-        """
-        the example data comes from the code here:
-        https://code.earthengine.google.com/1ffc9a50f7749d7be2f67368f465a993
-        """
-        daymet_dir = "example_data"
-        output_dir = os.path.join("test_data", "daymet")
-        camels = Camels(os.path.join(definitions.DATASET_DIR, "camels"), download=True)
-        gage_dict = camels.camels_sites.to_dict(orient="list")
-        region = "camels"
-        year = 2000
-        trans_daymet_to_camels_format(daymet_dir, output_dir, gage_dict, region, year)
-        insert_daymet_value_in_leap_year(output_dir, t_range=["2000-01-01", "2000-01-04"])
-        print("Trans finished")
-
-    def test_gee_daily_nldas_to_camels_format(self):
-        """
-        the example data comes from the code here:
-        https://code.earthengine.google.com/f62826e26e52996b63ccb3c0ceea3282
-        """
-        nldas_dir = "example_data"
-        output_dir = os.path.join("test_data", "nldas")
-        camels = Camels(os.path.join(definitions.DATASET_DIR, "camels"), download=True)
-        gage_dict = camels.camels_sites.to_dict(orient="list")
-        region = "camels"
-        year = 2000
-        trans_daily_nldas_to_camels_format(nldas_dir, output_dir, gage_dict, region, year)
-        print("Trans finished")
-
-    def test_gee_8day_pmlv2_to_camels_format(self):
-        pmlv2_dir = "example_data"
-        output_dir = os.path.join("test_data", "pmlv2")
-        camels = Camels(os.path.join(definitions.DATASET_DIR, "camels"), download=True)
-        gage_dict = camels.camels_sites.to_dict(orient="list")
-        region = "camels"
-        year = 2002
-        trans_8day_pmlv2_to_camels_format(pmlv2_dir, output_dir, gage_dict, region, year)
-        print()
-
-    def test_gee_8day_modis16a2v105_to_camels_format(self):
-        modis16a2v105_dir = "example_data"
-        output_dir = os.path.join("test_data", "modis16a2v105")
-        camels = Camels(os.path.join(definitions.DATASET_DIR, "camels"), download=True)
-        gage_dict = camels.camels_sites.to_dict(orient="list")
-        region = "camels"
-        year = 2000
-        trans_8day_modis16a2v105_to_camels_format(modis16a2v105_dir, output_dir, gage_dict, region, year)
-        print()
-
-    def test_read_nldas_nc(self):
-        nc_file = os.path.join("example_data", "NLDAS_FORA0125_H.A19790101.1300.020.nc")
-        nc4_file = os.path.join("example_data", "NLDAS_FORA0125_H.A19790101.1300.002.grb.SUB.nc4")
-        ds1 = xr.open_dataset(nc_file)
-        ds2 = xr.open_dataset(nc4_file)
-        # data from v002 and v2.0 are same
-        self.assertEqual(np.nansum(ds1["CAPE"].values), np.nansum(ds2["CAPE"].values))
-
-    def test_read_era5_land_nc(self):
-        nc_file = os.path.join("example_data", "ERA5_LAND_20010101_20010102_total_precipitation.nc")
-        # nc_file = os.path.join("test_data", "a_test_range.nc")
-        ds = xr.open_dataset(nc_file)
-        print(ds)
-
-
-if __name__ == '__main__':
-    unittest.main()
+from hydrodataset.ecmwf4basins.basin_era5_process import trans_era5_land_to_camels_format
+from hydrodataset.modis4basins.basin_mod16a2v105_process import trans_8day_modis16a2v105_to_camels_format
+from hydrodataset.modis4basins.basin_pmlv2_process import trans_8day_pmlv2_to_camels_format
+from hydrodataset.nldas4basins.basin_nldas_process import trans_daily_nldas_to_camels_format
+
+
+@pytest.fixture
+def save_dir():
+    dir_ = os.path.join(definitions.ROOT_DIR, "test", "test_data")
+    if not os.path.isdir(dir_):
+        os.makedirs(dir_)
+    return dir_
+
+
+@pytest.fixture
+def var():
+    return ['dayl', 'prcp', 'srad', 'swe', 'tmax', 'tmin', 'vp']
+
+
+@pytest.fixture
+def camels():
+    camels_dir = os.path.join(definitions.DATASET_DIR, "camels", "camels_us")
+    if not os.path.isfile(
+            os.path.join(camels_dir, "camels_attributes_v2.0", "camels_attributes_v2.0", "camels_name.txt")):
+        return Camels(camels_dir, True)
+    return Camels(camels_dir, False)
+
+
+def test1_trans_to_csv_load_to_gis(save_dir):
+    basin_id = "01013500"
+    read_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_nomask.nc")
+    daily = xr.open_dataset(read_path)
+
+    arr_lat = daily['lat'].values.flatten()
+    arr_lon = daily['lon'].values.flatten()
+    arr_data = daily['prcp'].values[0, :, :].flatten()
+
+    arr_all = np.c_[arr_lat, arr_lon, arr_data]
+    # remove the rows with nan value
+    arr = arr_all[~np.isnan(arr_all).any(axis=1)]
+    df = pd.DataFrame(data=arr, columns=['lat', 'lon', 'prcp'])
+    df.to_csv(os.path.join(save_dir, 'load_to_qgis.csv'), index=False)
+    # after getting the csv file, please use "Layer -> Add Layer -> Add Delimited Text Layer" in QGIS to import it.
+
+
+def test2_which_basin_boundary_out_of_camels(camels, save_dir):
+    basin_id = "01013500"
+    camels_shp_file = camels.data_source_description["CAMELS_BASINS_SHP_FILE"]
+    camels_shp = gpd.read_file(camels_shp_file)
+    # transform the geographic coordinates to wgs84 i.e. epsg4326  it seems NAD83 is equal to WGS1984 in geopandas
+    camels_shp_epsg4326 = camels_shp.to_crs(epsg=4326)
+    geometry = camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry.item()
+    gb = geometry.bounds
+    gb_west = gb[0]
+    gb_south = gb[1]
+    gb_east = gb[2]
+    gb_north = gb[3]
+
+    read_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_nomask.nc")
+    daily = xr.open_dataset(read_path)
+
+    arr_lat = daily['lat'].values.flatten()
+    arr_lon = daily['lon'].values.flatten()
+    arr_data = daily['prcp'].values[0, :, :].flatten()
+
+    arr_all = np.c_[arr_lat, arr_lon, arr_data]
+    # remove the rows with nan value
+    arr = arr_all[~np.isnan(arr_all).any(axis=1)]
+    df = pd.DataFrame(data=arr, columns=['lat', 'lon', 'prcp'])
+
+    df_east = df["lon"].max()
+    df_west = df["lon"].min()
+    df_north = df["lat"].max()
+    df_south = df["lat"].min()
+    # if boundary is in the
+    assert not (gb_west > df_west)
+    assert not (gb_east < df_east)
+    assert (gb_north < df_north)
+    assert not (gb_south > df_south)
+
+
+def test3_trans_to_rectangle(camels, save_dir):
+    basin_id = "01013500"
+    camels_shp_file = camels.data_source_description["CAMELS_BASINS_SHP_FILE"]
+    camels_shp = gpd.read_file(camels_shp_file)
+    # transform the geographic coordinates to wgs84 i.e. epsg4326  it seems NAD83 is equal to WGS1984 in geopandas
+    camels_shp_epsg4326 = camels_shp.to_crs(epsg=4326)
+    geometry = camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry.item()
+    save_path = os.path.join(save_dir, basin_id + "_camels.shp")
+    camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry.to_file(save_path)
+
+    read_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_from_urls.nc")
+    ds = xr.open_dataset(read_path)
+    ds_dims = ("y", "x")
+    transform, width, height = geoutils.pygeoutils._get_transform(ds, ds_dims)
+    _geometry = geoutils.pygeoutils._geo2polygon(geometry, "epsg:4326", ds.crs)
+
+    _mask = rio_features.geometry_mask([_geometry], (height, width), transform, invert=True)
+    # x - column, y - row
+    y_idx, x_idx = np.where(_mask)
+    y_idx_min = y_idx.min()
+    y_idx_max = y_idx.max()
+    x_idx_min = x_idx.min()
+    x_idx_max = x_idx.max()
+    _mask_bound = np.full(_mask.shape, False)
+    _mask_bound[y_idx_min:y_idx_max + 1, x_idx_min:x_idx_max + 1] = True
+
+    coords = {ds_dims[0]: ds.coords[ds_dims[0]], ds_dims[1]: ds.coords[ds_dims[1]]}
+    mask = xr.DataArray(_mask, coords, dims=ds_dims)
+    mask_bound = xr.DataArray(_mask_bound, coords, dims=ds_dims)
+
+    ds_masked = ds.where(mask, drop=True)
+    ds_masked.attrs["transform"] = transform
+    ds_masked.attrs["bounds"] = _geometry.bounds
+
+    ds_bound_masked = ds.where(mask_bound, drop=True)
+    ds_bound_masked.attrs["transform"] = transform
+    ds_bound_masked.attrs["bounds"] = _geometry.bounds
+
+    arr_lat = ds_masked['lat'].values.flatten()
+    arr_lon = ds_masked['lon'].values.flatten()
+    arr_data = ds_masked['prcp'].values[0, :, :].flatten()
+
+    arr_all = np.c_[arr_lat, arr_lon, arr_data]
+    # remove the rows with nan value
+    arr = arr_all[~np.isnan(arr_all).any(axis=1)]
+    df = pd.DataFrame(data=arr, columns=['lat', 'lon', 'prcp'])
+    df.to_csv(os.path.join(save_dir, 'geometry_load_to_qgis.csv'), index=False)
+
+    arr_bound_lat = ds_bound_masked['lat'].values.flatten()
+    arr_bound_lon = ds_bound_masked['lon'].values.flatten()
+    arr_bound_data = ds_bound_masked['prcp'].values[0, :, :].flatten()
+
+    arr_bound_all = np.c_[arr_bound_lat, arr_bound_lon, arr_bound_data]
+    # remove the rows with nan value
+    arr_bound = arr_bound_all[~np.isnan(arr_bound_all).any(axis=1)]
+    df_bound = pd.DataFrame(data=arr_bound, columns=['lat', 'lon', 'prcp'])
+    df_bound.to_csv(os.path.join(save_dir, 'bound_load_to_qgis.csv'), index=False)
+    # after getting the csv file, please use "Layer -> Add Layer -> Add Delimited Text Layer" in QGIS to import it.
+
+
+def test4_read_nc_write_boundary(camels, save_dir):
+    basin_id = "01013500"
+    camels_shp_file = camels.data_source_description["CAMELS_BASINS_SHP_FILE"]
+    camels_shp = gpd.read_file(camels_shp_file)
+    # transform the geographic coordinates to wgs84 i.e. epsg4326  it seems NAD83 is equal to WGS1984 in geopandas
+    camels_shp_epsg4326 = camels_shp.to_crs(epsg=4326)
+    geometry = camels_shp_epsg4326[camels_shp_epsg4326["hru_id"] == int(basin_id)].geometry.item()
+
+    read_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_from_urls.nc")
+    ds = xr.open_dataset(read_path)
+    ds_masked = generate_boundary_dataset(ds, geometry)
+
+    save_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_bound.nc")
+    ds_masked.to_netcdf(save_path)
+
+
+def test_resample_nc(save_dir):
+    basin_id = "01013500"
+    nc_path = os.path.join(save_dir, basin_id + "_2000_01_01-03_bound.nc")
+    ds = xr.open_dataset(nc_path)
+    ds_high_res = resample_nc(ds, 0.5)
+    ds_low_res = resample_nc(ds, 2)
+    # the direction of exploration is to the first row (y-axis in this example), so we chose [0, 1, 0]
+    np.testing.assert_array_equal(ds_high_res["swe"].values[0, 1, 0], ds["swe"].values[0, 0, 0])
+    np.testing.assert_array_equal(ds_low_res["swe"].values[0, 0, 0], np.mean(ds["swe"].values[0, 0:2, 0:2]))
+
+
+def test_gee_daymet_to_camels_format(camels):
+    """
+    the example data comes from the code here:
+    https://code.earthengine.google.com/1ffc9a50f7749d7be2f67368f465a993
+    """
+    daymet_dir = "example_data"
+    output_dir = os.path.join("test_data", "daymet")
+    gage_dict = camels.camels_sites.to_dict(orient="list")
+    region = "camels"
+    year = 2000
+    trans_daymet_to_camels_format(daymet_dir, output_dir, gage_dict, region, year)
+    insert_daymet_value_in_leap_year(output_dir, t_range=["2000-01-01", "2000-01-04"])
+    print("Trans finished")
+
+
+def test_gee_daily_nldas_to_camels_format(camels):
+    """
+    the example data comes from the code here:
+    https://code.earthengine.google.com/f62826e26e52996b63ccb3c0ceea3282
+    """
+    nldas_dir = "example_data"
+    output_dir = os.path.join("test_data", "nldas")
+    gage_dict = camels.camels_sites.to_dict(orient="list")
+    region = "camels"
+    year = 2000
+    trans_daily_nldas_to_camels_format(nldas_dir, output_dir, gage_dict, region, year)
+    print("Trans finished")
+
+
+def test_gee_8day_pmlv2_to_camels_format(camels):
+    pmlv2_dir = "example_data"
+    output_dir = os.path.join("test_data", "pmlv2")
+    gage_dict = camels.camels_sites.to_dict(orient="list")
+    region = "camels"
+    year = 2002
+    trans_8day_pmlv2_to_camels_format(pmlv2_dir, output_dir, gage_dict, region, year)
+
+
+def test_gee_8day_modis16a2v105_to_camels_format(camels):
+    modis16a2v105_dir = "example_data"
+    output_dir = os.path.join("test_data", "modis16a2v105")
+    gage_dict = camels.camels_sites.to_dict(orient="list")
+    region = "camels"
+    year = 2000
+    trans_8day_modis16a2v105_to_camels_format(modis16a2v105_dir, output_dir, gage_dict, region, year)
+
+
+def test_read_nldas_nc():
+    nc_file = os.path.join("example_data", "NLDAS_FORA0125_H.A19790101.1300.020.nc")
+    nc4_file = os.path.join("example_data", "NLDAS_FORA0125_H.A19790101.1300.002.grb.SUB.nc4")
+    ds1 = xr.open_dataset(nc_file)
+    ds2 = xr.open_dataset(nc4_file)
+    # data from v002 and v2.0 are same
+    np.testing.assert_array_equal(np.nansum(ds1["CAPE"].values), np.nansum(ds2["CAPE"].values))
+
+
+def test_read_era5_land_nc():
+    nc_file = os.path.join("example_data", "ERA5_LAND_20010101_20010102_total_precipitation.nc")
+    # nc_file = os.path.join("test_data", "a_test_range.nc")
+    ds = xr.open_dataset(nc_file)
+    print(ds)
+
+
+def test_gee_daily_era5_land_to_camels_format():
+    era5_land_dir = "example_data"
+    output_dir = os.path.join("test_data", "era5_land")
+    region = "camels_mr"
+    year = 2010
+    camels_mr_dir = os.path.join(definitions.DATASET_DIR, "camels", "camels_mr")
+    camels_mr_streamflow_dir = os.path.join(camels_mr_dir, "streamflow")
+    flow_files = os.listdir(camels_mr_streamflow_dir)
+    gage_dict = pd.DataFrame({"gage_id": np.sort([i[:-4] for i in flow_files])})
+    trans_era5_land_to_camels_format(era5_land_dir, output_dir, gage_dict, region, year)
+    print("Trans finished")
diff --git a/test/test_utils.py b/test/test_utils.py
new file mode 100644
index 0000000..d0b5a45
--- /dev/null
+++ b/test/test_utils.py
@@ -0,0 +1,19 @@
+import numpy as np
+from hydrodataset.utils.hydro_utils import utc_to_local
+
+
+def test_always_passes():
+    assert True
+
+
+def test_tz_trans():
+    utc_time_str = "2020-01-01T00:00:00"
+    local_tz = "Asia/Hong_Kong"
+    utc_ts = utc_to_local(utc_time_str, local_tz)
+    assert utc_ts == "2020-01-01T08:00:00"
+
+
+def test_tz_np_trans():
+    utc_time = np.datetime64("2020-01-01T00:00:00")
+    utc_ts = utc_to_local(utc_time)
+    assert utc_ts == "2020-01-01T08:00:00"