Skip to content

Commit

Permalink
Modify tests
Browse files Browse the repository at this point in the history
Signed-off-by: Sorin Birchi <sb.birchi.sorin@gmail.com>
  • Loading branch information
Sorin Birchi committed Aug 24, 2024
1 parent ae83c4e commit 81fbdea
Show file tree
Hide file tree
Showing 9 changed files with 101 additions and 83 deletions.
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
version: 2
updates:

# Maintain dependencies for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
2 changes: 1 addition & 1 deletion .github/workflows/pytest-ubuntu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ jobs:
- name: Run tests
run: |
pytest
pytest --doctest-modules
2 changes: 1 addition & 1 deletion QuantSI/allunits.py
Original file line number Diff line number Diff line change
Expand Up @@ -7922,7 +7922,7 @@ class _Celsius:
"ambiguities when mixed with absolute temperatures defined"
"in Kelvin. Directly use 'kelvin' when you are only"
"interested in temperature differences, and add the"
"'zero_celsius' constant from the unitSI.constants"
"'zero_celsius' constant from the QuantSI.constants"
"module if you want to convert a temperature from Celsius to"
"Kelvin."
)
Expand Down
15 changes: 15 additions & 0 deletions QuantSI/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import pytest

def pytest_collection_modifyitems(config, items):
# List of function names whose doctests should be skipped
functions_to_skip = {
"QuantSI.fundamentalunits.Quantity.fill",
"QuantSI.fundamentalunits.Quantity.trace",
}

for item in items:
function_name = item.location[2] # The third element often contains the name in doctests
# Skip specific functions' doctests
if any(fn in function_name for fn in functions_to_skip):
item.add_marker(pytest.mark.skip(reason="Skipping doctest for specific function due to known documentation issues"))

