Giter Site home page Giter Site logo

kenkundert / quantiphy Goto Github PK

View Code? Open in Web Editor NEW
61.0 8.0 5.0 1.54 MB

Physical quantities

Home Page: https://quantiphy.readthedocs.io

License: MIT License

Shell 0.14% Python 99.86%
python si-units si-prefixes quantities units unit-conversions quantiphy

quantiphy's Introduction

QuantiPhy — Physical Quantities

downloads build status coverage rtd status pypi version anaconda version python version

Author: Ken Kundert
Version: 2.20
Released: 2024-04-27

What?

QuantiPhy is a Python library that offers support for physical quantities. A quantity is the pairing of a number and a unit of measure that indicates the amount of some measurable thing. QuantiPhy provides quantity objects that keep the units with the number, making it easy to share them as single object. They subclass float and so can be used anywhere a real number is appropriate.

Why?

QuantiPhy naturally supports SI scale factors, which are widely used in science and engineering. SI scale factors make it possible to cleanly represent both very large and very small quantities in a form that is both easy to read and write. While generally better for humans, no general programming language provides direct support for reading or writing quantities with SI scale factors, making it difficult to write numerical software that communicates effectively with people. QuantiPhy addresses this deficiency, making it natural and simple to both input and output physical quantities.

Features

  • Flexibly reads amounts with units and SI scale factors.
  • Quantities subclass the float class and so can be used as conventional numbers.
  • Generally includes the units when printing or converting to strings and by default employs SI scale factors.
  • Flexible unit conversion and scaling is supported to make it easy to convert to or from any required form.
  • Supports the binary scale factors (Ki, Mi, etc.) along with the normal SI scale factors (k, M, etc.).
  • When a quantity is created from a string, the actual digits specified can be used in any output, eliminating any loss of precision.

Alternatives

There are a considerable number of Python packages dedicated to units and quantities (alternatives). However, as a rule, they focus on the units rather than the scale factors. In particular, they build a system of units that you are expected to use throughout your calculations. These packages demand a high level of commitment from their users and in turn provide unit consistency and built-in unit conversions.

In contrast, QuantiPhy treats units basically as documentation. They are simply strings that are attached to quantities largely so they can be presented to the user when the values are printed. As such, QuantiPhy is a light-weight package that demands little from the user. It is used when inputting and outputting values, and then only when it provides value. As a result, it provides a simplicity in use that cannot be matched by the other packages.

In addition, these alternative packages generally build their unit systems upon the SI base units, which tends to restrict usage to physical quantities with static conversion factors. They are less suited to non-physical quantities or conversion factors that change dynamically, such as with currencies. QuantiPhy gracefully handles all of these cases.

Quick Start

You can find the documentation on ReadTheDocs. Install with:

pip3 install --user quantiphy

Requires Python 3.6 or newer. If you using an earlier version of Python, install version 2.10 of QuantiPhy.

You can find the full documentation here.

You use Quantity to convert numbers and units in various forms to quantities:

>>> from quantiphy import Quantity

>>> Tclk = Quantity(10e-9, 's')
>>> print(Tclk)
10 ns

>>> Fhy = Quantity('1420.405751786 MHz')
>>> print(Fhy)
1.4204 GHz

>>> Rsense = Quantity('1e-4Ω')
>>> print(Rsense)
100 

>>> cost = Quantity('$11_200_000')
>>> print(cost)
$11.2M

>>> Tboil = Quantity('212 °F', scale='°C')
>>> print(Tboil)
100 °C

Once you have a quantity, there are a variety of ways of accessing aspects of the quantity:

>>> Tclk.real
1e-08

>>> float(Fhy)
1420405751.786

>>> 2*cost
22400000.0

>>> Rsense.units
'Ω'

>>> str(Tboil)
'100 °C'

You can use the render method to flexibly convert the quantity to a string:

>>> Tclk.render()
'10 ns'

>>> Tclk.render(show_units=False)
'10n'

>>> Tclk.render(form='eng', show_units=False)
'10e-9'

>>> Fhy.render(prec=8)
'1.42040575 GHz'

>>> Tboil.render(scale='°F')
'212 °F'

The fixed method is a variant that specializes in rendering numbers without scale factors or exponents:

>>> cost.fixed(prec=2, show_commas=True, strip_zeros=False)
'$11,200,000.00'

You can use the string format method or the new format strings to flexibly incorporate quantity values into strings:

>>> f'{Fhy}'
'1.4204 GHz'

>>> f'{Fhy:.6}'
'1.420406 GHz'

>>> f'❬{Fhy:<15.6}❭'
'❬1.420406 GHz   ❭'

>>> f'❬{Fhy:>15.6}❭'
'❬   1.420406 GHz❭'

>>> f'{cost:#,.2P}'
'$11,200,000.00'

>>> f'Boiling point of water: {Tboil:s}'
'Boiling point of water: 100 °C'

>>> f'Boiling point of water: {Tboil:s°F}'
'Boiling point of water: 212 °F'

QuantiPhy has many more features and capabilities. For more information, view the documentation.

quantiphy's People

Contributors

djailla avatar kenkundert avatar me-mark-o avatar rickyteng avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

