{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Predefined styles in Magics, ERA5 grib data example"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Magics comes with number of ways to define shading when visualizing your data.  \n",
    "If you want full control you can choose number of levels, the way levels are calculated, contours or no contours, shading or no shading, type of shading, showing grid values or not. Magics doesn't lack number of parameters you can set!\n",
    "\n",
    "Many times, we don't have time to make a style that fits partucular data, we just want to inspect data for further use. For this purpose Magics has built in predefined styles for large number of meteorological and climatological variables."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## First import Magics, cdsapi and the other libraries\n",
    "\n",
    "Aside of Magics, in this Notebook we will use couple of libraries to make work easier.\n",
    "cdsapi to \n",
    "At ECMWF make sure that Magics and cdsapi are loaded.  \n",
    "Documentation about **cdsapi** can be find [here](https://cds.climate.copernicus.eu/api-how-to.com \"CDS API how to\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [],
   "source": [
    "import Magics.macro as magics\n",
    "import cdsapi\n",
    "import datetime\n",
    "import ipywidgets as widgets\n",
    "from ipywidgets import Layout, Button, Box, VBox\n",
    "from cfgrib import xarray_store"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`menus.py` contains the code got menus to choose parameter, type, date and time..  \n",
    "We're just gonna run it here so our nice widgets work, but the code is not important for this excersize."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "505e486768f74f7b94f06f3c0db5dfb6",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Dropdown(description='Group:', options={'Temperature and pressure': ['2m_dewpoint_temperature', '2m_temperatur…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "ef279dd3b8db4cc98e77c1e6a0dd9657",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "VBox(children=(Box(children=(Dropdown(description='Choose parameter:', options=('2m_dewpoint_temperature', '2m…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "%run -i 'menus.py'\n",
    "\n",
    "display(group)\n",
    "display(VBox([box_auto]))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we have code for CDS API request.  \n",
    "It uses parameters we have chosen before, so we don't have to change the code and so we reduce the posibility of an error.  \n",
    "At the moment this request only works for surface fields, and there is separate Notebook for pressure levels fields. In future it might be merged in one Notebook."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 103,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "2018-10-10 11:26:38,649 INFO Sending request to https://cds.climate.copernicus.eu/api/v2/resources/reanalysis-era5-single-levels\n",
      "2018-10-10 11:26:38,705 INFO Request is completed\n",
      "2018-10-10 11:26:38,706 INFO Downloading http://136.156.132.110/cache-compute-0001/cache/data1/adaptor.mars.internal-1539158512.8064556-13067-10-7d719512-c9f1-4922-bcc5-1e77a1221cdf.grib to download.grib (3.1M)\n",
      "2018-10-10 11:26:38,871 INFO Download rate 18.8M/s\n"
     ]
    }
   ],
   "source": [
    "c = cdsapi.Client()\n",
    "\n",
    "a = c.retrieve(\n",
    "    'reanalysis-era5-single-levels',\n",
    "    {\n",
    "        'variable':[\n",
    "            parameters.value\n",
    "        ],\n",
    "            'grid': ['0.2', '0.2'],\n",
    "            'product_type': Type.value,\n",
    "            'year': dates.value.year,\n",
    "            'month': dates.value.month,\n",
    "            'day': dates.value.day,\n",
    "            'time': times.value,\n",
    "        'format':'grib'\n",
    "    },\n",
    "                \"download.grib\"\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load grib data and set area, coaslines and default tittle:\n",
    "More about loading grib files in Magics can be found [here](https://confluence.ecmwf.int/display/MAGP/Grib+Input \"GRIB input\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 104,
   "metadata": {},
   "outputs": [],
   "source": [
    "data =  magics.mgrib(grib_input_file_name  = 'download.grib')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 35,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "fe70c0c42dbf47019242fe64fd01b5fc",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Dropdown(description='Predefined areas:', index=15, options=('north_pole', 'eurasia', 'global', 'south_west_eu…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "areas = magics.predefined_areas()\n",
    "Area = widgets.Dropdown(options=areas, value = 'europe', description='Predefined areas:', style=style)\n",
    "display(Area)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 114,
   "metadata": {},
   "outputs": [],
   "source": [
    "projection = magics.mmap(\n",
    "    subpage_map_library_area = \"on\",\n",
    "    subpage_map_area_name = Area.value\n",
    ")\n",
    "\n",
    "coast = magics.mcoast(map_grid =  \"on\",\n",
    "                      map_grid_colour  =  \"charcoal\",\n",
    "                      map_coastline  =  'on',\n",
    "                      map_coastline_colour =  'navy',\n",
    "                      map_boundaries = 'on',\n",
    "                      map_boundaries_colour = 'navy',\n",
    "                      map_coastline_resolution = 'high'\n",
    "            )\n",
    "title = magics.mtext()\n",
    "legend = magics.mlegend(legend_display_type = \"continuous\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Load predefined ECMWF contour setting:\n",
    "Setting the parameter **contour_automatic_setting** to **'ecmwf'** will give us style developed at ECMWF for this parameter.  \n",
    "\n",
    "More about contour settings in Magics can be found [here](https://confluence.ecmwf.int/display/MAGP/Contouring \"Contouring\")  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 115,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 154652 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 115,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contour = magics.mcont(contour_automatic_setting = 'ecmwf')\n",
    "\n",
    "magics.plot(projection, data, contour, legend, coast, title)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### How does Magics know which default style to apply?\n",
    "\n",
    "Magics scans grib message and looks for specific combinations of grib keys. If more styles are found, Magics will choose the one with more keys matched. \n",
    "\n",
    "Grib keys that Magics is looking at are: shortName, paramId, type, levtype and levelist."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 95,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "shortName = lcc\n",
      "paramId = 186\n",
      "typeOfLevel = surface\n"
     ]
    }
   ],
   "source": [
    "ds = xarray_store.open_dataset('download.grib')\n",
    "\n",
    "ds.lcc.attrs\n",
    "lcc_atrrs = ds.lcc.attrs\n",
    "print('shortName =',lcc_atrrs['GRIB_shortName'])\n",
    "print('paramId =',lcc_atrrs['GRIB_paramId'])\n",
    "print('typeOfLevel =',lcc_atrrs['GRIB_typeOfLevel'])\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Some ERA5 parameters (that have representation in ecCharts) have more than one built in predefined styles.  \n",
    "Run the next cell and choose a style."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 106,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "application/vnd.jupyter.widget-view+json": {
       "model_id": "eccea7e9867f492c86b9727e02bf58a7",
       "version_major": 2,
       "version_minor": 0
      },
      "text/plain": [
       "Dropdown(description='Choose a style:', options=('sh_all_fM48t56i4', 'sh_all_fM64t52i4', 'ct_red_i2_dash', 'sh…"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "styles = magics.wmsstyles(data, )\n",
    "all_styles = []\n",
    "for i in styles['styles']:\n",
    "    all_styles.append(i[\"name\"])\n",
    "\n",
    "One_style = widgets.Dropdown(options=all_styles, value = all_styles[0], description='Choose a style:', style=style)\n",
    "display(One_style)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To use this new feature we need to set the parameter **contour_automatic_setting** to **'style_name'**, and add a new parameter **contour_style_name** with the chosen style. In this example it takes value choosen by the previous menu."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 117,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 241528 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 117,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contour = magics.mcont(contour_automatic_setting = 'style_name',\n",
    "                      contour_style_name = One_style.value,\n",
    "                      legend = 'on')\n",
    "\n",
    "magics.plot(projection, data, contour, coast, legend, title)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Magics offers number of predefined palettes, for a bit more flexibility\n",
    "\n",
    "It would be ideal if our number of levels matched number of colours in palette.  \n",
    "If for any reason that is not the case, we can set parameter **contour_shade_palette_policy** to **'lastone'** or **'cycle'**, so Magics knows what to do if there are more levels than colours.   \n",
    "Full list of Magics palletes can be found [here](https://confluence.ecmwf.int/display/MAGP/Predefined+palettes+in+Magics \"Magics palettes\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 121,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 186160 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 121,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contour = magics.mcont(\n",
    "    legend = 'on',\n",
    "    contour = 'off',\n",
    "    contour_shade = 'on',\n",
    "    contour_label = 'off',\n",
    "    contour_level_selection_type = 'interval',\n",
    "    contour_interval = 2.0,\n",
    "    contour_shade_min_level = -28.0,\n",
    "    contour_shade_max_level = 22.0,\n",
    "    contour_shade_method = 'area_fill',\n",
    "    contour_shade_palette_name = 'eccharts_rainbow_purple_red_25',\n",
    "    contour_shade_colour_method = 'palette'\n",
    ")\n",
    "\n",
    "magics.plot(projection, data, contour, legend, coast, title)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### If we want, we can have a full control, of course"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 120,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "[encoded data, 210436 characters]\n",
      "text/plain": [
       "<IPython.core.display.Image object>"
      ]
     },
     "execution_count": 120,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "contour = magics.mcont(legend = \"on\",\n",
    "                       contour = \"off\",\n",
    "                       contour_label = \"off\",\n",
    "                       contour_hilo = \"off\",\n",
    "                       contour_level_selection_type = \"interval\",\n",
    "                       contour_interval = 2.00,\n",
    "                       contour_shade_min_level = -32.00,\n",
    "                       contour_shade_max_level = 42.00,      \n",
    "                       contour_shade = \"on\",\n",
    "                       contour_shade_method = \"area_fill\",\n",
    "                       contour_shade_colour_method = \"list\",\n",
    "                       contour_shade_colour_list = ['rgb(0.3,0.3,0.3)', 'rgb(0.4,0.4,0.4)', 'rgb(0.5,0.5,0.5)', \n",
    "                                   'rgb(0.6,0.6,0.6)', 'rgb(0.7,0.7,0.7)', 'rgb(0.8,0.8,0.8)', \n",
    "                                   'rgb(0.35,0,0.6)', 'rgb(0.5,0,0.9)', 'rgb(0.6,0.2,1)', \n",
    "                                   'rgb(0.75,0.4,1)', 'rgb(0.85,0.6,1)', 'rgb(0,0,0.75)', \n",
    "                                   'rgb(0,0,1)', 'rgb(0.2,0.4,1)', 'rgb(0.4,0.7,1)', 'rgb(0.6,0.9,1)', \n",
    "                                   'rgb(0,0.55,0.19)', 'rgb(0.15,0.75,0.1)', 'rgb(0.5,0.85,0)', \n",
    "                                   'rgb(0.65,0.95,0)', 'rgb(0.8,1,0.2)', 'rgb(0.65,0.65,0)', \n",
    "                                   'rgb(0.8,0.8,0)', 'rgb(0.92,0.92,0)', 'rgb(1,1,0)', \n",
    "                                   'rgb(1,1,0.6)', 'rgb(0.85,0.45,0)', 'rgb(1,0.5,0)', \n",
    "                                   'rgb(1,0.62,0)', 'rgb(1,0.74,0)', 'rgb(1,0.85,0)', \n",
    "                                   'rgb(0.6,0,0)', 'rgb(0.8,0,0)', 'rgb(1,0,0)', \n",
    "                                   'rgb(1,0.4,0.4)', 'rgb(1,0.6,0.6)', 'rgb(1,0.75,0.75)'])\n",
    "\n",
    "magics.plot(projection, data, contour, legend, coast, title)"
   ]
  }
 ],
 "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.6.5"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