4 changes: 2 additions & 2 deletions QuantSI/constants.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
r"""
A module providing some physical units as `Quantity` objects. Note that these
units are not imported by wildcard imports (e.g. `from unitSI.constants import *`), they
units are not imported by wildcard imports (e.g. `from QuantSI.constants import *`), they
have to be imported explicitly. You can use ``import ... as ...`` to import them
with shorter names, e.g.::
from unitSI.constants import faraday_constant as F
from QuantSI.constants import faraday_constant as F
The available constants are:
Expand Down
65 changes: 17 additions & 48 deletions QuantSI/fundamentalunits.py
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ def fail_for_dimension_mismatch(
return dim1, dim2

# We do another check here, this should allow Brian1 units to pass as
# having the same dimensions as a unitSI unit
# having the same dimensions as a QuantSI unit
if dim1 == dim2:
return dim1, dim2

Expand Down Expand Up @@ -656,7 +656,7 @@ def get_or_create_dimension(*args, **kwds):
--------
The following are all definitions of the dimensions of force
>>> from unitSI import *
>>> from QuantSI import *
>>> get_or_create_dimension(length=1, mass=1, time=-2)
metre * kilogram * second ** -2
>>> get_or_create_dimension(m=1, kg=1, s=-2)
Expand Down Expand Up @@ -879,7 +879,7 @@ def in_unit(x, u, precision=None):
Examples
--------
>>> from unitSI import *
>>> from QuantSI import *
>>> in_unit(3 * volt, mvolt)
'3000. mV'
>>> in_unit(123123 * msecond, second, 2)
Expand Down Expand Up @@ -925,7 +925,7 @@ def in_best_unit(x, precision=None):
Examples
--------
>>> from unitSI.allunits import *
>>> from QuantSI.allunits import *
>>> in_best_unit(0.00123456 * volt)
'1.23456 mV'
>>> in_best_unit(0.00123456 * volt, 2)
Expand Down Expand Up @@ -970,7 +970,7 @@ def quantity_with_dimensions(floatval, dims):
Examples
--------
>>> from unitSI import *
>>> from QuantSI import *
>>> quantity_with_dimensions(0.001, volt.dim)
1. * mvolt
Expand Down Expand Up @@ -1013,7 +1013,7 @@ class Quantity(np.ndarray):
Examples
--------
>>> from unitSI import *
>>> from QuantSI import *
>>> I = 3 * amp # I is a Quantity object
>>> R = 2 * ohm # same for R
>>> I * R
Expand All @@ -1028,9 +1028,9 @@ class Quantity(np.ndarray):
DimensionMismatchError: Addition, dimensions were (A) (m^2 kg s^-3 A^-2)
>>> Is = np.array([1, 2, 3]) * amp
>>> Is * R
array([ 2., 4., 6.]) * volt
array([2., 4., 6.]) * volt
>>> np.asarray(Is * R) # gets rid of units
array([ 2., 4., 6.])
array([2., 4., 6.])
See also
--------
Expand Down Expand Up @@ -1280,7 +1280,7 @@ def with_dimensions(value, *args, **keywords):
--------
All of these define an equivalent `Quantity` object:
>>> from unitSI import *
>>> from QuantSI import *
>>> Quantity.with_dimensions(2, get_or_create_dimension(length=1))
2. * metre
>>> Quantity.with_dimensions(2, length=1)
Expand Down Expand Up @@ -1357,8 +1357,8 @@ def in_unit(self, u, precision=None, python_code=False):
Examples
--------
>>> from unitSI.allunits import *
>>> from unitSI.stdunits import *
>>> from QuantSI.allunits import *
>>> from QuantSI.stdunits import *
>>> x = 25.123456 * mV
>>> x.in_unit(volt)
'0.02512346 V'
Expand Down Expand Up @@ -1464,7 +1464,7 @@ def in_best_unit(self, precision=None, python_code=False, *regs):
Examples
--------
>>> from unitSI.allunits import *
>>> from QuantSI.allunits import *
>>> x = 0.00123456 * volt
Expand Down Expand Up @@ -1655,37 +1655,6 @@ def __format__(self, format_spec):
cumsum = wrap_function_keep_dimensions(np.ndarray.cumsum)
trace = wrap_function_keep_dimensions(np.trace)

# To work around an issue in matplotlib 1.3.1 (see
# https://github.com/matplotlib/matplotlib/pull/2591), we make `ravel`
# return a unitless array and emit a warning explaining the issue.
use_matplotlib_units_fix = False
try:
import matplotlib

if matplotlib.__version__ == "1.3.1":
use_matplotlib_units_fix = True
except ImportError:
pass

if use_matplotlib_units_fix:

def ravel(self, *args, **kwds):
warn(
"As a workaround for a bug in matplotlib 1.3.1, calling "
'"ravel()" on a quantity will return unit-less values. If you '
"get this warning during plotting, consider removing the units "
"before plotting, e.g. by dividing by the unit. If you are "
'explicitly calling "ravel()", consider using "flatten()" '
"instead."
)
return np.asarray(self).ravel(*args, **kwds)

ravel._arg_units = [None]
ravel._return_unit = 1
ravel.__name__ = np.ndarray.ravel.__name__
ravel.__doc__ = np.ndarray.ravel.__doc__
# argsort = wrap_function_remove_dimensions(np.ndarray.argsort)

def fill(self, values): # pylint: disable=C0111
fail_for_dimension_mismatch(self, values, "fill")
super().fill(values)
Expand Down Expand Up @@ -1816,8 +1785,8 @@ class Unit(Quantity):
purposes. So for example, to define the newton metre, you
write
>>> from unitSI import *
>>> from unitSI.allunits import newton
>>> from QuantSI import *
>>> from QuantSI.allunits import newton
>>> Nm = newton * metre
You can then do
Expand Down Expand Up @@ -2376,7 +2345,7 @@ def register_new_unit(u):
Examples
--------
>>> from unitSI import *
>>> from QuantSI import *
>>> 2.0*farad/metre**2
2. * metre ** -4 * kilogram ** -1 * second ** 4 * amp ** 2
>>> register_new_unit(pfarad / mmetre**2)
Expand Down Expand Up @@ -2448,7 +2417,7 @@ def check_units(**au):
Examples
--------
>>> from unitSI.allunits import *
>>> from QuantSI.allunits import *
>>> @check_units(I=amp, R=ohm, wibble=metre, result=volt)
... def getvoltage(I, R, **k):
... return I*R
Expand Down Expand Up @@ -2521,7 +2490,7 @@ def check_units(**au):
>>> multiply_sum(3*nA, 4*mV, 5*nA) # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
unitSI.fundamentalunits.DimensionMismatchError: Function 'multiply_sum' expected the same arguments for arguments 'summand_1', 'summand_2', but argument 'summand_1' has unit V, while argument 'summand_2' has unit A.
QuantSI.fundamentalunits.DimensionMismatchError: Function 'multiply_sum' expected the same arguments for arguments 'summand_1', 'summand_2', but argument 'summand_1' has unit V, while argument 'summand_2' has unit A.
Raises
------
Expand Down
32 changes: 7 additions & 25 deletions QuantSI/tests/test_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
import pytest
from numpy.testing import assert_equal

from unitSI.allunits import *
from unitSI.fundamentalunits import (
from QuantSI.allunits import *
from QuantSI.fundamentalunits import (
DIMENSIONLESS,
UFUNCS_DIMENSIONLESS,
UFUNCS_DIMENSIONLESS_TWOARGS,
Expand All @@ -27,20 +27,7 @@
is_scalar_type,
quantity_with_dimensions
)
from unitSI.stdunits import Hz, cm, kHz, mM, ms, mV, nA, nS

# To work around an issue in matplotlib 1.3.1 (see
# https://github.com/matplotlib/matplotlib/pull/2591), we make `ravel`
# return a unitless array and emit a warning explaining the issue.
use_matplotlib_units_fix = False
try:
import matplotlib

if matplotlib.__version__ == "1.3.1":
use_matplotlib_units_fix = True
except ImportError:
pass

from QuantSI.stdunits import Hz, cm, kHz, mM, ms, mV, nA, nS

def assert_quantity(q, values, unit):
assert isinstance(q, Quantity) or (
Expand Down Expand Up @@ -767,7 +754,6 @@ def test_special_case_numpy_functions():

quadratic_matrix = np.reshape(np.arange(9), (3, 3)) * mV

# Temporarily suppress warnings related to the matplotlib 1.3 bug
with warnings.catch_warnings():
warnings.simplefilter("ignore")
# Check that function and method do the same thing
Expand Down Expand Up @@ -824,11 +810,7 @@ def test_special_case_numpy_functions():
np.asarray(quadratic_matrix).prod(axis=0),
)

# Check for correct units
if use_matplotlib_units_fix:
assert have_same_dimensions(1, np.ravel(quadratic_matrix))
else:
assert have_same_dimensions(quadratic_matrix, np.ravel(quadratic_matrix))
assert have_same_dimensions(quadratic_matrix, np.ravel(quadratic_matrix))
assert have_same_dimensions(quadratic_matrix, np.trace(quadratic_matrix))
assert have_same_dimensions(quadratic_matrix, np.diagonal(quadratic_matrix))
assert have_same_dimensions(
Expand Down Expand Up @@ -1198,7 +1180,7 @@ def test_switching_off_unit_checks():
"""
Check switching off unit checks (used for external functions).
"""
import unitSI.fundamentalunits as fundamentalunits
import QuantSI.fundamentalunits as fundamentalunits

x = 3 * second
y = 5 * volt
Expand Down Expand Up @@ -1305,7 +1287,7 @@ def test_units_vs_quantities():


def test_all_units_list():
from unitSI.allunits import all_units
from QuantSI.allunits import all_units

assert meter in all_units
assert volt in all_units
Expand All @@ -1316,7 +1298,7 @@ def test_all_units_list():


def test_constants():
import unitSI.constants as constants
import QuantSI.constants as constants

# Check that the expected names exist and have the correct dimensions
assert constants.avogadro_constant.dim == (1 / mole).dim
Expand Down
2 changes: 1 addition & 1 deletion docs_sphinx/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ Welcome to QuantSI's documentation!

user/units
developer/units
usage/usage
usage/usage_comparison

modules

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,10 @@ For Astropy:
For QuantSI:

>>> from QuantSI import *
>>> 2.0*farad/metre**2
2. * metre ** -4 * kilogram ** -1 * second ** 4 * amp ** 2
>>> register_new_unit(pfarad / mmetre**2)
>>> 2.0*farad/metre**2
2000000. * pfarad / (mmetre ** 2)
>>> from QuantSI.allunits import newton
>>> Nm = newton*meter
>>> (1*Nm).in_unit(Nm)
'1. N m'


Using Numpy functions with units:
Expand Down Expand Up @@ -119,4 +118,49 @@ Furthermore with this approach we only use radians so the conversion to degrees
np.float64(1.0)
>>> print(90*radian)
90.0

Converting from units to standard classes in python or numpy arrays:

For Pint:

>>> distance = 24.0 * ureg.meter
>>> distance_float = distance.magnitude
>>> print(distance_float)
24.0
# To convert to a numpy array
>>> distance_arr = [10,20,30] * ureg.meter
>>> distnace_arr_numpy = distance_arr.magnitude
>>> print(distance_arr_numpy)
array([10, 20, 30])

For Astropy:

>>> distance = 24.0 * u.meter
>>> distance_float = distance.value
>>> print(distance_float)
24.0
# To convert to a numpy array
>>> distance_arr = [10,20,30] * u.meter
>>> distnace_arr_numpy = distance_arr.value
>>> print(distance_arr_numpy)
array([10, 20, 30])

For QuantSI:

>>> distance = 24.0 * si.meter
>>> distance_float = float(distance)
# Can convert to another types as well
>>> print(distance_float)
24.0
# To convert to a numpy array
>>> distance_arr = [10,20,30] * si.meter
>>> distnace_arr_numpy = np.asarray(distance_arr)
# np.array function can also be used
>>> print(distance_arr_numpy)
array([10, 20, 30])


From a developer perspective, QuantSI and units from Astropy have a similar approach in their code. Both packages implement their functionality by
inheriting from numpy.ndarray in order to use numpy functions without including more wrapper functions. Instead, Pint wraps NumPy functions to ensure
they behave correctly with units, thus providing the expected behavior.

0 comments on commit 81fbdea

Please sign in to comment.