pint icon indicating copy to clipboard operation
pint copied to clipboard

Override units display order (1 kW·h displayed as 1 h·kW)

Open scanzy opened this issue 1 year ago • 6 comments

Let's consider this code

import pint as pt

# sets compact display mode
u = pt.UnitRegistry()
u.default_format = '~P'

# creates quantity
q = u.Quantity("1 kW * 1 h")

# this prints "1 h·kW", not "1 kW·h" as expected
print(q)

During the string conversion I believe the units are sorted alphabetically, in fact hour comes before kilowatt.

How can I override this behaviour to have it printed correctly as 1 kW·h? For now I am doing str(q).replace("h·kW", "kW·h") but I am looking for a better solution, that may act globally and before string conversion.

Any suggestions? Thank you!

scanzy avatar Aug 29 '23 21:08 scanzy

With latest version you may be able to with a custom format that sorts the units in unit as desired. https://pint.readthedocs.io/en/latest/user/formatting.html?highlight=format#custom-unit-format-types

It may be worth adding custom sorting as an example there.

andrewgsavage avatar Sep 12 '23 20:09 andrewgsavage

Thank you! I have some ideas about how to do it. I will try

However, do you think it would be possible to use this to change only the order but not the format?

In other words: How to apply my custom order to all the existing possible formatting options? Compact, latex, etc.

I may find all the format specifiers and (programmatically) create a new updated format (with custom) for each one.

What do you think?

Il giorno mar 12 set 2023 alle 22:17 andrewgsavage @.***> ha scritto:

With latest version you may be able to with a custom format that sorts the units in unit as desired.

https://pint.readthedocs.io/en/latest/user/formatting.html?highlight=format#custom-unit-format-types

It may be worth adding custom sorting as an example there.

— Reply to this email directly, view it on GitHub https://github.com/hgrecco/pint/issues/1841#issuecomment-1716364476, or unsubscribe https://github.com/notifications/unsubscribe-auth/ADDJSQEPDSWUTW2OYBH7TRDX2C7M7ANCNFSM6AAAAAA4DRK7NI . You are receiving this because you authored the thread.Message ID: @.***>

scanzy avatar Sep 13 '23 21:09 scanzy

I do think it's pretty common to place time dimensions after all other dimensions (i.e., acceleration as m/s**2 or power as kW * h), so just doing that one thing might solve most of the problems.

MichaelTiemannOSC avatar Oct 20 '23 07:10 MichaelTiemannOSC

This is a very interesting point, however do you have any idea about how to implement this in pint?

Or maybe the library requires some sort of unit order customization functionality?


What about using a unit preprocessor argument for the formatter function?

Code from pint/pint/formatting.py


@register_unit_format("L")
def format_latex(unit: UnitsContainer, registry: UnitRegistry, **options) -> str:
    preprocessed = {rf"\mathrm{{{latex_escape(u)}}}": p for u, p in unit.items()}
    formatted = formatter(
        preprocessed.items(),
        as_ratio=True,
        single_denominator=True,
        product_fmt=r" \cdot ",
        division_fmt=r"\frac[{}][{}]",
        power_fmt="{}^[{}]",
        parentheses_fmt=r"\left({}\right)",
        **options,
    )
    return formatted.replace("[", "{").replace("]", "}")

scanzy avatar Oct 20 '23 08:10 scanzy

Xref (albeit to a partially closed-source answer): https://www.iso.org/obp/ui/#iso:std:iso:80000:%2D1:ed-1:v1:en

MichaelTiemannOSC avatar Oct 21 '23 23:10 MichaelTiemannOSC

There is a long standing plan to move the formatting to Delegate (like the Parser) which is composed (not inherited). In this way, string formatting would be more decoupled and therefore easy to change..

hgrecco avatar Oct 22 '23 03:10 hgrecco