quantiphy's Issues

setup.py no longer lists test requirements

The latest release has removed the list of test requirements from setup.py. The tests now also require parametrize_from_file. Is there any reason why this was done? It makes it more tricky to package if you can't obviously see what other modules are required to run tests.

Consider removing setup_requires from setup.py

Using setup_requires requires that pip has no way of controlling where these dependencies are located.

setup_requires = 'pytest-runner>=2.0'.split(),

See

This makes it difficult/impossible to bundle this library for offline installs, for example, using pip download or if a pip.conf file is needed to configure pip for a proxy settings, etc.

Typically test dependencies would be specified in tox.ini, which is already done:

pytest

This would make the sdist for this package much more portable. Users will likely just want to use tox to run the tests anyway?

Unitless scales

Hi Ken,

This is a great library. One feature I think I am missing though is some way to parse strings like "120 dB" as absolute values without requiring units. As far as I understand, I have to define a conversion like:

UnitConversion('V', 'dBV', from_dB, to_dB)

but what if my unit is dimensionless (such as an op-amp's open loop gain, commonly expressed in datasheets in dB)? I tried

UnitConversion('', 'dB', from_dB, to_dB)

but this doesn't seem to work. Is this behaviour somehow supported?

Upload wheels to PyPI

Wheels (.whl) for this package are currently missing from PyPI. Could wheels be uploaded for the current and future releases?

Read more about the advantages of wheels to understand why generating wheel distributions are important.

To create a wheel along with source distribution:

(venv) $ pip install --upgrade pip setuptools wheel
(venv) $ python setup.py sdist bdist_wheel

# See dist/*.whl

To upload wheels:

(venv) $ pip install twine
(venv) $ twine upload dist/*

meter is not recognized

Hi,
first of all great package!
I've some problem to convert meter, for example:
Quantity('10 m').units
return an empty string. I've also a strange behavior with:
Quantity('10 meter').units
Which return 'eter'.

I think it is a problem in the parsing, i thought that it is more intuitive that '10 m' is recognized like 10 meter instead of 0.01 without unit.
Package version 2.19
Thanks in advance.

Custom radix

Hi,
This looks much better than engfmt, thanks for the tip! Among the new stuff I want to use, I found the radix preference. Is it for the input, output or both?

from the doc:
radix (str) – The character to be used as the radix. By default it is ‘.’.
radix – The text to be used as the plus sign. By default it is ‘+’, but is sometimes ‘+’ (the unicode full width plus sign) or ‘’ to simply eliminate plus signs from numbers. You can access the Unicode full width plus sign using Quantity.plus_sign.

First, I assume the second radix is an error and should read 'plus' or something like that.

So for the actual radix, it does not seam to work for the output:

import quantiphy as eng
eng.Quantity.set_prefs(radix=',')
t= eng.Quantity(3.123e-6,'m')
print(t.render())

results in 3.123 um

as for the input, a comma will be interpreted as a 3 digit separator (3,123e-6 m -> 3.123 mm)
thanks

No trailing zeros?

The output of

Fhy = Quantity('1.0000 MHz')
print Fhy.render(prec=5)

is just 1 MHz. Shouldn't there be trailing zeros when I set the precision to 5, i.e., shouldn't it be 1.0000 MHz? How can I achieve this? (The trailing zeros indicate the resolution I'm working with so I don't want to throw them away).

Adding Packages to Spack

Hi @KenKundert,

Thank you for developing and sharing quantiphy! ✨

We recently started using this package in ImpactX and it is of great help adding meaningful labels over wide dynamic unit ranges that we can simulate.

Related to that, we ship our software and its dependencies on a variety of package managers to serve our scientific users. For that purpose. I already found the

and would add one more package to the

The Spack package will rely on the upload that you already push to PyPI and thus should require minimal maintenance. We use Spack extensively to deploy to high-performance computers (HPC systems). There is no work on your side required and we can maintain that extra package, but if you like to be listed as package maintainer as well then please let me know and you will get pings for new versions and reviews 🔔

All the best,
Axel

Rounding is wrong

print('Cx = Cs = %s' % Quantity(12.25, 'F').render(prec=2))

gives

Cx = Cs = 12.2 F

while 12.25 should be rounded to 12.3

translate to Russian Cyrillic

How I can translate SI units on Russian cyryllic?
like:
m: м (milli)
Ohm: Ом
k: к (killo)
Ghz: Гц
and so on

Quantity returns the wrong value

I noticed an error in the calculations when modifing my code to use Qunatity. It decodes 315p correctly but the string '5p4' was translated into 5. It is normal in electrical engineering to use the sci-unit instead of a decimal point and my own decode routine handled this ok. values like 2k7 for resistors and 4p7 for capacitors is normal engineering notation. It works fine if I change the string to 5.4p.

Converting nanoseconds to picoseconds?

I tried reading a bit through the docs, but cannot figure how to do this...

Let's say I have a '1 ns', and I would like to convert this to picoseconds; a-priori I know that 1 ns = 1000 ps. So:

>>> from quantiphy import Quantity
>>> mytime=Quantity('1 ns')
>>> mytime
Quantity('1 ns')
>>> mytime.real
1e-09
>>> mytime.units
's'
>>> mytime.render(scale='ps')
Traceback (most recent call last):
  File "/usr/lib/python3.8/site-packages/quantiphy.py", line 235, in convert_units
    return _unit_conversions[(to_units, from_units)](value)
KeyError: ('ps', 's')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.8/site-packages/quantiphy.py", line 2207, in render
    number, units = _scale(scale, number, self.units)
  File "/usr/lib/python3.8/site-packages/quantiphy.py", line 55, in _scale
    number = convert_units(scale, units, number)
  File "/usr/lib/python3.8/site-packages/quantiphy.py", line 237, in convert_units
    raise UnknownConversion(to_units, from_units)
quantiphy.UnknownConversion: unable to convert between 'ps' and 's'.

>>> mytime.render(1e-12, scale='s')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.8/site-packages/quantiphy.py", line 2250, in render
    assert form in ['eng', False], '{}: unknown form.'.format(form)
AssertionError: 1e-12: unknown form.

How can I correctly convert from one to another prefix (e.g. n to p), without changing the (physical) unit?


Edit: Read through https://quantiphy.readthedocs.io/en/stable/user.html#scaling-when-creating-a-quantity - so I tried using a tuple for scale:

>>> mytime
Quantity('1 ns')
>>> mytime.render(scale=(1e-12, 's'))
'1e-21 s'

.... and this passes code-wise, but gives me the wrong result.


Edit2: found https://stackoverflow.com/questions/10969759/python-library-to-convert-between-si-unit-prefixes/45122861#45122861 - and thought this would help:

>>> mytime.render(show_si=False, scale=(1e-12, 'ps'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: render() got an unexpected keyword argument 'show_si'

Thankfully, it was easy to find in the repo that: "... change show_si to form ..."; so I tried this:

>>> mytime.render(form=False, scale=(1e-12, 'ps'))
'1e-21 ps'

Wrong result again ... however, the opposite seems to work:

>>> mytime.render(form=False, scale=(1e12, 'ps'))
'1e3 ps'

... yes, indeed 1ns is 1e3 = 1000 ps, great! Except, now I'm not sure, what is the meaning of the first number in scale ...

However, the .render function apparently just prints - what I'd like is to convert to a new Quantity, so that when I specify '1 ns' as input time, and specify 'ps' as the "output" unit, then I'd like to be able to read the 1e3 == 1000 as a plain number somehow (without the units) ... - Ah, that probably works like this:

>>> mytime.scale(scale=(1e12, 'ps'))
Quantity('1 kps')
>>> mytime.scale(scale=(1e12, 'ps')).real
1000.0000000000001

So, this kind of conversion is possible - but how are these kinds of conversions supposed to work?

Scaling Problem when entering Quantity

Hello, this my first issue report ever, so sorry if make some mistakes. I think when initializing the quantity there is something unclear or not correct. e.g.

>>> stress = Quantity('138 MPa')
>>> stress
Quantity('138 MPa')
>>> stress.as_tuple()
(138000000.0, 'Pa')
>>> stress = Quantity('138e6 Pa')
>>> stress
Quantity('138 MPa')
>>> stress.as_tuple()
(138000000.0, 'Pa')
>>> stress = Quantity('138 Pa')
>>> stress
Quantity('138e15 a')
>>> stress.as_tuple()
(1.38e+17, 'a')

The last value is not correct. Please see if it is a bug or I am not using it right. How can I enter stress in pascals ('Pa')?

Thanks,

Consider permissive license?

I noticed that the package is licensed as GPL:

'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)',

This poses licensing challenges for integrating this package into projects that distribute their applications as binary installers using PyInstaller/PyOxidizer or for closed source/commercial use cases. Relicensing to a permissive license (such as MIT) would allow quantiphy to be used in a broader set of use cases.

This, of course, is completely your decision, and I will happily close this issue if you decline.

DeprecationWarning when running py.test

Hello,

When running tests using quantiphy, I got this warning :

python3.6/site-packages/quantiphy.py:1268: DeprecationWarning: Flags not at the start of the expression '\\A\\s*(?P<sign>[-+]?)' (truncated) 15:21:54 for pattern, get_mant, get_sf, get_units in [

Anyone aware of this ?

Regards

prec='full' fails

latest stable release
prec='full' fails for example 1.0 returns 1, 10.0 returns 10
probable bug at line 772
" if mantissa.find('.') >= 0:"

The check should exclude case prec='full'

Question on use

Hello,

Opening an issue here since the discussions aren't enabled on this repo.

I would like to use the Quantity object to handle a variable that represents milliseconds. I want to keep the number in ms units, since I am writing test code that passed on the value to some underlying Java that expects units of ms. Currently, quaniphy is showing me "kilo-milli-seconds", instead of the preferable "seconds. "

>>> t1 = Quantity(2500, "ms")
>>> print(t1)
2.5 kms

What I'd like to know is if I can tell quantiphy to normalize those units when printing, but still keep the internal number represented as milliseconds. I consulted the docs but didn't immediately see how to handle this situation.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.