hgrecco / pint

Operate and manipulate physical quantities in Python
http://pint.readthedocs.org/
Other
2.37k stars 466 forks source link

Logarithmic mixed units off by 1e3 #1840

Open KEClaytor opened 1 year ago

KEClaytor commented 1 year ago

I'm looking at defining custom log units. These seem to work fine when converting in isolation (I can convert between the base units and the dB units back and forth all day). However, when the log units consist of mixed base units, it seems to be off by a factor of 1e3 (30dB) for db units that are defined as divide or multiplies.

from pint import UnitRegistry

ureg = UnitRegistry(autoconvert_offset_to_baseunit=True)

ureg.define('decibelvolt = volt; logbase: 10; logfactor: 10 = dBV')
ureg.define('decibelampere = ampere; logbase: 10; logfactor: 10 = dBA')
A = 1 * ureg.V
B = 1 * ureg.A
print(A, B)
dB_A = A.to('dBV')
dB_B = B.to('dBA')
print(dB_A, dB_B)

ureg.define('decibelvoltperampere = volt / ampere; logbase: 10; logfactor: 10 = dBvoltperampre = dBVperA')
A_div_B = A/B
dB_A_div_B = A_div_B.to("dBVperA")
print(A_div_B, dB_A_div_B)

ureg.define('decibelvoltampere = volt * ampere; logbase: 10; logfactor: 10 = dBvoltampre = dBVA')
A_times_B = A * B
dB_A_times_B = A_times_B.to("dBVA")
print(A_times_B, dB_A_times_B)

Yields the output:

1 volt 1 ampere
0.0 decibelvolt 0.0 decibelampere
1.0 volt / ampere 29.999999999999996 decibelvoltperampere
1 ampere * volt 29.999999999999996 decibelvoltampere

Instead of the expected 0 decibelvoltperampere and 0 decibelvoltampere.

This is related to #1160, ideally I would like to just subtract the two log values and have a result of mixed log units 0 dBV - 0 dBA = 0 dB(V/A).

This has the same results if you call the to_base_units as well: A_div_B.to_base_units().to("dBVperA")

Edit: tried with multiply as well. Edit 2: adding results with to_base_units()

Edit3: version:

import pint
pint.__version__
'0.22'

Edit 4: Updated to v'0.22' and still having the issue.

KEClaytor commented 1 year ago

Here is perhaps an even more reduced example:

from pint import UnitRegistry

ureg = UnitRegistry(autoconvert_offset_to_baseunit=True)

ureg.define('decibelvoltperampere = volt/ampere; logbase: 10; logfactor: 10 = dBvoltperampere = dBVperA')

C = 1 * ureg.V/ureg.A
dB_C = C.to(ureg.dBVperA)
print(C, dB_C)

1.0 volt / ampere 29.999999999999996 decibelvoltperampere