# coding: utf-8 """ RC-lib.py library of functions for use with ImpedanceToken boards: """ import cmath def engineering_format(f,width=None,decimals=5): """Convert floating-point number to string using 'engineering' format, which is like the standard scientific format %.e, except that exponents are limited to multiples of three. """ scientific = '{0:e}'.format(f) e_at = scientific.find('e') if e_at<0: exponent=0 else: exponent = int(scientific[e_at+1:]) shift_right = exponent%3 new_exponent = exponent-shift_right adjusted_f = f/10**new_exponent after_decimals = str(decimals-shift_right) if new_exponent==0: format_string = '{0:.' + after_decimals + 'f}' combined= format_string.format(adjusted_f) else: format_string = '{0:.' + after_decimals + 'f}e{1:+03d}' combined= format_string.format(adjusted_f,new_exponent) if width and len(combined)=_infty: return "--" slop = 1.+ 0.5*10**(-digits) mp = ASCII_metric_prefixes if ASCII_only else metric_prefixes if f< metric_prefix_value[mp[0]]/slop: prefix = mp[0] else: for prefix in mp: if f<1000*metric_prefix_value[prefix]/slop: break mult = metric_prefix_value[prefix] if prefix==" ": prefix="" return ("{:"+str(width)+"."+str(digits)+"f}{}").format(f/mult,prefix) class seriesRLC: def __init__(self, R="--", C="--", L="--"): self.R = _infty if R=="--" else R self.C = 1./_infty if C=="--" else C self.L = _infty if L=="--" else L def newR(R): return seriesRLC(R=R, C=_infty, L=0) def newC(C): return seriesRLC(C=C, R=0, L=0) def newL(L): return seriesRLC(L=L, C=_infty, R=0) def Z(self,f): jomega = 2*cmath.pi*1j*f return self.R + 1./(jomega*self.C) + jomega*self.L def from_string(self,string): if string=="--": self.R = self.L = _infty self.C = 1./_infty elif string.endswith("ohm"): self.C = _infty self.L = 0 self.R = from_metric(string[:-3]) elif string.endswith("Ω"): self.C = _infty self.L = 0 self.R = from_metric(string[:-1]) elif string.endswith("F"): self.L = self.R = 0 self.C = from_metric(string[:-1]) elif string.endswith("H"): self.C = _infty self.R = 0 self.L = from_metric(string[:-1]) def is_infinite(self): return self.R>=_infty or self.L>=_infty or self.C<=1./_infty def is_zero(self): return self.R==0 and self.L==0 and self.C >= _infty def to_string(self,digits=10, ASCII_only=False): if self.is_infinite(): return "--" part="" plus="" if self.R>0: part=to_metric(self.R,digits=digits,ASCII_only=ASCII_only)+\ ("ohm" if ASCII_only else "Ω") plus="+" if self.L>0: part+= plus+to_metric(self.L,digits=digits,ASCII_only=ASCII_only)+"H" plus="+" if self.C<_infty: part+= plus+to_metric(self.C,digits=digits,ASCII_only=ASCII_only)+"F" return part def Zpar(Z1,Z2): return Z1*Z2/(Z1+Z2) def Z_AB(Zs): """ set Zs[0] to the impedance of the circuit between pins A and B for the impedances in Zs[1] through Zs[6]. Return the value also. """ assert len(Zs)==7 Zs[0] = Zpar( Zpar(Zs[2], Zs[5]+Zs[6]), Zs[1]+Zpar(Zs[3], Zs[4]) ) return Zs[0] def Z_BC(Zs): """ set Zs[0] to the impedance of the circuit between pins B and C for the impedances in Zs[1] through Zs[6]. Return the value also. """ assert len(Zs)==7 Zs[0] = Zpar( Zpar(Zs[3], Zs[4]), Zs[1]+ Zpar(Zs[2], Zs[5]+Zs[6]) ) return Zs[0] def Z_AC(Zs): """ set Zs[0] to the impedance of the circuit between pins A and C for the impedances in Zs[1] through Zs[6]. Return the value also. """ assert len(Zs)==7 Zs[0] = Zpar( Zs[1], Zpar(Zs[3], Zs[4])+ Zpar(Zs[2], Zs[5]+Zs[6]) ) return Zs[0] Z_pins = { "AB":Z_AB, "BC": Z_BC, "AC":Z_AC} class Ztoken: def __init__(self,label=None,pins="BC",components=None): self.label=label self.pins= pins self.components=components if components else [seriesRLC() for _ in range(7)] def from_string(line): """create an object representing an impedance token from a white-space separated string having label, pin-pair, and 6 component values """ new = Ztoken() fields = line.split() new.label = fields[0] new.pins = fields[1] for i in range(1,7): new.components[i].from_string(fields[i+1]) return new def to_string(self,ASCII_only=False): """create a string in the same format that from_string parses""" return self.label+ " " + self.pins + " " + \ " ".join( [ comp.to_string(digits=3,ASCII_only=ASCII_only) for comp in self.components[1:] ]) def Z(self,f): """Compute the impedance of the token at frequency f""" self.Zs = [x.Z(f) for x in self.components] return Z_pins[self.pins](self.Zs)