{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Horizontal conservative interpolation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [],
   "source": [
    "import nes\n",
    "import geopandas as gpd\n",
    "import matplotlib\n",
    "import matplotlib.pyplot as plt\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "countries = gpd.read_file('/gpfs/projects/bsc32/models/NES_tutorial_data/gadm_country_mask/gadm_country_ISO3166.shp')\n",
    "\n",
    "def plot_data(nessy, var_name, zoom=None):\n",
    "    nessy.create_spatial_bounds()\n",
    "    lon_bnds, lat_bnds = nessy.get_spatial_bounds_mesh_format()\n",
    "    \n",
    "    fig, ax = plt.subplots(1, figsize=(19, 7))\n",
    "    plt.pcolormesh(lon_bnds, \n",
    "                   lat_bnds, \n",
    "                   nessy.variables[var_name]['data'].sum(axis=(0, 1)), \n",
    "                   cmap='jet', \n",
    "                   norm=matplotlib.colors.LogNorm())\n",
    "    \n",
    "    countries.plot(ax=ax, facecolor='none', edgecolor='black', linewidth=0.3)\n",
    "    plt.colorbar(ax=ax)\n",
    "    ax.margins(0)\n",
    "    \n",
    "    if zoom is not None:\n",
    "        plt.axis([zoom['x_min'], zoom['x_max'], zoom['y_min'], zoom['y_max']])\n",
    "\n",
    "    return None"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Read data to interpolate"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Global CAMS domain\n",
    "source_path = \"/gpfs/projects/bsc32/models/NES_tutorial_data/nox_no_201505.nc\"\n",
    "var_name = \"nox_no\""
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "source_grid = nes.open_netcdf(path=source_path)\n",
    "source_grid.keep_vars(var_name)\n",
    "source_grid.load()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 265324 characters]\n",
      "text/plain": [
       "<Figure size 1368x504 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_data(source_grid, var_name)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Create destination grid"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [],
   "source": [
    "# CALIOPE EU domain (Lambert Conformal Conic 12x12 Km)\n",
    "\n",
    "lat_1 = 37.\n",
    "lat_2 = 43.\n",
    "lon_0 = -3.\n",
    "lat_0 = 40.\n",
    "nx = 478\n",
    "ny = 398\n",
    "inc_x = 12000\n",
    "inc_y = 12000\n",
    "x_0 = -2131849.000\n",
    "y_0 = -2073137.875\n",
    "\n",
    "dst_nes = nes.create_nes(comm=None, info=False, projection='lcc', \n",
    "                     lat_1=lat_1, lat_2=lat_2, lon_0=lon_0, lat_0=lat_0,\n",
    "                     nx=nx, ny=ny, inc_x=inc_x, inc_y=inc_y, x_0=x_0, y_0=y_0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Interpolation"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1. Create both shapefiles\n",
    "\n",
    "If the shapefiles are not created previous the conservative interpolation they will be created inside the interpolation funcion.\n",
    "\n",
    "Once created is not needed to create them anymore."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 2min 35s, sys: 4.19 s, total: 2min 39s\n",
      "Wall time: 2min 39s\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>geometry</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>FID</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>POLYGON ((-180.00000 -90.00000, -179.89999 -90...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>POLYGON ((-179.90001 -90.00000, -179.80000 -90...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>POLYGON ((-179.80000 -90.00000, -179.70000 -90...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>POLYGON ((-179.70000 -90.00000, -179.59999 -90...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>POLYGON ((-179.60001 -90.00000, -179.50000 -90...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6479995</th>\n",
       "      <td>POLYGON ((179.50000 89.89999, 179.60001 89.899...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6479996</th>\n",
       "      <td>POLYGON ((179.59999 89.89999, 179.70000 89.899...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6479997</th>\n",
       "      <td>POLYGON ((179.70000 89.89999, 179.80000 89.899...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6479998</th>\n",
       "      <td>POLYGON ((179.80000 89.89999, 179.90001 89.899...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>6479999</th>\n",
       "      <td>POLYGON ((179.89999 89.89999, 180.00000 89.899...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>6480000 rows × 1 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                  geometry\n",
       "FID                                                       \n",
       "0        POLYGON ((-180.00000 -90.00000, -179.89999 -90...\n",
       "1        POLYGON ((-179.90001 -90.00000, -179.80000 -90...\n",
       "2        POLYGON ((-179.80000 -90.00000, -179.70000 -90...\n",
       "3        POLYGON ((-179.70000 -90.00000, -179.59999 -90...\n",
       "4        POLYGON ((-179.60001 -90.00000, -179.50000 -90...\n",
       "...                                                    ...\n",
       "6479995  POLYGON ((179.50000 89.89999, 179.60001 89.899...\n",
       "6479996  POLYGON ((179.59999 89.89999, 179.70000 89.899...\n",
       "6479997  POLYGON ((179.70000 89.89999, 179.80000 89.899...\n",
       "6479998  POLYGON ((179.80000 89.89999, 179.90001 89.899...\n",
       "6479999  POLYGON ((179.89999 89.89999, 180.00000 89.899...\n",
       "\n",
       "[6480000 rows x 1 columns]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time source_grid.create_shapefile()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 4.73 s, sys: 33.8 ms, total: 4.77 s\n",
      "Wall time: 4.78 s\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>geometry</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>FID</th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>POLYGON ((-22.40086 19.60176, -22.29505 19.623...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>POLYGON ((-22.29505 19.62375, -22.18918 19.645...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>POLYGON ((-22.18918 19.64562, -22.08325 19.667...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>POLYGON ((-22.08325 19.66739, -21.97728 19.689...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>POLYGON ((-21.97728 19.68903, -21.87124 19.710...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>...</th>\n",
       "      <td>...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>190239</th>\n",
       "      <td>POLYGON ((53.04242 53.74019, 53.18577 53.67835...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>190240</th>\n",
       "      <td>POLYGON ((53.18577 53.67835, 53.32878 53.61636...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>190241</th>\n",
       "      <td>POLYGON ((53.32878 53.61636, 53.47145 53.55421...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>190242</th>\n",
       "      <td>POLYGON ((53.47145 53.55421, 53.61379 53.49191...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>190243</th>\n",
       "      <td>POLYGON ((53.61379 53.49191, 53.75580 53.42946...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>190244 rows × 1 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                 geometry\n",
       "FID                                                      \n",
       "0       POLYGON ((-22.40086 19.60176, -22.29505 19.623...\n",
       "1       POLYGON ((-22.29505 19.62375, -22.18918 19.645...\n",
       "2       POLYGON ((-22.18918 19.64562, -22.08325 19.667...\n",
       "3       POLYGON ((-22.08325 19.66739, -21.97728 19.689...\n",
       "4       POLYGON ((-21.97728 19.68903, -21.87124 19.710...\n",
       "...                                                   ...\n",
       "190239  POLYGON ((53.04242 53.74019, 53.18577 53.67835...\n",
       "190240  POLYGON ((53.18577 53.67835, 53.32878 53.61636...\n",
       "190241  POLYGON ((53.32878 53.61636, 53.47145 53.55421...\n",
       "190242  POLYGON ((53.47145 53.55421, 53.61379 53.49191...\n",
       "190243  POLYGON ((53.61379 53.49191, 53.75580 53.42946...\n",
       "\n",
       "[190244 rows x 1 columns]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "%time dst_nes.create_shapefile()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3. Interpolation"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 5min 38s, sys: 3.55 s, total: 5min 42s\n",
      "Wall time: 5min 43s\n"
     ]
    }
   ],
   "source": [
    "%time interp_nes = source_grid.interpolate_horizontal(dst_nes, kind='Conservative')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 193084 characters]\n",
      "text/plain": [
       "<Figure size 1368x504 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_data(interp_nes, var_name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 268392 characters]\n",
      "text/plain": [
       "<Figure size 1368x504 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_data(interp_nes, var_name, zoom={'x_min': -40, 'x_max': 55, 'y_min': 15, 'y_max':65})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.1 Flux conservative\n",
    "Previous interpolation is wrong due to the fact that the data is in flux units and it has been applied the mass conservative method"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'m-2.kg.s-1'"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "source_grid.variables[var_name]['units']"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 19min 56s, sys: 5.97 s, total: 20min 2s\n",
      "Wall time: 20min 8s\n"
     ]
    }
   ],
   "source": [
    "%time interp_nes = source_grid.interpolate_horizontal(dst_nes, kind='Conservative', flux=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 267912 characters]\n",
      "text/plain": [
       "<Figure size 1368x504 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_data(interp_nes, var_name, zoom={'x_min': -40, 'x_max': 55, 'y_min': 15, 'y_max':65})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 3.2. Creating weight matrix\n",
    "\n",
    "The conservative interpolation takes lot of time to create the corresponding weight matrix.\n",
    "\n",
    "It is possible to create it and then reuse it in twho different ways:\n",
    "\n",
    "1. Save the WeightMatrix in memory\n",
    "2. Save the WeightMatrix in a file"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.2.1 Save Weight Matrix in memory"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 20min 4s, sys: 6.93 s, total: 20min 11s\n",
      "Wall time: 20min 17s\n"
     ]
    }
   ],
   "source": [
    "# Create WM\n",
    "\n",
    "%time wm_nes = source_grid.interpolate_horizontal(dst_nes, kind='Conservative', only_create_wm=True, flux=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 236 ms, sys: 16.9 ms, total: 253 ms\n",
      "Wall time: 252 ms\n"
     ]
    }
   ],
   "source": [
    "# Apply Interpolation\n",
    "\n",
    "%time interp_nes = source_grid.interpolate_horizontal(dst_grid=dst_nes, kind='Conservative', wm=wm_nes)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 267912 characters]\n",
      "text/plain": [
       "<Figure size 1368x504 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_data(interp_nes, var_name, zoom={'x_min': -40, 'x_max': 55, 'y_min': 15, 'y_max':65})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### 3.2.2 Save Weight Matrix in a file"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/gpfs/scratch/bsc32/bsc32538/NES_tests/NES/nes/nc_projections/default_nes.py:2453: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To silence this warning, use `object` by itself. Doing this will not modify any behavior and is safe. \n",
      "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
      "  if var_dtype is np.object:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 20min 4s, sys: 6.55 s, total: 20min 11s\n",
      "Wall time: 20min 17s\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<nes.nc_projections.lcc_nes.LCCNes at 0x7ef6aa8379d0>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# Create WM file\n",
    "\n",
    "%time source_grid.interpolate_horizontal(dst_nes, kind='Conservative', weight_matrix_path=\"WM.nc\", only_create_wm=True, flux=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/gpfs/scratch/bsc32/bsc32538/NES_tests/NES/nes/nc_projections/default_nes.py:1884: DeprecationWarning: `np.object` is a deprecated alias for the builtin `object`. To silence this warning, use `object` by itself. Doing this will not modify any behavior and is safe. \n",
      "Deprecated in NumPy 1.20; for more details and guidance: https://numpy.org/devdocs/release/1.20.0-notes.html#deprecations\n",
      "  if variables[var_name]['dtype'] in [str, np.object]:\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CPU times: user 816 ms, sys: 33.8 ms, total: 850 ms\n",
      "Wall time: 853 ms\n"
     ]
    }
   ],
   "source": [
    "# Apply Interpolation\n",
    "\n",
    "%time interp_nes = source_grid.interpolate_horizontal(dst_grid=dst_nes, kind='Conservative', weight_matrix_path=\"WM.nc\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 267912 characters]\n",
      "text/plain": [
       "<Figure size 1368x504 with 2 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "plot_data(interp_nes, var_name, zoom={'x_min': -40, 'x_max': 55, 'y_min': 15, 'y_max':65})"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
