From 7c97f8bb5e1e8f4df2539022a095f793c163c05a Mon Sep 17 00:00:00 2001 From: Jannis Hoch Date: Thu, 28 Jun 2018 15:35:01 +0200 Subject: [PATCH 1/5] fixing code to initialize par-file via config --- couplingFramework_PCR_to_LFP.ipynb | 69 +++++++++++++----------------- glofrim-py/glofrim/glofrim_lfp.py | 10 +++-- glofrim-py/glofrim/main.py | 15 +++---- 3 files changed, 41 insertions(+), 53 deletions(-) diff --git a/couplingFramework_PCR_to_LFP.ipynb b/couplingFramework_PCR_to_LFP.ipynb index 9a60422..7517fe3 100644 --- a/couplingFramework_PCR_to_LFP.ipynb +++ b/couplingFramework_PCR_to_LFP.ipynb @@ -144,41 +144,7 @@ "/home/jannis/Programmes/lisflood-bmi-v5.9/liblisflood.so\n", "/home/jannis/PhD/code/GLOFRIMplusCAMA/model_test_data/test_Elbe/LFP_data\n", "/home/jannis/PhD/code/GLOFRIMplusCAMA/model_test_data/test_Elbe/LFP_data/LFPmodel_Elbe.par\n", - "/home/jannis/PhD/code/GLOFRIMplusCAMA/output30min/PCR2LFP/LFP\n", - "[dummysection]\n", - "DEMfile LFP_Elbe_DEM_2km.asc\t# provide DEM file\n", - "resroot res\t\t\t\t\t# prefix of output files\n", - "dirroot results_Elbe_2km\t\t# output folder name\n", - "sim_time 220838.0\t\t\t\t# total simulation time\n", - "initial_tstep 500\t\t\t\t\t# intial solver time step\n", - "massint 86400.0\t\t\t\t# interval of time series output\n", - "saveint 864000.0\t\t\t\t# interval of map output\n", - "bcifile LFPmodel_Elbe_BCs.bci\t# file containing boundary condition information\n", - "SGCwidth LFP_Elbe_WIDTH_2km.asc\t# privde widhts of channels\n", - "SGCbank LFP_Elbe_DEM_2km.asc\t# provide elevation of river banks\n", - "SGCbed LFP_Elbe_DEPTH_2km.asc\t# provide surface elevation of river bed\n", - "gaugefile NeuDarchau.gauge\t\t# provide location of discharge measurements\n", - "fpfric 0.05\t\t\t\t\t# floodplain friction\n", - "SGCn 0.035\t\t\t\t\t# sub-grid channel friction\n", - "SGCr 0.15\t\t\t\t\t# parameter to determine river geometry\n", - "SGCp 0.65\t\t\t\t\t# parameter to determine river geometry\n" - ] - }, - { - "ename": "ParsingError", - "evalue": "Source contains parsing errors: u'/home/jannis/PhD/code/GLOFRIMplusCAMA/model_test_data/test_Elbe/LFP_data/tmp.par'\n\t[line 2]: u'DEMfile LFP_Elbe_DEM_2km.asc\\t# provide DEM file\\n'\n\t[line 3]: u'resroot res\\t\\t\\t\\t\\t# prefix of output files\\n'\n\t[line 4]: u'dirroot results_Elbe_2km\\t\\t# output folder name\\n'\n\t[line 5]: u'sim_time 220838.0\\t\\t\\t\\t# total simulation time\\n'\n\t[line 6]: u'initial_tstep 500\\t\\t\\t\\t\\t# intial solver time step\\n'\n\t[line 7]: u'massint 86400.0\\t\\t\\t\\t# interval of time series output\\n'\n\t[line 8]: u'saveint 864000.0\\t\\t\\t\\t# interval of map output\\n'\n\t[line 9]: u'bcifile LFPmodel_Elbe_BCs.bci\\t# file containing boundary condition information\\n'\n\t[line 10]: u'SGCwidth LFP_Elbe_WIDTH_2km.asc\\t# privde widhts of channels\\n'\n\t[line 11]: u'SGCbank LFP_Elbe_DEM_2km.asc\\t# provide elevation of river banks\\n'\n\t[line 12]: u'SGCbed LFP_Elbe_DEPTH_2km.asc\\t# provide surface elevation of river bed\\n'\n\t[line 13]: u'gaugefile NeuDarchau.gauge\\t\\t# provide location of discharge measurements\\n'\n\t[line 14]: u'fpfric 0.05\\t\\t\\t\\t\\t# floodplain friction\\n'\n\t[line 15]: u'SGCn 0.035\\t\\t\\t\\t\\t# sub-grid channel friction\\n'\n\t[line 16]: u'SGCr 0.15\\t\\t\\t\\t\\t# parameter to determine river geometry\\n'\n\t[line 17]: u'SGCp 0.65\\t\\t\\t\\t\\t# parameter to determine river geometry'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mParsingError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m LFP_bmi = LFP_model(LFP_engine, LFP_config_fn, LFP_model_dir, LFP_out_dir,\n\u001b[0;32m---> 12\u001b[0;31m start_date, end_date)\n\u001b[0m", - "\u001b[0;32m/home/jannis/PhD/code/GLOFRIMplusCAMA/glofrim/glofrim-py/glofrim/glofrim_lfp.pyc\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, engine, config_fn, model_data_dir, out_dir, start_date, end_date, missing_value, **kwargs)\u001b[0m\n\u001b[1;32m 46\u001b[0m \u001b[0moptions\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mconfigparser\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mconfigparser\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 47\u001b[0m \u001b[0msi_unit_conversions\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0msi_unit_conversions\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 48\u001b[0;31m **kwargs)\n\u001b[0m\u001b[1;32m 49\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 50\u001b[0m \u001b[0;31m# set some basic model properties\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/jannis/PhD/code/GLOFRIMplusCAMA/glofrim/glofrim-py/glofrim/main.py\u001b[0m in \u001b[0;36m__init__\u001b[0;34m(self, bmi, config_fn, name, t_unit, model_data_dir, forcing_data_dir, out_dir, options, configparser, si_unit_conversions, **kwargs)\u001b[0m\n\u001b[1;32m 40\u001b[0m \u001b[0mmkdir\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mout_dir\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 41\u001b[0m \u001b[0;31m# first step of two step initialization.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 42\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minitialize_config\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 43\u001b[0m \u001b[0;31m# second step is not yet performed\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 44\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minitialized\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mFalse\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/jannis/PhD/code/GLOFRIMplusCAMA/glofrim/glofrim-py/glofrim/main.py\u001b[0m in \u001b[0;36minitialize_config\u001b[0;34m(self, config_fn, **kwargs)\u001b[0m\n\u001b[1;32m 93\u001b[0m \t\t\tself.model_config = config_to_dict(self.config_fn,\n\u001b[1;32m 94\u001b[0m \u001b[0mcf\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_configparser\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 95\u001b[0;31m **kwargs) # create dictionary\n\u001b[0m\u001b[1;32m 96\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 97\u001b[0m \u001b[0;31m#os.remove(tmpFile)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/jannis/PhD/code/GLOFRIMplusCAMA/glofrim/glofrim-py/glofrim/utils.pyc\u001b[0m in \u001b[0;36mconfig_to_dict\u001b[0;34m(config_fn, encoding, cf)\u001b[0m\n\u001b[1;32m 93\u001b[0m \u001b[0mcf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0moptionxform\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mstr\u001b[0m \u001b[0;31m# preserve capital letter\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 94\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mcodecs\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mopen\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mconfig_fn\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'r'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mencoding\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mencoding\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mfp\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 95\u001b[0;31m \u001b[0mcf\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_file\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfp\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 96\u001b[0m out_dict = OrderedDict((sec, OrderedDict((opt, cf.get(sec, opt))\n\u001b[1;32m 97\u001b[0m for opt in cf.options(sec)))\n", - "\u001b[0;32m/home/jannis/anaconda2/lib/python2.7/site-packages/backports/configparser/__init__.pyc\u001b[0m in \u001b[0;36mread_file\u001b[0;34m(self, f, source)\u001b[0m\n\u001b[1;32m 722\u001b[0m \u001b[0;32mexcept\u001b[0m \u001b[0mAttributeError\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 723\u001b[0m \u001b[0msource\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m''\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 724\u001b[0;31m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_read\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msource\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 725\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 726\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mread_string\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstring\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0msource\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m''\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/jannis/anaconda2/lib/python2.7/site-packages/backports/configparser/__init__.pyc\u001b[0m in \u001b[0;36m_read\u001b[0;34m(self, fp, fpname)\u001b[0m\n\u001b[1;32m 1129\u001b[0m \u001b[0;31m# if any parsing errors occurred, raise an exception\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1130\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1131\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0me\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1132\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_join_multiline_values\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1133\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mParsingError\u001b[0m: Source contains parsing errors: u'/home/jannis/PhD/code/GLOFRIMplusCAMA/model_test_data/test_Elbe/LFP_data/tmp.par'\n\t[line 2]: u'DEMfile LFP_Elbe_DEM_2km.asc\\t# provide DEM file\\n'\n\t[line 3]: u'resroot res\\t\\t\\t\\t\\t# prefix of output files\\n'\n\t[line 4]: u'dirroot results_Elbe_2km\\t\\t# output folder name\\n'\n\t[line 5]: u'sim_time 220838.0\\t\\t\\t\\t# total simulation time\\n'\n\t[line 6]: u'initial_tstep 500\\t\\t\\t\\t\\t# intial solver time step\\n'\n\t[line 7]: u'massint 86400.0\\t\\t\\t\\t# interval of time series output\\n'\n\t[line 8]: u'saveint 864000.0\\t\\t\\t\\t# interval of map output\\n'\n\t[line 9]: u'bcifile LFPmodel_Elbe_BCs.bci\\t# file containing boundary condition information\\n'\n\t[line 10]: u'SGCwidth LFP_Elbe_WIDTH_2km.asc\\t# privde widhts of channels\\n'\n\t[line 11]: u'SGCbank LFP_Elbe_DEM_2km.asc\\t# provide elevation of river banks\\n'\n\t[line 12]: u'SGCbed LFP_Elbe_DEPTH_2km.asc\\t# provide surface elevation of river bed\\n'\n\t[line 13]: u'gaugefile NeuDarchau.gauge\\t\\t# provide location of discharge measurements\\n'\n\t[line 14]: u'fpfric 0.05\\t\\t\\t\\t\\t# floodplain friction\\n'\n\t[line 15]: u'SGCn 0.035\\t\\t\\t\\t\\t# sub-grid channel friction\\n'\n\t[line 16]: u'SGCr 0.15\\t\\t\\t\\t\\t# parameter to determine river geometry\\n'\n\t[line 17]: u'SGCp 0.65\\t\\t\\t\\t\\t# parameter to determine river geometry'" + "/home/jannis/PhD/code/GLOFRIMplusCAMA/output30min/PCR2LFP/LFP\n" ] } ], @@ -206,7 +172,16 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, + "metadata": {}, + "outputs": [], + "source": [ + "# LFP_bmi.update()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -232,15 +207,29 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 9, "metadata": {}, - "outputs": [], + "outputs": [ + { + "ename": "IndexError", + "evalue": "index 16 is out of bounds for axis 0 with size 14", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# get coupled dictionaries\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mPCR_bmi\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcouple_grid_to_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mLFP_bmi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;31m# get DFM 1d nodes in local grid coordinates\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mLFP_bmi\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodel_1d_coords\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/jannis/PhD/code/GLOFRIMplusCAMA/glofrim/glofrim-py/glofrim/main.pyc\u001b[0m in \u001b[0;36mcouple_grid_to_1d\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 339\u001b[0m \u001b[0mlogger\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Coupling {} grid to {} 1D nodes.'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 340\u001b[0m \u001b[0;31m# get cell indices at 1D coordinates\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 341\u001b[0;31m \u001b[0mcellidx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalid\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodel_2d_index\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodel_1d_coords\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 342\u001b[0m \u001b[0mrows\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcols\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mcellidx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 343\u001b[0m \u001b[0mrows\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcols\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0matleast_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrows\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0matleast_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcols\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/jannis/PhD/code/GLOFRIMplusCAMA/glofrim/glofrim-py/glofrim/glofrim_pcr.pyc\u001b[0m in \u001b[0;36mmodel_2d_index\u001b[0;34m(self, xy, **kwargs)\u001b[0m\n\u001b[1;32m 113\u001b[0m \u001b[0mlm_map\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpcr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreadmap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_fn_landmask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 114\u001b[0m \u001b[0mlm_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpcr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpcr2numpy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlm_map\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnodata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 115\u001b[0;31m \u001b[0mvalid\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlm_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 116\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalid\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 117\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mIndexError\u001b[0m: index 16 is out of bounds for axis 0 with size 14" + ] + } + ], "source": [ "# get coupled dictionaries\n", - "PCR_bmi.couple_grid_to_1d(DFM_bmi)\n", + "PCR_bmi.couple_grid_to_1d(LFP_bmi)\n", "\n", "# get DFM 1d nodes in local grid coordinates\n", - "x, y = zip(*DFM_bmi.model_1d_coords)\n", + "x, y = zip(*LFP_bmi.model_1d_coords)\n", "c, r = ~PCR_bmi.model_grid_transform * (np.atleast_1d(x), np.atleast_1d(y))\n", "c, r = c-0.5, r-0.5\n", "\n", diff --git a/glofrim-py/glofrim/glofrim_lfp.py b/glofrim-py/glofrim/glofrim_lfp.py index a0df5a7..3fabc71 100644 --- a/glofrim-py/glofrim/glofrim_lfp.py +++ b/glofrim-py/glofrim/glofrim_lfp.py @@ -83,10 +83,11 @@ def get_model_coords(self): logger.info('Getting LFP model coordinates.') i_ind, j_ind = np.where(np.logical_and(self.get_var('SGCwidth') > 0., self.get_var('DEM') != -9999)) - print i_ind.shape, j_ind.shape + # print i_ind.shape, j_ind.shape fn_map = join(self.model_data_dir, - self.model_config['dummysection']['DEMfile']) + self.model_config['header1']['DEMfile']) + if not isfile(fn_map): raise IOError('landmask file not found') self._fn_landmask = fn_map @@ -113,6 +114,7 @@ def get_area_1d(self): class ParConfigParser(ConfigParser): def __init__(self, **kwargs): + self.optionxform = lambda option:option # keep format with capital/lower letters defaults = dict(comment_prefixes=('!', '/', '#'), inline_comment_prefixes=('!'), delimiters=('=')) @@ -133,5 +135,5 @@ def _write_section(self, fp, section_name, section_items, delimiter): for key, value in section_items: value = self._interpolation.before_write(self, section_name, key, value) value = ' ' + str(value).replace('\n', '\n\t') - fp.write("{}{}\n".format(key.upper(), value)) - fp.write("/\n") \ No newline at end of file + fp.write("{}{}\n".format(key, value)) + fp.write("\n") \ No newline at end of file diff --git a/glofrim-py/glofrim/main.py b/glofrim-py/glofrim/main.py index fac2357..2edfcfa 100644 --- a/glofrim-py/glofrim/main.py +++ b/glofrim-py/glofrim/main.py @@ -77,14 +77,10 @@ def write_config(self, **kwargs): """The internal model_config dictionary is written to the out_dir. This step should be excecuted just before the model initialization.""" self.config_fn = join(self.out_dir, basename(self.config_fn)) - #addded if-switch for LFP; 31-May-2018; JMH - if (self.name not in ['LFP']): - dict_to_config(self.model_config, self.config_fn, - cf=self._configparser, **kwargs) - logger.info('Ini file for {:s} written to {:s}'.format(self.name, self.config_fn)) - if (self.name in ['LFP']): - print 'LFP section of write_config' - logger.info('Ini file for {:s} written to {:s}'.format(self.name, self.config_fn)) + + dict_to_config(self.model_config, self.config_fn, cf=self._configparser, **kwargs) + + logger.info('Ini file for {:s} written to {:s}'.format(self.name, self.config_fn)) def set_config(self, model_config): """Change multiple model config file settings with dictionary. @@ -142,7 +138,8 @@ def initialize(self, **kwargs): """ # write possibly updated config file self.write_config() - # initialize model with updated config file + # import pdb; pdb.set_trace() + # initialize model with updated config file self.bmi.initialize(self.config_fn, **kwargs) # set start time attribute self.start_time = self.get_start_time() From cdac67a1888ef1347e09a2bc2d71c11adfed824c Mon Sep 17 00:00:00 2001 From: Jannis Hoch Date: Thu, 28 Jun 2018 17:03:46 +0200 Subject: [PATCH 2/5] now possible to couple 1D LFP with PCR; no updating yet --- couplingFramework_PCR_to_LFP.ipynb | 53 ++++++++++++++++-------------- glofrim-py/glofrim/glofrim_dfm.py | 1 + glofrim-py/glofrim/glofrim_lfp.py | 8 ++--- glofrim-py/glofrim/glofrim_pcr.py | 6 +++- glofrim-py/glofrim/main.py | 3 +- 5 files changed, 41 insertions(+), 30 deletions(-) diff --git a/couplingFramework_PCR_to_LFP.ipynb b/couplingFramework_PCR_to_LFP.ipynb index 7517fe3..bb631de 100644 --- a/couplingFramework_PCR_to_LFP.ipynb +++ b/couplingFramework_PCR_to_LFP.ipynb @@ -175,15 +175,6 @@ "execution_count": 7, "metadata": {}, "outputs": [], - "source": [ - "# LFP_bmi.update()" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], "source": [ "# initialize LFP to expose model coordinates via BMI\n", "LFP_bmi.initialize()" @@ -207,21 +198,35 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": {}, "outputs": [ { - "ename": "IndexError", - "evalue": "index 16 is out of bounds for axis 0 with size 14", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mIndexError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;31m# get coupled dictionaries\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mPCR_bmi\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mcouple_grid_to_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mLFP_bmi\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;31m# get DFM 1d nodes in local grid coordinates\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0my\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mLFP_bmi\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodel_1d_coords\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/jannis/PhD/code/GLOFRIMplusCAMA/glofrim/glofrim-py/glofrim/main.pyc\u001b[0m in \u001b[0;36mcouple_grid_to_1d\u001b[0;34m(self, other)\u001b[0m\n\u001b[1;32m 339\u001b[0m \u001b[0mlogger\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minfo\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Coupling {} grid to {} 1D nodes.'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mother\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mname\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 340\u001b[0m \u001b[0;31m# get cell indices at 1D coordinates\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 341\u001b[0;31m \u001b[0mcellidx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalid\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodel_2d_index\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mother\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mmodel_1d_coords\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 342\u001b[0m \u001b[0mrows\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcols\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mcellidx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 343\u001b[0m \u001b[0mrows\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcols\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0matleast_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrows\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0matleast_1d\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcols\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;32m/home/jannis/PhD/code/GLOFRIMplusCAMA/glofrim/glofrim-py/glofrim/glofrim_pcr.pyc\u001b[0m in \u001b[0;36mmodel_2d_index\u001b[0;34m(self, xy, **kwargs)\u001b[0m\n\u001b[1;32m 113\u001b[0m \u001b[0mlm_map\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpcr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mreadmap\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstr\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_fn_landmask\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 114\u001b[0m \u001b[0mlm_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpcr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mpcr2numpy\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mlm_map\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnodata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 115\u001b[0;31m \u001b[0mvalid\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mlm_data\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 116\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mr\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mc\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalid\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 117\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mIndexError\u001b[0m: index 16 is out of bounds for axis 0 with size 14" + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING: main.couple_grid_to_1d(): 1D nodes found outside of valid 2D domain\n" ] + }, + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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Bk444QT88Ic/jO7zta99DTfffDP27NmDgwcP4rOf/SwA4MEHH8S73vUu/MM//AP27NmDN7zhDTj33HPR19eHZ555BvPnz8e73/1u7N27F29729uwbt262ph333033vve9+KGG27A3r17sWjRIrz5zW/GM888gwcffBCrV6/GXXfdhf379+N73/sepk2b1pLrJSMDGg6EkBFPXx/Q1QUccQTw6U+H9/nKV5L9Hn8ciDyA4xvfAD7zGeD3v2/t/H75y19i8uTJmDRpEiZPnoxvfetb1jm/gcmTJ+PEE0/E3XffjfXr17f03Mcdd1zQg2G46KKLcPLJJ+Pwww/H29/+dtxzzz0AgG9+85s455xzcPbZZ6OzsxMf/vCH8Yc//AGbN2/GnXfeib6+PnzgAx9AZ2cnFixYgDPOOKM25g033ICLL74YL3/5yyEiuOCCC3D44YfjzjvvRGdnJw4dOoRt27ahr68PL3jBCzB9+vSWXjMZXpoyHETk9SLygIg8KCIfadWkCCHE5rHHgC1bEq/D9deH9/nkJ4HnPx94zWuA2bPz2zduBN7zHuCKK4CPfrS18zv++OOxd+9e7Nu3D3v37sVb3/rW2rZ3vOMd2Lt3L37961/jBz/4AV760pe29NzGaInxvOc9r/b+Wc96Fp566ikAwK5du3DiiSfWtokITjjhBPzyl7/Erl27cPzxxzvj2Pvu2LEDK1aswOTJk2sG02OPPYZdu3bh5JNPxuc//3ksX74cU6ZMwbve9S786le/atXlkhFAw4aDiHQAWAXgdQBmAniniLy4VRMjhBDDC14AvOlNwJFHAh//eHif174W2LULuO024LDD8tvNZx0dwPjxgzfXoeQnP/kJdu3ahbPOOqvuY4877rhcX5CdO3fi+OOPx/Of/3w89thjzrZf/OIXtfdTp07Fxz72Mezdu7dmMD311FN4xzveAQA4//zz8cMf/rA2/uWXX173/MjIpRmPwysA/K+q7lDVZwB8HcB5rZkWIYRkdHQAt9wC7N+feA0aoasL+OY3gc9/HrjqqsbGOHToEA4ePFh7+SWTzWLGVVUcPHgQhyJJHU8++SRuv/12vPOd78QFF1yAmTNn1n2ut7/97fjOd76DO+64A319ffjsZz+LI444Al1dXXjlK1+Jww47DF/4whfQ19eHW265BT/+8Y9rx77//e/HtddeW/vs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\n", + "text/plain": [ + "" + ] + }, + "metadata": {}, + "output_type": "display_data" } ], "source": [ @@ -241,15 +246,15 @@ "fig = plt.figure(figsize=(10, 5))\n", "b=fig.add_subplot(1,1,1)\n", "plt.imshow(PCR_bmi.coupled_mask, interpolation='nearest', cmap=cmap, norm=norm)\n", - "PCR_bmi.dd.plot_dd(ax=b, color='grey', label='PCR ldd')\n", - "b.scatter(c, r, s=4, color='b', label='DFM 1D nodes')\n", + "# PCR_bmi.dd.plot_dd(ax=b, color='grey', label='PCR ldd')\n", + "b.scatter(c, r, s=4, color='b', label='LFP 1D nodes')\n", "# fix colorbar\n", "cbar = plt.colorbar()\n", "cbar.set_ticks([0, 1, 2])\n", "cbar.set_ticklabels(['none', 'Runoff', 'Discharge'])\n", "b.set_title('PCR coupled to DFM mask')\n", - "b.set_xlim([4, 13])\n", - "b.set_ylim([7, 1])\n", + "# b.set_xlim([4, 13])\n", + "# b.set_ylim([7, 1])\n", "plt.legend()" ] }, diff --git a/glofrim-py/glofrim/glofrim_dfm.py b/glofrim-py/glofrim/glofrim_dfm.py index ab6064c..1954447 100644 --- a/glofrim-py/glofrim/glofrim_dfm.py +++ b/glofrim-py/glofrim/glofrim_dfm.py @@ -130,3 +130,4 @@ def model_2d_index(self, xy, n=1): #TODO: assess validity based on e.g. max distance valid = np.ones(len(index), dtype=bool) return index, valid + \ No newline at end of file diff --git a/glofrim-py/glofrim/glofrim_lfp.py b/glofrim-py/glofrim/glofrim_lfp.py index 3fabc71..8b1317d 100644 --- a/glofrim-py/glofrim/glofrim_lfp.py +++ b/glofrim-py/glofrim/glofrim_lfp.py @@ -98,16 +98,16 @@ def get_model_coords(self): self.model_grid_bounds = ds.bounds self.model_grid_shape = ds.shape self.model_grid_transform = ds.transform - - list_x_coords, list_y_coords = self.model_grid_transform * (i_ind, j_ind) + list_x_coords, list_y_coords = ds.xy(i_ind, j_ind) self.model_1d_coords = zip(list_x_coords, list_y_coords) - self.model_1d_indices = zip(i_ind, j_ind) + self.model_1d_indices = np.arange(i_ind.size) + self.model_1d_rc = (i_ind, j_ind) pass def get_area_1d(self): - row, col = zip(*self.model_1d_indices) + row, col = self.model_1d_rc area_1D = self.get_var('dA')[row, col] return area_1D diff --git a/glofrim-py/glofrim/glofrim_pcr.py b/glofrim-py/glofrim/glofrim_pcr.py index 770837c..801b64c 100644 --- a/glofrim-py/glofrim/glofrim_pcr.py +++ b/glofrim-py/glofrim/glofrim_pcr.py @@ -109,10 +109,14 @@ def model_2d_index(self, xy, **kwargs): r, c = self.grid_index(*zip(*xy), **kwargs) r = np.array(r).astype(int) c = np.array(c).astype(int) + # check if inside domain + nrows, ncols = self.model_grid_shape + inside = np.logical_and.reduce((r>=0, r=0, c Date: Fri, 29 Jun 2018 14:41:47 +0200 Subject: [PATCH 3/5] reset ipynb --- couplingFramework_PCR_to_DFM.ipynb | 100 +++++------------------------ 1 file changed, 16 insertions(+), 84 deletions(-) diff --git a/couplingFramework_PCR_to_DFM.ipynb b/couplingFramework_PCR_to_DFM.ipynb index 1315b15..7df6357 100644 --- a/couplingFramework_PCR_to_DFM.ipynb +++ b/couplingFramework_PCR_to_DFM.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -21,7 +21,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -33,19 +33,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "2000-01-01 00:00:00\n", - "2001-12-31 00:00:00\n", - "730\n" - ] - } - ], + "outputs": [], "source": [ "# IMPORT MODEL SETTINGS FROM INI-FILE\n", "argv1 = r'couplingSettings.set'\n", @@ -69,18 +59,9 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/home/jannis/PhD/code/GLOFRIMplusCAMA/output30min/PCR2DFM/\n", - "/home/jannis/PhD/code/GLOFRIMplusCAMA/model_test_data/test_Elbe/\n" - ] - } - ], + "outputs": [], "source": [ "# setup output dir\n", "in_dir = options['GENERAL']['inputDir']\n", @@ -100,19 +81,9 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/home/jannis/PhD/code/GLOFRIMplusCAMA/model_test_data/test_Elbe/PCR_Elbe/input30min\n", - "/home/jannis/PhD/code/GLOFRIMplusCAMA/model_test_data/test_Elbe/PCR_Elbe/setup_PCR_30min_Elbe.ini\n", - "/home/jannis/PhD/code/GLOFRIMplusCAMA/output30min/PCR2DFM/PCR\n" - ] - } - ], + "outputs": [], "source": [ "PCR_config_fn = os.path.join(in_dir, options['hydrologic_model']['config_file'])\n", "PCR_in_dir = os.path.join(os.path.dirname(PCR_config_fn), 'input30min')\n", @@ -134,20 +105,9 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "/home/jannis/Programmes/DFLOWFM/lib/libdflowfm.so\n", - "/home/jannis/PhD/code/GLOFRIMplusCAMA/model_test_data/test_Elbe/DFM_Elbe/delta\n", - "/home/jannis/PhD/code/GLOFRIMplusCAMA/model_test_data/test_Elbe/DFM_Elbe/delta/DFM_Elbe_VU.mdu\n", - "/home/jannis/PhD/code/GLOFRIMplusCAMA/output30min/PCR2DFM/DFM\n" - ] - } - ], + "outputs": [], "source": [ "DFM_engine = options['DFM_engine']['DFM_path']\n", "DFM_config_fn = os.path.join(in_dir, options['hydrodynamic_model']['model_file'])\n", @@ -172,7 +132,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -198,37 +158,9 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "WARNING: main.couple_grid_to_1d(): 1D nodes found outside of valid 2D domain\n" - ] - }, - { - "data": { - "text/plain": [ - "" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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X/3qV3z88ceICKWlpT0e+8EHHzBs2DB2795Neno6f/nLXygsLOz1mh988AEOh4Mrr7wSgAULFjBr1qyu7c8++ywXX3wxU6ZMAaC8vJynn366H+9Sqchpy4ZSSkXJiy++SFNTE9XV1TzwwANkZmZSUFAAwNatW3s89qijjqKpqYmdO3dyxhlnsHLlyrCuuXXrVkaOHOn3mm+LyJYtW/xGrowZM0ZrNlTcabKhlFJREuwmPnnyZEaPHu3XtdGT7OxsHn74YZ588knWrl3b6/6lpaXU19f7vfb111/7bd+8eXPX89raWq3ZUHGnyYZSSsXY3Xffza233sqSJUtobW3FGMN7773HT3/606D75+fn8+Mf/zisYb1HHXUUaWlpPPDAAzgcDpYtW8ZHH33Utf373/8+jz/+OF999RVtbW3ccsstUXtfSoVLkw2llIqCnloLFixYwDPPPMOf//xnRo4cyfDhw7nxxhs588wzQx5z1VVXsXz58q4RLaGkp6ezbNkyHnvsMQoKCnj22Wf9ilFPPvlkfv7zn3P88cdTVlbGvHnzIn9zSvWTRKvvTkSMMWuici6llApGZKbWGyhEhGD3G/f3I259RCJiyimL+LhyKuIaZzJIidEornt+nugQ9ju2a+5LdAhKKaUGCO1GUUoppVRMabKhlFJKqZjSZEMppZRSMaXJhlJKKaViSpMNpZRSSsWUJhtKKaWUiilNNpRSSikVU5psKKWUiplx48bx1ltvJToMlWCabCilVBSMHTuW7Oxs8vLyGDZsGMcccwyLFy/2m/H04osvJjMzkyFDhjB48GCGDBnCs88+23X8oEGDaGpq8jvvjBkzsNlsfour+Xr22Wc5+uijycnJ4fjjj/fbVltbi81mY8iQIQwZMoTS0lLOOOMM3njjjSi/e6V6psmGUkpFgYjw6quvsmvXLmpra/mf//kf7rjjDi655BK//a677jpaWlpobW2lpaWFc845p+v4cePG8be//a1r33Xr1tHe3t7juisFBQVcffXV/OpXvwoZ165du2hpaWHt2rWccMIJzJ8/nyeeeCIK71qp8GiyoZTaLxgDTU3W79hdwzr54MGDOe2003jmmWdYsmQJX375ZVjHL1y4kCVLlnQ9X7JkCRdeeGGPxxx//PGcffbZlJaW9hpXcXExV155JeXl5Vx33XUh97fZbCxevJiysjKG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\n", - "text/plain": [ - "" - ] - }, - "metadata": {}, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "# get coupled dictionaries\n", "PCR_bmi.couple_grid_to_1d(DFM_bmi)\n", @@ -449,9 +381,9 @@ "metadata": { "anaconda-cloud": {}, "kernelspec": { - "display_name": "Python [default]", + "display_name": "Python [conda env:glofrim]", "language": "python", - "name": "python2" + "name": "conda-env-glofrim-py" }, "language_info": { "codemirror_mode": { @@ -463,7 +395,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", - "version": "2.7.15" + "version": "2.7.14" } }, "nbformat": 4, From 4bce13930a7fa6e223aa0797bcb16cc5d81ba80a Mon Sep 17 00:00:00 2001 From: DirkEilander Date: Fri, 29 Jun 2018 14:42:18 +0200 Subject: [PATCH 4/5] firt step to better logging --- glofrim-py/glofrim/utils.py | 44 +++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/glofrim-py/glofrim/utils.py b/glofrim-py/glofrim/utils.py index 3179b5a..9714ac8 100644 --- a/glofrim-py/glofrim/utils.py +++ b/glofrim-py/glofrim/utils.py @@ -5,7 +5,51 @@ from configparser import ConfigParser from collections import OrderedDict from subprocess import check_output, STDOUT, CalledProcessError +import logging +import logging.handlers +def setlogger(logfilename,loggername, thelevel=logging.INFO): + """ + Set-up the logging system and return a logger object. Exit if this fails + """ + + try: + #create logger + logger = logging.getLogger(loggername) + if not isinstance(thelevel, int): + logger.setLevel(logging.DEBUG) + else: + logger.setLevel(thelevel) + ch = logging.FileHandler(logfilename,mode='w') + console = logging.StreamHandler() + console.setLevel(logging.DEBUG) + ch.setLevel(logging.DEBUG) + #create formatter + formatter = logging.Formatter( + "%(asctime)s - %(name)s - %(module)s - %(levelname)s - %(message)s") + #add formatter to ch + ch.setFormatter(formatter) + console.setFormatter(formatter) + #add ch to logger + logger.addHandler(ch) + logger.addHandler(console) + logger.debug("File logging to " + logfilename) + return logger + except IOError: + print("ERROR: Failed to initialize logger with logfile: " + logfilename) + sys.exit(2) + +def closeLogger(logger, ch): + logger.removeHandler(ch) + ch.flush() + ch.close() + return logger, ch + +def close_with_error(logger, ch, msg): + logger.error(msg) + logger, ch = closeLogger(logger, ch) + del logger, ch + sys.exit(1) # utils def set_values_in_array(vals, idx, update_vals): From 91ca333e15b392334cb6d98b25aa8b96ec2f0a71 Mon Sep 17 00:00:00 2001 From: DirkEilander Date: Fri, 29 Jun 2018 15:32:01 +0200 Subject: [PATCH 5/5] implemented central logger --- glofrim-py/glofrim/glofrim_cmf.py | 17 ++++++----------- glofrim-py/glofrim/glofrim_dfm.py | 14 ++++---------- glofrim-py/glofrim/glofrim_lfp.py | 8 +------- glofrim-py/glofrim/glofrim_pcr.py | 18 ++++++------------ glofrim-py/glofrim/glofrim_wfl.py | 19 ++++++------------- glofrim-py/glofrim/main.py | 7 +++---- 6 files changed, 26 insertions(+), 57 deletions(-) diff --git a/glofrim-py/glofrim/glofrim_cmf.py b/glofrim-py/glofrim/glofrim_cmf.py index 85d5cd1..62624f6 100644 --- a/glofrim-py/glofrim/glofrim_cmf.py +++ b/glofrim-py/glofrim/glofrim_cmf.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import logging import glob import shutil from os import mkdir, unlink @@ -15,10 +14,6 @@ from main import BMI_model_wrapper from utils import subcall -log_fmt = '%(asctime)s - %(levelname)s - %(message)s' -logging.basicConfig(level=logging.INFO, format=log_fmt, filemode='w') -logger = logging.getLogger(__name__) - class CMF_model(BMI_model_wrapper): def __init__(self, engine, config_fn, model_data_dir, out_dir, @@ -81,7 +76,7 @@ def set_model_input_files(self): shutil.copy(src_fn, dst_path) # remove *tmp.* files from data_dir if 'tmp.' in basename(src_fn): - logger.info('removing tmp file {:s} from model data dir'.format(basename(src_fn))) + self.logger.info('removing tmp file {:s} from model data dir'.format(basename(src_fn))) unlink(src_fn) # update config_fn self.update_config(sec, opt, '"./{}/{}"'.format(folder, fn)) @@ -101,7 +96,7 @@ def set_inpmat_file(self, bounds, res, olat='NtoS'): # generate inpmat msg2 = './generate_inpmat {} {} {} {} {} {:s}'.format( abs(res[0]), westin, eastin, northin, southin, olat) - logger.info(msg2) + self.logger.info(msg2) subcall(msg2, cwd=ddir) # set new inpmat and diminfo in config rel_path = relpath(dirname(self.config_fn), ddir) @@ -132,7 +127,7 @@ def get_model_grid(self): """ from nb.dd_ops import NextXY - logger.info('Getting CMF model grid parameters.') + self.logger.info('Getting CMF model grid parameters.') fn_lsmask = join(self.model_data_dir, 'lsmask.tif') if not isfile(fn_lsmask): raise IOError("lsmask.tif file not found at {}".format(fn_lsmask)) @@ -144,10 +139,10 @@ def get_model_grid(self): self.model_grid_transform = ds.transform self._fn_landmask = fn_lsmask msg = 'Model bounds {:s}; width {}, height {}' - logger.debug(msg.format(self.model_grid_bounds, *self.model_grid_shape)) + self.logger.debug(msg.format(self.model_grid_bounds, *self.model_grid_shape)) # read drainage direction data - logger.info('Getting CMF model drainage direction') + self.logger.info('Getting CMF model drainage direction') fn_nextxy = join(self.model_data_dir, 'nextxy.bin') if not isfile(fn_nextxy): raise IOError("nextxy.bin file not found at {}".format(fn_nextxy)) @@ -177,7 +172,7 @@ def model_2d_index(self, xy, **kwargs): indices : list of tuples list of (row, col) index tuples """ - logger.info('Getting CMF model indices for xy coordinates.') + self.logger.info('Getting CMF model indices for xy coordinates.') fn_catmxy = join(self.model_data_dir, 'hires', 'reg.catmxy.tif') if not isfile(fn_catmxy): raise IOError("{} file not found".format(fn_catmxy)) diff --git a/glofrim-py/glofrim/glofrim_dfm.py b/glofrim-py/glofrim/glofrim_dfm.py index 1954447..77acabe 100644 --- a/glofrim-py/glofrim/glofrim_dfm.py +++ b/glofrim-py/glofrim/glofrim_dfm.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import logging import glob import shutil from os import mkdir @@ -13,11 +12,6 @@ from main import BMI_model_wrapper from utils import ConfigParser -log_fmt = '%(asctime)s - %(levelname)s - %(message)s' -logging.basicConfig(level=logging.INFO, format=log_fmt, filemode='w') -logger = logging.getLogger(__name__) - - class DFM_model(BMI_model_wrapper): def __init__(self, engine, config_fn, model_data_dir, out_dir, @@ -76,7 +70,7 @@ def get_model_coords(self): """Get DFM model coordinates for 1D and 2D mesh via BMI. The DFM model should be initialized first in order to access the variables.""" - logger.info('Getting DFM model coordinates.') + self.logger.info('Getting DFM model coordinates.') # define separator between 2D and 1D parts of arrays == lenght of 2d cell points self._1d2d_idx = len(self.get_var('flowelemnode')) x_coords = self.get_var('xz') # x-coords of each cell centre point @@ -96,12 +90,12 @@ def get_area_1d(self): def get_model_1d_index(self): """Creat a spatial index for the 1d coordinates. A model_1d_index attribute funtion is created to find the nearest 1d coordinate tuple""" - logger.info('Constructing spatial index for the 1D coordinates of the DFM model.') + self.logger.info('Constructing spatial index for the 1D coordinates of the DFM model.') # 1d coords n1d = len(self.model_1d_coords) self.model_1d_indices = np.arange(n1d, dtype=np.int32) + self._1d2d_idx # build spatial rtree index of points2 - logger.info('Constructing spatial index for 1D vertices of DFM model') + self.logger.info('Constructing spatial index for 1D vertices of DFM model') self.model_1d_rtree = rtree.index.Index() for i, xy in enumerate(self.model_1d_coords): self.model_1d_rtree.insert(i+n1d, xy) # return index including 2d @@ -117,7 +111,7 @@ def get_model_2d_index(self): A model_2d_index attribute funtion is created to find the nearest 2d cell center""" # build spatial rtree index of 2d coords - logger.info('Constructing spatial index for the 2D mesh of the DFM model') + self.logger.info('Constructing spatial index for the 2D mesh of the DFM model') self.model_2d_rtree = rtree.index.Index() for i, xy in enumerate(self.model_2d_coords): self.model_2d_rtree.insert(i, xy) diff --git a/glofrim-py/glofrim/glofrim_lfp.py b/glofrim-py/glofrim/glofrim_lfp.py index 8b1317d..78b2bd7 100644 --- a/glofrim-py/glofrim/glofrim_lfp.py +++ b/glofrim-py/glofrim/glofrim_lfp.py @@ -1,6 +1,5 @@ # -*- coding: utf-8 -*- -import logging import glob import shutil import os @@ -15,11 +14,6 @@ from bmi.wrapper import BMIWrapper from main import BMI_model_wrapper -log_fmt = '%(asctime)s - %(levelname)s - %(message)s' -logging.basicConfig(level=logging.INFO, format=log_fmt, filemode='w') -logger = logging.getLogger(__name__) - - class LFP_model(BMI_model_wrapper): def __init__(self, engine, config_fn, model_data_dir, out_dir, @@ -80,7 +74,7 @@ def get_model_coords(self): """Get LFP model coordinates for 1D and 2D mesh via BMI. The LFP model should be initialized first in order to access the variables.""" - logger.info('Getting LFP model coordinates.') + self.logger.info('Getting LFP model coordinates.') i_ind, j_ind = np.where(np.logical_and(self.get_var('SGCwidth') > 0., self.get_var('DEM') != -9999)) # print i_ind.shape, j_ind.shape diff --git a/glofrim-py/glofrim/glofrim_pcr.py b/glofrim-py/glofrim/glofrim_pcr.py index 801b64c..83a2096 100644 --- a/glofrim-py/glofrim/glofrim_pcr.py +++ b/glofrim-py/glofrim/glofrim_pcr.py @@ -1,18 +1,11 @@ # -*- coding: utf-8 -*- -import logging from os.path import isdir, join, basename, dirname, abspath, isfile, isabs import numpy as np import rasterio - -from pcrglobwb_bmi_v203 import pcrglobwb_bmi - from main import BMI_model_wrapper from utils import ConfigParser -log_fmt = '%(asctime)s - %(levelname)s - %(message)s' -logging.basicConfig(level=logging.INFO, format=log_fmt, filemode='w') -logger = logging.getLogger(__name__) class PCR_model(BMI_model_wrapper): def __init__(self, config_fn, @@ -21,6 +14,7 @@ def __init__(self, config_fn, missing_value=-999, landmask_mv=255, forcing_data_dir=None, **kwargs): """initialize the PCR-GLOBWB (PCR) model BMI class and model configuration file""" + from pcrglobwb_bmi_v203 import pcrglobwb_bmi # BMIWrapper for PCR model model pcr_bmi = pcrglobwb_bmi.pcrglobwbBMI() # set config parser @@ -60,7 +54,7 @@ def get_model_grid(self): model_grid_shape : tuple model number of rows and cols """ - logger.info('Getting PCR model grid parameters.') + self.logger.info('Getting PCR model grid parameters.') fn_map = join(self.model_config['globalOptions']['inputDir'], self.model_config['globalOptions']['landmask']) if not isfile(fn_map): @@ -73,14 +67,14 @@ def get_model_grid(self): self.model_grid_shape = ds.shape self.model_grid_transform = ds.transform msg = 'Model bounds {:s}; width {}, height {}' - logger.debug(msg.format(self.model_grid_bounds, *self.model_grid_shape)) + self.logger.debug(msg.format(self.model_grid_bounds, *self.model_grid_shape)) pass def get_drainage_direction(self): from nb.nb_io import read_dd_pcraster # read file with pcr readmap nodata = self.options.get('landmask_mv', 255) - logger.info('Getting PCR LDD map.') + self.logger.info('Getting PCR LDD map.') fn_ldd = self.model_config['routingOptions']['lddMap'] if not isabs(fn_ldd): ddir = self.model_config['globalOptions']['inputDir'] @@ -105,7 +99,7 @@ def model_2d_index(self, xy, **kwargs): """ import pcraster as pcr nodata = self.options.get('landmask_mv', 255) - logger.info('Getting PCR model indices of xy coordinates.') + self.logger.info('Getting PCR model indices of xy coordinates.') r, c = self.grid_index(*zip(*xy), **kwargs) r = np.array(r).astype(int) c = np.array(c).astype(int) @@ -143,7 +137,7 @@ def deactivate_routing(self, coupled_indices=None): msg = "Deactivating the LDD is only possible before the model is initialized" raise AssertionError(msg) - logger.info('Editing PCR ldd grid to deactivate routing in coupled cells.') + self.logger.info('Editing PCR ldd grid to deactivate routing in coupled cells.') # get ldd filename from config fn_ldd = self.model_config['routingOptions']['lddMap'] if not isabs(fn_ldd): diff --git a/glofrim-py/glofrim/glofrim_wfl.py b/glofrim-py/glofrim/glofrim_wfl.py index 77d0448..2cbafa1 100644 --- a/glofrim-py/glofrim/glofrim_wfl.py +++ b/glofrim-py/glofrim/glofrim_wfl.py @@ -2,19 +2,12 @@ #TODO: guess the input dir as in PCR has to be set up to work with path of the WFLOW ini-file instead -import logging from os.path import isdir, join, basename, dirname, abspath, isfile, isabs import numpy as np import rasterio - - - from main import BMI_model_wrapper from utils import ConfigParser -log_fmt = '%(asctime)s - %(levelname)s - %(message)s' -logging.basicConfig(level=logging.INFO, format=log_fmt, filemode='w') -logger = logging.getLogger(__name__) class WFL_model(BMI_model_wrapper): @@ -67,7 +60,7 @@ def get_model_grid(self): model_grid_shape : tuple model number of rows and cols """ - logger.info('Getting WFLOW model grid parameters.') + self.logger.info('Getting WFLOW model grid parameters.') fn_map = getattr(self.model_config['model'], 'wflow_subcatch', 'staticmaps/wflow_subcatch.map') if not isabs(fn_map): ddir = self.model_data_dir @@ -82,14 +75,14 @@ def get_model_grid(self): self.model_grid_shape = ds.shape self.model_grid_transform = ds.transform msg = 'Model bounds {:s}; width {}, height {}' - logger.debug(msg.format(self.model_grid_bounds, *self.model_grid_shape)) + self.logger.debug(msg.format(self.model_grid_bounds, *self.model_grid_shape)) pass def get_drainage_direction(self): from nb.nb_io import read_dd_pcraster # read file with pcr readmap nodata = self.options.get('landmask_mv', 255) - logger.info('Getting WFLOW LDD map.') + self.logger.info('Getting WFLOW LDD map.') fn_ldd = getattr(self.model_config['model'], 'wflow_ldd', 'staticmaps/wflow_ldd.map') if not isabs(fn_ldd): ddir = self.model_data_dir @@ -113,7 +106,7 @@ def model_2d_index(self, xy, **kwargs): indices : list of tuples list of (row, col) index tuples """ - logger.info('Getting WFLOW model indices of xy coordinates.') + self.logger.info('Getting WFLOW model indices of xy coordinates.') r, c = self.grid_index(*zip(*xy), **kwargs) r = np.array(r).astype(int) c = np.array(c).astype(int) @@ -163,11 +156,11 @@ def update(self, dt=None, **kwargs): state variables. """ if dt is not None: # by default take internally set dt - logger.warning('dt is not used in the wflow bmi update function') + self.logger.warning('dt is not used in the wflow bmi update function') self.bmi.update() current_time = self.get_current_time() time_step = self.get_time_step() - logger.info( + self.logger.info( "%s -> start_time: %s, current_time %s, timestep %s", self.name, self.start_time, diff --git a/glofrim-py/glofrim/main.py b/glofrim-py/glofrim/main.py index ec5ce9b..b8e22cb 100644 --- a/glofrim-py/glofrim/main.py +++ b/glofrim-py/glofrim/main.py @@ -14,11 +14,8 @@ from bmi.wrapper import BMIWrapper # local libraries -from utils import config_to_dict, dict_to_config, ConfigParser +from utils import config_to_dict, dict_to_config, ConfigParser, setlogger -log_fmt = '%(asctime)s - %(levelname)s - %(message)s' -logging.basicConfig(level=logging.INFO, format=log_fmt, filemode='w') -logger = logging.getLogger(__name__) # wrapper around BMI class BMI_model_wrapper(object): @@ -38,6 +35,8 @@ def __init__(self, bmi, config_fn, name, t_unit, self.out_dir = abspath(out_dir) if not isdir(self.out_dir): mkdir(self.out_dir) + log_fn = join(self.out_dir, 'glofrim_{}.log'.format(self.name)) + self.logger = setlogger(log_fn, self.name, thelevel=logging.INFO) # first step of two step initialization. self.initialize_config() # second step is not yet performed