From 933b9b64fe610b435b31300c20425ff5e8fe1b43 Mon Sep 17 00:00:00 2001 From: Andrew Savage Date: Sun, 15 Dec 2024 15:26:15 +0000 Subject: [PATCH 1/3] human --- pint/facets/plain/qto.py | 44 ++++++++++++++++++++++++++++++++++- pint/facets/plain/quantity.py | 1 + test.py | 14 +++++++++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 test.py diff --git a/pint/facets/plain/qto.py b/pint/facets/plain/qto.py index 22176491d..f042f17bd 100644 --- a/pint/facets/plain/qto.py +++ b/pint/facets/plain/qto.py @@ -16,6 +16,7 @@ ) from ...errors import UndefinedBehavior from ...util import infer_base_unit +import itertools if TYPE_CHECKING: from ..._typing import UnitLike @@ -84,7 +85,7 @@ def to_reduced_units( def to_compact( quantity: PlainQuantity, unit: UnitsContainer | None = None ) -> PlainQuantity: - """ "Return PlainQuantity rescaled to compact, human-readable units. + """ "Return PlainQuantity in compact, human-readable units by adding or modifying the SI prefix. To get output in terms of a different unit, use the unit parameter. @@ -170,6 +171,47 @@ def to_compact( return quantity.to(new_unit_container) +def to_human( + quantity: PlainQuantity, human_units: list[UnitLike] | None = None +) -> PlainQuantity: + """Return Quantity converted to the smallest human_unit with a magnitude greater than 1, + or the largest magnitude if all conversions give magnitudes less than 1. + + Examples + -------- + + >>> import pint + >>> ureg = pint.UnitRegistry() + >>> time_units = [ureg.s, ureg.min, ureg.hr, ureg.day, ureg.year] + >>> (1000*ureg.s).to_human(time_units) + + >>> (100000*ureg.s).to_human(time_units) + + >>> (100000000*ureg.s).to_human(time_units) + + >>> ureg.Quantity(100000,"m**3/hr").to_human([ureg.Unit("m**3/s"), ureg.Unit("liter/s")]) + + >>> ureg.Quantity(1000,"m**3/hr").to_human([ureg.Unit("m**3/s"), ureg.Unit("liter/s")]) + + + """ + candidate_units = [] + if human_units: + for unit in human_units: + if unit.dimensionality == quantity.dimensionality: + candidate_units.append(unit) + if candidate_units == []: + return quantity + + results = [quantity.to(cu) for cu in candidate_units] + results = sorted(results, key=lambda x:x.m) + + for result in results: + if result.m > 1: + return result + return results[-1] + + def to_preferred( quantity: PlainQuantity, preferred_units: list[UnitLike] | None = None diff --git a/pint/facets/plain/quantity.py b/pint/facets/plain/quantity.py index a18919273..0adccedcc 100644 --- a/pint/facets/plain/quantity.py +++ b/pint/facets/plain/quantity.py @@ -579,6 +579,7 @@ def to_base_units(self) -> PlainQuantity[MagnitudeT]: # convenient that they live in PlainQuantity. # They are implemented elsewhere to keep Quantity class clean. to_compact = qto.to_compact + to_human = qto.to_human to_preferred = qto.to_preferred ito_preferred = qto.ito_preferred to_reduced_units = qto.to_reduced_units diff --git a/test.py b/test.py new file mode 100644 index 000000000..29833f491 --- /dev/null +++ b/test.py @@ -0,0 +1,14 @@ +import pint + +ureg = pint.UnitRegistry() +UC = pint.util.UnitsContainer +q=ureg.Quantity("0.1234 s") +units = [ureg.Unit(u) for u in ["us", "ms", "s", "min", "hour", "day"]] +q.to_human({UC({'[time]':1}): units}) + +ureg = pint.UnitRegistry() +UC = pint.util.UnitsContainer +q=ureg.Quantity("0.1234 m**3") +units = [ureg.Unit(u) for u in ["us", "ms", "s", "min", "hour", "day"]] +units2 = [ureg.Unit(u) for u in ["m**3", "liter",]] +q.to_human({UC({'[time]':1}): units, UC({'[length]':3}): units2}) From 12508bdc81ddd75d3b2ea29fd6050670547eedc2 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 16 Dec 2024 09:18:01 +0000 Subject: [PATCH 2/3] tests --- pint/facets/plain/qto.py | 3 ++ pint/testsuite/test_quantity.py | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/pint/facets/plain/qto.py b/pint/facets/plain/qto.py index f042f17bd..b4a1eb6cb 100644 --- a/pint/facets/plain/qto.py +++ b/pint/facets/plain/qto.py @@ -195,6 +195,9 @@ def to_human( """ + if human_units is None: + human_units = quantity._REGISTRY.default_human_units + candidate_units = [] if human_units: for unit in human_units: diff --git a/pint/testsuite/test_quantity.py b/pint/testsuite/test_quantity.py index 26a5ee05d..7866afe05 100644 --- a/pint/testsuite/test_quantity.py +++ b/pint/testsuite/test_quantity.py @@ -377,6 +377,56 @@ def test_convert(self): round(abs(self.Q_("2 second").to("millisecond").magnitude - 2000), 7) == 0 ) + def test_to_human(self): + ureg = self.ureg + Q_ = self.Q_ + time_units = [ureg.s, ureg.min, ureg.hr, ureg.day, ureg.year] + + temp = (1000*ureg.s).to_human(time_units) + helpers.assert_quantity_almost_equal(temp, Q_(16.6666667, 'minute')) + assert temp.units == ureg.minute + + temp = (100000*ureg.s).to_human(time_units) + helpers.assert_quantity_almost_equal(temp, Q_(1.15740741, 'day')) + assert temp.units == ureg.day + + temp = (100000000*ureg.s).to_human(time_units) + helpers.assert_quantity_almost_equal(temp, Q_(3.16880878, 'year')) + assert temp.units == ureg.year + + temp = ureg.Quantity(100000,"m**3/hr").to_human([ureg.Unit("m**3/s"), ureg.Unit("liter/s")]) + helpers.assert_quantity_almost_equal(temp, Q_(27.7777778, 'meter ** 3 / second')) + assert temp.units == ureg.Unit("m**3/s") + + temp = ureg.Quantity(1000,"m**3/hr").to_human([ureg.Unit("m**3/s"), ureg.Unit("liter/s")]) + helpers.assert_quantity_almost_equal(temp, Q_(277.777778, 'liter / second')) + assert temp.units == ureg.Unit("liter/s") + + def test_to_human_registry(self): + ureg = self.ureg + Q_ = self.Q_ + ureg.default_human_units = [ureg.s, ureg.min, ureg.hr, ureg.day, ureg.year, ureg.Unit("m**3/s"), ureg.Unit("liter/s")] + + temp = (1000*ureg.s).to_human() + helpers.assert_quantity_almost_equal(temp, Q_(16.6666667, 'minute')) + assert temp.units == ureg.minute + + temp = (100000*ureg.s).to_human() + helpers.assert_quantity_almost_equal(temp, Q_(1.15740741, 'day')) + assert temp.units == ureg.day + + temp = (100000000*ureg.s).to_human() + helpers.assert_quantity_almost_equal(temp, Q_(3.16880878, 'year')) + assert temp.units == ureg.year + + temp = ureg.Quantity(100000,"m**3/hr").to_human() + helpers.assert_quantity_almost_equal(temp, Q_(27.7777778, 'meter ** 3 / second')) + assert temp.units == ureg.Unit("m**3/s") + + temp = ureg.Quantity(1000,"m**3/hr").to_human() + helpers.assert_quantity_almost_equal(temp, Q_(277.777778, 'liter / second')) + assert temp.units == ureg.Unit("liter/s") + @helpers.requires_mip def test_to_preferred(self): ureg = self.ureg From ac21dc7f2f1c3848e8d364650e83be2e353c9e44 Mon Sep 17 00:00:00 2001 From: Andrew Date: Mon, 16 Dec 2024 09:18:50 +0000 Subject: [PATCH 3/3] remove file --- test.py | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 test.py diff --git a/test.py b/test.py deleted file mode 100644 index 29833f491..000000000 --- a/test.py +++ /dev/null @@ -1,14 +0,0 @@ -import pint - -ureg = pint.UnitRegistry() -UC = pint.util.UnitsContainer -q=ureg.Quantity("0.1234 s") -units = [ureg.Unit(u) for u in ["us", "ms", "s", "min", "hour", "day"]] -q.to_human({UC({'[time]':1}): units}) - -ureg = pint.UnitRegistry() -UC = pint.util.UnitsContainer -q=ureg.Quantity("0.1234 m**3") -units = [ureg.Unit(u) for u in ["us", "ms", "s", "min", "hour", "day"]] -units2 = [ureg.Unit(u) for u in ["m**3", "liter",]] -q.to_human({UC({'[time]':1}): units, UC({'[length]':3}): units2})