-
Notifications
You must be signed in to change notification settings - Fork 11
/
test_all.py
171 lines (138 loc) · 5.67 KB
/
test_all.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import numpy as np
import pint
import pytest
from numpy.testing import assert_almost_equal, assert_array_almost_equal
from pint.util import UnitsContainer
from iam_units import convert_gwp, emissions, format_mass, registry
DEFAULTS = pint.get_application_registry()
# Parameters for test_units(), tuple of:
# 1. A literal string to be parsed as a unit.
# 2. Expected dimensionality of the parsed unit.
# 3. True if the units are not in pint's default_en.txt, but are defined in
# definitions.txt.
energy = UnitsContainer({"[energy]": 1})
PARAMS = [
("GW a", energy, False),
("kWa", energy, True),
("Lge", energy, True),
("tce", energy, True),
("toe", energy, False),
("EUR_2005", UnitsContainer({"[currency]": 1}), True),
]
@pytest.mark.parametrize(
"unit_str, dim, new_def", PARAMS, ids=lambda v: v if isinstance(v, str) else ""
)
def test_units(unit_str, dim, new_def):
if new_def:
# Units defined in dimensions.txt are not recognized by base pint
with pytest.raises(pint.UndefinedUnitError):
DEFAULTS("1 " + unit_str)
# Physical quantity of units is recognized
dim = registry.get_dimensionality(dim)
# Units can be parsed and have the correct dimensionality
assert registry("1 " + unit_str).dimensionality == dim
def test_orders_of_magnitude():
# The registry recognizes units prefixed by an order of magnitude
assert registry("1.2 billion EUR").to("million EUR").magnitude == 1.2e3
def test_kt():
# The registry should correctly interpret `kt` as a weight (not velocity)
assert str(registry("1000 kt").to("Mt")) == "1.0 megametric_ton"
# A default UnitRegistry should interpret `kt` as velocity
with pytest.raises(pint.DimensionalityError):
pint.UnitRegistry()("kt").to("Mt")
def test_emissions_gwp_versions():
assert isinstance(emissions.GWP_VERSION, str)
def test_emissions_metrics():
assert "SARGWP100" in emissions.METRICS
def test_emissions_internal():
# Dummy units can be created
registry("0.5 _gwp").dimensionality == {"[_GWP]": 1.0}
# Context can be enabled
with registry.context("AR5GWP100", __a=1.0) as r:
# Context-specific values are activated
assert r("a_CH4 * a_N2O").to_base_units().magnitude == 28 * 265
# Context-specific conversion rules are available
r("0.5 t").to("_gwp")
@pytest.mark.parametrize(
"units",
[
"t {}", # Mass
"Mt {} / a", # Mass rate
"kt {} / (ha * yr)", # Mass flux
],
)
@pytest.mark.parametrize(
"metric, species_in, species_out, expected_value",
[
("AR6GWP100", "CH4", "CO2", 27.9),
("AR5CCFGWP100", "CH4", "CO2", 34),
("AR5GWP100", "CH4", "CO2", 28),
("AR5GWP100", "CH4", "CO2e", 28),
("AR4GWP100", "CH4", "CO2", 25),
("SARGWP100", "CH4", "CO2", 21),
# Same-species conversion with metric=None and compatible names
(None, "CO2", "CO2_eq", 1.0),
(None, "CO2eq", "CO2e", 1.0),
# Species names which are substrings of one another match correctly
("AR5GWP100", "HFC143", "CO2", 328.0),
("AR5GWP100", "HFC143a", "CO2", 4800.0),
],
)
def test_convert_gwp(units, metric, species_in, species_out, expected_value):
# Bare masses can be converted
qty = registry.Quantity(1.0, units.format(""))
expected = registry(f"{expected_value} {units}")
observed = convert_gwp(metric, qty, species_in, species_out)
assert observed.units == expected.units
np.testing.assert_almost_equal(observed.magnitude, expected.magnitude)
# '[mass] [speciesname] (/ [time])' can be converted; the input species is extracted
# from the *qty* argument
qty = "1.0 " + units.format(species_in)
expected = registry(f"{expected_value} {units}")
observed = convert_gwp(metric, qty, species_out)
assert observed.units == expected.units
np.testing.assert_almost_equal(observed.magnitude, expected.magnitude)
# Tuple of (vector magnitude, unit expression) can be converted where the
# the unit expression contains the input species name
arr = np.array([1.0, 2.5, 0.1])
qty = (arr, units.format(species_in))
expected = arr * expected_value
# Conversion works
result = convert_gwp(metric, qty, species_out)
# Magnitudes are as expected
assert_array_almost_equal(result.magnitude, expected)
@pytest.mark.parametrize(
"context",
["AR5GWP100", None],
)
def test_convert_gwp_carbon(context):
# CO2 can be converted to C
qty = (44.0 / 12, "tonne CO2")
result = convert_gwp(context, qty, "C")
assert result.units == registry("tonne")
assert_almost_equal(result.magnitude, 1.0)
# C can be converted to CO2
qty = (1, "tonne C")
expected = registry.Quantity(44.0 / 12, "tonne")
assert convert_gwp(context, qty, "CO2e") == expected
@pytest.mark.parametrize(
"units_in, species_str, spec, output",
[
("Mt", "CO2", None, "megametric_ton CO2"),
("kg / year", "CO2", None, "kilogram CO2 / year"),
# Compact spec: no spaces around '/'
("kg / year", "CO2", ":C", "kilogram CO2/year"),
# Abbreviated/symbol spec AND Unicode subscript
("Mt", "CO₂", ":~", "Mt CO₂"),
("kg / year", "CO₂", ":~", "kg CO₂ / a"),
# Abitrary string, e.g. including a hint at the metric name
("gram / a", "CO₂-e (AR4)", ":~", "g CO₂-e (AR4) / a"),
],
)
def test_format_mass(units_in, species_str, spec, output):
# Quantity object can be formatted
qty = registry.Quantity(3.5, units_in)
assert format_mass(qty, species_str, spec) == output
# Unit object can be formatted
qty = registry.Unit(units_in)
assert format_mass(qty, species_str, spec) == output