Completed
Push — master ( 912dc8...6b82ea )
by Ryan
19s
created

add_unidata_logo()   B

Complexity

Conditions 1

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
c 0
b 0
f 0
dl 0
loc 26
rs 8.8571
1
# Copyright (c) 2008-2015 MetPy Developers.
2
# Distributed under the terms of the BSD 3-Clause License.
3
# SPDX-License-Identifier: BSD-3-Clause
4
"""Utilities for use in making plots."""
5
6
from datetime import datetime
7
import posixpath
8
9
from matplotlib.collections import LineCollection
10
from matplotlib.pyplot import imread
11
import numpy as np
12
import pkg_resources
13
14
from ..units import concatenate
15
16
17
def add_timestamp(ax, time=None, x=0.99, y=-0.04, ha='right', **kwargs):
18
    """Add a timestamp at plot creation time.
19
20
    Adds an ISO format timestamp with the time of plot creation to the plot.
21
22
    Parameters
23
    ----------
24
    ax : `matplotlib.axes.Axes`
25
        The `Axes` instance used for plotting
26
    time : `datetime.datetime`
27
        Specific time to be plotted - datetime.utcnow will be use if not specified
28
    x : float
29
        Relative x position on the axes of the timestamp
30
    y : float
31
        Relative y position on the axes of the timestamp
32
    ha : str
33
        Horizontal alignment of the time stamp string
34
35
    Returns
36
    -------
37
    ax : `matplotlib.axes.Axes`
38
        The `Axes` instance used for plotting
39
40
    """
41
    if not time:
42
        time = datetime.utcnow()
43
    timestr = datetime.strftime(time, 'Created: %Y-%m-%dT%H:%M:%SZ')
44
    ax.text(x, y, timestr, ha=ha, transform=ax.transAxes, **kwargs)
45
    return ax
46
47
48
def _add_logo(fig, x=10, y=25, zorder=100, which='metpy', size='small', **kwargs):
49
    """Add the MetPy or Unidata logo to a figure.
50
51
    Adds an image to the figure.
52
53
    Parameters
54
    ----------
55
    fig : `matplotlib.figure`
56
       The `figure` instance used for plotting
57
    x : int
58
       x position padding in pixels
59
    y : float
60
       y position padding in pixels
61
    zorder : int
62
       The zorder of the logo
63
    which : str
64
       Which logo to plot 'metpy' or 'unidata'
65
    size : str
66
       Size of logo to be used. Can be 'small' for 75 px square or 'large' for
67
       150 px square.
68
69
    Returns
70
    -------
71
    fig : `matplotlib.figure`
72
       The `figure` instance used for plotting
73
74
    """
75
    fname_suffix = {'small': '_75x75.png',
76
                    'large': '_150x150.png'}
77
    fname_prefix = {'unidata': 'unidata',
78
                    'metpy': 'metpy'}
79
    try:
80
        fname = fname_prefix[which] + fname_suffix[size]
81
        fpath = posixpath.join('_static', fname)
82
    except KeyError:
83
        raise ValueError('Unknown logo size or selection')
84
85
    logo = imread(pkg_resources.resource_stream('metpy.plots', fpath))
86
    fig.figimage(logo, x, y, zorder=zorder, **kwargs)
87
    return fig
88
89
90
def add_metpy_logo(fig, x=10, y=25, zorder=100, size='small', **kwargs):
91
    """Add the MetPy logo to a figure.
92
93
    Adds an image of the MetPy logo to the figure.
94
95
    Parameters
96
    ----------
97
    fig : `matplotlib.figure`
98
       The `figure` instance used for plotting
99
    x : int
100
       x position padding in pixels
101
    y : float
102
       y position padding in pixels
103
    zorder : int
104
       The zorder of the logo
105
    size : str
106
       Size of logo to be used. Can be 'small' for 75 px square or 'large' for
107
       150 px square.
108
109
    Returns
110
    -------
111
    fig : `matplotlib.figure`
112
       The `figure` instance used for plotting
113
114
    """
115
    _add_logo(fig, x=x, y=y, zorder=zorder, which='metpy', size=size, **kwargs)
116
117
118
def add_unidata_logo(fig, x=10, y=25, zorder=100, size='small', **kwargs):
119
    """Add the Unidata logo to a figure.
120
121
    Adds an image of the MetPy logo to the figure.
122
123
    Parameters
124
    ----------
125
    fig : `matplotlib.figure`
126
       The `figure` instance used for plotting
127
    x : int
128
       x position padding in pixels
129
    y : float
130
       y position padding in pixels
131
    zorder : int
132
       The zorder of the logo
133
    size : str
134
       Size of logo to be used. Can be 'small' for 75 px square or 'large' for
135
       150 px square.
136
137
    Returns
138
    -------
139
    fig : `matplotlib.figure`
140
       The `figure` instance used for plotting
141
142
    """
143
    _add_logo(fig, x=x, y=y, zorder=zorder, which='unidata', size=size, **kwargs)
144
145
146
# Not part of public API
147
def colored_line(x, y, c, **kwargs):
148
    """Create a multi-colored line.
149
150
    Takes a set of points and turns them into a collection of lines colored by another array.
151
152
    Parameters
153
    ----------
154
    x : array-like
155
        x-axis coordinates
156
    y : array-like
157
        y-axis coordinates
158
    c : array-like
159
        values used for color-mapping
160
    kwargs : dict
161
        Other keyword arguments passed to :class:`matplotlib.collections.LineCollection`
162
163
    Returns
164
    -------
165
        The created :class:`matplotlib.collections.LineCollection` instance.
166
167
    """
168
    # Mask out any NaN values
169
    nan_mask = ~(np.isnan(x) | np.isnan(y) | np.isnan(c))
170
    x = x[nan_mask]
171
    y = y[nan_mask]
172
    c = c[nan_mask]
173
174
    # Paste values end to end
175
    points = concatenate([x, y])
176
177
    # Exploit numpy's strides to present a view of these points without copying.
178
    # Dimensions are (segment, start/end, x/y). Since x and y are concatenated back to back,
179
    # moving between segments only moves one item; moving start to end is only an item;
180
    # The move between x any moves from one half of the array to the other
181
    num_pts = points.size // 2
182
    final_shape = (num_pts - 1, 2, 2)
183
    final_strides = (points.itemsize, points.itemsize, num_pts * points.itemsize)
184
    segments = np.lib.stride_tricks.as_strided(points, shape=final_shape,
185
                                               strides=final_strides)
186
187
    # Create a LineCollection from the segments and set it to colormap based on c
188
    lc = LineCollection(segments, **kwargs)
189
    lc.set_array(c)
190
    return lc
191