Skip to content

Feature Request: human readible index or catalogue of registry content #2249

@velovole

Description

@velovole

In many apps there is a need for showing users drill down catalogues of metrics and corresponding units, so they can make choices for the kind of unit conversion they need.

Such a metric/unit drill down menu would look like this:

metric = "speed" , units = [ "meter_per_second", "kilometer_per_second", "kilometer_per_hour", ... ]

Currently, pint does not offer any API functions to read such catalogue information from the registry. You have to apply a hack to get it squeezed out like shown below. Although the hack works, it would be better not having to read such data from private class attributes of the registry object.

------------------ hack accessing the _units attribute of the registry -------------------------------------------

u_reg = pint.UnitRegistry()

# build pint-metric-to-units index
def build_pm2u():
    index = defaultdict(list)
    for name, unit_def in u_reg._units.items(): # ugly access of private attribute - currently no alternative
        try:
            unit = u_reg.Unit(name)
            canonical_name = str(unit._units)
            dimensionality = unit.dimensionality
            if not dimensionality:  # covers dimensionless units as arcsecond, rad, ....
                dimensionality_key = "dimensionless"
            else:
                dimensionality_key = str(dimensionality)
            index[dimensionality_key].append(canonical_name)
        except Exception:
            continue
    return {key: set(value) for key, value in index.items()}

PINT_METRIC_TO_UNITS = build_pm2u()

# custom wrapper index for pint metrics
METRIC_TO_PINT_METRICS = {"acceleration": {"label": "Acceleration", "dims": ["[length] / [time] ** 2"]},
                          "area": {"label": "Area", "dims": ["[length] ** 2"]},
                          "catalytic_activity": {"label": "Catalytic Activity", "dims": ["[substance] / [time]"]},
                          "concentration": {"label": "Concentration", "dims": ["[substance] / [length] ** 3"]},
                          "density": {"label": "Density", "dims": ["[mass] / [length] ** 3"]},
                          "electric_capacitance": {"label": "Electric Capacitance", "dims": ["[current] ** 2 * [time] ** 4 / [mass] / [length] ** 2"]},
                          "electric_charge": {"label": "Electric Charge", "dims": ["[current] * [time]"]},
                          (...)
                          }

# build the wrapped and sorted metric-to-units index for use with UI clients
def build_m2u(m2pm, pm2u):
    index = {}
    for key, value in m2pm.items():
        units = []
        for dim in value["dims"]:
            units.extend(pm2u.get(dim, []))
        index[key] = sorted(set(units)) 
    return index

METRIC_TO_UNITS = build_m2u(METRIC_TO_PINT_METRICS, PINT_METRIC_TO_UNITS)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions