Source code for tracktable.render.mapmaker

#
# Copyright (c) 2014-2017 National Technology and Engineering
# Solutions of Sandia, LLC. Under the terms of Contract DE-NA0003525
# with National Technology and Engineering Solutions of Sandia, LLC,
# the U.S. Government retains certain rights in this software.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

"""Convenience wrappers for geographic map creation and decoration
"""

from __future__ import print_function

from matplotlib import pyplot

import logging
from tracktable.render import maps
from tracktable.render import geographic_decoration as decoration


[docs]def mapmaker(domain='terrestrial', *args, **kwargs): if kwargs.get('map_bbox', None) is not None: kwargs['map_bbox'] = _make_bounding_box(kwargs['map_bbox'], domain) if domain == 'terrestrial': return terrestrial_map(*args, **kwargs) elif domain == 'cartesian' or domain == 'cartesian2d': return cartesian_map(*args, **kwargs) else: raise ValueError(('Mapmaker only works on the terrestrial and ' ' cartesian2d domains, not "{}".').format(domain))
# ----------------------------------------------------------------------
[docs]def cartesian_map(map_bbox=None, gridline_spacing=None, axes=None, **kwargs): """Create a Cartesian map Since Cartesian space is flat and undistinguished, a "map" is just a display region. You can also change the background color and draw axes/grid lines on the figure. """ if axes is None: axes = pyplot.gca() logging.getLogger(__name__).debug( "cartesian_map: map_bbox is {}".format(map_bbox)) axes.set_aspect(kwargs.get('aspect', 'equal')) if map_bbox is not None: axes.set_xlim(left=map_bbox.min_corner[0], right=map_bbox.max_corner[0]) axes.set_ylim(bottom=map_bbox.min_corner[1], top=map_bbox.max_corner[1]) return (axes, list())
# ----------------------------------------------------------------------
[docs]def terrestrial_map(map_name, draw_coastlines=True, draw_countries=True, draw_states=True, draw_lonlat=True, fill_land=True, fill_water=True, land_fill_color='#101010', water_fill_color='#000000', land_zorder=4, water_zorder=4, lonlat_spacing=10, lonlat_color='#A0A0A0', lonlat_linewidth=0.2, lonlat_zorder=6, coastline_color='#808080', coastline_linewidth=1, coastline_zorder=5, country_border_color='#606060', country_fill_color='#303030', country_linewidth=0.5, country_zorder=3, state_border_color='#404040', state_fill_color='none', state_linewidth=0.3, state_zorder=2, draw_largest_cities=None, draw_cities_larger_than=None, city_label_size=12, city_dot_size=2, city_dot_color='white', city_label_color='white', city_zorder=6, border_resolution='110m', map_bbox=None, map_projection=None, map_scale_length=None, region_size=None, axes=None, **kwargs): """Create and decorate a map Call the Cartopy toolkit to create a map of some predefined area, up to and including the entire world. The map will be decorated with some subset of coastlines, country borders, state/province borders and cities according to the keyword arguments you supply to mapmaker() or terrestrial_map(). Args: map_name: Region name ('region:XXX' or 'airport:XXX' or 'city:XXX' or 'custom'). Available regions are in tracktable.render.maps.available_maps(). draw_coastlines: Whether or not to draw coastlines on the map draw_countries: Whether or not to draw country borders on the map draw_states: Whether or not to draw US/Canada state borders draw_lonlat: Whether or not to draw longitude/latitude lines land_color: Color name or hex string for land area sea_color: Color name or hex string for sea area lonlat_spacing: Distance in degrees between lon/lat lines lonlat_color: Color name or hex string for longitude/latitude lines lonlat_linewidth: Width (in point) for lon/lat lines lonlat_zorder: Image layer for coastlines coastline_color: Color name or hex string for coastlines coastline_linewidth: Width (in points) of coastlines coastline_zorder: Image layer for coastlines country_color: Color name or hex string for coastlines country_linewidth: Width (in points) of coastlines country_zorder: Image layer for coastlines state_color: Color name or hex string for coastlines state_linewidth: Width (in points) of coastlines state_zorder: Image layer for coastlines draw_largest_cities: Draw the N largest cities on the map draw_cities_larger_than: Draw cities with populations greater than N city_label_size: Size (in points) for city name labels city_dot_size: Size (in points) for city markers city_dot_color: Color name or hex string for city markers city_label_color: Color name or hex string for city names border_resolution: 'c', 'i', 'h' or 'f' (in increasing order of complexity) axes: Matplotlib axes to render into map_bbox: Bounding box for custom map extent region_size: Size of region depicted around an airport (km width x km height) map_projection: Cartopy CRS projection object (optional) map_scale_length: Length of map scale indicator (in km) Raises: KeyError: unknown map name Returns: (basemap, artist_list): Basemap instance and a list of Matplotlib artists that were rendered """ if map_name == "custom": map_axes = maps.instantiate_map( min_corner=map_bbox.min_corner, max_corner=map_bbox.max_corner, projection=map_projection ) artists = [] else: map_axes = maps.predefined_map( map_name, region_size=region_size, projection=map_projection ) artists = [] if draw_coastlines: artists.extend( decoration.draw_coastlines( map_axes, edgecolor=coastline_color, zorder=coastline_zorder )) if fill_land: artists.extend( decoration.fill_land( map_axes, facecolor=land_fill_color, zorder=land_zorder )) if fill_water: water_actors = decoration.fill_oceans( map_axes, facecolor=water_fill_color, zorder=water_zorder ) lake_actors = decoration.fill_lakes( map_axes, facecolor=water_fill_color, zorder=water_zorder ) artists.extend(water_actors) artists.extend(lake_actors) if draw_countries: artists.extend( decoration.draw_countries( map_axes, edgecolor=country_border_color, facecolor=country_fill_color, linewidth=country_linewidth, zorder=country_zorder )) if draw_states: artists.extend( decoration.draw_states( map_axes, edgecolor=state_border_color, facecolor=state_fill_color, linewidth=state_linewidth, zorder=state_zorder )) if draw_lonlat: artists.extend( decoration.draw_lonlat( map_axes, color=lonlat_color, linewidth=lonlat_linewidth, zorder=lonlat_zorder )) if draw_largest_cities is not None: artists.extend( decoration.draw_largest_cities( map_axes, draw_largest_cities, dot_color=city_dot_color, dot_size=city_dot_size, label_color=city_label_color, label_size=city_label_size )) if draw_cities_larger_than is not None: artists.extend( decoration.draw_cities_larger_than( map_axes, draw_cities_larger_than, dot_color=city_dot_color, dot_size=city_dot_size, label_color=city_label_color, label_size=city_label_size )) if map_scale_length is not None: artists.extend( decoration.draw_scale( map_axes, map_scale_length, label_color=city_label_color, label_size=city_label_size )) return (map_axes, artists)
def _make_bounding_box(bbox_args, domain): """Make a sensible bounding box out of whatever the user gave us.""" # Case 1: Is it a list of coordinates from the command line? if type(bbox_args) is list and len(bbox_args) == 4: if domain == 'terrestrial': from tracktable.domain.terrestrial import BoundingBox as TerrestrialBoundingBox min_corner = (bbox_args[0], bbox_args[1]) max_corner = (bbox_args[2], bbox_args[3]) return TerrestrialBoundingBox(min_corner, max_corner) elif domain == 'cartesian2d': from tracktable.domain.cartesian2d import BoundingBox as Cartesian2DBoundingBox min_corner = (bbox_args[0], bbox_args[1]) max_corner = (bbox_args[2], bbox_args[3]) return Cartesian2DBoundingBox(min_corner, max_corner) else: raise ValueError('Custom bounding box for domain {} is not defined.'.format(domain)) # Case 2: is it a bbox already? else: # just hope for the best return bbox_args