Repository: IAMconsortium/pyam
Pull request #386 (2020-05-28 13:55:09)

Removed equiv before performing unit conversion
# Please confirm that this PR has done the following:

- [x] Tests Added
- [x] Documentation Added
- [x] Description in RELEASE_NOTES.md Added

## Adding to RELEASE_NOTES.md (remove section after adding to RELEASE_NOTES.md)

Please add a single line in the release notes similar to the following:

```
- (#XX)[http://link-to-pr.com] Added feature which does something
```

# Description of PR

Please describe the changes introduced by this PR.


coveralls: 
[![Coverage Status](https://coveralls.io/builds/31092005/badge)](https://coveralls.io/builds/31092005)

Coverage decreased (-0.2%) to 86.162% when pulling **1ee72c3099cabbf9f2250b0a0b5fb82d5822d44b on Rlamboll:co2-equiv** into **ef2f69aba9cebe0c0d953fdc55debf0d44e66861 on IAMconsortium:master**.

Rlamboll: Seems to have failed a test for time reasons, I don't think I can restart it though
danielhuppmann: Yes, there is some version-conflict in the py3.6 dependencies - guess we'll need to remove that test at some point...
danielhuppmann: thanks @Rlamboll, looks great - can you still pull my suggested changes in https://github.com/Rlamboll/pyam/pull/2 (or do you disagree?), then good to go!
Rlamboll: Honestly I find those variable names very confusing because unless you read that specific line of code, you'd have no idea what those variables were and I would likely assume current was still the input value if I wanted to use it later. 
danielhuppmann: > Honestly I find those variable names very confusing because unless you read that specific line of code, you'd have no idea what those variables were and I would likely assume current was still the input value if I wanted to use it later.

I pushed another commit to the PR-branch so that the "cleaned" (without `-equiv`) unit-args are both saved as new internal variables. But I think that cleaning `current` to `_current` is much more python than `clean_current`...

Still, if you can't be convinced, please cherry-pick  the other commits (removed unused utility function and add extra test).
Rlamboll: Well, you're the one doing the upkeep so if you want those names you can have them. 

Patch:
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
index 4d00bb5..66bddf2 100644
--- a/RELEASE_NOTES.md
+++ b/RELEASE_NOTES.md
@@ -1,6 +1,7 @@
 # Next Release
 
 ## Individual Updates
+- [#386](https://github.com/IAMconsortium/pyam/pull/386) Enables unit conversion to apply to strings with "-equiv" in them. 
 - [#373](https://github.com/IAMconsortium/pyam/pull/373) Extends the error message when initializing with duplicate rows.
 - [#370](https://github.com/IAMconsortium/pyam/pull/370) Allowed filter to work with np.int64 years and np.datetime64 dates.  
 - [#369](https://github.com/IAMconsortium/pyam/pull/369) `convert_unit()` supports GWP conversion of same GHG species without context, lower-case aliases for species symbols.
diff --git a/pyam/units.py b/pyam/units.py
index b5333e5..37fdc3a 100644
--- a/pyam/units.py
+++ b/pyam/units.py
@@ -26,21 +26,23 @@ def convert_unit(df, current, to, factor=None, registry=None, context=None,
     # Convert using a pint.UnitRegistry; default the one from iam_units
     registry = registry or iam_units.registry
 
+    # Make versions without -equiv
+    _current, _to = [i.replace('-equiv', '') for i in [current, to]]
     # Pair of (magnitude, unit)
-    qty = [ret.data.loc[where, 'value'].values, current]
+    qty = [ret.data.loc[where, 'value'].values, _current]
 
     try:
         # Create a vector pint.Quantity
         qty = registry.Quantity(*qty)
     except pint.UndefinedUnitError:
         # *qty* might include a GHG species; try GWP conversion
-        result, to = convert_gwp(context, qty, to)
+        result, _to = convert_gwp(context, qty, _to)
     except AttributeError:
         # .Quantity() did not exist
         raise TypeError(f'{registry} must be `pint.UnitRegistry`') from None
     else:
         # Ordinary conversion, using an empty Context if none was provided
-        result = qty.to(to, context or pint.Context())
+        result = qty.to(_to, context or pint.Context())
 
     # Copy values from the result Quantity
     ret.data.loc[where, 'value'] = result.magnitude
@@ -59,6 +61,7 @@ def convert_unit(df, current, to, factor=None, registry=None, context=None,
 SPECIES_ALIAS = {
     'ch4': 'CH4',
     'co2': 'CO2',
+    'CO2-equiv': 'CO2e',
     'co2_eq': 'CO2_eq',
     'co2e': 'CO2e',
     'co2eq': 'CO2eq',


Test patch:
diff --git a/tests/test_units.py b/tests/test_units.py
index 3db5fea..6eefc5f 100644
--- a/tests/test_units.py
+++ b/tests/test_units.py
@@ -1,9 +1,8 @@
-import pytest
-
 import pandas as pd
 import pint
-from pyam import IamDataFrame
+import pytest
 
+from pyam import IamDataFrame
 
 PRECISE_ARG = dict(check_less_precise=True)
 
@@ -86,9 +85,14 @@ def test_convert_unit_with_custom_registry(test_df):
     # Lower-case symbol, handled as alias for CH4
     ('AR5GWP100', 'ch4', 28),
 
-    # Lower-case alias for CO2_eq handled *and* convertible to 'CO2e' without a
-    # context/metric
-    (None, 'co2_eq', 1.)
+    # Lower-case alias for CO2_eq and 'co2-equiv' handled *and* convertible to
+    # 'CO2e' without a context/metric
+    (None, 'co2_eq', 1.),
+    (None, 'co2-equiv', 1.),
+
+    # Using "-equiv" after a unit should make no difference
+    ('AR4GWP100', 'co2-equiv', 1.),
+    ('AR5GWP100', 'ch4-equiv', 28)
 ])
 @pytest.mark.parametrize('current_expr, to_expr, exp_factor', [
     # exp_factor is used when the conversion includes both a species *and* unit