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.

⚠️ This project is currently under heavy development. Expect API changes.

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.0.tar.gz (30.6 kB view hashes)

Uploaded Source

Built Distribution

qnit-0.5.0-py3-none-any.whl (29.7 kB view hashes)

Uploaded Python 3

Supported by

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