Last updated:
0 purchases
qnit 0.5.0
qnit
[kjuː.nɪt] (though some may call it [knɪt])
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.
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.