33 from math
import log10, pi, sin, cos, sqrt, exp, sinh, cosh
41 from libcommonfunc
import pkgNameVersion, complexStr, myPrint, printHeader, synthError, askQuestion, readVerbose, warningMsg
43 printHeader(
'Successful import:' , __doc__, importModule =
True)
64 for key, value
in variablesDict.items():
65 globals()[key] = value
93 def __init__(self, P, FT, symmetrizeZeros = None):
131 if N < 2:
raise synthError,
"Filter order must be equal or greater than 2"
138 if P.filterTransferFunc.title()
in (
u'Butterworth',
u'Chebyshev',
u'Quasieliptic' ):
144 if type(P.transImagZeros) != types.ListType: P.transImagZeros = [ P.transImagZeros ]
145 if type(P.transComplexZeros) != types.ListType: P.transComplexZeros = [ P.transComplexZeros ]
146 if type(P.LPcomplexZeros) != types.ListType: P.LPcomplexZeros = [ P.LPcomplexZeros ]
147 if type(P.LPrealZeros) != types.ListType: P.LPrealZeros = [ P.LPrealZeros ]
150 if np.any( np.abs(FT.normFreq(np.array( P.transImagZeros ))) < 1):
151 raise synthError,
'There are transmission zeros in the passband.'
159 if P.genChebyLP
or len(P.transComplexZeros) > 0: self.
flagComplexTZ =
True
164 if (N == 4)
and (P.synthTech.title() ==
u'Prescribed Insertion Loss')
and (P.nuqTech ==
u'kS21+kS11')
and (P.nuqK11c1 == P.nuqK21c1
and P.nuqK11c1 == P.nuqK22c1):
166 elif (N == 6)
and (P.synthTech.title() ==
u'Prescribed Insertion Loss')
and (P.nuqTech ==
u'kS21+kS11')
and (P.nuqK11c1 == P.nuqK21c1
and P.nuqK11c1 == P.nuqK22c1):
168 elif (N == 6)
and (P.synthTech.title() ==
u'Prescribed Insertion Loss')
and (P.nuqTech ==
u'kS21+pole/zero'):
173 if symmetrizeZeros
is None:
175 """<center><b>Asymmetric transmission zeros:</b></center><p>
176 In order to compute a folded coupling matrix with uniform Q of resonators, the software needs that transmission zeros are symmetric in the normalized frequency axis.<p>
177 Transmission zeros are symmetric with respect to center frequency in Hz, but not in normalized frequency.<p>
178 <center><font color="red"><b>Do you want to move transmission zeros?</b></font></center>""",
179 QMessageBox.Yes | QMessageBox.No )
181 symmetrizeZeros = (reply == QMessageBox.Yes)
184 P.transImagZeros = self.
symmetrizeTZ(P.transImagZeros, FT)
191 if P.filterTransferFunc.title() ==
u'Butterworth': Ps, Es, Fs, eps, epsR, rootsErr =
butterworthFilter(P, FT, symmetrizeZeros)
192 elif P.filterTransferFunc.title() ==
u'Chebyshev': Ps, Es, Fs, eps, epsR, rootsErr =
chebyshevFilter(P, FT, symmetrizeZeros)
193 elif P.filterTransferFunc.title() ==
u'Quasieliptic': Ps, Es, Fs, eps, epsR, rootsErr =
quasiElipticFilter(P, FT, symmetrizeZeros)
195 elif P.filterTransferFunc.title() ==
u'Generalized Chebyshev':
196 if importedExtraFilters
is False:
197 if existingExtraFilters
is False:
198 raise synthError,
"""Generalized Chebyshev filter is in the Library of Extra Filters,<br>
199 which is not installed in this system.
200 <p>Contact lossyfilters@tsc.upc.edu to get the Library of Extra Filters.
203 raise synthError,
"""Importing the 'Library of Extra Filters' failed. <br>
204 You have a libextrafilters.pyc file, but it cannot be imported. <br>
205 Possibly libextrafilters.pyc was compiled using a different Python version than yours.
206 <p>Your installed Python version is: %s on %s
207 <p>Read the README.html documentation or contact lossyfilters@tsc.upc.edu for assistence.
208 """ % (platform.python_version(), platform.system())
209 elif importedCheckLicense
is False:
210 if existingCheckLicense
is False:
211 raise synthError,
"""There is no check_license.pyc file in your system.
212 It should have been installed together with libextrafilters.pyc file,
213 which actually is in your system.
214 Please follow the 'Extra Filters Library' installation instructions.
217 raise synthError,
"""Importing the 'License Check Library' failed. <br>
218 You have a libchecklicense.pyc file, but it cannot be imported. <br>
219 Possibly libchecklicense.pyc was compiled using a different Python version than yours.
220 <p>Your installed Python version is: %s on %s
221 <p>Read the README.html documentation or contact lossyfilters@tsc.upc.edu for assistence.
222 """ % (platform.python_version(), platform.system())
224 Ps, Es, Fs, eps, epsR, rootsErr = generalizedChebyshevFilter(P, FT, symmetrizeZeros)
226 else:
raise synthError,
u"Filter topology type '%s' not available." % P.filterTransferFunc
235 self.
Ps, self.
Es, self.
Fs, self.
F22s, self.
eps, self.
epsR = Ps, Es, Fs, F22s, eps, epsR
248 TZnorm = np.array(FT.normFreq(TZ))
249 TZpos = np.sort(TZnorm[np.nonzero(TZnorm>tol)])
250 TZneg = np.sort(-TZnorm[np.nonzero(TZnorm<-tol)])
251 TZnull = len(np.nonzero(np.abs(TZnorm)<=tol)[0])
252 TZsymNorm = (TZpos+TZneg)/2.
253 TZsymNorm = np.concatenate((np.zeros(TZnull), TZsymNorm, -TZsymNorm))
254 TZsym = [ f
for f
in FT.unormFreq(TZsymNorm) ]
265 if len(TZ) == 0:
return True
268 TZpos = np.sort(TZ[np.nonzero(TZ - FT.f0 > tol)])
269 TZneg = np.sort(TZ[np.nonzero(TZ - FT.f0 < -tol)])
270 if len(TZpos)==len(TZneg):
271 if np.max(np.abs((TZpos+TZneg)/(2*FT.f0)-1)) < 1e-3:
283 if len(TZ) == 0:
return True
286 TZpos =np.sort(TZ[np.nonzero(TZ > tol)])
287 TZneg = np.sort(TZ[np.nonzero(TZ < -tol)])
288 if len(TZpos)==len(TZneg)
and np.max(np.abs(TZpos+TZneg)) < 1e-3:
304 for k
in range(pol.order+1):
309 stcoef +=
complexStr(pol.coef[k], prec) +
', '
322 fileName = P.outDirName +
'.pol'
323 fout = open(fileName,
'w')
325 fout.write(
'# Characteristic polynomials file.\n')
326 fout.write(
'# Polynomial coefficients are ordered from highest to lowest degree.\n\n')
327 fout.write(
'F(s) = %s\n' % self.
polyStr(self.
Fs, prec))
328 fout.write(
'P(s) = %s\n' % self.
polyStr(self.
Ps, prec))
329 fout.write(
'E(s) = %s\n' % self.
polyStr(self.
Es, prec))
331 fout.write(
'\n# Constant in the denominator of S12 and S21\n')
334 fout.write(
'\n# Constant in the denominator of S11\n')
337 myPrint(
"Characteristic Polynomials saved to file: %s" % fileName )
361 Ps = np.poly1d(Pw.coef * pow(-1j, np.arange(N+1.)[::-1]))
380 Tn = [ np.poly1d([1]), np.poly1d([1, 0]) ]
381 for k
in range(2, N+1): Tn.append( 2*Tn[1]*Tn[k-1] - Tn[k-2] )
403 Pc = np.poly1d(np.conj(P)*pow(-1, np.arange(N+1.)[::-1]))
431 DERnum = SQNUM.deriv() * SQDEN - SQNUM * SQDEN.deriv()
433 POL=abs(NUM(1j*np.imag(jOm))/DEN(1j*np.imag(jOm)))
455 errSym = min( np.real ( roots_SQF + roots_SQF[k] ))
456 maxErr = max( maxErr, errSym )
518 roots_SQF = SQF.roots
524 roots_PRP = roots_SQF[np.nonzero( np.real(roots_SQF) > rootsErr) ]
525 roots_NRP = roots_SQF[np.nonzero( np.real(roots_SQF) < -rootsErr) ]
526 roots_ZRP = roots_SQF[np.nonzero( np.abs(np.real(roots_SQF)) <= rootsErr) ]
531 roots_ZPRP = 1j*np.imag(roots_ZPRP)
532 roots_ZNRP = 1j*np.imag(roots_ZNRP)
535 roots_PRP =
vecSort(np.concatenate( ( roots_PRP, roots_ZPRP ), 1))
536 roots_NRP =
vecSort(np.concatenate( ( roots_NRP, roots_ZNRP ), 1))
539 myPrint(
'\nFactorization of F(s)F(-s)):')
540 myPrint(
'Zeros in left-s plane =' + str( [
complexStr(r, 3)
for r
in roots_NRP ] ) )
541 myPrint(
'Zeros in right-s plane =' + str( [
complexStr(r, 3)
for r
in roots_PRP ] ) )
544 if mainWindow
is not None and type(method).__name__ ==
'list' and type(method[0]).__name__ ==
'bool':
553 if type(method).__name__ ==
'int':
555 roots_F =
vecSort(roots_NRP.copy())
556 roots_F22 =
vecSort(roots_PRP.copy())
558 roots_F =
vecSort(roots_PRP.copy())
559 roots_F22 =
vecSort(roots_NRP.copy())
561 roots_F =
vecSort(np.concatenate( (roots_PRP[::2], roots_NRP[1::2]), 1))
562 roots_F22 =
vecSort(np.concatenate( (roots_PRP[1::2], roots_NRP[::2]), 1))
564 roots_F =
vecSort(np.concatenate( (roots_PRP[1::2], roots_NRP[::2]), 1))
565 roots_F22 =
vecSort(np.concatenate( (roots_PRP[::2], roots_NRP[1::2]), 1))
567 raise synthError,
u"Factorization of F(s)F(-s): Factorization method is not an integer in the range [1,4]."
569 elif type(method).__name__ ==
'list' and type(method[0]).__name__ ==
'bool':
570 if len(method) != len(roots_PRP):
raise synthError,
u"Length of Factorization method boolean list is different than filter order."
571 aMethod = np.asarray(method)
572 roots_F =
vecSort(np.concatenate( (roots_PRP[ ~aMethod], roots_NRP[ aMethod]), 1))
573 roots_F22 =
vecSort(np.concatenate( (roots_PRP[ aMethod], roots_NRP[~aMethod]), 1))
575 else:
raise synthError,
u"Factorization of F(s)F(-s): Factorization method is not an integer in the range [1,4] or a list of Booleans."
578 myPrint(
'Factorization method = ' + str(method))
584 Fs = np.poly1d(roots_F, r=1)
585 F22s = np.poly1d(roots_F22, r=1)
589 F22s =F22s / F22s.coef[0]
592 return Fs, F22s , rootsErr
603 ind = np.argsort(np.imag(vec))[: : -1]
656 if N>=10:
warningMsg(
u'<b>WARNING:</b> <p>Butterworth filter coupling matrices are not accurate for order 10 or more.')
659 k = np.arange(1, 2*N+1)
661 rootsEs = np.exp(1j * pi * (2*k-1) / (2*N) )
663 rootsEs = np.exp(1j * pi * k / N)
664 rootsEs = rootsEs[np.where(np.real(rootsEs) < 0)]
667 Es = np.poly1d( rootsEs, r=1, variable=
's' )
671 Ps = np.poly1d(1., variable=
's' )
673 if (N - Ps.o)% 2 == 0: Ps *= 1j
676 Fs = np.poly1d(np.concatenate(( np.array([1]), np.zeros(N) )), variable=
's' )
682 return Ps, Es, Fs, eps, epsR , rootsErr
739 eps = 1.0 / sqrt(10**(P.chebyLr/10.0) - 1)
742 k = np.arange(1, N+1)
743 theta = (pi/2.0) * (2*k - 1.0)/N
744 mu = (1.0/N) * np.arcsinh(1/eps)
745 rootsEs = -sinh(mu)*np.sin(theta) + 1j*cosh(mu)*np.cos(theta)
746 Es = np.poly1d(rootsEs, r=1, variable=
's')
750 Ps = np.poly1d(1, variable=
's' )
752 if (N - Ps.o)% 2 == 0: Ps *= 1j
763 epsR = Fs.coef[0] / Es.coef[0]
768 return Ps, Es, Fs, eps, epsR , rootsErr
837 if N < 3:
raise synthError,
u'Quasieliptic filter is not possible for order N=2.'
840 a = FT.normFreq(np.array(P.qeZero))
843 if abs(a) < 1:
raise synthError,
u'Quasieliptic transmission zero in the bandpass.'
847 eps = 1.0 / sqrt(10**(P.qeLr/10.0) - 1)
850 Ps = np.poly1d([ 1, 0, a**2], variable=
's')
852 if (N - Ps.o)% 2 == 0: Ps *= 1j
855 alpha = ((a+sqrt(a**2-1))**2)/2
857 gamma = ((a-sqrt(a**2-1))**2)/2
860 w = np.poly1d([1, 0])
862 Knw =w * Tn[N-1] * alpha + Tn[N-2] * beta + w * Tn[N-3] * gamma
865 SQEw = np.poly1d([ 1, 0, -2*a**2, 0, a**4]) + eps**2 * (Knw*Knw)
867 rootsSQEs = SQEs.roots
868 Es = np.poly1d( rootsSQEs[np.real(rootsSQEs) < 0] , r=1, variable=
's')
881 epsR = Fs.coef[0] / Es.coef[0]
884 return Ps, Es, Fs, eps, epsR, rootsErr
895 if os.path.exists(
'libextrafilters.pyc'): existingExtraFilters =
True
896 else: existingExtraFilters =
False
897 from libextrafilters
import importedCheckLicense, existingCheckLicense, generalizedChebyshevFilter
901 importedExtraFilters =
False
903 importedExtraFilters =
True
908 from mwfiltersgui
import PredisZeorsDlg