<jupyter_start><jupyter_text>![image](https://github.com/eWaterCycle/ewatercycle/raw/main/docs/examples/logo.png)  Case study 2: Hello worlds. Run two models on the same forcing data and compare output (discharge)This notebooks demonstrates how to use models in eWaterCycle by showing how to run two different models for the same region (Merrimack) and on the same forcing data (ERA5: 1990). In this notebook, in contrast with the `Case1_Marrmot_Merrimack_ESMValTool` notebook, two distributed models are used. The models used in this notebook are:- WFlow (Schellekens et. al. 2020, [https://doi.org/10.5281/ZENODO.593510](https://doi.org/10.5281/ZENODO.593510))- LISFLood (<NAME> et. al. 2010, [https://doi.org/10.1080/13658810802549154](https://doi.org/10.1080/13658810802549154))The pre-processing (ie. generating forcing data) for this experiment was already done. For information on how to generate forcing data for a given combination of model, forcing dataset and time period, see the notebook titled `Case1_Marrmot_Merrimack_ESMValTool` in this repo.  Import statementsWe'll be using the following modules<jupyter_code>import warnings
warnings.filterwarnings("ignore", category=UserWarning)

import pandas as pd
from cartopy.io import shapereader

import ewatercycle.forcing
import ewatercycle.models
import ewatercycle.analysis
import ewatercycle.observation.grdc<jupyter_output><empty_output><jupyter_text>Experiment settingsJust like in `Case1_Marrmot_Merrimack_ESMValTool` the Merrimack will be used.<jupyter_code>experiment_start_date = "1990-01-01T00:00:00Z"
experiment_end_date = "1990-12-31T00:00:00Z"

# GRDC observation station for Merrimack river
grdc_station_id = "4147380"<jupyter_output><empty_output><jupyter_text>Observation<jupyter_code># Get grdc observations at 4147380 station related to Merrimack
df, metadata = ewatercycle.observation.grdc.get_grdc_data(
    station_id=grdc_station_id,
    start_time=experiment_start_date,
    end_time=experiment_end_date,
)

# Get lat/lon of the station
station_lat = [metadata["grdc_latitude_in_arc_degree"]]
station_lon = [metadata["grdc_longitude_in_arc_degree"]]

# Convert it to dataframe and rename it to GRDC
observations = df.rename(columns={"streamflow": "GRDC"})
observations<jupyter_output>GRDC station 4147380 is selected. The river name is: MERRIMACK RIVER.The coordinates are: (42.6459, -71.2984).The catchment area in km2 is: 12004.7. There are 0 missing values during 1990-01-01T00:00:00Z_1990-12-31T00:00:00Z at this station. See the metadata for more information.<jupyter_text>Wflow  Load forcing dataHere we use pre-generated forcing data. Although data is available for 1990-2001, we will only need the first year.<jupyter_code>experiment_forcing_wflow = ewatercycle.forcing.load('/mnt/data/forcing/wflow_ERA5_1990-2001_merrimack')
print(experiment_forcing_wflow)<jupyter_output>Forcing data for Wflow
----------------------
Directory: /mnt/data/forcing/wflow_ERA5_1990-2001_merrimack
Start time: 1990-01-01T12:00:00Z
End time: 2001-12-31T12:00:00Z
Shapefile: None
Additional information for model config:
  - netcdfinput: wflow_ERA5_Merrimack_1990_2001.nc
  - Precipitation: /pr
  - Temperature: /tas
  - EvapoTranspiration: /pet
  - Inflow: None<jupyter_text>Load parameterset<jupyter_code>experiment_parameterset_wflow = ewatercycle.parameter_sets.get_parameter_set('wflow_merrimack_techpaper')
print(experiment_parameterset_wflow)<jupyter_output>Parameter set
-------------
name=wflow_merrimack_techpaper
directory=/mnt/data/parameter-sets/wflow_merrimack_techpaper
config=/mnt/data/parameter-sets/wflow_merrimack_techpaper/wflow_sbm_era5_test.ini
doi=N/A
target_model=wflow
supported_model_versions={'2020.1.1'}<jupyter_text>Set up the model<jupyter_code>ewatercycle.models.Wflow.available_versions
model = ewatercycle.models.Wflow(version='2020.1.1', parameter_set=experiment_parameterset_wflow, 
                                 forcing=experiment_forcing_wflow)<jupyter_output>Config file from parameter set is missing RiverRunoff option in API section, added it with value '2, m/s option'<jupyter_text>Forcing time range is 1990-2001, but we want to run the model for the year 1990, so set `end_time` in setup() function:<jupyter_code>cfg_file, cfg_dir = model.setup(end_time=experiment_end_date)
print(cfg_file)
print(cfg_dir)
# Initialize
model.initialize(cfg_file)
# Get metadata
model.output_var_names<jupyter_output><empty_output><jupyter_text>Run the modelWe store discharge and time values. For time, only date part is kept using the function `date()`. So, we can create a dataframe joining the data on date later for the hydrograph. Wflow has steps at noon, while GRDC and lisflood uses midnight.<jupyter_code>discharge = []
time_range = []

while model.time < model.end_time:
    model.update()
    # Get Discharge at one location
    discharge_at_pixel = model.get_value_at_coords('RiverRunoff', lon=station_lon, lat=station_lat)[0]
    discharge.append(discharge_at_pixel)
    time_range.append(model.time_as_datetime.date())
    print(model.time_as_isostr, end="\r")
# Stop the model
model.finalize()
# Concatenate timeseries
wflow = pd.DataFrame({'wflow': discharge}, index=pd.to_datetime(time_range))
wflow<jupyter_output><empty_output><jupyter_text>Lisflood  Load forcing dataPre-generated lisflood forcing data is available for the year 1990. It is a global file, where all but the Merrimack catchment (and a few others that are irrelevant for this example) are masked.<jupyter_code>experiment_forcing_lisflood = ewatercycle.forcing.load('/mnt/data/forcing/lisflood_ERA5_1990_global-masked')
print(experiment_forcing_lisflood)<jupyter_output>eWaterCycle forcing
-------------------
start_time=1990-01-01T12:00:00Z
end_time=1990-12-31T12:00:00Z
shape=None
PrefixPrecipitation=lisflood_ERA5_pr_1990_1990.nc
PrefixTavg=lisflood_ERA5_tas_1990_1990.nc
PrefixE0=lisflood_ERA5_e0_1990_1990.nc
PrefixES0=lisflood_ERA5_es0_1990_1990.nc
PrefixET0=lisflood_ERA5_et0_1990_1990.nc
directory=/mnt/data/forcing/lisflood_ERA5_1990_global-masked<jupyter_text>Load parameter set<jupyter_code>experiment_parameterset_lisflood = ewatercycle.parameter_sets.get_parameter_set('lisflood_global-masked_01degree')
print(experiment_parameterset_lisflood)<jupyter_output>Parameter set
-------------
name=lisflood_global-masked_01degree
directory=/mnt/data/parameter-sets/lisflood_global-masked_01degree
config=/mnt/data/parameter-sets/lisflood_global-masked_01degree/settings_lisflood_ERA5.xml
doi=N/A
target_model=lisflood
supported_model_versions={'20.10'}<jupyter_text>Set up the model<jupyter_code>ewatercycle.models.Lisflood.available_versions
model = ewatercycle.models.Lisflood(version='20.10', parameter_set=experiment_parameterset_lisflood, 
                                    forcing=experiment_forcing_lisflood)
print(model)
# Lisflood requires a mask map, in this case only the Merrimack is unmasked
model_mask = 'settingFiles/lisflood_model_mask.nc'

config_file, config_dir = model.setup(end_time=experiment_end_date, MaskMap=model_mask)
print(config_file)
print(config_dir)
# Initialize 
model.initialize(config_file)

# Get metadata
model.output_var_names<jupyter_output><empty_output><jupyter_text>Run the modelThe model is masked by the Merrimack catchment shapefile. However, GRDC station (-71.2984, 42.6459) is located outside of the catchment boundary. Therefore, the model returns none value at these coordinates. Here, we use the coordinates (-71.35, 42.65) inside the catchment given by lisflood modelers that is close to the GRDC station.<jupyter_code>model_lon = [-71.35]
model_lat = [42.65]
discharge = []
time_range = []

while model.time < model.end_time:
    model.update()
    # Get Discharge at one location
    discharge_at_pixel = model.get_value_at_coords('Discharge', lon=model_lon, lat=model_lat)[0]
    discharge.append(discharge_at_pixel)
    time_range.append(model.time_as_datetime.date())
    print(model.time_as_isostr, end="\r")
# Stop the model
model.finalize()
lisflood = pd.DataFrame({'lisflood': discharge}, index=pd.to_datetime(time_range))
lisflood<jupyter_output><empty_output><jupyter_text>Hydrograph<jupyter_code># Combine simulated and observed values to one dataframe according to time axis
hydro_data = pd.concat([wflow, lisflood, observations], axis=1)

# Plot hydrograph and show metrics
ewatercycle.analysis.hydrograph(hydro_data, reference='GRDC', filename = 'figures/case2_HelloWorldsHydrograph.png')<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09508080688922968, 'fraction_numerical': 0.04895599858440486, 'mean_word_length': 6.372173913043478, 'pattern_counts': {'":': 1, '<': 50, '<?xml version=': 0, '>': 48, 'https://': 5, 'lorem ipsum': 0, 'www.': 0, 'xml': 1}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '89943', 'license': 'Apache-2.0', 'n_tokens_mistral': 3189, 'n_tokens_neox': 2830, 'n_words': 627, 'path': 'Case2_wflow_LISFlood_merrimack_inc_ESMValtool.ipynb', 'repo_name': 'eWaterCycle/technicalPaperExampleNotebooks', 'size': '8485'}