IEasyHydro SDK is a Python library used to simplify access to the iEasyHydro data. It supports both iEasyHydro and iEasyHydroHF. At the moment, support for iEasyHydroHF is limited to "static" data, but more functionalities will be added once the application becomes fully operational.
pip install git+https://github.com/hydrosolutions/ieasyhydro-python-sdk
To use IEasyHydroSDK you need to configure next environment variables:
IEASYHYDRO_HOST=https://api.ieasyhydro.org
IEASYHYDRO_USERNAME=username
IEASYHYDRO_PASSWORD=password
ORGANIZATION_ID=1 # only fill if user is superadmin
For SDK for iEasyHydroHF, similar environment variables are required:
IEASYHYDROHF_HOST=https://api.ieasyhydro.org
IEASYHYDROHF_USERNAME=username
IEASYHYDROHF_PASSWORD=password
We strongly recommend to create a dedicated "machine" user for API usage.
from ieasyhydro_sdk.sdk import IEasyHydroSDK, IEasyHydroHFSDK
# initialize SDK (configuration will be read from environment variables)
ieasyhydro_sdk = IEasyHydroSDK()
ieasyhydro_sdk_hf = IEasyHydroHFSDK()
from ieasyhydro_sdk.sdk import IEasyHydroSDK, IEasyHydroHFSDK
# initialize and configure SDK by providing configuration on class creation
ieasyhydro_sdk = IEasyHydroSDK(
host='https://api.ieasyhydro.org',
username='username',
password='password',
organization_id=1,
)
ieasyhydro_hf_sdk = IEasyHydroHFSDK(
host='https://hf.ieasyhydro.org/api/v1/',
username='username',
password='password',
)
We can fetch details about all available discharge and meteo sites in the organization.
Example 1: Fetch discharge sites data
from ieasyhydro_sdk.sdk import IEasyHydroSDK
ieasyhydro_sdk = IEasyHydroSDK()
discharge_sites_data = ieasyhydro_sdk.get_discharge_sites()
For the HF SDK, it's exactly the same:
from ieasyhydro_sdk.sdk import IEasyHydroHFSDK
ieasyhydro_hf_sdk = IEasyHydroHFSDK()
discharge_sites_data = ieasyhydro_hf_sdk.get_discharge_sites()
The difference with the discharge stations is that due to different structure of the database in iEasyHydroHF, the virtual stations are separated from the discharge ones. If you need to retrieve the virtual stations, you can do it as follows:
from ieasyhydro_sdk.sdk import IEasyHydroHFSDK
ieasyhydro_hf_sdk = IEasyHydroHFSDK()
virtual_sites_data = ieasyhydro_hf_sdk.get_virtual_sites()
Example 2: Fetch meteo sites data
from ieasyhydro_sdk.sdk import IEasyHydroSDK
ieasyhydro_sdk = IEasyHydroSDK()
meteo_sites_data = ieasyhydro_sdk.get_meteo_sites()
The HF client works exactly the same.
Both methods are returning dictionary with the following structure (for the iEasyHydro SDK):
[
{
'elevation': 0.0,
'organization_id': 1,
'longitude': 0.0,
'site_name': 'Site name 1',
'site_type': 'discharge',
'region': 'Region 1',
'is_virtual': False,
'country': 'Kyrgyzstan',
'latitude': 0.0,
'basin': 'Basin 1',
'id': 23,
'site_code': '10000'
},
{
'elevation': 0.0,
'organization_id': 1,
'longitude': 0.0,
'site_name': 'Site name 2',
'site_type': 'discharge',
'region': 'Region 2',
'is_virtual': False,
'country': 'Kyrgyzstan',
'latitude': 0.0,
'basin': 'Basin 2',
'id': 53,
'site_code': '11000'
},
]
Again, since iEasyHydro HF works differently "under the hood", there are some differences in the output the SDK will return.
[
{
'basin': {
'national_name': '',
'official_name': 'Иссык-Куль'
},
'bulletin_order': 0,
'country': 'Кыргызстан',
'dangerous_discharge': 100.0,
'elevation': 0.0,
'enabled_forecasts': {
'daily_forecast': False,
'decadal_forecast': False,
'monthly_forecast': False,
'pentad_forecast': False,
'seasonal_forecast': False
},
'historical_discharge_maximum': None,
'historical_discharge_minimum': None,
'id': 96,
'latitude': 42.8746,
'longitude': 74.5698,
'national_name': '',
'official_name': 'Ак-Сай - с.Көк-Сай',
'region': {
'national_name': '',
'official_name': 'ИССЫК-КУЛЬСКАЯ ОБЛАСТЬ'
},
'site_code': '15054',
'site_type': 'manual'
},
{
'basin': {
'national_name': '',
'official_name': 'Сыр-Дарья'
},
'bulletin_order': 0,
'country': 'Кыргызстан',
'dangerous_discharge': 50.2,
'elevation': 0.0,
'enabled_forecasts': {
'daily_forecast': False,
'decadal_forecast': False,
'monthly_forecast': False,
'pentad_forecast': False,
'seasonal_forecast': False
},
'historical_discharge_maximum': None,
'historical_discharge_minimum': None,
'id': 97,
'latitude': 40.214,
'longitude': 72.529,
'national_name': '',
'official_name': 'Араван-Сай-к.Жаны-Ноокат',
'region': {
'national_name': '',
'official_name': 'БАТКЕНСКАЯ ОБЛАСТЬ'
},
'site_code': '16158',
'site_type': 'manual'
}
]
You will get similar response for meteo stations with the exception that the enabled_forecasts
will be None
.
The iEasyHydro has an API endpoint for fetching the norm for the next data types:
discharge
temperature
precitipation
It's important to understand that iEasyHydro is calculating norm with the "cutoff" logic -
this logic is the legacy from the times when it was calculated manually on the paper.
This was used to avoid frequent manual recalculation of the norm, but to do a recalculation
every 5 years. The logic is just not considering the latest data in norm calculation, and
the cutoff year is calculated by the next python code (the lowest_year
is the year of the
first data in the system):
def get_norm_cutoff_year(cls, lowest_year):
current_year = datetime.datetime.now().year
if current_year - lowest_year < 10:
return current_year
return (current_year / 5) * 5
Example 1:
from ieasyhydro_sdk.sdk import IEasyHydroSDK
ieasyhydro_sdk = IEasyHydroSDK()
norm_data = ieasyhydro_sdk.get_norm_for_site(
site_code='15212',
data_type='discharge')
The method is returning dictionary with the following structure:
{
'norm_data': [
2.02,
1.88,
1.69,
1.65,
1.72,
1.6,
1.69,
1.61,
1.5,
1.42,
1.51,
1.61,
1.64,
2.31,
3.76,
10.2,
13.3,
13.6,
13.9,
11.0,
12.1,
12.6,
9.21,
6.13,
4.68,
3.7,
2.6,
2.82,
2.36,
2.09,
2.05,
2.3,
2.5,
2.44,
2.35,
2.02
],
'end_year': 2020,
'site_id': 10,
'start_year': 2013
}
As norms also work differently in iEasyHydroHF, the output you get when requesting norms from its SDK is slightly different. iEasyHydroHF only works with the current norm values, instead of calculating it from norm data for all the previous years which also means the "cutoff" logic described above isn't relevant here. The interface for retrieving the norm however is the same:
from ieasyhydro_sdk.sdk import IEasyHydroHFSDK
ieasyhydro_hf_sdk = IEasyHydroHFSDK()
norm_data = ieasyhydro_hf_sdk.get_norm_for_site("15194", "discharge")
The data you would get in the norm_data
variable would be:
[
1.76306,
1.69184,
1.64643,
1.61071,
1.57296,
1.5401,
1.5451,
1.54677,
1.53255,
1.53218,
1.60733,
1.7696,
2.27225,
3.08059,
4.1617,
6.32663,
8.14099,
10.01703,
11.67733,
13.4458,
14.639,
15.05198,
13.84901,
11.10554,
8.11796,
5.90596,
4.43908,
3.43042,
2.89649,
2.53247,
2.32948,
2.1932,
2.08865,
2.00885,
1.92897,
1.85072
]
We can fetch data for all data types stored in iEasyHydro database by using the get_data_values_for_site()
method.
We just need to specify site_code
and variable_type
we want to fetch, and function will automatically fetch all
data values from the API. It will take care to perform requests in chunks in order to avoid overloading of the server.
IMPORTANT At this time, iEasyHydro HF still doesn't provide the interface for retrieving the data values. As soon as it is in operational use, the library will be updated to provide support for this as well.
Examples 1: Fetch all daily discharge values
from ieasyhydro_sdk.sdk import IEasyHydroSDK
ieasyhydro_sdk = IEasyHydroSDK()
response_data = ieasyhydro_sdk.get_data_values_for_site('15212', 'discharge_daily')
Example 2: Fetch all historical decade averages
from ieasyhydro_sdk.sdk import IEasyHydroSDK
ieasyhydro_sdk = IEasyHydroSDK()
response_data = ieasyhydro_sdk.get_data_values_for_site('15212', 'discharge_historical_decade_average')
Example 3: Fetch all discharge measurements measured after 2018-01-01
import datetime
from ieasyhydro_sdk.sdk import IEasyHydroSDK
from ieasyhydro_sdk.filters import BasicDataValueFilters
ieasyhydro_sdk = IEasyHydroSDK()
filters = BasicDataValueFilters(
local_date_time__gt=datetime.datetime(2018, 1, 1)
)
response_data = ieasyhydro_sdk.get_data_values_for_site(
'15212',
'discharge_historical_decade_average',
filters=filters
)
You can find all variable types listed here:
Variable type | Description |
---|---|
water_level_daily | |
water_level_daily_average | |
water_level_daily_estimation | |
discharge_measurement | |
discharge_daily | |
free_river_area | |
maximum_depth | |
decade_discharge | |
dangerous_discharge | |
discharge_daily_average | |
ice_phenomena | |
water_level_measurement | |
water_temperature | |
air_temperature | |
fiveday_discharge | |
decade_temperature | |
monthly_temperature | |
decade_precipitation | |
monthly_precipitation | |
discharge_historical_decade_average |
Available filters are described here:
Parameter | Type | Description |
---|---|---|
data_value |
float , optional |
Only include data with specified data value |
data_value__ne |
float , optional |
Excludes the specified data value |
data_value__gt |
float , optional |
Data values greater than the specified value |
data_value__gte |
float , optional |
Data values greater than or equal to the specified value |
data_value__lt |
float , optional |
Data values less than the specified value |
data_value__lte |
float , optional |
Data values less than or equal to the specified value |
data_value__isnull |
bool , optional |
Whether the data value is null |
data_value__is_no_data_value |
bool , optional |
Whether the data value is not a data value |
local_date_time |
datetime , optional |
Specific local date and time to filter the results |
local_date_time__gt |
datetime , optional |
Local date and time greater than the specified value |
local_date_time__gte |
datetime , optional |
Local date and time greater than or equal to the specified value |
local_date_time__lt |
datetime , optional |
Local date and time less than the specified value |
local_date_time__lte |
datetime , optional |
Local date and time less than or equal to the specified value |
utc_date_time |
datetime , optional |
Specific UTC date and time to filter the results |
utc_date_time__gt |
datetime , optional |
UTC date and time greater than the specified value |
utc_date_time__gte |
datetime , optional |
UTC date and time greater than or equal to the specified value |
utc_date_time__lt |
datetime , optional |
UTC date and time less than the specified value |
utc_date_time__lte |
datetime , optional |
UTC date and time less than or equal to the specified value |
order_by |
str , optional |
Name of the column we want to order data. Suported ordering local_date_time and -local_date_time |
The method is returning dictionary with the following structure:
{
'site': {
'name': 'р.Ак-Суу с.Чон-Арык',
'region': 'ЧУЙСКАЯ ОБЛАСТЬ',
'site_code': '15212',
'basin': 'Чу',
'longitude': 74.008333,
'latitude': 42.613889
},
'variable': {
'variable_code': '0020',
'variable_name': 'Discharge',
'unit': 'm^3/s',
'variable_type': 'discharge_historical_decade_average'
},
'data_values': [
{
'data_value': 2.02,
'local_date_time': datetime .datetime (2013, 1, 5, 13, 0),
'utc_date_time': datetime .datetime (2013, 1, 5, 13, 0)
},
{
'data_value': 1.88,
'local_date_time': datetime .datetime (2013, 1, 15, 13, 0),
'utc_date_time': datetime .datetime (2013, 1, 15, 13, 0)
},
{
'data_value': 1.69,
'local_date_time': datetime .datetime (2013, 1, 25, 13, 0),
'utc_date_time': datetime .datetime (2013, 1, 25, 13, 0)
},
]
}