Added options to normalize R, L and C values.
This commit is contained in:
parent
7544f75a53
commit
e35ef8ec3c
|
|
@ -4,6 +4,7 @@ This code is adapted from https://github.com/SchrodingersGat/KiBoM by Oliver Hen
|
||||||
|
|
||||||
Here is all the logic to convert a list of components into the rows and columns used to create the BoM.
|
Here is all the logic to convert a list of components into the rows and columns used to create the BoM.
|
||||||
"""
|
"""
|
||||||
|
import locale
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from .units import compare_values, comp_match
|
from .units import compare_values, comp_match
|
||||||
from .bom_writer import write_bom
|
from .bom_writer import write_bom
|
||||||
|
|
@ -315,7 +316,7 @@ def get_value_sort(comp):
|
||||||
""" Try to better sort R, L and C components """
|
""" Try to better sort R, L and C components """
|
||||||
res = comp.value_sort
|
res = comp.value_sort
|
||||||
if res:
|
if res:
|
||||||
value, mult, unit = res
|
value, (mult, mult_s), unit = res
|
||||||
if comp.ref_prefix in "CL":
|
if comp.ref_prefix in "CL":
|
||||||
# fempto Farads
|
# fempto Farads
|
||||||
value = "{0:15d}".format(int(value * 1e15 * mult + 0.1))
|
value = "{0:15d}".format(int(value * 1e15 * mult + 0.1))
|
||||||
|
|
@ -326,6 +327,18 @@ def get_value_sort(comp):
|
||||||
return comp.value
|
return comp.value
|
||||||
|
|
||||||
|
|
||||||
|
def normalize_value(c, decimal_point):
|
||||||
|
if c.value_sort is None:
|
||||||
|
return c.value
|
||||||
|
value, (mult, mult_s), unit = c.value_sort
|
||||||
|
ivalue = int(value)
|
||||||
|
if value == ivalue:
|
||||||
|
value = ivalue
|
||||||
|
elif decimal_point:
|
||||||
|
value = str(value).replace('.', decimal_point)
|
||||||
|
return '{} {}{}'.format(value, mult_s, unit)
|
||||||
|
|
||||||
|
|
||||||
def group_components(cfg, components):
|
def group_components(cfg, components):
|
||||||
groups = []
|
groups = []
|
||||||
# Iterate through each component, and test whether a group for these already exists
|
# Iterate through each component, and test whether a group for these already exists
|
||||||
|
|
@ -338,7 +351,7 @@ def group_components(cfg, components):
|
||||||
continue
|
continue
|
||||||
# Cache the value used to sort
|
# Cache the value used to sort
|
||||||
if c.ref_prefix in RLC_PREFIX:
|
if c.ref_prefix in RLC_PREFIX:
|
||||||
c.value_sort = comp_match(c.value)
|
c.value_sort = comp_match(c.value, c.ref_prefix)
|
||||||
else:
|
else:
|
||||||
c.value_sort = None
|
c.value_sort = None
|
||||||
# Try to add the component to an existing group
|
# Try to add the component to an existing group
|
||||||
|
|
@ -354,11 +367,18 @@ def group_components(cfg, components):
|
||||||
g.add_component(c)
|
g.add_component(c)
|
||||||
groups.append(g)
|
groups.append(g)
|
||||||
# Now unify the data from the components of each group
|
# Now unify the data from the components of each group
|
||||||
|
decimal_point = None
|
||||||
|
if cfg.normalize_locale:
|
||||||
|
decimal_point = locale.localeconv()['decimal_point']
|
||||||
|
if decimal_point == '.':
|
||||||
|
decimal_point = None
|
||||||
for g in groups:
|
for g in groups:
|
||||||
# Sort the references within each group
|
# Sort the references within each group
|
||||||
g.sort_components()
|
g.sort_components()
|
||||||
# Fill the columns
|
# Fill the columns
|
||||||
g.update_fields(cfg.use_alt)
|
g.update_fields(cfg.use_alt)
|
||||||
|
if cfg.normalize_values:
|
||||||
|
g.fields[ColumnList.COL_VALUE_L] = normalize_value(g.components[0], decimal_point)
|
||||||
# Sort the groups
|
# Sort the groups
|
||||||
# First priority is the Type of component (e.g. R?, U?, L?)
|
# First priority is the Type of component (e.g. R?, U?, L?)
|
||||||
groups = sorted(groups, key=lambda g: [g.components[0].ref_prefix, get_value_sort(g.components[0])])
|
groups = sorted(groups, key=lambda g: [g.components[0].ref_prefix, get_value_sort(g.components[0])])
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,17 @@ match = None
|
||||||
decimal_point = None
|
decimal_point = None
|
||||||
|
|
||||||
|
|
||||||
def get_unit(unit):
|
def get_unit(unit, ref_prefix):
|
||||||
""" Return a simplified version of a units string, for comparison purposes """
|
""" Return a simplified version of a units string, for comparison purposes """
|
||||||
if not unit:
|
if not unit:
|
||||||
return None
|
if ref_prefix == 'L':
|
||||||
|
return "H"
|
||||||
|
if ref_prefix == 'C':
|
||||||
|
return "F"
|
||||||
|
return u"Ω"
|
||||||
unit = unit.lower()
|
unit = unit.lower()
|
||||||
if unit in UNIT_R:
|
if unit in UNIT_R:
|
||||||
return "R"
|
return u"Ω"
|
||||||
if unit in UNIT_C:
|
if unit in UNIT_C:
|
||||||
return "F"
|
return "F"
|
||||||
if unit in UNIT_L:
|
if unit in UNIT_L:
|
||||||
|
|
@ -57,29 +61,29 @@ def get_unit(unit):
|
||||||
def get_prefix(prefix):
|
def get_prefix(prefix):
|
||||||
""" Return the (numerical) value of a given prefix """
|
""" Return the (numerical) value of a given prefix """
|
||||||
if not prefix:
|
if not prefix:
|
||||||
return 1
|
return 1, ''
|
||||||
# 'M' is mega, 'm' is milli
|
# 'M' is mega, 'm' is milli
|
||||||
if prefix != 'M':
|
if prefix != 'M':
|
||||||
prefix = prefix.lower()
|
prefix = prefix.lower()
|
||||||
if prefix in PREFIX_PICO:
|
if prefix in PREFIX_PICO:
|
||||||
return 1.0e-12
|
return 1.0e-12, 'p'
|
||||||
if prefix in PREFIX_NANO:
|
if prefix in PREFIX_NANO:
|
||||||
return 1.0e-9
|
return 1.0e-9, 'n'
|
||||||
if prefix in PREFIX_MICRO:
|
if prefix in PREFIX_MICRO:
|
||||||
return 1.0e-6
|
return 1.0e-6, u"µ"
|
||||||
if prefix in PREFIX_MILLI:
|
if prefix in PREFIX_MILLI:
|
||||||
return 1.0e-3
|
return 1.0e-3, 'm'
|
||||||
if prefix in PREFIX_KILO:
|
if prefix in PREFIX_KILO:
|
||||||
return 1.0e3
|
return 1.0e3, 'k'
|
||||||
if prefix in PREFIX_MEGA:
|
if prefix in PREFIX_MEGA:
|
||||||
return 1.0e6
|
return 1.0e6, 'M'
|
||||||
if prefix in PREFIX_GIGA:
|
if prefix in PREFIX_GIGA:
|
||||||
return 1.0e9
|
return 1.0e9, 'G'
|
||||||
# Unknown, we shouldn't get here because the regex matched
|
# Unknown, we shouldn't get here because the regex matched
|
||||||
# BUT: I found that sometimes unexpected things happend, like mu matching micro and then we reaching this code
|
# BUT: I found that sometimes unexpected things happend, like mu matching micro and then we reaching this code
|
||||||
# Now is fixed, but I can't be sure some bizarre case is overlooked
|
# Now is fixed, but I can't be sure some bizarre case is overlooked
|
||||||
logger.error('Unknown prefix, please report') # pragma: no cover
|
logger.error('Unknown prefix, please report') # pragma: no cover
|
||||||
return 1 # pragma: no cover
|
return 1, '' # pragma: no cover
|
||||||
|
|
||||||
|
|
||||||
def group_string(group): # Return a reg-ex string for a list of values
|
def group_string(group): # Return a reg-ex string for a list of values
|
||||||
|
|
@ -90,7 +94,7 @@ def match_string():
|
||||||
return r"(\d*\.?\d*)\s*(" + group_string(PREFIX_ALL) + ")*(" + group_string(UNIT_ALL) + r")*(\d*)$"
|
return r"(\d*\.?\d*)\s*(" + group_string(PREFIX_ALL) + ")*(" + group_string(UNIT_ALL) + r")*(\d*)$"
|
||||||
|
|
||||||
|
|
||||||
def comp_match(component):
|
def comp_match(component, ref_prefix):
|
||||||
"""
|
"""
|
||||||
Return a normalized value and units for a given component value string
|
Return a normalized value and units for a given component value string
|
||||||
e.g. comp_match('10R2') returns (10, R)
|
e.g. comp_match('10R2') returns (10, R)
|
||||||
|
|
@ -145,22 +149,7 @@ def comp_match(component):
|
||||||
val = float(value)
|
val = float(value)
|
||||||
|
|
||||||
# Return all the data, let the caller join it
|
# Return all the data, let the caller join it
|
||||||
return (val, get_prefix(prefix), get_unit(units))
|
return (val, get_prefix(prefix), get_unit(units, ref_prefix))
|
||||||
|
|
||||||
|
|
||||||
# def component_value(valString):
|
|
||||||
#
|
|
||||||
# result = comp_match(valString)
|
|
||||||
#
|
|
||||||
# if not result:
|
|
||||||
# return valString # Return the same string back
|
|
||||||
#
|
|
||||||
# if not len(result) == 2: # Result length is incorrect
|
|
||||||
# return valString
|
|
||||||
#
|
|
||||||
# val = result[0]
|
|
||||||
#
|
|
||||||
# return val
|
|
||||||
|
|
||||||
|
|
||||||
def compare_values(c1, c2):
|
def compare_values(c1, c2):
|
||||||
|
|
@ -174,8 +163,8 @@ def compare_values(c1, c2):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# Join the data to compare
|
# Join the data to compare
|
||||||
(v1, p1, u1) = r1
|
(v1, (p1, ps1), u1) = r1
|
||||||
(v2, p2, u2) = r2
|
(v2, (p2, ps2), u2) = r2
|
||||||
|
|
||||||
v1 = "{0:.15f}".format(v1 * 1.0 * p1)
|
v1 = "{0:.15f}".format(v1 * 1.0 * p1)
|
||||||
v2 = "{0:.15f}".format(v2 * 1.0 * p2)
|
v2 = "{0:.15f}".format(v2 * 1.0 * p2)
|
||||||
|
|
|
||||||
|
|
@ -250,6 +250,10 @@ class BoMOptions(BaseOptions):
|
||||||
self.columns = BoMColumns
|
self.columns = BoMColumns
|
||||||
""" [list(dict)|list(string)] List of columns to display.
|
""" [list(dict)|list(string)] List of columns to display.
|
||||||
Can be just the name of the field """
|
Can be just the name of the field """
|
||||||
|
self.normalize_values = False
|
||||||
|
""" Try to normalize the R, L and C values, producing uniform units and prefixes """
|
||||||
|
self.normalize_locale = False
|
||||||
|
""" When normalizing values use the locale decimal point """
|
||||||
self.html = BoMHTML
|
self.html = BoMHTML
|
||||||
""" [dict] Options for the HTML format """
|
""" [dict] Options for the HTML format """
|
||||||
self.xlsx = BoMXLSX
|
self.xlsx = BoMXLSX
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue