#!/usr/bin/env python
# encoding: utf-8
# Copyright (C) 2015 Chintalagiri Shashank
#
# This file is part of tendril.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
Docstring for series.py
"""
import copy
import iec60063
from math import log10
from decimal import InvalidOperation
from tendril.conventions import electronics
from tendril.utils.types.electromagnetic import Resistance
from tendril.utils.types.electromagnetic import Capacitance
[docs]class ValueSeries(object):
def __init__(self, stype, start, end, device, footprint):
self._stype = stype
self._start = start
self._end = end
self._device = device
self._footprint = footprint
if self._stype == 'resistor':
self._typeclass = Resistance
if self._stype == 'capacitor':
self._typeclass = Capacitance
[docs] def gen_vals(self, stype=None, start=None, end=None):
raise NotImplementedError
[docs] def get_symbol(self, value, device=None, footprint=None):
from tendril.gedaif import gsymlib
if device is None:
device = self._device
if footprint is None:
footprint = self._footprint
if self._stype == 'resistor':
if isinstance(value, (str, Resistance)):
try:
return gsymlib.find_resistor(value, footprint, device)
except (gsymlib.NoGedaSymbolException, InvalidOperation):
pass
if self._stype == 'capacitor':
if isinstance(value, (str, Capacitance)):
try:
return gsymlib.find_capacitor(value, footprint, device)
except (gsymlib.NoGedaSymbolException, InvalidOperation):
pass
ident = electronics.ident_transform(device, value, footprint)
return gsymlib.get_symbol(ident)
[docs] def get_type_value(self, value):
if self._stype == 'capacitor':
capacitance, voltage = electronics.parse_capacitor(value)
return self._typeclass(capacitance)
if self._stype == 'resistor':
resistance, wattage = electronics.parse_resistor(value)
return self._typeclass(resistance)
[docs] def get_closest_value(self, target, heuristic=None):
if heuristic == '+':
raise NotImplementedError
elif heuristic == '-':
raise NotImplementedError
elif heuristic is None:
ldelta = None
lvalue = None
for value in self.gen_vals(self._stype):
if value == target:
return value
if value > target:
if ldelta is None:
return value
else:
ndelta = target - value
if abs(ndelta) < abs(ldelta):
return value
else:
return lvalue
ldelta = target - value
lvalue = value
else:
raise AttributeError
[docs] def get_characteristic_value(self):
s = 0
n = 0
for value in self.gen_vals(self._stype):
s += log10(float(value))
n += 1
return self._typeclass(10 ** (s/n))
[docs]class IEC60063ValueSeries(ValueSeries):
def __init__(self, series, stype, start=None, end=None,
device=None, footprint=None):
super(IEC60063ValueSeries, self).__init__(stype, start, end,
device, footprint)
self._series = iec60063.get_series(series)
self._ostrs = iec60063.get_ostr(stype)
[docs] def gen_vals(self, stype=None, start=None, end=None):
if stype != self._stype:
raise TypeError('This {0} series is not defined for {1}'
''.format(self._stype, stype))
if start is None:
start = self._start
if end is None:
end = self._end
for value in iec60063.gen_vals(self._series, self._ostrs,
start=start, end=end):
yield self._typeclass(value)
[docs]class CustomValueSeries(ValueSeries):
def __init__(self, name, stype, start=None, end=None,
device=None, footprint=None):
super(CustomValueSeries, self).__init__(
stype, start, end, device, footprint
)
self._name = name
self._values = {}
self._desc = None
self._aparams = {}
if self._start is not None:
if not isinstance(self._start, self._typeclass):
self._start = self._typeclass(self._start)
if self._end is not None:
if not isinstance(self._end, self._typeclass):
self._end = self._typeclass(self._end)
[docs] def add_value(self, type_value, value):
if not isinstance(type_value, self._typeclass):
type_value = self._typeclass(type_value)
type_value = str(type_value)
self._values[type_value] = value
[docs] def _value_generator(self, start=None, end=None):
values = sorted([self._typeclass(x) for x in self._values.keys()])
for value in values:
if start is not None and value < start:
continue
if end is not None and value > end:
break
yield value
[docs] def gen_vals(self, stype=None, start=None, end=None):
if stype and stype != self._stype:
raise ValueError("{0} is not an allowed stype for the {1} series!"
"".format(stype, self._name))
return self._value_generator(start=start, end=end)
[docs] def get_partno(self, value):
if isinstance(value, self._typeclass):
value = str(value)
return self._values[value]
[docs] def get_symbol(self, value, device=None, footprint=None):
if isinstance(value, self._typeclass):
value = str(value)
return super(CustomValueSeries, self).get_symbol(
self._values[value], device, footprint
)
[docs] def get_type_value(self, value):
for type_value, lvalue in self._values.iteritems():
if lvalue == value:
return self._typeclass(type_value)
# TODO Improve isolation from gedaif
custom_series = {}
[docs]def get_series(series, stype, start=None, end=None,
device=None, footprint=None):
try:
return IEC60063ValueSeries(
series, stype, start=start, end=end,
device=device, footprint=footprint
)
except ValueError:
from tendril.gedaif.gsymlib import custom_series
cseries = copy.deepcopy(custom_series[series])
assert stype == cseries._stype
if start is not None:
cseries._start = start
if end is not None:
cseries._end = end
if device is not None:
assert device == cseries._device
if footprint is not None:
assert footprint == cseries._footprint
return cseries