-
Notifications
You must be signed in to change notification settings - Fork 473
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
Make physical constants (numerically) more easily accessible #1078
Comments
Right now, physical are just quantities, which is very useful but not complete. I been looking forward to create better support for constants. But I want to have better support for measurements first (so we can parse uncertainties from the definition file). |
Dear Sir,
Understood. There is a workaround for my issue anyway.
Thanks for a wonderful utility!
Sincerely,
Duane
…----- Original Message -----
Right now, physical are just quantities, which is very useful but not
complete. I been looking forward to create better support for constants. But
I want to have better support for measurements first (so we can parse
uncertainties from the definition file).
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub , or unsubscribe .
|
Constants can be considered a unit; like g0, gn for default gravity acceleration, or g_(yourlocation) for the gravitational accelleration at your measurement facility. At ours we used to use "g" which was not a problem until we started scaling values using pint. Of course "1 g" for 9.81 m/s^2 conflicts with 1 gram. |
Dear All,
gn or g_n (perhaps more memorable, but more letters...) works for me.
Sincerely,
Duane
…----- Original Message -----
Constants can be considered a unit; like g0, gn for default gravity
acceleration, or g_ for the gravitational accelleration at your measurement
facility. At ours we used to use "g" which was not a problem until we
started scaling values using pint. Of course "1 g" for 9.81 m/s^2 conflicts
with 1 gram.
What is a standard for computer interpretable units that also support
constants, either be it common ones or industry specific? I found an elegant
solution at http://unitsofmeasure.org/ucum.html#const but I understood that
pint does not recognize the notation of this standard and I also don't know
if this standard is broadly adopted.
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub , or unsubscribe .
|
Really looking forward to this issue closure. I think it is a much-needed ability that can really elevate my code. |
@codejager asked
Indeed it is. UCUM is built in to LOINC and FHIR, which gets you much of the health and clinical community. So there is a practical benefit to adopting the UCUM style of unit codes/symbols. FWIW there is an API for testing and converting UCUM here: https://ucum.nlm.nih.gov/ucum-service.html |
I've just come across this issue whilst work on pint-xarray, and I'm confused as to
I don't understand what is meant by this - they are In [1]: from pint import UnitRegistry
In [2]: ureg = UnitRegistry()
In [3]: ureg.speed_of_light
Out[3]: <Unit('speed_of_light')> It seems to me that physical constants are regularly used as both units and like quantities. If I say "we measure the speed of the galaxy in units of c" then I'm using it like a unit, and if I say " The argument for having constants represented as a Quantity is that the speed of light is a single real-world data point with a specific value (so has a magnitude), that is commonly expressed with certain units (and those units may be different in a different unit system). Isn't that simply just a (For what it's worth the uynt package just has two lists, one for Units and one for Physical Constants, and they both have the speed of light in them.) Can we have physical constants listed as both Units and Quantities? Presumably that would mean the
Why do we need support for uncertainties first? Can we not have functionality for physical constants without uncertainties to begin with and with uncertainties later? |
I am 100% in favor of restructuring the constants API to include your suggestion. The reason of having the measurement API overhaul is to include constants with their uncertainties. But if someone wants to work on the constants first, go for it! |
Okay, so thinking about this more, I think I need to:
|
So is the idea that "constants" can be accessed as quantities in system-specific base units? Right now, What should dimensionless constants return? Will >>> import decimal
>>> decimal.getcontext().prec = 55
>>> import pint
>>> ureg = pint.UnitRegistry(non_int_type=decimal.Decimal)
>>> ureg.Quantity(1, ureg.pi)
<Quantity(1, 'pi')>
>>> _.to_base_units()
<Quantity(3.1415926535897932384626433832795028841971693993751, 'dimensionless')>
>>> _.m
Decimal('3.1415926535897932384626433832795028841971693993751') # is this what ureg.constants.pi should return? If a user has a custom list of constants, will there be a new way to load the definitions file? Can we maybe implement a kwarg like Will there be a way to programmatically define new constants once the registry is initiated? Maybe Personally, I think it will be more of a hassle to support this instead of just telling users in the documentation they can just use The big problem I see is that the whole unit definition process right now is designed to be easily expanded and that prevents us from separating constants and units in the definition files. The constants are currently just explicitly imported into default_en.txt with no differentiation, and it's definitely useful to be able to represent values in terms of pi etc. so them being units as default just works IMO. Although this should definitely be talked about in another issue, the easiest way to allow much more flexible unit/constant definitions (with uncertainties too) would be to define them as dicts or some other python structure in a |
Indeed constants are just units right now. There is on difference in terms of definition in a text file or internal usage or API. This was great in pint early stages as it allowed us to expand pint capabilities without making the code harder nor longer. Another nice thing is that many time you want an "algebraic" usage (i.e The main complain that I have seen is that constants are "different" and we should provide by default the "explicity value". I think that @OrangeChannel makes a great point that might allow use to satisfy both user cases without changing the code to much.
What if we provide
This requires minor changes to the codebase, no change to the definitions and just some documentation. It does not solve the uncertainty problem which is an important one but could be a nice way in the right direction as I do not see any drawback of this API in the future. |
You raise a lot of good points @OrangeChannel .
You might well be right about this.
I do quite like this idea of just providing more functional ways to access things as constants instead of defining entirely new lists. |
Let me describe my suggestion in more detail:
def __getattr__(self, item):
getattr_maybe_raise(self, item)
u = getattr(self._REGISTRY, self.name + "_" + item, None)
if u is not None:
return u
if u in self._REGISTRY.get_group("constants"):
return 1 * self._REGISTRY.get_base_units(u)
return getattr(self._REGISTRY, item)
def __getattr__(self, item):
if u in self._REGISTRY.constants.members:
return 1 * self._REGISTRY.get_base_units(u)
return getattr(self._REGISTRY, item)
@property
def constants(self):
return self._REGISTRY.get_group("constants") (1) provides a way to declare constants without any additional syntax In use >>> ureg.speed_of_light
<Unit('speed_of_light')>
>>> 1 * ureg.speed_of_light
<Quantity(1, 'speed_of_light')>
>>> ureg.sys.imperial.speed_of_light
<Quantity(3.27857019e+08, 'yard / second')>
>>> ureg.constants.speed_of_light # if the current system is 'mks'
<Quantity(2.99792458e+08, 'meter / second')> If I get your comment 3 days ago as a list of requirements:
And then
Not needed as we used the Group API
Not needed.
Not needed . What do you think? |
Oh, I was working on my own solution and just finished as well. I didn't know about the group api and the way I did it is definitely not the most elegant 😄 . Here's how my solution works (I lazily just used the UnitRegistry in places and I think that's wrong) >>>import pint
>>>ureg = pint.UnitRegistry()
>>>ureg.constants.speed_of_light
<Quantity(2.99792458e+08, 'meter / second')>
>>>ureg.constants.US.speed_of_light
<Quantity(3.27857019e+08, 'yard / second')>
>>>ureg.constants.US('c')
<Quantity(3.27857019e+08, 'yard / second')>
>>>ureg.constants['c']
<Quantity(2.99792458e+08, 'meter / second')>
@hgrecco That looks great, I think this part (shown below) should be changed though. It should probably be >>> ureg.sys.imperial.speed_of_light
<Quantity(3.27857019e+08, 'yard / second')> |
1. A new property `contants` is added to the registry. 2. This property is just a reference to the `constants` Group. 3. This group is populated using the @group directive in the definitions file. 4. Minor changes to Group and System __getattr__ This change is fully backwards compatible: ```python >>> ureg.speed_of_light <Unit('speed_of_light')> >>> 1 * ureg.speed_of_light <Quantity(1, 'speed_of_light')> >>> ureg.sys.imperial.speed_of_light <Quantity(3.27857019e+08, 'yard / second')> >>> ureg.constants.speed_of_light # if the current system is 'mks' <Quantity(2.99792458e+08, 'meter / second')> ``` Close #1078
1. A new property `contants` is added to the registry. 2. This property is just a reference to the `constants` Group. 3. This group is populated using the @group directive in the definitions file. 4. Minor changes to Group and System __getattr__ This change is fully backwards compatible: ```python >>> ureg.speed_of_light <Unit('speed_of_light')> >>> 1 * ureg.speed_of_light <Quantity(1, 'speed_of_light')> >>> ureg.sys.imperial.speed_of_light <Quantity(3.27857019e+08, 'yard / second')> >>> ureg.constants.speed_of_light # if the current system is 'mks' <Quantity(2.99792458e+08, 'meter / second')> ``` Close #1078
Hi @OrangeChannel and the rest of the people in this thread. I have pushed to my develop branch an implementation of my proposed constants API. AFAIK is fully backwards compatible and does not change Pint too much. It is also future compatible (I think) as any upgrades to the constants (ie. adding uncertainties) could be added. The only thing that I do not like is that I am open to ideas, suggestions and criticisms. |
I was experimenting with some stuff and found some possibly unwanted behavior in >>> ureg.c, ureg.speed_of_light
(<Unit('speed_of_light')>, <Unit('speed_of_light')>)
>>> ureg.constants.c, ureg.constants.speed_of_light
(<Unit('speed_of_light')>, <Quantity(2.99792458e+08, 'meter / second')>)
# why is c returning a Unit but speed_of_light a Quantity Let's say I want to add my own constant, >>> ureg.define('testing = 0.8 * meter')
>>> ureg.constants.members
frozenset({'neutron_mass', 'K_alpha_W_d_220', 'coulomb_constant', ...})
>>> 'testing' in _
False
>>> ureg.constants.testing # should not be accessible
<Unit('testing')> # how? # correct behavior
>>> ureg.define('testing = 0.8 * meter')
>>> ureg.constants.add_units('testing')
>>> ureg.testing, ureg.constants.testing
(<Unit('testing')>, <Quantity(0.8, 'meter')>) # expected
>>> 'testing' in ureg.constants
TypeError: argument of type 'Group' is not iterable # should this work?
>>> ureg.constants.members
frozenset({'boltzmann_constant', 'elementary_charge', ...}) # 'testing' is in this
>>> 'testing' in ureg.constants.members
True # expected Now if I load my own definitions with this file: testing.txt:
>>> ureg.load_definitions(r'testing.txt')
>>> ureg.constants.members
frozenset({'testing_in_file'}) # did we overwrite the group?
>>> ureg.constants.testing_in_file
<Quantity(0.01524, 'meter')> # correct unit conversion
>>> ureg.constants.c, ureg.constants.speed_of_light
(<Unit('speed_of_light')>, <Unit('speed_of_light')>)
# !!! this is now using the wrong behavior again Now if I load my own definitions with this file: testing_groups.txt:
# correct behavior
>>> ureg.get_group('my_constants').members
frozenset({'testing_in_file'}) # correct behavior
>>> ureg.constants.add_groups('my_constants') # is this way the only way?
>>> ureg.constants.speed_of_light, ureg.constants.testing_in_file
(<Quantity(2.99792458e+08, 'meter / second')>, <Quantity(0.01524, 'meter')>) I also think the Also, would be nice to have a |
@OrangeChannel Regarding c/speed_of_light good catch, membership is not checked agains cannonical names, not alias. I should fix this. Also regarding overwriting and extending a group, I think is something to discuss. I think both API could be useful and we can provide a syntax for that along the following lines
raises an error
warns if GROUP does not exists
warns if GROUP does not exists I like the |
Is this also desired behavior? >>> ureg.define('testing = 0.8 * meter')
>>> 'testing' in ureg.constants.members
False
>>> ureg.constants.testing # should not be accessible
<Unit('testing')> # how? Seems anything defined in the UnitRegistry is fetched even if it's not in the group, but it ignores the new constants behavior of returning a Quantity. It also happens with other groups, and not just members. >>> ureg.get_group('USCSLengthSurvey').testing
<Unit('testing')>
>>> ureg.get_group('USCSLengthSurvey').constants
<pint.systems.build_group_class.<locals>.Group object at 0x0000020EE55A9070>
>>> ureg.get_group('USCSLengthSurvey').define
<bound method BaseRegistry.define of <pint.registry.UnitRegistry object at 0x0000020EDD8FB8B0>> |
Any progress on this? Alternatively, can the workaround that is mentioned at the beginning of this thread be documented? I love using pint for quick calculations but I often need constants and it's a pain to define them manually using Scipy and look up the dimensionality every time. |
What is the current status of this issue? |
Hi,
I would like to easily be able to retrieve the numerical value of a constant in Pint.
I believe this is a follow-on to "Make physical constants more easily accessible #159", and forgive me if my request has been answered and I have just been unable to find it
If I try to use the .to() method with constants, I get an error.
Right now I am converting constants to Quantities by multiplying by 1, like this:
Is this the preferred way to get a numerical representation of a constant?
Thanks,
Duane
The text was updated successfully, but these errors were encountered: