Skip to content

Latest commit

 

History

History
253 lines (193 loc) · 10.7 KB

index.rst

File metadata and controls

253 lines (193 loc) · 10.7 KB

Pycoast

Pycoast is a Python package to add coastlines, borders and rivers to raster images using data from the GSHHS and WDBII datasets

Installation

Pycoast depends on pyshp and PIL.

Install pycoast and dependencies.

Download the zipped GSHHS and WDBII Shapefiles from SOEST. Unzip the files to a data directory (hereafter called GSHHS_DATA_ROOT). The structure of GSHHS_DATA_ROOT should now be:

.
├── GSHHS_shp
│   ├── c
│   ├── f
│   ├── h
│   ├── i
│   └── l
└── WDBII_shp
    ├── c
    ├── f
    ├── h
    ├── i
    └── l

Where each dir on the lowest level contains Shapefiles like GSHHS_shp/c/GSHHS_c_L1.shp

Usage

Pycoast can be used to add coastlines, borders and rivers to a raster image if the geographic projection of the image and the image extent in projection coordinates are known

images/BMNG_clouds_201109181715_areaT2.png

Pycoast can add contours to either a PIL image object:

>>> from PIL import Image
>>> from pycoast import ContourWriter
>>> img = Image.open('BMNG_clouds_201109181715_areaT2.png')
>>> proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
>>> area_extent = (-3363403.31,-2291879.85,2630596.69,2203620.1)
>>> area_def = (proj4_string, area_extent)
>>> cw = ContourWriter('/home/esn/data/gshhs')
>>> cw.add_coastlines(img, area_def, resolution='l', level=4)
>>> cw.add_rivers(img, area_def, level=5, outline='blue')
>>> cw.add_borders(img, area_def, outline=(255, 0, 0))
>>> img.show()

or to an image file:

>>> from pycoast import ContourWriter
>>> proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
>>> area_extent = (-3363403.31,-2291879.85,2630596.69,2203620.1)
>>> area_def = (proj4_string, area_extent)
>>> cw = ContourWriter('/home/esn/data/gshhs')
>>> cw.add_coastlines_to_file('BMNG_clouds_201109181715_areaT2.png', area_def, resolution='l', level=4)
>>> cw.add_rivers_to_file('BMNG_clouds_201109181715_areaT2.png', area_def, level=5, outline='blue')
>>> cw.add_borders_to_file('BMNG_clouds_201109181715_areaT2.png', area_def, outline=(255, 0, 0))

Where the :attr:`area_extent` is the extent of the image in projection coordinates as (x_ll, y_ll, x_ur, x_ur) measured at pixel edges.

The argument to :attr:`ContourWriter` must be replaced with your GSHHS_DATA_ROOT.

images/euro_coast.png

The resulting (not so pretty) image shows the effect of the various arguments. The :attr:`resolution` keyword argument controls the resolution of the dataset used. It defaults to 'c' for coarse. Increasing the resolution also increases the processing time. The :attr:`level` keyword argument controls the detail level of the dataset used. It defaults to 1 for the lowest detail level.

Instead of a tuple for :attr:`area_def` a pyresample :attr:`AreaDefinition` object can be used.

See method docstrings for information about possible argument values see method docstrings.

Creating an image with coastlines only:

>>> from PIL import Image
>>> from pycoast import ContourWriter
>>> img = Image.new('RGB', (425, 425))
>>> proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
>>> area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612)
>>> area_def = (proj4_string, area_extent)
>>> cw = ContourWriter('/home/esn/data/gshhs')
>>> cw.add_coastlines(img, area_def, resolution='l')
>>> img.show()

images/geos_coast.png

High quality contours using AGG

The default plotting mode of pycoast uses PIL for rendering of contours. PIL does not support antialiasing and opacity. The AGG engine can be used for making high quality images using the aggdraw module.

First install the aggdraw module.

Tip: if the building of aggdraw fails with:

agg_array.h:523: error: cast from ‘agg::int8u*’ to ‘unsigned int’ loses precision

Try:

export CFLAGS="-fpermissive"

before building.

Using pycoast with AGG for making antialiased drawing:

>>> from PIL import Image
>>> from pycoast import ContourWriterAGG
>>> img = Image.new('RGB', (425, 425))
>>> proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
>>> area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612)
>>> area_def = (proj4_string, area_extent)
>>> cw = ContourWriterAGG('/home/esn/data/gshhs')
>>> cw.add_coastlines(img, (proj4_string, area_extent), resolution='l', width=0.5)
>>> img.show()

images/geos_coast_agg.png

and making the not-so-nice image from the first example nice:

>>> from PIL import Image
>>> from pycoast import ContourWriterAGG
>>> img = Image.open('BMNG_clouds_201109181715_areaT2.png')
>>> proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
>>> area_extent = (-3363403.31,-2291879.85,2630596.69,2203620.1)
>>> area_def = (proj4_string, area_extent)
>>> cw = ContourWriterAGG('/home/esn/data/gshhs')
>>> cw.add_coastlines(img, area_def, resolution='l', level=4)
>>> cw.add_rivers(img, area_def, level=5, outline='blue', width=0.5, outline_opacity=127)
>>> cw.add_borders(img, area_def, outline=(255, 0, 0), width=3, outline_opacity=32)
>>> img.show()

images/euro_coast_agg.png

See docstrings of :attr:`ContourWriterAGG` methods for argument descriptions.

Adding graticule to images

Pycoast can be used to add graticule to images. For PIL:

>>> from PIL import Image, ImageFont
>>> from pycoast import ContourWriter
>>> proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
>>> area_extent = (-3363403.31,-2291879.85,2630596.69,2203620.1)
>>> area_def = (proj4_string, area_extent)
>>> cw = ContourWriter('/home/esn/data/gshhs')
>>> font = ImageFont.truetype("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf",16)
>>> img = Image.open('BMNG_clouds_201109181715_areaT2.png')
>>> cw.add_coastlines(img, area_def, resolution='l', level=4)
>>> cw.add_grid(img, area_def, (10.0,10.0),(2.0,2.0), font,fill='blue',
...             outline='blue', minor_outline='blue')
>>> img.show()

images/euro_grid.png

The font argument is optional for PIL if it is not given a default font will be used.

and for AGG:

>>> from PIL import Image, ImageFont
>>> from pycoast import ContourWriterAGG
>>> import aggdraw
>>> proj4_string = '+proj=stere +lon_0=8.00 +lat_0=50.00 +lat_ts=50.00 +ellps=WGS84'
>>> area_extent = (-3363403.31,-2291879.85,2630596.69,2203620.1)
>>> area_def = (proj4_string, area_extent)
>>> cw = ContourWriterAGG('/home/esn/data/gshhs')
>>> font = aggdraw.Font('black', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf',
...                     opacity=127, size=16)
>>> img = Image.open('BMNG_clouds_201109181715_areaT2.png')
>>> cw.add_coastlines(img, area_def, resolution='l', level=4)
>>> cw.add_grid(img, area_def, (10.0,10.0),(2.0,2.0),font,
...             outline='blue',outline_opacity=175,width=1.0,
...             minor_outline='lightblue',minor_outline_opacity=200,minor_width=0.5,
...             minor_is_tick=False)
>>> img.show()

images/euro_grid_agg.png

Note the difference in the optional font argument for PIL and AGG. With AGG the font argument is mandatory unless the keyword argument :attr:`write_text=False` is used.

From v0.5.0 the graticule is also usable for globe projections:

>>> from PIL import Image
>>> from pycoast import ContourWriterAGG
>>> img = Image.new('RGB', (425, 425))
>>> proj4_string = '+proj=geos +lon_0=0.0 +a=6378169.00 +b=6356583.80 +h=35785831.0'
>>> area_extent = (-5570248.4773392612, -5567248.074173444, 5567248.074173444, 5570248.4773392612)
>>> area_def = (proj4_string, area_extent)
>>> cw = ContourWriterAGG(gshhs_root_dir)
>>> cw.add_coastlines(img, area_def, resolution='l')
>>> cw.add_grid(img, area_def, (10.0,10.0),(2.0,2.0), fill='blue',
... outline='blue', minor_outline='blue', write_text=False)
>>> img.show()

images/grid_geos_agg.png

The lon and lat labeling is shown where the lines intersect the image border. By default the lon intersections with top and bottom and the lat intersections with left and right border are displayed . The placement behaviour can be controlled with the :attr:`lon_placement` and :attr:`lat_placement` keyword variables. The placement specifier is a string containing the desired placement where 't' is top, 'b' bottom, 'l' left and 'r' right. E.g. :attr:`lon_placement='tl'` will make the lon labels display at the top and left border.

>>> from PIL import Image
>>> from pycoast import ContourWriterAGG
>>> import aggdraw
>>> img = Image.new('RGB', (425, 425))
>>> proj4_string = '+proj=laea +lat_0=90 +lon_0=0 +a=6371228.0 +units=m'
>>> area_extent = (-5326849.0625, -5326849.0625, 5326849.0625, 5326849.0625)
>>> area_def = (proj4_string, area_extent)
>>> cw = ContourWriterAGG('/home/esn/data/gshhs')
>>> cw.add_coastlines(img, area_def, resolution='c', level=4)
>>> font = aggdraw.Font('blue', '/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf', size=10)
>>> cw.add_grid(img, area_def, (10.0,10.0),(2.0,2.0), font=font, fill='blue',
...             outline='blue', minor_outline='blue',
...             lon_placement='tblr', lat_placement='')
>>> img.show()

images/nh_grid_coarse_agg.png

Tip: If the adding graticule with AGG fails with something like:

Traceback (most recent call last):
    File "grid_demo_AGG.py", line 13, in <module>
        font=aggdraw.Font("blue", "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSerif.ttf", size=16)
IOError: cannot load font (no text renderer)

make sure the FREETYPE_ROOT in setup.py of aggdraw points to the correct location e.g. set FREETYPE_ROOT = "/usr"

Testing

The tests can be run using nosetest:

$ cd <pycoast_dir>
$ nosetests tests/