Added options to normalize R, L and C values.

This commit is contained in:
SET 2020-08-13 22:45:25 -03:00
parent 7544f75a53
commit e35ef8ec3c
3 changed files with 46 additions and 33 deletions

View File

@ -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])])

View File

@ -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)

View File

@ -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