Repository: wright-group/WrightTools

Issue:
Zero
>>> wt.units.convert(0, "wn", "nm")
ZeroDivisionError: division by zero
>>> wt.units.convert(0, "nm", "wn")
ZeroDivisionError: division by zero

Should return inf


Discussion:
On a philosophic level, I would be more comfortable with `np.nan`. 
As a "fun" aside, conversion of 0 from or to `'wn'` causes a division by zero error, but conversion of 0 energy amongst other energy units works fine.
For context, this change (due to our new usage of pint) breaks yaqc-cmds, so something needs to change. Keeping WrightTools behavior the same is my vote at the moment, but willing to go with other options if that's what the community wants.
```
>>> np.array(0) / 0
<stdin>:1: RuntimeWarning: invalid value encountered in true_divide
nan
>>> np.array(2929) / 0
<stdin>:1: RuntimeWarning: divide by zero encountered in true_divide
inf
>>> np.array(-2929) / 0
-inf
```

For reference here is numpy behavior, probably the best would be to replicate this, though not sure that is actually fully possible in the arbitrary case (The only conversion with a potentially zero denominator that I can think of is the various forms of wavenumber <-> energy, which all have a positive numerator, but arbitrary computation is possible and we do not have both values in our own namespace) 
Thus I'm fine with saying "just return inf" for right now, but willing to be convinced of other cases where my preference would be to match numpy behavior: warn (numpy actually only warns the _first_ time, I don't feel like making that much work right now, but would be willing to if desired), but return +inf, 0, or -inf based on the sign of the numerator
(Actually warnings itself does the warn only once per warning for you... so that is done)


Resolving patch:
diff --git a/WrightTools/units.py b/WrightTools/units.py
--- a/WrightTools/units.py
+++ b/WrightTools/units.py
@@ -115,10 +115,13 @@ def converter(val, current_unit, destination_unit):
         val = ureg.Quantity(val, current_unit).to(destination_unit).magnitude
     except (pint.errors.DimensionalityError, pint.errors.UndefinedUnitError, AttributeError):
         warnings.warn(
-            "conversion {0} to {1} not valid: returning input".format(
-                current_unit, destination_unit
-            )
+            f"conversion {current_unit} to {destination_unit} not valid: returning input"
         )
+    except ZeroDivisionError:
+        warnings.warn(
+            f"conversion {current_unit} to {destination_unit} resulted in ZeroDivisionError: returning inf"
+        )
+        return float("inf")
     return val
 
 


Test patch:
diff --git a/tests/units.py b/tests/units.py
--- a/tests/units.py
+++ b/tests/units.py
@@ -4,6 +4,7 @@
 # --- import -------------------------------------------------------------------------------------
 
 import numpy as np
+import pytest
 
 import WrightTools as wt
 from WrightTools import datasets
@@ -28,25 +29,21 @@ def test_in_mm_conversion():
     assert np.isclose(wt.units.convert(1.0, "in", "mm"), 25.4)
 
 
-def unit_registry_test1():
+def test_unit_registry():
     values = np.linspace(-1, 1, 51)
     d = wt.Data(name="test")
-    try:
-        d.create_variable("Bgood", values=values, units="tesla")
-        d.transform("Bgood")
-    except ValueError:
-        assert False
-    else:
-        assert True
+    d.create_variable("Bgood", values=values, units="tesla")
+    d.transform("Bgood")
 
 
-def unit_registry_test2():
+def test_bad_unit_registry():
     values = np.linspace(-1, 1, 51)
     d = wt.Data(name="test")
-    try:
+    with pytest.raises(ValueError):
         d.create_variable("Bbad", values=values, units="Tesla")
         d.transform("Bbad")
-    except ValueError:
-        assert True
-    else:
-        assert False
+
+
+def test_0_inf():
+    assert wt.units.convert(0, "wn", "nm") == np.inf
+    assert wt.units.convert(0, "nm", "wn") == np.inf