uom.uom   A
last analyzed

Complexity

Total Complexity 28

Size/Duplication

Total Lines 141
Duplicated Lines 0 %

Test Coverage

Coverage 94.59%

Importance

Changes 0
Metric Value
wmc 28
eloc 79
dl 0
loc 141
ccs 70
cts 74
cp 0.9459
rs 10
c 0
b 0
f 0

4 Functions

Rating   Name   Duplication   Size   Complexity  
D convert() 0 32 13
B base_unit() 0 47 6
A base_conversion_factors() 0 17 3
B conversion_factors() 0 27 6
1
"""UOM conversion tool."""
2
3 1
from __future__ import absolute_import, division
4
5 1
from colorlog import debug, info
6
7 1
from uom.unit_alias import unit_alias
8
9 1
from .uomdata import DF_UOM
10
11
12 1
def base_conversion_factors(unit_or_alias):
13
    """Return conversion facors to the base unit."""
14 1
    unit = unit_alias(unit_or_alias)
15
16 1
    if unit not in DF_UOM.index:
17 1
        debug(f"Unit {unit_or_alias} unknown.")
18
19 1
        return None, None, None
20
21 1
    debug(f"""{unit}, {DF_UOM["A"][unit]}, {DF_UOM["B"][unit]}, {DF_UOM["C"][unit]}""")
22
23 1
    if DF_UOM["baseUnit"][unit] == "IS-BASE":
24 1
        debug(f"The unit {unit} it is a base unit.")
25
26 1
        return 0, 1, 1
27
28 1
    return DF_UOM["A"][unit], DF_UOM["B"][unit], DF_UOM["C"][unit]
29
30
31 1
def base_unit(unit_or_alias):
32
    """Return base unit."""
33 1
    unit = unit_alias(unit_or_alias)
34
35 1
    if unit not in DF_UOM.index:
36 1
        debug(f"Unit {unit_or_alias} unknown.")
37
38 1
        return None
39
40 1
    b_unit = DF_UOM["baseUnit"][unit]
41 1
    underlying_def = DF_UOM["underlyingDef"][unit]
42
43 1
    debug(
44
        f"Input: {unit_or_alias}, unit: {unit}, base_unit: {b_unit}, underlying_unit: "
45
        f"{underlying_def}"
46
    )
47
48 1
    if b_unit == "IS-BASE":
49 1
        if underlying_def:
50 1
            if underlying_def not in DF_UOM.index:
51 1
                debug(
52
                    f"{unit_or_alias} => {unit} [Case1: IsBase, UD = {underlying_def}, "
53
                    "but not available]>"
54
                )
55
56 1
                return unit
57
58 1
            debug(
59
                f"{unit_or_alias} => {unit} [Case2: IsBase, UD = {underlying_def} and " "available]"
60
            )
61
62 1
            unit2 = DF_UOM["baseUnit"][underlying_def]
63
64 1
            if unit2 not in DF_UOM.index:
65 1
                debug(f"Base unit {unit2} not in the index")
66
67 1
                return underlying_def
68
69
            info(f"Base unit {b_unit} in the index")
70
        else:
71
            info(f"{unit_or_alias} => {unit} [Case3: IsBase, UD is missing]")
72
73
            return unit
74
75 1
    debug(f"{unit_or_alias} => {b_unit} [Case4: IsNotBase available]")
76
77 1
    return base_unit(b_unit)
78
79
80 1
def conversion_factors(source, target):
81
    """Return conversion scale and offset."""
82 1
    source_base_unit = base_unit(source)
83 1
    target_base_unit = base_unit(target)
84
85 1
    if source_base_unit is None or target_base_unit is None:
86 1
        return None, None
87
88 1
    if source_base_unit != target_base_unit:
89 1
        debug(f"The units {source} and {target} are not compatible.")
90
91 1
        source_dim = DF_UOM["dimension"][unit_alias(source)]
92
93 1
        if source_dim == DF_UOM["dimension"][unit_alias(target)] and source_dim != "none":
94
            raise ValueError("ERROR: Houston, we have a problem")
95
96 1
        return None, None
97
98 1
    source_a, source_b, source_c = base_conversion_factors(source)
99 1
    target_a, target_b, target_c = base_conversion_factors(target)
100
101 1
    scale = source_b * target_c / source_c / target_b
102 1
    offset = source_a * target_c / source_c / target_b - target_a / target_b
103
104 1
    info(f"Scale: {scale:.15g}, offset: {offset:.15g}")
105
106 1
    return scale, offset
107
108
109 1
def convert(value, source=None, target=None):
110
    """Convert value(s) from source to target."""
111 1
    if source == target or ("unitless" in [source, target] and "" in [source, target]):
112 1
        return value
113
114 1
    if target is None and source is not None:
115 1
        target = base_unit(source)
116
117 1
        if target is None:
118 1
            return None
119
120 1
    if source is None and target is not None:
121 1
        source = base_unit(target)
122
123 1
        if source is None:
124 1
            return None
125
126 1
    scale, offset = conversion_factors(source, target)
127
128 1
    if scale is None or offset is None:
129 1
        return None
130
131 1
    debug(f"value: {type(value)}")
132
133 1
    if isinstance(value, list):
134 1
        target_value = [scale * i + offset for i in value]
135
    else:
136 1
        target_value = scale * value + offset
137
138 1
    debug(f"target_value: {type(target_value)}")
139
140
    return target_value
141