UnitValues 0.1.1__tar.gz → 0.1.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,20 +1,21 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UnitValues
3
- Version: 0.1.1
4
- Summary: A small package for using units in Python. Allows for computation with dimensioned qauntities and allows you to convert between different units. Do anything you would do with regular floats or integers in Python except now with units. I think you'll find this implementation more elegant then most other unit packages.
3
+ Version: 0.1.3
4
+ Summary: A small package for using units in Python. Allows for computation with dimensioned qauntities and allows you to convert between different units. Do anything you would do with regular floats or integers in Python except now with units. Package is compatible with NumPy, SciPy + Pandas are in the works. I think you'll find this implementation more elegant then most other unit packages.
5
5
  Author-email: Brody Howard <brody.howard@mail.utoronto.ca>
6
6
  Project-URL: Homepage, https://github.com/BroRocket/unitvalue/
7
7
  Project-URL: Issues, https://github.com/BroRocket/unitvalue/issues
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.8
11
+ Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
+ Requires-Dist: numpy>=1.23.2
14
15
 
15
- # UnitValue Package
16
+ # UnitValues Package
16
17
  ## Introduction
17
- The UnitValue package is designed to allow easy manipulation and conversion of numerical values associated with units. It currently supports both Imperial and Metric systems and includes commonly used units, with the flexibility to add more units as needed. It works with numpy as well.
18
+ The UnitValue package is designed to allow easy manipulation and conversion of numerical values associated with units. It currently supports both Imperial and Metric systems and includes commonly used units, with the flexibility to add more units as needed. It works with numpy as well, empowering you to use units in your numpy arrays and funciton calls.
18
19
 
19
20
  This package is ideal for applications that require precise unit conversions and tracking of units alongside numerical values.
20
21
 
@@ -1,6 +1,6 @@
1
- # UnitValue Package
1
+ # UnitValues Package
2
2
  ## Introduction
3
- The UnitValue package is designed to allow easy manipulation and conversion of numerical values associated with units. It currently supports both Imperial and Metric systems and includes commonly used units, with the flexibility to add more units as needed. It works with numpy as well.
3
+ The UnitValue package is designed to allow easy manipulation and conversion of numerical values associated with units. It currently supports both Imperial and Metric systems and includes commonly used units, with the flexibility to add more units as needed. It works with numpy as well, empowering you to use units in your numpy arrays and funciton calls.
4
4
 
5
5
  This package is ideal for applications that require precise unit conversions and tracking of units alongside numerical values.
6
6
 
@@ -1,12 +1,16 @@
1
1
  [project]
2
2
  name = "UnitValues"
3
- version = "0.1.1"
3
+ version = "0.1.3"
4
+ dependencies = [
5
+ "numpy >= 1.23.2"
6
+ ]
7
+ requires-python = ">=3.10"
4
8
  authors = [
5
9
  { name="Brody Howard", email="brody.howard@mail.utoronto.ca" },
6
10
  ]
7
- description = "A small package for using units in Python. Allows for computation with dimensioned qauntities and allows you to convert between different units. Do anything you would do with regular floats or integers in Python except now with units. I think you'll find this implementation more elegant then most other unit packages."
11
+ description = "A small package for using units in Python. Allows for computation with dimensioned qauntities and allows you to convert between different units. Do anything you would do with regular floats or integers in Python except now with units. Package is compatible with NumPy, SciPy + Pandas are in the works. I think you'll find this implementation more elegant then most other unit packages."
8
12
  readme = "README.md"
