Skip to main content

A Python library for object-oriented parameters, physical quantities and units with a strong support for typing.

Project description

qnit

[kjuː.nɪt] (though some may call it [knɪt])

PyPI - Version GitLab Issues PyPI license PyPI pyversions Code style: black

A Python package for object-oriented physical parameters, quantities and units with a strong support for typing.

This library heavily builds upon Pint and Pint-Pandas.

Contents

[[TOC]]

Features

  • Physical Quantitys you can set with magnitude and units, convert to other units, get magnitudes or work with the underlying pint quantity.
  • Parameters with quantity values ("units-aware") which can be worked with accordingly.
  • Parameters with non-quantity values ("units-naive").
  • Complete and enhanced interface to pint and pint-pandas
  • Easily extensible library of physical quantities (s. Library)
  • Heavy support for typing:
    • Specify a quantity's units type and get type hints when you're about to do something wrong, e.g. convert an Energy quantity to kg units.
    • Specify a parameter's data type and be hinted when you're about to set an incompatible value.

Getting Started

Prerequisites

  • Python 3.9 or later

Install

Install qnit from the PyPI in your virtual environment:

$ python -m pip install qnit

Usage

The package provides two main classes: Quantity and Parameter.

Quantity objects represent physical quantities and support units-aware calculations.

Likewise, Parameter objects can also handle units and physical quantities through their quantity property. However, as parameters in a scientific or engineering context may not always be physical quantities, they can also represent units-naive values such as booleans or strings.

Both Quantity and Parameter can handle multi-dimensional array magnitudes and values.

Quantity

A Quantity's magnitude and units can be set during or after instantiation by using the initializer or set method. The quantity can be converted to other units or its magnitude (as specified units) can be picked out.

It is also possible to work further with the underlying pint Quantity object by using the pint_quantity property.

from qnit import Quantity, quantity_types, units_collections, units_types, ureg

# Create a mass quantity and set its value
mass: Quantity[units_types.Mass] = Quantity(
  quantity_type=quantity_types.Mass,
  description="A mass quantity.",
)
mass.set(magnitude=42, units=units_collections.Mass.kg)

# Convert units and get magnitudes using the underlying `pint` quantity.
mass.pint_quantity.to(units_collections.Mass.g)
mass.pint_quantity.to('g')
# <Quantity(42000.0, 'gram')>

mass.pint_quantity.m_as(units_collections.Mass.g)
mass.pint_quantity.m_as('g')
# 42000.0

mass.pint_quantity + 4 * ureg.kg
# <Quantity(46.0, 'kilogram')>

# Get magnitudes as different units
mass.magnitude(units=units_collections.Mass.tonne)
# 0.042

# Internal and display units are defined in the `Mass` quantity type.
quantity_types.Mass.internal_units
# 'kg'
quantity_types.Mass.default_display_units
# 'kg'
mass.internal_magnitude
# 42.0
mass.display_magnitude
# 42.0

Use mypy or your favorite IDE to warn you about units related errors before runtime

from qnit import Quantity, quantity_types, units_collections, units_types

mass: Quantity[units_types.Mass] = Quantity(
  quantity_type=quantity_types.Mass,
  description="A mass quantity.",
  magnitude=42,
  units=units_collections.Mass.kg,
)
mass.magnitude(units_collections.Energy.kWh)
# Warning here: Expected type 'Mass', got 'Energy' instead 

Parameter

To handle units-aware as well as units-naive Parameter objects, Parameter provides a value property. For units-naive parameters it is either a scalar or array-like units-naive value (of type specified at parameter declaration). In case of a units-aware parameter it is a Quantity (with the given units type specified at parameter declaration).

Units-aware Parameter objects also provide properties and methods for getting or setting the underlying Quantity object or magnitudes/units.

All Parameters provide a value comment to be set through the initializer or the set_value or set_magnitude_units methods or to be get through the valueComment attribute.

from qnit import Parameter, quantity_types, units_collections, units_types

# Create a units-naive parameter and set its value
name: Parameter[str, units_types.NoUnits] = Parameter(
  data_type=str,
  description="Name of developer",
)
name.set_value(value='Peter', value_comment="We might also call it `q-nit`!")

# Create a units-aware parameter and set its value
temperature : Parameter[float, units_types.Temperature] = Parameter(
  data_type=float,
  quantity_type=quantity_types.Temperature,
  description="Temperature of developer"
)
temperature.set_magnitude_units(
  magnitude=36.6, 
  units=units_collections.Temperature.deg_C,
  value_comment="Temperature measured today"
)

