Skip to content

Commit

Permalink
Fix value formatting
Browse files Browse the repository at this point in the history
  • Loading branch information
mph- committed Nov 16, 2024
1 parent ec7c362 commit a7f54db
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 56 deletions.
21 changes: 5 additions & 16 deletions doc/schematics.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1518,24 +1518,13 @@ Label value style

Label values are formatted according to the `label_value_style`
attribute. The default is `eng3` which uses an engineering format
with a maximum of three digits. Other formats include 'spice' and
`sci` (scientific).
with a maximum of three digits. Other formats include `spice`,
`sci` (scientific), and `ratfun` (rational functions).

Here's an example with `label_value_style=sci2`:

.. image:: examples/schematics/VRLC1-sci2.png
:width: 7cm

Here's an example with `label_value_style=eng`:

.. image:: examples/schematics/VRLC1-eng.png
:width: 7cm

Here's an example with `label_value_style=spice`:

.. image:: examples/schematics/VRLC1-spice.png
:width: 7cm
Here's an example showing the different formats:

.. image:: examples/schematics/label_value_style.png
:width: 12cm


.. _label_placement:
Expand Down
29 changes: 15 additions & 14 deletions lcapy/labelmaker.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ def _format_expr(self, expr):

def _format_value_units(self, value, units, style):

expr = Expr(value, cache=False)
if not expr.is_constant or units == '':
return expr.latex_math()

if style == 'ratfun':
value = expr

return value_formatter(style=style).latex_math(value, units)

def _format_name(self, cpt_type, cpt_id):
Expand All @@ -31,7 +38,7 @@ def _format_name(self, cpt_type, cpt_id):
name = name + '_{%s}' % subscript
return latex_format_label('$' + name + '$')

def make(self, cpt, label_ports=False, style='SI'):
def make(self, cpt, label_ports=False, style='eng'):

# There are two possible labels for a component:
# 1. Component name, e.g., R1
Expand Down Expand Up @@ -76,19 +83,13 @@ def make(self, cpt, label_ports=False, style='SI'):
expr = cpt.args[1]
value_label = self._format_expr(expr)
elif cpt.classname not in ('TP',):
try:
# Handle things like 9/1000 that can occur
# when substituting cpt values.
value = float(sym.Rational(expr))
if cpt.type in units_map:
value_label = self._format_value_units(
value, units_map[cpt.type], style)
else:
value_label = self._format_expr(expr)

except (ValueError, TypeError):
# This catches non numeric arg.
value_label = self._format_expr(expr)

if cpt.type in units_map:
units = units_map[cpt.type]
else:
units = ''

value_label = self._format_value_units(expr, units, style)

# Ensure labels are the same when the value is not specified.
# This will prevent printing the name and value.
Expand Down
3 changes: 2 additions & 1 deletion lcapy/schematic.py
Original file line number Diff line number Diff line change
Expand Up @@ -552,7 +552,8 @@ def draw(self, filename=None, **kwargs):
kwargs include:
'label_ids': True to show component ids
'label_values': True to display component values
'label_value_style': 'eng3' for SI; 'spice3' for SPICE
"label_value_style': 'eng' for engineering (SI); 'sci' for scientific;
'ratfun' for rational function; 'spice' for SPICE"
'label_delimiter': Delimiter between component name and value
'label_flip': Place label on other side of component
'annotate_values': True to display component values as separate label
Expand Down
74 changes: 49 additions & 25 deletions lcapy/valueformatter.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,26 @@

class ValueFormatter(object):

def __init__(self, trim=True, hundreds=False, num_digits=3):
def __init__(self, trim=True, hundreds=False, fmt=''):
"""If `hundreds` True format like 100 pF rather than 0.1 nF"""

self.trim = trim
self.hundreds = hundreds
self.num_digits = num_digits

if fmt == '':
self.num_digits = 3
else:
try:
self.num_digits = int(fmt)
except ValueError:
raise ValueError('Expected a digit for format, got ' + fmt)

def _do(self, value, unit, aslatex):

prefixes = ('f', 'p', 'n', 'u', 'm', '', 'k', 'M', 'G', 'T')

value = value
value = float(value)

if value == 0:
return self._fmt('0', unit, '', aslatex)

Expand All @@ -29,12 +37,19 @@ def _do(self, value, unit, aslatex):
if not self.hundreds:
m += 1
n = int(floor(m / 3))
k = int(floor(m)) - n * 3
else:
n = 0
k = m - 1

dp = self.num_digits - k
# value m n
# 3141592 6.5 2
# 314159. 5.5 1
# 31415.9 4.5 1
# 3141.59 3.5 1
# 314.159 2.5 0
# 31.4159 1.5 0
# 3.14159 0.5 0
# .314159 -0.5 0
# .0314159 -1.5 -1

idx = n + 5
# Handle extremely large or small values without a prefix
Expand All @@ -43,13 +58,13 @@ def _do(self, value, unit, aslatex):
elif idx >= len(prefixes):
return self._fmt('%e' % value, unit, '', aslatex)

if dp < 0:
dp = 0
fmt = '%%.%df' % dp
svalue = value * 10**(-3 * n)

value = value * 10**(-3 * n)
# Round to num_digits
scale = 10 ** (self.num_digits - 1 - floor(log10(abs(svalue))))
rvalue = round(svalue * scale) / scale

valstr = fmt % value
valstr = str(rvalue)

if self.trim:
# Remove trailing zeroes after decimal point
Expand Down Expand Up @@ -129,6 +144,8 @@ class SciValueFormatter(ValueFormatter):

def _do(self, value, unit, aslatex):

value = float(value)

fmt = '%%.%dE' % (self.num_digits - 1)

valstr = fmt % value
Expand Down Expand Up @@ -156,23 +173,30 @@ def _do(self, value, unit, aslatex):
return valstr + '\\,' + '\\mathrm{' + unit + '}'


class RatfunValueFormatter(ValueFormatter):

def _do(self, value, unit, aslatex):

if not aslatex:
return str(value) + ' ' + unit

if unit.startswith('$'):
return value.latex() + '\\,' + unit[1:-1]

return value.latex() + '\\,' + '\\mathrm{' + unit + '}'


def value_formatter(style='eng3'):

style = style.lower()

# Split into style and num
num = 3
for m in range(len(style)):
if style[m].isdigit():
num = int(style[m:])
style = style[0:m]
break

if style == 'eng':
return EngValueFormatter(num_digits=num)
elif style == 'spice':
return SPICEValueFormatter(num_digits=num)
elif style == 'sci':
return SciValueFormatter(num_digits=num)
if style.startswith('eng'):
return EngValueFormatter(fmt=style[3:])
elif style.startswith('spice'):
return SPICEValueFormatter(fmt=style[5:])
elif style.startswith('sci'):
return SciValueFormatter(fmt=style[3:])
elif style.startswith('ratfun'):
return RatfunValueFormatter(fmt='')
else:
raise ValueError('Unknown style: ' + style)

0 comments on commit a7f54db

Please sign in to comment.