9
- requires-python = ">=3.8"
13
+
10
14
  classifiers = [
11
15
  "Programming Language :: Python :: 3",
12
16
  "License :: OSI Approved :: MIT License",
@@ -1,20 +1,21 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: UnitValues
3
- Version: 0.1.1
4
- Summary: A small package for using units in Python. Allows for computation with dimensioned qauntities and allows you to convert between different units. Do anything you would do with regular floats or integers in Python except now with units. I think you'll find this implementation more elegant then most other unit packages.
3
+ Version: 0.1.3
4
+ Summary: A small package for using units in Python. Allows for computation with dimensioned qauntities and allows you to convert between different units. Do anything you would do with regular floats or integers in Python except now with units. Package is compatible with NumPy, SciPy + Pandas are in the works. I think you'll find this implementation more elegant then most other unit packages.
5
5
  Author-email: Brody Howard <brody.howard@mail.utoronto.ca>
6
6
  Project-URL: Homepage, https://github.com/BroRocket/unitvalue/
7
7
  Project-URL: Issues, https://github.com/BroRocket/unitvalue/issues
8
8
  Classifier: Programming Language :: Python :: 3
9
9
  Classifier: License :: OSI Approved :: MIT License
10
10
  Classifier: Operating System :: OS Independent
11
- Requires-Python: >=3.8
11
+ Requires-Python: >=3.10
12
12
  Description-Content-Type: text/markdown
13
13
  License-File: LICENSE
14
+ Requires-Dist: numpy>=1.23.2
14
15
 
15
- # UnitValue Package
16
+ # UnitValues Package
16
17
  ## Introduction
17
- The UnitValue package is designed to allow easy manipulation and conversion of numerical values associated with units. It currently supports both Imperial and Metric systems and includes commonly used units, with the flexibility to add more units as needed. It works with numpy as well.
18
+ The UnitValue package is designed to allow easy manipulation and conversion of numerical values associated with units. It currently supports both Imperial and Metric systems and includes commonly used units, with the flexibility to add more units as needed. It works with numpy as well, empowering you to use units in your numpy arrays and funciton calls.
18
19
 
19
20
  This package is ideal for applications that require precise unit conversions and tracking of units alongside numerical values.
20
21
 
@@ -4,6 +4,7 @@ pyproject.toml
4
4
  src/UnitValues.egg-info/PKG-INFO
5
5
  src/UnitValues.egg-info/SOURCES.txt
6
6
  src/UnitValues.egg-info/dependency_links.txt
7
+ src/UnitValues.egg-info/requires.txt
7
8
  src/UnitValues.egg-info/top_level.txt
8
9
  src/unitvalue/__init__.py
9
10
  src/unitvalue/units.py
@@ -0,0 +1 @@
1
+ numpy>=1.23.2
@@ -6,7 +6,7 @@ Typically used units are supported and more can be added upon request or in your
6
6
  import warnings
7
7
  import numpy as np
8
8
 
9
- class UnitValue:
9
+ class UnitValue: # add specific heat
10
10
  """
11
11
  Represents a value with dimension/units.
12
12
 
@@ -26,7 +26,7 @@ class UnitValue:
26
26
  "AREA": {"in^2": 0.00064516, "mi^2": 2590000, "yd^2": 0.836127, "ft^2": 0.092903},
27
27
  "TEMPERATURE": {"f": None, "R":None},
28
28
  "MASS FLOW RATE": {"lb/s": 0.453592, "ton/s": 907.1847, "st/s": 6.35029, "oz": 0.0283495, "lb/min": 0.00755987},
29
- "ENERGY": {"ftlb": 1.35582, "kcal": 4184, "cal": 4.184},
29
+ "ENERGY": {"BTU": 1055.05585, "ftlb": 1.35582, "kcal": 4184, "cal": 4.184},
30
30
  "TIME": {"s": 1, "h": 3600, "min": 60, "ms": 0.001},
31
31
  "MOMENTUM": {"slugft/s": 4.449670915354, "lbft/s": 0.1383},
32
32
  "FREQUENCY": {"rpm": 0.016667},
@@ -35,10 +35,11 @@ class UnitValue:
35
35
  "ENERGY PER UNIT MASS": {"ft^2/s^2": 0.09290304},
36
36
  "MASS PER UNIT LENGTH": {"lb/ft": 1.48816, "oz/in": 1.11612},
37
37
  "MASS PER AREA": {"lb/ft^2": 4.88243},
38
- "VOLUMETRIC FLOW RATE": {"ft^3/s": 0.0283168, "gal/s": 0.00378541},
38
+ "VOLUMETRIC FLOW RATE": {"ft^3/s": 0.0283168, "gal/s": 0.00378541, "ft^3/min": 0.000471947},
39
39
  "DYNAMIC VISCOCITY": {"lb/fts": 1.488163943568},
40
40
  "KINEMATIC VISCOCITY": {"ft^2/s": 0.092903},
41
- "MASS FLUX": {"lb/ft^2s": 4.88243}
41
+ "MASS FLUX": {"lb/ft^2s": 4.88243},
42
+ "SPECIFIC HEAT": {"BTU/lbf": 4186.8000000087}
42
43
  },
43
44
  "METRIC": {
44
45
  "DISTANCE": {"m": 1, "km": 1000, "cm": 0.01, "mm": 0.001},
@@ -62,11 +63,12 @@ class UnitValue:
62
63
  "VOLUMETRIC FLOW RATE": {"m^3/s": 1, "cm^3/s": 0.000001},
63
64
  "DYNAMIC VISCOCITY": {"kg/ms": 1, "g/cms":0.1},
64
65
  "KINEMATIC VISCOCITY": {"m^2/s": 1, "cm^2/s": 0.0001},
65
- "MASS FLUX": {"kg/m^2s": 1}
66
+ "MASS FLUX": {"kg/m^2s": 1},
67
+ "SPECIFIC HEAT": {"m^2/s^2K": 1, "J/kgK": 1, "J/kgc": 1}
66
68
  }
67
69
  }
68
70
 
69
- SPELLING_MAP = {'mtr': 'm', 'meters': 'm', 'mtr.': 'm', 'metres': 'm', 'metre': 'm', 'm ': 'm', 'meter': 'm', 'kilometer': 'km', 'kilometre': 'km', 'kilo meter': 'km', 'k meter': 'km', 'klometer': 'km', 'km ': 'km', 'kmeter': 'km', 'kmtr': 'km', 'centemeter': 'cm', 'centimetre': 'cm', 'cn': 'cm', 'c meter': 'cm', 'cm ': 'cm', 'centi meter': 'cm', 'centimeter': 'cm', 'cmeter': 'cm', 'cmtr': 'cm', 'mmeter': 'mm', 'millimeter': 'mm', 'milimeter': 'mm', 'milli meter': 'mm', 'millimetre': 'mm', 'm meter': 'mm', 'mn': 'mm', 'mmtr': 'mm', 'mm ': 'mm', 'g ': 'g', 'gramme': 'g', 'grm': 'g', 'gms': 'g', 'gram': 'g', 'gm': 'g', 'gramm': 'g', 'gram ': 'g', 'kilograms': 'kg', 'k gram': 'kg', 'kilogramme': 'kg', 'kilogram ': 'kg', 'kilogramme ': 'kg', 'kilogrammes': 'kg', 'kg ': 'kg', 'kilogram': 'kg', 'kilo gram': 'kg', 'kgrm': 'kg', 'liters': 'L', 'l': 'L', 'litres': 'L', 'ltrs': 'L', 'liter': 'L', 'litre ': 'L', 'litre': 'L', 'liters ': 'L', 'liter ': 'L', 'litter': 'L', 'ltr': 'L', 'ml': 'mL', 'milliliter': 'mL', 'mlitres': 'mL', 'millilitre': 'mL', 'milli litre': 'mL', 'mliters': 'mL', 'milli liter': 'mL', 'mltr': 'mL', 'sec': 's', 'seconds': 's', 'sedonds': 's', 'sconds': 's', 'second': 's', 'secs': 's', 'secnd': 's', 'minute': 'min', 'minuts': 'min', 'mins': 'min', 'minutes': 'min', 'min': 'min', 'minut': 'min', 'hours': 'h', 'hr': 'h', 'howr': 'h', 'houer': 'h', 'hour': 'h', 'hou': 'h', 'hrs': 'h', 'square meters': 'm^2', 'square meter': 'm^2', 'sqr meter': 'm^2', 'square metre': 'm^2', 'sq meter': 'm^2', 'sqmetre': 'm^2', 'sq metres': 'm^2', 'sqm': 'm^2', 'cube meter': 'm^3', 'cu meter': 'm^3', 'cbm': 'm^3', 'cubic meters': 'm^3', 'cubic metre': 'm^3', 'cubic meter': 'm^3', 'cu m': 'm^3', 'degree centigrade': 'c', 'degree celsius': 'c', 'celcius': 'c', 'deg celsius': 'c', 'celsius degree': 'c', 'celsus': 'c', 'celsius': 'c', 'deg c': 'c', 'fahrenheit degree': 'f', 'deg f': 'f', 'deg fahrenheit': 'f', 'fahrenhiet': 'f', 'degree fahrenheit': 'f', 'farhenheit': 'f', 'force': 'kgm/s^2', 'Newton': 'kgm/s^2', 'newtn': 'kgm/s^2', 'nwton': 'kgm/s^2', 'nwt': 'kgm/s^2', 'newton': 'kgm/s^2', 'joule': 'kgm^2/s^2', 'energy': 'kgm^2/s^2', 'juole': 'kgm^2/s^2', 'jl': 'kgm^2/s^2', 'joules': 'kgm^2/s^2', 'juul': 'kgm^2/s^2', 'inck': 'in', 'inche': 'in', 'inch': 'in', 'inc': 'in', 'inch ': 'in', 'inchh': 'in', 'foot': 'ft', 'foott': 'ft', 'fot': 'ft', 'foor': 'ft', 'foot ': 'ft', 'feet': 'ft', 'yardd': 'yd', 'yad': 'yd', 'yarrd': 'yd', 'yard ': 'yd', 'yard': 'yd', 'mille': 'mi', 'mile ': 'mi', 'milee': 'mi', 'mil': 'mi', 'mile': 'mi', 'pounds': 'lb', 'pounnd': 'lb', 'pound ': 'lb', 'pound': 'lb', 'lbs': 'lb', 'poundd': 'lb', 'galln': 'gal', 'gllon': 'gal', 'gallon': 'gal', 'galllon': 'gal', 'gallon ': 'gal', 'ounze': 'oz', 'ouncce': 'oz', 'ounce ': 'oz', 'ozs': 'oz', 'ounce': 'oz', 'ounc': 'oz', 'ounc ': 'oz', 'stn': 'st', 'stone ': 'st', 'sts': 'st', 'stone': 'st', 'st ': 'st', 'ft2': 'ft^2', 'square foot': 'ft^2', 'sqft': 'ft^2', 'square feet': 'ft^2', 'sq foot': 'ft^2', 'ft3': 'ft^3', 'cft': 'ft^3', 'cubic foot': 'ft^3', 'cu ft': 'ft^3', 'cubic feet': 'ft^3'}
71
+ SPELLING_MAP = {'mtr': 'm', 'meters': 'm', 'mtr.': 'm', 'metres': 'm', 'metre': 'm', 'm ': 'm', 'meter': 'm', 'kilometer': 'km', 'kilometre': 'km', 'kilo meter': 'km', 'k meter': 'km', 'klometer': 'km', 'km ': 'km', 'kmeter': 'km', 'kmtr': 'km', 'centemeter': 'cm', 'centimetre': 'cm', 'cn': 'cm', 'c meter': 'cm', 'cm ': 'cm', 'centi meter': 'cm', 'centimeter': 'cm', 'cmeter': 'cm', 'cmtr': 'cm', 'mmeter': 'mm', 'millimeter': 'mm', 'milimeter': 'mm', 'milli meter': 'mm', 'millimetre': 'mm', 'm meter': 'mm', 'mn': 'mm', 'mmtr': 'mm', 'mm ': 'mm', 'g ': 'g', 'gramme': 'g', 'grm': 'g', 'gms': 'g', 'gram': 'g', 'gm': 'g', 'gramm': 'g', 'gram ': 'g', 'kilograms': 'kg', 'k gram': 'kg', 'kilogramme': 'kg', 'kilogram ': 'kg', 'kilogramme ': 'kg', 'kilogrammes': 'kg', 'kg ': 'kg', 'kilogram': 'kg', 'kilo gram': 'kg', 'kgrm': 'kg', 'liters': 'L', 'l': 'L', 'litres': 'L', 'ltrs': 'L', 'liter': 'L', 'litre ': 'L', 'litre': 'L', 'liters ': 'L', 'liter ': 'L', 'litter': 'L', 'ltr': 'L', 'ml': 'mL', 'milliliter': 'mL', 'mlitres': 'mL', 'millilitre': 'mL', 'milli litre': 'mL', 'mliters': 'mL', 'milli liter': 'mL', 'mltr': 'mL', 'sec': 's', 'seconds': 's', 'sedonds': 's', 'sconds': 's', 'second': 's', 'secs': 's', 'secnd': 's', 'minute': 'min', 'minuts': 'min', 'mins': 'min', 'minutes': 'min', 'min': 'min', 'minut': 'min', 'hours': 'h', 'hr': 'h', 'howr': 'h', 'houer': 'h', 'hour': 'h', 'hou': 'h', 'hrs': 'h', 'square meters': 'm^2', 'square meter': 'm^2', 'sqr meter': 'm^2', 'square metre': 'm^2', 'sq meter': 'm^2', 'sqmetre': 'm^2', 'sq metres': 'm^2', 'sqm': 'm^2', 'cube meter': 'm^3', 'cu meter': 'm^3', 'cbm': 'm^3', 'cubic meters': 'm^3', 'cubic metre': 'm^3', 'cubic meter': 'm^3', 'cu m': 'm^3', 'C': 'c','degree centigrade': 'c', 'degree celsius': 'c', 'celcius': 'c', 'deg celsius': 'c', 'celsius degree': 'c', 'celsus': 'c', 'celsius': 'c', 'deg c': 'c', 'fahrenheit degree': 'f', 'deg f': 'f', 'deg fahrenheit': 'f', 'fahrenhiet': 'f', 'degree fahrenheit': 'f', 'farhenheit': 'f', 'force': 'kgm/s^2', 'Newton': 'kgm/s^2', 'newtn': 'kgm/s^2', 'nwton': 'kgm/s^2', 'nwt': 'kgm/s^2', 'newton': 'kgm/s^2', 'joule': 'kgm^2/s^2', 'energy': 'kgm^2/s^2', 'juole': 'kgm^2/s^2', 'jl': 'kgm^2/s^2', 'joules': 'kgm^2/s^2', 'juul': 'kgm^2/s^2', 'inck': 'in', 'inche': 'in', 'inch': 'in', 'inc': 'in', 'inch ': 'in', 'inchh': 'in', 'foot': 'ft', 'foott': 'ft', 'fot': 'ft', 'foor': 'ft', 'foot ': 'ft', 'feet': 'ft', 'yardd': 'yd', 'yad': 'yd', 'yarrd': 'yd', 'yard ': 'yd', 'yard': 'yd', 'mille': 'mi', 'mile ': 'mi', 'milee': 'mi', 'mil': 'mi', 'mile': 'mi', 'pounds': 'lb', 'pounnd': 'lb', 'pound ': 'lb', 'pound': 'lb', 'lbs': 'lb', 'poundd': 'lb', 'galln': 'gal', 'gllon': 'gal', 'gallon': 'gal', 'galllon': 'gal', 'gallon ': 'gal', 'ounze': 'oz', 'ouncce': 'oz', 'ounce ': 'oz', 'ozs': 'oz', 'ounce': 'oz', 'ounc': 'oz', 'ounc ': 'oz', 'stn': 'st', 'stone ': 'st', 'sts': 'st', 'stone': 'st', 'st ': 'st', 'ft2': 'ft^2', 'square foot': 'ft^2', 'sqft': 'ft^2', 'square feet': 'ft^2', 'sq foot': 'ft^2', 'ft3': 'ft^3', 'cft': 'ft^3', 'cubic foot': 'ft^3', 'cu ft': 'ft^3', 'cubic feet': 'ft^3'}
70
72
 
71
73
  @classmethod
72
74
  def add_custom_unit(cls, system: str, dimension:str, unit:str, conversion_factor: float) -> None:
@@ -323,10 +325,13 @@ class UnitValue:
323
325
  return self.value * m.value
324
326
 
325
327
  return UnitValue(None, None, new_unit, self.value * m.value)
326
- elif isinstance(m, (int, float, np.ndarray)):
328
+ elif isinstance(m, (int, float)):
327
329
  return UnitValue(self.__system, self.__dimension, self.__unit, self.value * m)
328
330
  else:
329
- return NotImplemented
331
+ try:
332
+ return self * float(m) # checking if whatever the type is if it can be converted to float and then used
333
+ except:
334
+ return NotImplemented
330
335
 
331
336
  def __rmul__(self, m) -> 'UnitValue':
332
337
  return self.__mul__(m)
@@ -365,10 +370,13 @@ class UnitValue:
365
370
  return self.value / d.value
366
371
 
367
372
  return UnitValue(None, None, new_unit, self.value / d.value)
368
- elif isinstance(d, (int, float, np.ndarray)):
373
+ elif isinstance(d, (int, float)):
369
374
  return UnitValue(self.__system, self.__dimension, self.__unit, self.value / d)
370
375
  else:
371
- return NotImplemented
376
+ try:
377
+ return self / float(d)
378
+ except:
379
+ return NotImplemented
372
380
 
373
381
  def __rtruediv__(self, d) -> 'UnitValue':
374
382
  """
@@ -404,7 +412,7 @@ class UnitValue:
404
412
  return d.value / self.value
405
413
 
406
414
  return UnitValue(None, None, new_unit, d.value / self.value)
407
- elif isinstance(d, (int, float, np.ndarray)):
415
+ elif isinstance(d, (int, float)):
408
416
 
409
417
  units = {}
410
418
  self.__process_unit(self.__unit, units, -1)
@@ -429,7 +437,10 @@ class UnitValue:
429
437
  new_unit = numer + denom
430
438
  return UnitValue(None, None, new_unit, d / self.value)
431
439
  else:
432
- return NotImplemented
440
+ try:
441
+ return float(d) / self
442
+ except:
443
+ return NotImplemented
433
444
 
434
445
  def __pow__(self, p) -> 'UnitValue':
435
446
  """
@@ -466,7 +477,10 @@ class UnitValue:
466
477
  return UnitValue(None, None, new_unit, self.value ** p)
467
478
 
468
479
  else:
469
- raise NotImplementedError(f"Raising to the power with type {type(p)} not supported")
480
+ try:
481
+ return self ** float(p)
482
+ except:
483
+ return NotImplemented
470
484
 
471
485
  def __add__(self, a) -> 'UnitValue':
472
486
  """
@@ -480,11 +494,14 @@ class UnitValue:
480
494
  self.convert_base_metric()
481
495
  a.convert_base_metric()
482
496
  return UnitValue(self.__system, self.__dimension, self.__unit, self.value + a.value)
483
-
484
- elif isinstance(a, (int, float, np.ndarray)):
497
+ elif isinstance(a, (int, float)):
498
+ warnings.warn("Adding unitless value to quantity with units")
485
499
  return UnitValue(self.__system, self.__dimension, self.__unit, self.value + a)
486
500
  else:
487
- return NotImplemented
501
+ try:
502
+ return self + float(a)
503
+ except:
504
+ return NotImplemented
488
505
 
489
506
  def __radd__(self, a) -> 'UnitValue':
490
507
  return self.__add__(a)
@@ -501,16 +518,36 @@ class UnitValue:
501
518
  self.convert_base_metric()
502
519
  s.convert_base_metric()
503
520
  return UnitValue(self.__system, self.__dimension, self.__unit, self.value - s.value)
504
- elif isinstance(s, (int, float, np.ndarray)):
521
+ elif isinstance(s, (int, float)):
522
+ warnings.warn("Subtracting unitless value to quantity with units")
505
523
  return UnitValue(self.__system, self.__dimension, self.__unit, self.value - s)
506
- else:
507
- return NotImplemented
524
+ else:
525
+ try:
526
+ return self - float(s)
527
+ except:
528
+ return NotImplemented
508
529
 
509
530
  def __rsub__(self, s) -> 'UnitValue':
510
531
  return -self.__sub__(s)
511
532
 
512
533
  def __neg__(self):
513
534
  return UnitValue(self.__system, self.__dimension, self.__unit, -self.value)
535
+
536
+ def __mod__(self, other) -> int:
537
+ if isinstance(other, UnitValue):
538
+ return self.value % other.value
539
+ elif isinstance(other, (int, float)):
540
+ return self.value % other
541
+ else:
542
+ return NotImplemented
543
+
544
+ def __rmod__(self, other) -> int:
545
+ if isinstance(other, UnitValue):
546
+ return other.value % self.value
547
+ elif isinstance(other, (int, float)):
548
+ return other % self.value
549
+ else:
550
+ return NotImplemented
514
551
 
515
552
  def __abs__(self):
516
553
  """
@@ -523,8 +560,8 @@ class UnitValue:
523
560
  Checks if UnitValue object is equal to other.
524
561
  """
525
562
  if isinstance(other, UnitValue):
526
- a = self.__cpy().convert_base_metric()
527
- b = other.__cpy().convert_base_metric()
563
+ a = self.copy().convert_base_metric()
564
+ b = other.copy().convert_base_metric()
528
565
  return a.value == b.value and a.__unit == b.__unit
529
566
  elif isinstance(other, (int, float)):
530
567
  return self.value == other
@@ -532,8 +569,8 @@ class UnitValue:
532
569
 
533
570
  def __ne__(self, other) -> bool:
534
571
  if isinstance(other, UnitValue):
535
- a = self.__cpy().convert_base_metric()
536
- b = other.__cpy().convert_base_metric()
572
+ a = self.copy().convert_base_metric()
573
+ b = other.copy().convert_base_metric()
537
574
  return a.value != b.value and a.__unit != b.__unit
538
575
  elif isinstance(other, (int, float)):
539
576
  return self.value != other
@@ -541,8 +578,8 @@ class UnitValue:
541
578
 
542
579
  def __lt__(self, other) -> bool:
543
580
  if isinstance(other, UnitValue):
544
- a = self.__cpy().convert_base_metric()
545
- b = other.__cpy().convert_base_metric()
581
+ a = self.copy().convert_base_metric()
582
+ b = other.copy().convert_base_metric()
546
583
  return a.value < b.value
547
584
  elif isinstance(other, (int, float)):
548
585
  return self.value < other
@@ -550,8 +587,8 @@ class UnitValue:
550
587
 
551
588
  def __le__(self, other) -> bool:
552
589
  if isinstance(other, UnitValue):
553
- a = self.__cpy().convert_base_metric()
554
- b = other.__cpy().convert_base_metric()
590
+ a = self.copy().convert_base_metric()
591
+ b = other.copy().convert_base_metric()
555
592
  return a.value <= b.value
556
593
  elif isinstance(other, (int, float)):
557
594
  return self.value <= other
@@ -559,8 +596,8 @@ class UnitValue:
559
596
 
560
597
  def __gt__(self, other) -> bool:
561
598
  if isinstance(other, UnitValue):
562
- a = self.__cpy().convert_base_metric()
563
- b = other.__cpy().convert_base_metric()
599
+ a = self.copy().convert_base_metric()
600
+ b = other.copy().convert_base_metric()
564
601
  return a.value > b.value
565
602
  elif isinstance(other, (int, float)):
566
603
  return self.value > other
@@ -568,8 +605,8 @@ class UnitValue:
568
605
 
569
606
  def __ge__(self, other) -> bool:
570
607
  if isinstance(other, UnitValue):
571
- a = self.__cpy().convert_base_metric()
572
- b = other.__cpy().convert_base_metric()
608
+ a = self.copy().convert_base_metric()
609
+ b = other.copy().convert_base_metric()
573
610
  return a.value >= b.value
574
611
  elif isinstance(other, (int, float)):
575
612
  return self.value >= other
@@ -599,17 +636,55 @@ class UnitValue:
599
636
  Handle NumPy ufunc (universal function) operations for UnitValue objects.
600
637
  """
601
638
  out = kwargs.get('out', ())
602
- inputs = [i.value if isinstance(i, UnitValue) else i for i in inputs]
603
639
 
604
- result = getattr(ufunc, method)(*inputs, **kwargs)
605
-
606
- if method == 'reduce':
607
- return UnitValue(self.__system, self.__dimension, self.__unit, result)
608
- elif method == 'outer':
609
- return np.vectorize(lambda x: UnitValue(self.__system, self.__dimension, self.__unit, x))(result)
610
- else:
611
- return UnitValue(self.__system, self.__dimension, self.__unit, result)
640
+ if method == "__call__":
641
+ if isinstance(inputs[0], np.ndarray):
642
+ inputs = [inputs[0], inputs[1]]
643
+ for ind, element in enumerate(inputs[0]):
644
+ inputs[0][ind] = ufunc(element, inputs[1], **kwargs)
645
+ return inputs[0]
646
+ elif len(inputs) > 1 and isinstance(inputs[1], np.ndarray):
647
+ inputs = [inputs[0], inputs[1]]
648
+ for ind, element in enumerate(inputs[1]):
649
+ inputs[1][ind] = ufunc(inputs[0], element, **kwargs)
650
+ return inputs[1]
651
+ else:
652
+ if isinstance(inputs[0], (np.float64, np.int64)):
653
+ inputs = [float(inputs[0]), inputs[1]]
654
+ if ufunc == np.add:
655
+ return inputs[0] + inputs[1]
656
+ elif ufunc == np.subtract:
657
+ return inputs[0] - inputs[1]
658
+ elif ufunc == np.multiply:
659
+ return inputs[0] * inputs[1]
660
+ elif ufunc == np.divide:
661
+ return inputs[0] / inputs[1]
662
+ elif ufunc == np.sqrt:
663
+ return inputs[0] ** 0.5
664
+ elif ufunc == np.power:
665
+ return inputs[0] ** inputs[1]
666
+ elif ufunc == np.mod:
667
+ return inputs[0] % inputs[1]
668
+ elif ufunc == np.log10:
669
+ return np.log10(inputs[0].value)
670
+ else:
671
+ return NotImplemented
612
672
 
673
+ def __array_function__(self, func, types, *args, **kwargs):
674
+ if func is np.concatenate:
675
+ unit_cache = []
676
+ for arr in args[0]:
677
+ unit_cache += [item.get_unit if isinstance(item, UnitValue) else None for item in arr]
678
+ for i in range(len(arr)):
679
+ arr[i] = arr[i].value if isinstance(arr[i], UnitValue) else arr[i]
680
+ new_array = np.concatenate(args[0], **kwargs)
681
+ for ind, unit in enumerate(unit_cache):
682
+ if unit is not None:
683
+ new_array[ind] = self.create_unit(unit, new_array[ind])
684
+ return new_array
685
+ else:
686
+ return NotImplemented
687
+
613
688
  def __convert_system(self, unit: str = "") -> None:
614
689
  self.value *= UnitValue.UNITS[self.__system][self.__dimension][self.__unit]
615
690
  self.__system = "IMPERIAL" if self.__system == "METRIC" else "METRIC"
@@ -636,7 +711,7 @@ class UnitValue:
636
711
  else:
637
712
  raise Exception(f"Unit {unit} invalid: Unit must be {list(UnitValue.UNITS[self.__system][self.__dimension].keys())} for {self.__system} {self.__dimension}")
638
713
 
639
- def __cpy(self) -> 'UnitValue':
714
+ def copy(self) -> 'UnitValue':
640
715
  return UnitValue(self.__system, self.__dimension, self.__unit, self.value)
641
716
 
642
717
  def __temperature_handler(self, old_unit: str, new_unit: str): # add Rankine
@@ -772,5 +847,4 @@ class UnitValue:
772
847
  @property
773
848
  def get_system(self) -> str:
774
849
  return self.__system
775
-
776
- print(UnitValue.available_units())
850
+
File without changes
File without changes