Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add units #35

Merged
merged 32 commits into from
Nov 4, 2018
Merged

Add units #35

merged 32 commits into from
Nov 4, 2018

Conversation

znicholls
Copy link
Collaborator

@znicholls znicholls commented Oct 29, 2018

notebooks/emissions-units-with-pint.ipynb gives an example of how this works with Pint

@znicholls znicholls mentioned this pull request Oct 29, 2018
@codecov
Copy link

codecov bot commented Oct 29, 2018

Codecov Report

Merging #35 into master will increase coverage by 18.1%.
The diff coverage is 96.49%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master      #35      +/-   ##
==========================================
+ Coverage   59.01%   77.11%   +18.1%     
==========================================
  Files           5        6       +1     
  Lines          61      118      +57     
  Branches        0       11      +11     
==========================================
+ Hits           36       91      +55     
  Misses         25       25              
- Partials        0        2       +2
Impacted Files Coverage Δ
openscm/units.py 96.49% <96.49%> (ø)

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 38ad4ba...2f058b4. Read the comment docs.

@rgieseke
Copy link
Member

Haha, before i can even comment the CEDS stuff is gone :-)

@rgieseke
Copy link
Member

To discuss:
Hyphens or Underscores in unit names:

Maybe "N2O_N"

N2O-N is not possible I think, they need to be valid Python variable names.

@znicholls
Copy link
Collaborator Author

znicholls commented Oct 30, 2018 via email

dev-requirements.txt Outdated Show resolved Hide resolved
openscm/definitions/__init__.py Outdated Show resolved Hide resolved
openscm/definitions/emissions_units.txt Outdated Show resolved Hide resolved
openscm/definitions/emissions_units.txt Outdated Show resolved Hide resolved
@swillner
Copy link
Member

In general, are the units we would actually use so complex we need a sophisticated library for that?

@swillner
Copy link
Member

Hmmm, having looked into it, I am not that happy with using Pint. If I have two units and want to do lots of conversions between the two, I cannot get just a (pre-/post-) offset and a scaling factor (without hacking Pint or resorting to calculating these myself from some chosen points). Anything else would be inefficient, at least in the low-level API... What can we do about that?
Where do you need conversion in the high-level API?
What units do we need actually?

@swillner
Copy link
Member

Alternatively, we could have a look at unyt, which seems to have the functionality I want: https://unyt.readthedocs.io/en/latest/modules/unyt.unit_object.html#unyt.unit_object.Unit.get_conversion_factor

@rgieseke
Copy link
Member

@swillner What unit conversion is happening in the low-level API?

@znicholls znicholls mentioned this pull request Oct 30, 2018
@znicholls
Copy link
Collaborator Author

In general, are the units we would actually use so complex we need a sophisticated library for that?

I would argue yes. People (me) have cocked them up enough to mean that if we can just do the unit handling once, in a fairly clever way, we should.

@znicholls
Copy link
Collaborator Author

znicholls commented Oct 30, 2018

Hmmm, having looked into it, I am not that happy with using Pint.

It's the only unit library with Pandas support. For me that's reason enough to use it.

What can we do about that?

I'm happy to make a PR to Pint this week which gives you a convenience function to Pint which does this (or put it first in OpenSCM, then make a PR in Pint)

>>> import pint
>>> ureg = pint.UnitRegistry()
>>> a = 1*ureg.m
>>> a
<Quantity(1, 'meter')>
>>> a.to("km").magnitude
0.001

It would look like this

def get_conversion_factor(start_units, other_units):
    # type checking etc goes here
    pint_quantity = 1 * ureg(start_units)
    return pint_quantity.to(other_units).magnitude

or as a method on a quantity

def get_conversion_factor(self, other_units):
    # type checking etc goes here
    pint_quantity = 1 * ureg(self)  # or something like this
    return pint_quantity.to(other_units).magnitude

We could then cache those values or whatever you wanted.

@znicholls
Copy link
Collaborator Author

Where do you need conversion in the high-level API?

If people want to make plots in different units, that should be easy (I can't think of any other use cases...).

What unit conversion is happening in the low-level API?

All of the conversion when we get requests from models e.g. MAGICC's adaptor says, give me CO2 emissions in GtC/yr but the user set them as MtC / month, the low-level API has to do that conversion.

@znicholls
Copy link
Collaborator Author

znicholls commented Oct 30, 2018

What units do we need actually?

Ideally all the emissions units in that file, plus conversions for all the key IPCC metrics (AR5GWP20, AR5GWP100, AR5GTP20, AR5GTP100, AR4GWP100, AR4GWP20 etc.), concentrations units (ppm, ppb, ppt), physical units (K, C, W/m^2, kg, m, s) etc. plus all the conversions between them as, including prefixes and different times for the fluxes (e.g. per year, per month, per day, per second).

@swillner
Copy link
Member

Hmm, ok, we shouldn't use two different unit libraries... Then I will use such a function getting offset and scaling from points, though far from optimal. But including something like that in Pint would probably better rely on Pint internals...

@znicholls
Copy link
Collaborator Author

though far from optimal

I don't understand why? If we implement something in Pint which is exactly the same as the unyt functionality, isn't that fine?

@swillner
Copy link
Member

unyt directly exposes the offset and scaling that are used internally (in Pint these are hidden much deeper). Using two points (e.g. 1 unit and 10 unit) to calculate offset and scaling is just a work-around. Maybe it's just my desire for asthetic code then ;)
At best, I would want a unit library to expose something like a "Converter" class, that takes two units and exposes functions to convert numbers (just floats, not some wrapping Unit classes) back and forth between the two units...

@swillner
Copy link
Member

Ok, I will have a look if we can make a PR in Pint with something like that, what do you think?

@znicholls
Copy link
Collaborator Author

Ok, I will have a look if we can make a PR in Pint with something like that, what do you think?

I like it. Good procrastination ;)

@znicholls
Copy link
Collaborator Author

@rgieseke to you for final say and then merge?

Is this all we needed in this PR?

@rgieseke
Copy link
Member

rgieseke commented Nov 2, 2018

@swillner @znicholls In general, is this ready to be merged or are you still tweaking?

@rgieseke
Copy link
Member

rgieseke commented Nov 2, 2018

Current failure is from the notebook.

@znicholls
Copy link
Collaborator Author

In general, is this ready to be merged or are you still tweaking?

Nope. Let's let Sven do his additions then I'll do the usual:

  • add tests
  • add docs
  • add changelog entry
  • add example

@swillner
Copy link
Member

swillner commented Nov 2, 2018

I'm not yet done with the units... Since it's just adding two lines (g and t) for each gas, should'nt we resort to defining them programmaitcally, e.g.

gases = {
    "C": "carbon,
    ...
}
for k, v in gases.items():
    ureg.define("{} = [{}]".format(k, v))
    ureg.define("g{} = g * {}".format(k, k))
    ureg.define("t{} = t * {}".format(k, k))

and then add the conversions between them?

@znicholls
Copy link
Collaborator Author

znicholls commented Nov 4, 2018 via email

@swillner
Copy link
Member

swillner commented Nov 4, 2018

@rgieseke Have you disabled the "normal" merge option?

@znicholls
Copy link
Collaborator Author

Have you disabled the "normal" merge option?

yep merge commits are annoying, I prefer rebase...

@swillner
Copy link
Member

swillner commented Nov 4, 2018

ah, ok. will you have the honor then? ;)

@znicholls
Copy link
Collaborator Author

znicholls commented Nov 4, 2018 via email

@swillner swillner merged commit d61e5d7 into master Nov 4, 2018
@swillner swillner deleted the add-units branch November 4, 2018 13:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants