Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add notebook example showing how to add overlays and decorate an image #45

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
10 changes: 5 additions & 5 deletions satpy/Cartopy Plot.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -115,21 +115,21 @@
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"display_name": "Python 3",
"language": "python",
"name": "python2"
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.5"
"pygments_lexer": "ipython3",
"version": "3.8.0"
}
},
"nbformat": 4,
Expand Down
274 changes: 274 additions & 0 deletions satpy/add_overlays_and_decorate_image.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,274 @@
{
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line #1.    output_filename=f'seviri_{composite_name:s}_{local_scn.start_time:%Y%m%d_%H%M}_{areaid:s}.tif'

Thoughts on putting a space between the "=" for styling? And maybe instead of printing just doing "output_filename" and letting the notebook handle printing it?


Reply via ReviewNB

"cells": [
{
"cell_type": "markdown",
"id": "99b04380",
"metadata": {},
"source": [
"# Decorate your satellite images to make them ready for publication\n",
"This example demonstrate how you can add various overlays like coastlines, borders and graticules and how to decorate your image with text, points, logos, etc, in order to make it ready for publication.\n",
"\n",
"We load Meteosat SEVIRI data using Satpy and make an RGB using the `overview` composite. Data are resampled to the area defined in the `areas.yaml` file that comes with Satpy.\n",
"\n",
"First we need to locate the logo images we want to use, specify the fonts for overlaying text, and define the area and composite name/type:"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "d1b041bc",
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from glob import glob\n",
"from satpy import Scene\n",
"\n",
"DATA_DIR = \"/home/a000680/data/hrit/20200923\"\n",
"FILES = glob(os.path.join(DATA_DIR, \"*\"))\n",
"\n",
"areaid = 'euro4'\n",
"composite_name = 'overview'\n",
"font = \"/usr/share/fonts/dejavu/DejaVuSerif.ttf\"\n",
"pytroll_logo = \"/home/a000680/data/logos/pytroll_dark_small.png\"\n",
"eumetsat_logo = \"/home/a000680/data/logos/eumetsat_logo.gif\"\n"
]
},
{
"cell_type": "markdown",
"id": "8d987a76",
"metadata": {},
"source": [
"## Prepare the drawing of graticules (grid lines) and ticks\n",
"\n",
"Then we prepare a dictionary specifying how we want the graticules to be later drawn over the image. Adding graticules is done via the Pycoast package, which in turn is using PIL and aggdraw to draw unaliased lines on images. See https://pycoast.readthedocs.io/en/latest/index.html. It will take the same key word arguments as the `add_grid` method, see https://pycoast.readthedocs.io/en/latest/api/pycoast.html#pycoast.cw_agg.ContourWriterAGG.add_grid."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "250273be",
"metadata": {},
"outputs": [],
"source": [
"grid = {'major_lonlat': (10, 10), 'minor_lonlat': (2, 2),\n",
" 'outline': (255, 255, 0), 'outline_opacity': 175,\n",
" 'width': 1.0, 'minor_width': 0.5, 'minor_is_tick': 1,\n",
" 'write_text': True, 'lat_placement': 'lr', 'lon_placement': 'b',\n",
" 'font': font}"
]
},
{
"cell_type": "markdown",
"id": "76bfa33d",
"metadata": {},
"source": [
"## Define how to draw points showing geographical places\n",
"\n",
"We also want to point out a few geographical places, in this case four capitals in Europe.\n",
"Each city will be marked by a white dot with a black ring around, and for each dot the name of the city is written in a red text box:"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "ba4354ba",
"metadata": {},
"outputs": [],
"source": [
"poi_list = [((2.3522, 48.8566), 'Paris'),\n",
" ((0.1278, 51.5074), 'London'),\n",
" ((12.568, 55.676), 'Copenhagen'),\n",
" ((24.938, 60.170), 'Helsinki')]\n",
"points = {'font': font,\n",
" 'font_size': 20, 'points_list': poi_list, 'symbol': 'circle', 'ptsize': 5,\n",
" 'outline': 'black', 'fill': 'white', 'width': 8, 'fill_opacity': 255, 'box_outline': 'black',\n",
" 'box_linewidth': 2.0, 'box_fill': (255, 0, 0), 'box_opacity': 127}"
]
},
{
"cell_type": "markdown",
"id": "83af0deb",
"metadata": {},
"source": [
"## Prepare the drawing of coastlines, borders and rivers\n",
"Now prepare the dictionaries with specifications for the coastlines, borders and rivers to be shown on the image:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "f619961a",
"metadata": {},
"outputs": [],
"source": [
"coast = {'outline': (255, 255, 255), 'width': 1.5, 'level': 1, 'resolution': 'l'}\n",
"borders = {'outline': (255, 255, 255), 'width': 1.0, 'level': 3, 'resolution': 'i'}\n",
"rivers = {'outline': (0, 0, 255), 'width': 1.0, 'level': 3, 'resolution': 'i'}"
]
},
{
"cell_type": "markdown",
"id": "918f6b17",
"metadata": {},
"source": [
"Adding points, coastlines, borders and rivers on the image is delegated to Pycoast as well.\n",
"\n",
"## Create the Scene object and load and resample the data\n",
"Now load the Meteosat SEVIRI scene and resample it onto the area specified via its name above (euro4):"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "56f76609",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/a000680/miniconda3/envs/python38/lib/python3.8/site-packages/pyproj/crs/crs.py:543: UserWarning: You will likely lose important projection information when converting to a PROJ string from another format. See: https://proj.org/faq.html#what-is-the-best-format-for-describing-coordinate-reference-systems\n",
" proj_string = self.to_proj4()\n",
"/home/a000680/miniconda3/envs/python38/lib/python3.8/site-packages/pyproj/crs/crs.py:543: UserWarning: You will likely lose important projection information when converting to a PROJ string from another format. See: https://proj.org/faq.html#what-is-the-best-format-for-describing-coordinate-reference-systems\n",
" proj_string = self.to_proj4()\n"
]
}
],
"source": [
"scn = Scene(filenames=FILES, reader='seviri_l1b_hrit')\n",
"scn.load([composite_name])\n",
"local_scn = scn.resample(areaid, radius_of_influence=35000.0)"
]
},
{
"cell_type": "markdown",
"id": "6be1b4af",
"metadata": {},
"source": [
"## Define the adding of logos and text on the image\n",
"\n",
"Now we prepare how to decorate the image with logos and a header text including the time of observation, taken from the scene object:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "8aa5ca1a",
"metadata": {},
"outputs": [],
"source": [
"start_time_txt = local_scn.start_time.strftime('%Y-%m-%d %H:%M')\n",
"\n",
"decoration = [\n",
" {'logo': {'logo_path': pytroll_logo,\n",
" 'height': 60, 'bg': 'white', 'bg_opacity': 120}},\n",
" {'logo': {'logo_path': eumetsat_logo,\n",
" 'height': 60, 'bg': 'white', 'bg_opacity': 120}},\n",
" {'text': {'txt': 'Meteosat-11' + ' ' + start_time_txt +\n",
" \"\\nComposite: \" + composite_name + \", Area: \" + areaid,\n",
" 'font': font,\n",
" 'font_size': 20, 'height': 10, 'bg': 'white', 'bg_opacity': 127, 'line': 'black'}}]"
]
},
{
"cell_type": "markdown",
"id": "c83081c9",
"metadata": {},
"source": [
"Adding logos and text to images is done via the Pytroll package Pydecorate. See https://pydecorate.readthedocs.io/en/latest/index.html. See the documentation for the `add_logo` and `add_text` methods for what options can be provided."
]
},
{
"cell_type": "markdown",
"id": "4fdfba2b",
"metadata": {},
"source": [
"## Apply the overlays and decoration defined above and save the image\n",
"\n",
"Now we can either show the image directly or save it to disk. When doing this it is possible to also add the decorations (logos and text) and draw the overlays (coastlines, rivers, borders, graticules and points). This is done using the keyword arguments `overlay` and `decorate` in this case. The path to the shape files with coastlines etc. needs to be specified:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "f11690a9",
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"seviri_overview_20200923_0815_euro4.tif\n"
]
}
],
"source": [
"output_filename=f'seviri_{composite_name:s}_{local_scn.start_time:%Y%m%d_%H%M}_{areaid:s}.tif'\n",
"print(output_filename)"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "18f49bc0",
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/a000680/miniconda3/envs/python38/lib/python3.8/site-packages/pyproj/crs/crs.py:543: UserWarning: You will likely lose important projection information when converting to a PROJ string from another format. See: https://proj.org/faq.html#what-is-the-best-format-for-describing-coordinate-reference-systems\n",
" proj_string = self.to_proj4()\n",
"/home/a000680/miniconda3/envs/python38/lib/python3.8/site-packages/dask/core.py:121: RuntimeWarning: invalid value encountered in cos\n",
" return func(*(_execute_task(a, cache) for a in args))\n",
"/home/a000680/miniconda3/envs/python38/lib/python3.8/site-packages/dask/core.py:121: RuntimeWarning: invalid value encountered in sin\n",
" return func(*(_execute_task(a, cache) for a in args))\n",
"/home/a000680/miniconda3/envs/python38/lib/python3.8/site-packages/dask/core.py:121: RuntimeWarning: invalid value encountered in log\n",
" return func(*(_execute_task(a, cache) for a in args))\n"
]
}
],
"source": [
"local_scn.save_dataset(composite_name,\n",
" filename=output_filename,\n",
" overlay={'coast_dir': '/home/a000680/data/shapes/',\n",
" 'overlays': {'grid': grid,\n",
" 'coasts': coast,\n",
" 'borders': borders,\n",
" 'rivers': rivers,\n",
" 'points': points}},\n",
" decorate={'decorate': decoration})"
]
},
{
"cell_type": "markdown",
"id": "ee03dfb6",
"metadata": {},
"source": [
"![Final SEVIRI overview RGB image with overlays, logos and text](https://www.kaggleusercontent.com/kf/65796474/eyJhbGciOiJkaXIiLCJlbmMiOiJBMTI4Q0JDLUhTMjU2In0..ZWve_3NbetaDimdsLVnd7w.Jt7byRDr-fZq62NNy6Qmp-qirYw4BDTzB8X_20Kx1ilMqjeSqbN0kGyAEAioyEucspv6KfgjhecFrM5RQvW8dIG_mSoIQ2AvE19DGKfoKhCxnMLt16eyI2Ebdg4YI2fOqbyrSZs36SKnwULH5sC3BkA5bmrnErPg6DNZnQcJW18rau1PmIj5xe0Q643HM2e_BP_GiFIZLULRUEFv6COKGRc_4Am1Lv6PrR8MW2XW1UwOCTFV7F7SP11qEORC3b0KZrzXWNmXDjw_5j0HVx6o17tRdHZDR1efEspv72a8i5_CnoIW-Gftcml-jCAeA5AiUhGDK315G0ntudjvUuu_sfNlNYwJQ6-OW7lk-VOb9VoQDpYX4-QKv0UhpmnE33bovm73mDQVWgEFFvg2KRvDhPOWfU6U8begv0z6v9bkpMGv0HzVka09HFIkUuP4copPvO56IeP2xFviOnXtme3Gs5VzlXU4pm-zsf6uKrhqyo_1BurT3ogk7QcYllhhMC4pnp58c7ckLzCJWwJenyjVSPBfq40ch0gBxviUXMqWc8DZFjnr9DptZjPGEDnDlwlYtpy4aP1lEAptA718-QzxGRilYo1q4NpsAuh9wvD1ESsHO18KP5fCksvn1MomMs513309bqWB_aYij1It4iqRv810rZAJuQGgGZzCmWSges27v2wPiA6YnJaQiwzpchCQzMJ1mw0gYnF_9mWbyJHAyQ.FU7-SbVowS9l4n6F7USB2A/__results___files/__results___18_0.png)"
]
}
],
"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.8.0"
}
},
"nbformat": 4,
"nbformat_minor": 5
}