hgrecco / pint

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

Enable Mixed Unit Operations with Log Units [0dBm -10 dB = -10dBm] #1160

Open 5igno opened 4 years ago

5igno commented 4 years ago

In electrical engineering, quantities with logarithmic units such as dB and dBm are "summed" or "subtracted" although having different dimensionalities (which is forbidden for base units in pint). It would be nice if pint could support such operations.

Example 1: dB and dBm Let's consider a transmitter that generates a signal of 10 dBm. This signal goes through a channel that has an attenuation of -20 dB. The output power we expect is:

Q(10, ureg.dBm) - Q(20, ureg.dB) = Q(-10, ureg.dBm)

"Under the hood", the algebraic sum between dBm and dB is a product of two quantities in linear units (power and transmission probability), so the "difference" does not present a problem. When converting the logarithmic units to base units, the operation becomes:

Q(10, ureg.dBm) -> 1e1 mW Q(-20, ureg.dB) -> 1e-2

the sum in logarithmic units becomes a product in linear units, and the result is a power:

Q(10, ureg.dBm) + Q(-20, ureg.dB) -> 1e1 mW * 1e-2 = 1e-1 mW

The output power is converted back into a logarithmic unit, if that unit is available:

1e-1 mW -> Q(-10, ureg.dBm)

Here you see that the sum of dBm and dB gives a result in dBm and the result looks like a difference.

*Example 2: dB/km km** A related operation could pop-up when dealing with a channel with -10 dB/km losses, which attenuates the power of a signal by a factor of 10% for every km of propagation. If the channel is 3 km long one would get.

Q(-10, ureg.dB / ureg.km) * Q(3, ureg.km)

Pint can handle the computation with linear units in three steps:

Step#1: convert the log unit into base unit, which is from dB/km to dimensionless/km: Q(-10, ureg.dBm/ ureg.km) -> 1e-1 ureg.km^-1

Step#2: change the product into an exponentiation Q(-10, ureg.dB / ureg.km) * Q(3, ureg.km) -> (1e-1) ** (Q(3, ureg.km) / ureg.km)= 1e-3

Step#3: go back into a logarithmic unit, if that is available: 1e-3 -> Q(-30, ureg.dB)

Also here the exponentiation in linear units looks as a product in log units.

5igno commented 4 years ago

Notice that at if pint should support operations between log units, it should do so in a generic way. Let us make one example.

Q(10, ureg.dBm) + Q(20, ureg.dBm)

Let's try to see what this operation means in linear lunits:

Step#1: convert the units to base units: Q(10, ureg.dBm) -> 10 mW Q(20, ureg.dBm) -> 100 mW

Step#2: change the sum into a product and compute the result Q(10, ureg.dBm) + Q(20, ureg.dBm) -> 10 mW * 100 mW -> 1000 mW^2

Step#3: go back into a logarithmic unit, if that is available 1000 mW^2 -> 30 dBmW^2

As it is know dBmW^2 is not defined in the list of units, so the final conversion cannot be done.

Gracecr commented 2 years ago

Just ran into this issue with pint 0.19.

>>> Q(30, ureg.dBm) - Q(20, ureg.dBm)
<Quantity(10, 'delta_decibelmilliwatt')>
>>> (Q(30, ureg.dBm).to_base_units() - Q(20, ureg.dBm).to_base_units()).to("dB")
pint.errors.DimensionalityError: Cannot convert from 'kilogram * meter ** 2 / second ** 3' ([length] ** 2 * [mass] / [time] ** 3) to 'decibel' (dimensionless)

I can get my desired output with

>>> Q(Q(30, ureg.dBm).magnitude - Q(20, ureg.dBm).magnitude, ureg.dB)
<Quantity(10, 'decibel')>

but that's kind of working around pint, not with it.

5igno commented 2 years ago

Would this be ok for you to do? You get your desired output with the ratio operator in base units.

(Q(30, ureg.dBm).to_base_units() / Q(20, ureg.dBm).to_base_units()).to(ureg.dB)

I would use pint only to express a quantity with log units, use base units conversion for operations, and conversion back to log unit if that unit is defined and available.

Gracecr commented 2 years ago

That does work, thanks!

It isn't until just now that I recognize why subtracting and adding logarithmic units poses a problem for pint and how it causes problems for determining dimensions.

I read through https://pint.readthedocs.io/en/stable/log_units.html and https://pint.readthedocs.io/en/stable/log_units.html#compound-log-units, but these articles assume you have a good understanding of what logarithmic units are, which is a reasonable assumption.