Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: xnx/pyqn
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.4
Choose a base ref
...
head repository: xnx/pyqn
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref
  • 2 commits
  • 6 files changed
  • 1 contributor

Commits on May 19, 2024

  1. Fix conversion of molar units

    xnx committed May 19, 2024
    Copy the full SHA
    2bb2680 View commit details

Commits on Jan 29, 2025

  1. Remove email address

    xnx committed Jan 29, 2025
    Copy the full SHA
    f92f782 View commit details
Showing with 74 additions and 23 deletions.
  1. +1 −2 setup.py
  2. +1 −2 src/pyqn/dimensions.py
  3. +16 −12 src/pyqn/units.py
  4. +39 −1 tests/test_conversions.py
  5. +1 −6 tests/test_units.py
  6. +16 −0 tests/test_userdef_units.py
3 changes: 1 addition & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -8,13 +8,12 @@

setup(
name="pyqn",
version="1.4",
version="1.4.1",
description="A package for managing physical units and quantities",
long_description=long_description,
long_description_content_type="text/x-rst",
url="https://github.com/xnx/pyqn",
author="Christian Hill",
author_email="xn.hill@gmail.com",
classifiers=[
"Development Status :: 4 - Beta",
"Intended Audience :: Science/Research",
3 changes: 1 addition & 2 deletions src/pyqn/dimensions.py
Original file line number Diff line number Diff line change
@@ -47,8 +47,7 @@ def __init__(self, dims=None, **kwargs):
if not kwargs:
self.dims = dims
else:
print("bad initialisation of Dimensions object")
sys.exit(1)
raise ValueError("Bad initialisation of Dimensions object")
else:
# initialize by keyword arguments
for dim_name in kwargs:
28 changes: 16 additions & 12 deletions src/pyqn/units.py
Original file line number Diff line number Diff line change
@@ -29,6 +29,10 @@
h, NA, c, kB = (6.62607015e-34, 6.02214076e23, 299792458.0, 1.380649e-23)


class UnitsConversionError(UnitsError):
pass


class Units:
"""
A class to represent the units of a physical quantity.
@@ -327,25 +331,25 @@ def kBT_conversion(self, other):
else:
raise UnitsError(
"Failure in conversion of units: was expecting to "
"covert between energy and temperature"
"convert between energy and temperature"
)
return fac / other.to_si()

def mol_conversion(self, other):
from_dims = self.get_dims() # original unit dimensions
to_dims = other.get_dims() # desired unit dimensions
fac = self.to_si() # factor needed to conver to SI units
from_dims_Q = self.get_dims().dims[4]
to_dims_Q = other.get_dims().dims[4]

if from_dims.dims[4] == to_dims.dims[4]:
raise UnitsError(
"Failure in conversion of units: no "
"different in quantity dimensions between %s and %s" % from_dims,
to_dims,
# We can only remove or add the amount dimension in its entirity.
if from_dims_Q and to_dims_Q:
raise UnitsConversionError(
f"Cannot force molar conversion between {self} and {other}"
)
elif from_dims.dims[4] > to_dims.dims[4]:
fac = fac / (NA ** (from_dims.dims[4] - to_dims.dims[4]))

fac = self.to_si()
if from_dims_Q:
fac = fac * NA**from_dims_Q
else:
fac = fac * (NA ** (to_dims.dims[4] - from_dims.dims[4]))
fac = fac * NA**to_dims_Q
return fac / other.to_si()

def spec_conversion(self, other):
40 changes: 39 additions & 1 deletion tests/test_conversions.py
Original file line number Diff line number Diff line change
@@ -31,13 +31,51 @@ def test_litres(self):
self.assertEqual(u1.to_si(), 1.0e-3)

def test_molar_units_conversion(self):

u1 = Units("mol")
u2 = Units("1")
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 6.02214076e23)

u1 = Units("mol-1")
u2 = Units("1")
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 1 / 6.02214076e23)
print(u1.dims.dims)

u1 = Units("mol2")
u2 = Units("1")
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 6.02214076e23**2)

u1 = Units("mol-2")
u2 = Units("1")
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 6.02214076e23**-2)

u1 = Units("kJ")
u2 = Units("J/mol")
u2 = Units("kJ.mol-1")

with self.assertRaises(UnitsError) as cm:
u1.conversion(u2, strict=True)
self.assertAlmostEqual(u1.conversion(u2, force="mol"), 1.660e-21)

u3 = Units("cal.mol-1")
u4 = Units("eV")
self.assertAlmostEqual(u3.conversion(u4, force="mol"), 4.3364104350063916e-05)

u9 = Units("nmol2.L-1")
u10 = Units("L-1")
self.assertAlmostEqual(u9.conversion(u10, force="mol"), 3.626617933325338e29)

u5 = Units("J.mmol-1")
u6 = Units("J")
self.assertAlmostEqual(u5.conversion(u6, force="mol"), 1.6605390671738467e-21)

u7 = Units("1")
u8 = Units("mol-2")
self.assertAlmostEqual(u7.conversion(u8, force="mol"), 2.757389993610589e-48)

u9 = Units("nmol2.L-1")
u10 = Units("L-1")
self.assertAlmostEqual(u9.conversion(u10, force="mol"), 3.626617933325338e29)

def test_kBT_units_conversion(self):
u1 = Units("K")
u2 = Units("J")
7 changes: 1 addition & 6 deletions tests/test_units.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
# test_units.py
#
# Copyright (C) 2012-2016 Christian Hill
#
# Version 1.0
# Unit tests for the Units class.
"""Unit tests of basic functionality for the Units class."""

import unittest
from fractions import Fraction
16 changes: 16 additions & 0 deletions tests/test_userdef_units.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import unittest
from fractions import Fraction
from pyqn.units import Units
from pyqn.dimensions import Dimensions, d_energy


class UserDefinedUnitsCheck(unittest.TestCase):
"""Unit tests for user-defined units."""

def test_dimensionless_units(self):
return
u1 = Units("cm-2.molec-1", dimensionless=("molec",))


if __name__ == "__main__":
unittest.main()