Library

In order to ensure a strong support for typing the package contains internal library of physical quantities, specifying:

  • units types (e.g. units_types.Mass),
  • units collections with supported units for each units type
  • quantity types (e.g. quantity_types.Mass) which themselves provide
    • internal units (to be used for conversion at user interfaces)
    • default display units (to be used in user frontends)
    • available units (given as UnitsCollection objects)

At the present the library consists of the quantities listed in the table below.

Physical Domains Quantities
Dimensionless Dimensionless
Base Quantities Length
Mass
Time
Temperature
Current
Base Derived Quantities Volume
Density
Pressure
Time Frequency
DurationShare
ShareInPeriod
Geometry Angle
Area
Mechanics & Kinetics Velocity
Acceleration
Thermodynamics TemperatureDifference
Energy
Enthalpy
InternalEnergy
MechanicalWork
EnthalpyFlow
Power
HeatFlow
ThermalEfficiency
HeatFlowLossShare
HeatLossShare
SpecificHeatCapacity
CarnotEfficiency
FuelPerformance
Fluid Dynamics VolumeFlow
MassFlow
DynamicViscosity
KinematicViscosity
Heat and Mass Transfer HeatCapacityRate
HeatTransferCoefficient
ThermalConductivity
QuadraticHeatTransferCoefficient
Financial Currency
HourlyCosts
EnergyCosts
Energy Engineering EnergyYield
PowerAreaRatio
GeothermalProdIndex
LinearPressure
QuadraticPressure
TemperatureCorrection

If needed, the library can be easily extended by subclassing BaseUnitsType, UnitsCollection or QuantityType. Especially by subclassing QuantityType developers can define their own internal_magnitude and default_magnitude.

from qnit import quantity_types, units_collections, units_types

sample_mass: quantity_types.QuantityType[units_types.Mass] = (
  quantity_types.QuantityType(
    units_type=units_types.Mass,
    internal_units=units_collections.Mass.g,
    default_display_units=units_collections.Mass.g,
    available_units=units_collections.Mass()
))

Development

To set up a development environment you need a virtual environment and Poetry, for example:

POETRY_VIRTUALENVS_IN_PROJECT=1 poetry install

Testing and Type Checks

Tests for qnit are written with pytest. You can run the test suite with

pytest tests

Both qnit itself as well as its tests are to be properly typed. To check this you can run

mypy src
mypy tests

You can also run the test suite in all supported Python environments together with the type checks using tox:

tox run

For this to work, you should have all supported Python versions installed in your operating system, e.g. by using pyenv.

Formatting

We use Black as our code formatter.

black --preview .

Contributing

Before requesting your contribution to be merged, please make sure that all tests check out and that your code is properly formatted:

black --preview .
tox run

License

qnit is licensed under the terms of the GNU AGPLv3 License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

qnit-0.5.1.tar.gz (29.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

qnit-0.5.1-py3-none-any.whl (29.7 kB view details)

Uploaded Python 3

File details

Details for the file qnit-0.5.1.tar.gz.

File metadata

  • Download URL: qnit-0.5.1.tar.gz
  • Upload date:
  • Size: 29.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.12.3 Linux/6.8.0-87-generic

File hashes

Hashes for qnit-0.5.1.tar.gz
Algorithm Hash digest
SHA256 a0c405da9fa42869097c8e1f6d90f104ad8059337c37a1c3e413f0108f5a293a
MD5 774b31cbdb05d62862052c545be02c81
BLAKE2b-256 6519537760fe529ee3c6d1d87b10e915f66ab6f36bd654044f41db6ca45ea4cf

See more details on using hashes here.

File details

Details for the file qnit-0.5.1-py3-none-any.whl.

File metadata

  • Download URL: qnit-0.5.1-py3-none-any.whl
  • Upload date:
  • Size: 29.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/2.2.1 CPython/3.12.3 Linux/6.8.0-87-generic

File hashes

Hashes for qnit-0.5.1-py3-none-any.whl
Algorithm Hash digest
SHA256 aa7bf6d869e7355293d8f124668ace3e0ddb4589a92add297d7f56428c9698dd
MD5 360d5d4f4e6a7c12b9898e79959cf571
BLAKE2b-256 693363ae8e5c7655205605f4fc23e4c15018b5997edb56da801f7c984f2a56c5

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page