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
|
|
|
"""Simplify using the weather symbol font. |
5
|
|
|
|
6
|
|
|
See WMO manual 485 Vol 1 for more info on the symbols. |
7
|
|
|
""" |
8
|
|
|
|
9
|
|
|
import matplotlib.font_manager as fm |
10
|
|
|
from pkg_resources import resource_filename |
11
|
|
|
|
12
|
|
|
# Create a matplotlib font object pointing to our weather symbol font |
13
|
|
|
wx_symbol_font = fm.FontProperties(fname=resource_filename('metpy.plots', |
14
|
|
|
'fonts/wx_symbols.ttf')) |
15
|
|
|
|
16
|
|
|
# Deal with the fact that Python 2 chr() can't handle unicode, but unichr is gone |
17
|
|
|
# on python 3 |
18
|
|
|
try: |
19
|
|
|
code_point = unichr |
20
|
|
|
except NameError: |
21
|
|
|
code_point = chr |
22
|
|
|
|
23
|
|
|
|
24
|
|
|
class CodePointMapping(object): |
25
|
|
|
"""Map integer values to font code points.""" |
26
|
|
|
|
27
|
|
|
def __init__(self, num, font_start, font_jumps=None, char_jumps=None): |
28
|
|
|
"""Initialize the instance. |
29
|
|
|
|
30
|
|
|
Parameters |
31
|
|
|
---------- |
32
|
|
|
num : int |
33
|
|
|
The number of values that will be mapped |
34
|
|
|
font_start : int |
35
|
|
|
The first code point in the font to use in the mapping |
36
|
|
|
font_jumps : list[int, int], optional |
37
|
|
|
Sequence of code point jumps in the font. These are places where the next |
38
|
|
|
font code point does not correspond to a new input code. This is usually caused |
39
|
|
|
by there being multiple symbols for a single code. Defaults to :data:`None`, which |
40
|
|
|
indicates no jumps. |
41
|
|
|
char_jumps : list[int, int], optional |
42
|
|
|
Sequence of code jumps. These are places where the next code value does not |
43
|
|
|
have a valid code point in the font. This usually comes from place in the WMO |
44
|
|
|
table where codes have no symbol. Defaults to :data:`None`, which indicates no |
45
|
|
|
jumps. |
46
|
|
|
""" |
47
|
|
|
next_font_jump = self._safe_pop(font_jumps) |
48
|
|
|
next_char_jump = self._safe_pop(char_jumps) |
49
|
|
|
font_point = font_start |
50
|
|
|
self.chrs = [] |
51
|
|
|
code = 0 |
52
|
|
|
while code < num: |
53
|
|
|
if next_char_jump and code >= next_char_jump[0]: |
54
|
|
|
jump_len = next_char_jump[1] |
55
|
|
|
code += jump_len |
56
|
|
|
self.chrs.extend([''] * jump_len) |
57
|
|
|
next_char_jump = self._safe_pop(char_jumps) |
58
|
|
|
else: |
59
|
|
|
self.chrs.append(code_point(font_point)) |
60
|
|
|
if next_font_jump and code >= next_font_jump[0]: |
61
|
|
|
font_point += next_font_jump[1] |
62
|
|
|
next_font_jump = self._safe_pop(font_jumps) |
63
|
|
|
code += 1 |
64
|
|
|
font_point += 1 |
65
|
|
|
|
66
|
|
|
@staticmethod |
67
|
|
|
def _safe_pop(l): |
68
|
|
|
"""Safely pop from a list. |
69
|
|
|
|
70
|
|
|
Returns None if list empty. |
71
|
|
|
""" |
72
|
|
|
return l.pop(0) if l else None |
73
|
|
|
|
74
|
|
|
def __call__(self, code): |
75
|
|
|
"""Return the Unicode code point corresponding to `code`.""" |
76
|
|
|
return self.chrs[code] |
77
|
|
|
|
78
|
|
|
def __len__(self): |
79
|
|
|
"""Return the number of codes supported by this mapping.""" |
80
|
|
|
return len(self.chrs) |
81
|
|
|
|
82
|
|
|
def alt_char(self, code, alt): |
83
|
|
|
"""Get one of the alternate code points for a given value. |
84
|
|
|
|
85
|
|
|
In the WMO tables, some code have multiple symbols. This allows getting that |
86
|
|
|
symbol rather than main one. |
87
|
|
|
|
88
|
|
|
Parameters |
89
|
|
|
---------- |
90
|
|
|
code : int |
91
|
|
|
The code for looking up the font code point |
92
|
|
|
alt : int |
93
|
|
|
The number of the alternate symbol |
94
|
|
|
|
95
|
|
|
Returns |
96
|
|
|
------- |
97
|
|
|
int |
98
|
|
|
The appropriate code point in the font |
99
|
|
|
""" |
100
|
|
|
return code_point(ord(self(code)) + alt) |
101
|
|
|
|
102
|
|
|
|
103
|
|
|
# |
104
|
|
|
# Set up mapping objects for various groups of symbols. The integer values follow from |
105
|
|
|
# the WMO. |
106
|
|
|
# |
107
|
|
|
|
108
|
|
|
#: Current weather |
109
|
|
|
current_weather = CodePointMapping(100, 0xE9A2, [(7, 2), (93, 2), (94, 2), (95, 2), (97, 2)], |
110
|
|
|
[(0, 4)]) |
111
|
|
|
|
112
|
|
|
#: Current weather from an automated station |
113
|
|
|
current_weather_auto = CodePointMapping(100, 0xE94B, [(92, 2), (95, 2)], |
114
|
|
|
[(6, 4), (13, 5), (19, 1), (36, 4), (49, 1), (59, 1), |
115
|
|
|
(69, 1), (79, 1), (88, 1), (97, 2)]) |
116
|
|
|
|
117
|
|
|
#: Low clouds |
118
|
|
|
low_clouds = CodePointMapping(10, 0xE933, [(7, 1)], [(0, 1)]) |
119
|
|
|
|
120
|
|
|
#: Mid-altitude clouds |
121
|
|
|
mid_clouds = CodePointMapping(10, 0xE93D, char_jumps=[(0, 1)]) |
122
|
|
|
|
123
|
|
|
#: High clouds |
124
|
|
|
high_clouds = CodePointMapping(10, 0xE946, char_jumps=[(0, 1)]) |
125
|
|
|
|
126
|
|
|
#: Sky cover symbols |
127
|
|
|
sky_cover = CodePointMapping(12, 0xE90A) |
128
|
|
|
|
129
|
|
|
#: Pressure tendency |
130
|
|
|
pressure_tendency = CodePointMapping(10, 0xE900) |
131
|
|
|
|