Open 5igno opened 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.
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.
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.
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.
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.