@@ -7,12 +7,29 @@ from core.freqency import auto_select_multple_ports
import matplotlib . pyplot as plt
import random as rnd
def cond_row_inf ( A , use_pinv = True ) :
""" 行条件数 κ∞(A) = ||A||∞ * ||A^ { -1}||∞;矩形阵用广义逆。 """
A = np . asarray ( A )
Ainv = np . linalg . pinv ( A ) if ( use_pinv or A . shape [ 0 ] != A . shape [ 1 ] ) else np . linalg . inv ( A )
return np . linalg . norm ( A , ord = np . inf ) * np . linalg . norm ( Ainv , ord = np . inf )
def cond_col_one ( A , use_pinv = True ) :
""" 列条件数 κ1(A) = ||A||1 * ||A^ { -1}||1; 矩形阵用广义逆。 """
A = np . asarray ( A )
Ainv = np . linalg . pinv ( A ) if ( use_pinv or A . shape [ 0 ] != A . shape [ 1 ] ) else np . linalg . inv ( A )
return np . linalg . norm ( A , ord = 1 ) * np . linalg . norm ( Ainv , ord = 1 )
class MultiPortOrthonormalBasis :
def __init__ ( self , H , freqs , poles , weights = None , passivity = True , dc_enforce = Fals e, fit_constant = True , fit_proportional = False ) :
self . least_squares_rms_error = None
def __init__ ( self , H , freqs , poles , weights = None , passivity = True , dc_enforce = Tru e, fit_constant = True , fit_proportional = False ) :
self . least_squares_condition = None
self . least_squares_row_condition = None
self . least_squares_col_condition = None
self . least_squares_rms_error = None
self . eigenval_condition = None
self . eigenval_row_condition = None
self . eigenval_col_condition = None
self . eigenval_rms_error = None
self . Cr = None
self . dc_tol = 1e-18
@@ -20,38 +37,60 @@ class MultiPortOrthonormalBasis:
self . fit_constant = fit_constant
self . fit_proportional = fit_proportional
# self.H = H
# self.freqs = freqs
self . freqs = freqs
self . H = H
self . ports = H . shape [ 1 ]
self . s = self . freqs * 2 j * np . pi
self . P = len ( poles )
self . poles = poles
self . Phi = self . generate_basis ( self . s , self . poles )
self . A = self . matrix_A ( self . poles )
self . B = self . vector_B ( self . poles )
self . Cw , self . w0 , self . e = self . fit_denominator ( self . H , weights = weights )
self . C , self . w0 , self . e = self . fit_denominator ( self . H , weights = weights )
self . D = self . w0
self . Cr = None
z = np . linalg . eigvals ( self . A - self . B @ self . Cw )
p_next = z
self . residuals = self . C / np . sqrt ( 2 * np . real ( - np . array ( self . poles ) ) )
z = np . linalg . eigvals ( self . A - self . B @ self . C )
if passivity :
self . next_poles = self . passivity_enforce ( p_next )
self . next_poles = self . passivity_enforce ( z )
else :
self . next_poles = p_next
# z = np.where(np.real(z) < 0, z, -np.conj(z)) # enforce LHP
# self.next_poles = np.sort_complex(z)
self . eigenval_condition = np . linalg . cond ( self . A - self . B @ self . Cw )
self . eigenval_rms_error = np . sqrt ( np . mean ( np . abs ( np . real ( z ) - np . real ( poles ) ) * * 2 + np . abs ( np . imag ( z ) - np . imag ( poles ) ) * * 2 ) )
self . next_poles = z
self. eigenval_condition , \
self . eigenval_row_ condition , \
self . eigenval_col_condition , \
self . eigenval_rms_error = self . eigen_metric ( )
self . Dt = self . eval_Dt_state_space ( )
self . delta = self . Dt / weights if weights is not None else self . Dt
self . Dt_Dt_1 = np . linalg . norm ( self . Dt ) / np . linalg . norm ( weights) if weights is not None else np . linalg . norm ( self . Dt )
pass
def eigen_metric ( self ) :
""" Return condition number and RMS error of eigenvalues of A-BC. """
z = np . linalg . eigvals ( self . A - self . B @ self . C )
cond = np . linalg . cond ( self . A - self . B @ self . C )
rms = np . sqrt ( np . mean ( np . abs ( np . real ( z ) - np . real ( self . poles ) ) * * 2 + np . abs ( np . imag ( z ) - np . imag ( self . poles ) ) * * 2 ) )
row_cond = cond_row_inf ( self . A - self . B @ self . C )
col_cond = cond_col_one ( self . A - self . B @ self . C )
return cond , row_cond , col_cond , rms
def least_squares_metric ( self , A , b ) :
""" Return condition number and RMS error of least-squares matrix A and rhs b. """
cond = np . linalg . cond ( A )
rms = np . sqrt ( np . mean ( ( A @ np . linalg . pinv ( A ) @ b - b ) * * 2 ) )
row_cond = cond_row_inf ( A )
col_cond = cond_col_one ( A )
return cond , row_cond , col_cond , rms
def passivity_enforce ( self , poles ) :
""" enforce poles ' real parts to be negative """
enforced_poles = [ ]
@@ -64,12 +103,12 @@ class MultiPortOrthonormalBasis:
def eval_Dt_state_space ( self ) :
""" Return D(s_k)=C(s_k I - A)^(-1)B + D for all k (complex 1D array). """
s = 1 j * 2 * np . pi * np . asarray ( self . freqs , float ) . ravel ( )
A = np . asarray ( self . A , np . complex128 ) ; n = A . shape [ 0 ]
B = np . asarray ( self . B , np . complex128 ) . reshape ( n , 1 )
C = np . asarray ( self . Cw , float ) . reshape ( 1 , n )
A = np . asarray ( self . A , float ) ; n = A . shape [ 0 ]
B = np . asarray ( self . B , float ) . reshape ( n , 1 )
C = np . asarray ( self . C , float ) . reshape ( 1 , n )
D = self . D
I = np . eye ( n , dtype = np . complex128 )
out = np . empty_like ( s , dtype = np . complex128 )
I = np . eye ( n , dtype = float )
out = np . empty_like ( s , dtype = float )
for k , sk in enumerate ( s ) :
DS = D + ( C @ np . linalg . inv ( sk * I - A ) @ B )
out [ k ] = DS [ 0 , 0 ]
@@ -78,7 +117,14 @@ class MultiPortOrthonormalBasis:
def generate_basis ( self , s , poles ) :
""" Real basis of (15)-(16); returns Φ(s) and a layout for packing C. """
def all_pass ( s , ap_list ) :
res = 1.0 + 0.0 j
for ap in ap_list :
res * = ( s - np . conj ( ap ) ) / ( s + ap )
return res
cols = [ ]
ap_list = [ ]
i = 0
while i < len ( poles ) :
ap = - poles [ i ]
@@ -86,42 +132,56 @@ class MultiPortOrthonormalBasis:
raise ValueError ( " poles must be in the LHP " )
if i + 1 < len ( poles ) and np . isclose ( poles [ i + 1 ] , np . conj ( - ap ) ) :
ap1 = - poles [ i + 1 ]
phi1 = 1 / ( s + ap ) + 1 / ( s + ap1 ) # eq (15)generate_basis
phi2 = 1 j * ( 1 / ( s + ap ) - 1 / ( s + ap1 ) ) # eq (16) (fixed sign )
phi1 = np . sqrt ( 2 * ap . real ) * all_pass ( s , ap_list ) * ( ( s - np . abs ( ap ) ) / ( ( s + ap) * ( s + ap1 ) ) )
phi2 = np . sqrt ( 2 * ap . real ) * all_pass ( s , ap_list ) * ( ( s + np . abs ( ap ) ) / ( ( s + ap ) * ( s + ap1 ) ) )
cols + = [ phi1 , phi2 ]
i + = 2
ap_list . append ( ap )
ap_list . append ( ap1 )
else :
cols . append ( 1 / ( s + ap ) )
basis = np . sqrt ( 2 * ap . real ) * all_pass ( s , ap_list ) * ( 1 / ( s + ap ) )
cols . append ( basis )
i + = 1
ap_list . append ( ap )
Phi = np . column_stack ( cols ) . astype ( np . complex128 )
return Phi
def matrix_A ( self , poles ) :
def A_block ( p ) :
if abs ( p . imag ) < 1e-14 :
return np . array ( [ [ p . real ] ] , float ) # A_p = [ p ]
return np . array ( [ [ p . real , p . imag ] , # A_p = [[Re p, Im p],
[ - p . imag , p . real ] ] , float ) # [-Im p, Re p]]
A = None ; i = 0
def A_col ( p : np . complex128 , index : int ):
ap = - p
if abs ( ap . imag ) < 1e-14 :
col = [ ]
for i in range ( index ) :
col . append ( 0.0 )
col . append ( - ap . real )
for i in range ( len ( poles ) - index - 1 ) :
col . append ( 2 * ( - ap ) . real )
return np . array ( [ col ] , float )
else :
col1 = [ ]
col2 = [ ]
for i in range ( index ) :
col1 . append ( 0.0 )
col2 . append ( 0.0 )
col1 . append ( - ap . real ) ; col2 . append ( - ap . real - np . abs ( ap ) )
col1 . append ( - ap . real + np . abs ( ap ) ) ; col2 . append ( - ap . real )
for i in range ( len ( poles ) - index - 2 ) :
col1 . append ( 2 * ( - ap ) . real )
col2 . append ( 2 * ( - ap ) . real )
return np . array ( [ col1 , col2 ] , float )
i = 0
cols = [ ]
while i < len ( poles ) :
p = poles [ i ]
Ab = A_block ( p )
cols . extend ( A_col ( p , i ) )
if i + 1 < len ( poles ) and np . isclose ( poles [ i + 1 ] , np . conj ( p ) ) : i + = 2
else : i + = 1
A = Ab if A is None else block_diag ( A , Ab )
A = np . column_stack ( cols ) . astype ( float )
return A
def vector_B ( self , poles ) :
def B_block ( p ) :
return np . array ( [ [ 1.0 ] ] , float ) if abs ( p . imag ) < 1e-14 else np . array ( [ [ 2.0 ] , [ 0.0 ] ] , float )
B = None ; i = 0
while i < len ( poles ) :
p = poles [ i ]
Bb = B_block ( p )
if i + 1 < len ( poles ) and np . isclose ( poles [ i + 1 ] , np . conj ( p ) ) : i + = 2
else : i + = 1
B = Bb if B is None else np . vstack ( [ B , Bb ] )
return B
return np . ones ( ( len ( poles ) , 1 ) , float )
def fit_denominator ( self , H , weights = None , d0 = 1.0 ) :
"""
@@ -161,7 +221,7 @@ class MultiPortOrthonormalBasis:
M_kp = None
for i in range ( self . ports ) :
for j in range ( self . ports ) :
M0 = np . zeros ( ( K , N * ports * * 2 ) , dtype = complex )
M0 = np . zeros ( ( K , N * self . ports * * 2 ) , dtype = complex )
M0 [ : , index * N : ( index + 1 ) * N ] = Phi
M0 = np . hstack ( [ M0 , - ( H [ : , i , j ] . reshape ( - 1 , 1 ) * Phi ) ] ) . reshape ( ( K , - 1 ) ) [ keep , : ] # (K, 2N), complex
index + = 1
@@ -169,7 +229,7 @@ class MultiPortOrthonormalBasis:
assert M_kp is not None
if weights is None :
weights_kp = np . diag ( np . ones ( len ( freqs [ keep ] ) * self . ports * * 2 , np . complex128 ) )
weights_kp = np . diag ( np . ones ( len ( self . freqs [ keep ] ) * self . ports * * 2 , np . complex128 ) )
else :
weights_kp0 = weights [ keep ]
weights0 = [ ]
@@ -225,10 +285,10 @@ class MultiPortOrthonormalBasis:
H_kp = None
for i in range ( self . ports ) :
for j in range ( self . ports ) :
H_kp 0 = weights_kp @ ( H[ : , i , j ] ) . reshape ( 1 , - 1 ) [keep , : ]
H_kp = H_kp 0 if H_kp is None else np . hstack ( [ H_kp , H_kp 0 ] )
H_0 = H [ : , i , j ] [ keep ]
H_kp = H_0 if H_kp is None else np . hstack ( [ H_kp , H_0 ] )
assert H_kp is not None
H_kp = H_kp . reshape ( - 1 , 1 )
H_kp = weights_kp @ H_kp. reshape ( - 1 , 1 )
b_re = np . real ( d0 * H_kp )
b_im = np . imag ( d0 * H_kp )
@@ -256,35 +316,40 @@ class MultiPortOrthonormalBasis:
# diagnostics
resid = Q2 @ R22 @ x - b
self. least_squares_rms_error = float ( np . sqrt ( np . mean ( resid * * 2 ) ) )
self. least_squares_condition = float ( np . linalg . cond ( R ) )
# self. least_squares_rms_error = float(np.sqrt(np.mean(resid**2)) )
# self. least_squares_condition = float(np.linalg.cond(R) )
self . least_squares_condition , \
self . least_squares_row_condition , \
self . least_squares_col_condition , \
self . least_squares_rms_error = self . least_squares_metric ( A , b )
# split cw and return
# cw = x[N:] # last (N+1) entries = [w0, w_1..w_N]
# w0 = float(cw[0])
# Cw = cw[1:].reshape(1, N) # row vector (1, N)
return self . extract_Cw_d_e ( x , N , d0 )
return self . extract_C_d_e ( x , N , d0 )
def extract_Cw _d_e ( self , C , N , d0 = 1.0 ) :
def extract_C_d_e ( self , C , N , d0 = 1.0 ) :
a = np . sqrt ( 2 * np . real ( - np . array ( self . poles ) ) )
if self . fit_proportional and self . fit_constant :
d = C [ 1 ]
e = C [ 0 ]
return C [ 2 : ] . reshape ( 1 , - 1 ) , d , e
C = a * C [ 2 : ]
return C . reshape ( 1 , - 1 ) , d , e
elif self . fit_proportional and not self . fit_constant :
d = 0.0
e = C [ 0 ]
return C [ 1 : ] . reshape ( 1 , - 1 ) , d , e
C = a * C [ 1 : ]
return C . reshape ( 1 , - 1 ) , d , e
elif not self . fit_proportional and self . fit_constant :
d = C [ 0 ]
e = 0.0
return C [ 1 : ] . reshape ( 1 , - 1 ) , d , e
C = a * C [ 1 : ]
return C . reshape ( 1 , - 1 ) , d , e
else :
C = a * C
return C . reshape ( 1 , - 1 ) , d0 , 0.0
def non_bias_Cr ( self , w0 ) :
A = np . asarray ( self . Phi )
den = np . diag ( ( w0 + self . Phi @ self . Cw . T ) . ravel ( ) )
den = np . diag ( ( w0 + self . Phi @ self . residuals . T ) . ravel ( ) )
Cr = [ ]
for i in range ( self . ports ) :
Cr . append ( [ ] )
@@ -294,19 +359,132 @@ class MultiPortOrthonormalBasis:
Cr [ i ] . append ( Cr_ij )
return Cr
def evaluate ( self , freqs , w0 ):
def get_model_responses ( self , freqs ) :
H = np . zeros ( ( len ( freqs ) , self . ports , self . ports ) , dtype = complex )
s = 1 j * 2 * np . pi * np . asarray ( freqs , float ) . ravel ( )
phi = self . generate_basis ( s , self . poles )
den = w0 + phi @ self . Cw . T
den = self . w0 + phi @ self . residuals . T
if self . Cr is None :
self . Cr = self . non_bias_Cr ( w0 = w0 )
self . Cr = self . non_bias_Cr ( w0 = self . w0 )
for i in range ( self . ports ) :
for j in range ( self . ports ) :
num = phi @ self . Cr [ i ] [ j ]
H [ : , i , j ] = ( num / den ) . reshape ( 1 , - 1 )
return H
class VFUtils ( ) :
def __init__ ( self , npoles_cplx , freqs , H , model = MultiPortOrthonormalBasis , iterations : int = 5 ) :
poles = generate_starting_poles ( npoles_cplx , beta_min = 1e4 , beta_max = freqs [ - 1 ] * 1.1 )
self . model = model ( H = H , freqs = freqs , poles = poles )
self . freqs = freqs
self . H = H
self . iterations = iterations
self . nports = H . shape [ 1 ]
self . least_squares_condition = [ ]
self . least_squares_row_condition = [ ]
self . least_squares_col_condition = [ ]
self . least_squares_rms_error = [ ]
self . eigenval_condition = [ ]
self . eigenval_row_condition = [ ]
self . eigenval_col_condition = [ ]
self . eigenval_rms_error = [ ]
self . model_responses_freqs = None
self . model_responses_H = None
def fit ( self ) :
for i in range ( self . iterations ) :
print ( f " Iteration { i + 1 } / { self . iterations } " )
poles = self . model . next_poles
weights = self . model . Dt
self . model = self . model . __class__ ( H = self . H , freqs = self . freqs , poles = poles , weights = weights )
print ( " A: " , self . model . A )
print ( " B: " , self . model . B )
print ( " C: " , self . model . C )
print ( " D: " , self . model . D )
print ( " next_pozles: " , self . model . next_poles )
print ( " Dt: " , self . model . Dt )
print ( " Dt/Dt_1: " , np . linalg . norm ( self . model . Dt_Dt_1 ) )
self . least_squares_condition . append ( self . model . least_squares_condition )
self . least_squares_row_condition . append ( self . model . least_squares_row_condition )
self . least_squares_col_condition . append ( self . model . least_squares_col_condition )
self . least_squares_rms_error . append ( self . model . least_squares_rms_error )
self . eigenval_condition . append ( self . model . eigenval_condition )
self . eigenval_row_condition . append ( self . model . eigenval_row_condition )
self . eigenval_col_condition . append ( self . model . eigenval_col_condition )
self . eigenval_rms_error . append ( self . model . eigenval_rms_error )
return self . model
def plot_metrics ( self ) :
plt . figure ( figsize = ( 16 , 12 ) )
plt . subplot ( 4 , 2 , 1 )
plt . plot ( self . least_squares_condition , label = ' Least Squares Condition ' )
plt . legend ( )
plt . subplot ( 4 , 2 , 2 )
plt . plot ( self . least_squares_row_condition , label = ' Least Squares Row Condition ' )
plt . legend ( )
plt . subplot ( 4 , 2 , 3 )
plt . plot ( self . least_squares_col_condition , label = ' Least Squares Col Condition ' )
plt . legend ( )
plt . subplot ( 4 , 2 , 4 )
plt . plot ( self . least_squares_rms_error , label = ' Least Squares RMS Error ' )
plt . legend ( )
plt . subplot ( 4 , 2 , 5 )
plt . plot ( self . eigenval_condition , label = ' Eigenvalue Condition ' )
plt . legend ( )
plt . subplot ( 4 , 2 , 6 )
plt . plot ( self . eigenval_row_condition , label = ' Eigenvalue Row Condition ' )
plt . legend ( )
plt . subplot ( 4 , 2 , 7 )
plt . plot ( self . eigenval_col_condition , label = ' Eigenvalue Col Condition ' )
plt . legend ( )
plt . subplot ( 4 , 2 , 8 )
plt . plot ( self . eigenval_rms_error , label = ' Eigenvalue RMS Error ' )
plt . legend ( )
plt . savefig ( " fit_metrics.png " )
def plot_model_responses ( self ) :
assert self . model_responses_freqs is not None and self . model_responses_H is not None , " Please run get_model_responses() first. "
for i in range ( self . nports ) :
for j in range ( self . nports ) :
plt . figure ( figsize = ( 12 , 6 ) )
plt . subplot ( 2 , 2 , 1 )
plt . plot ( self . freqs , np . abs ( self . H [ : , i , j ] ) , ' o ' , ms = 4 , color = ' red ' , label = ' Input Samples ' )
plt . plot ( self . model_responses_freqs , np . abs ( self . model_responses_H [ : , i , j ] ) , ' - ' , lw = 2 , color = ' k ' , label = ' Fit ' )
plt . title ( f " Response i= { i + 1 } , j= { j + 1 } " )
plt . ylabel ( " Magnitude " )
plt . legend ( loc = " best " )
plt . subplot ( 2 , 2 , 2 )
plt . plot ( self . freqs , np . angle ( self . H [ : , i , j ] , deg = True ) , ' o ' , ms = 4 , color = ' red ' , label = ' Input Samples ' )
plt . plot ( self . model_responses_freqs , np . angle ( self . model_responses_H [ : , i , j ] , deg = True ) , ' - ' , lw = 2 , color = ' k ' , label = ' Fit ' )
plt . title ( f " Response i= { i + 1 } , j= { j + 1 } " )
plt . ylabel ( " Phase (deg) " )
plt . legend ( loc = " best " )
plt . tight_layout ( )
plt . subplot ( 2 , 2 , 3 )
plt . plot ( self . freqs , np . real ( self . H [ : , i , j ] ) , ' o ' , ms = 4 , color = ' red ' , label = ' Input Samples ' )
plt . plot ( self . model_responses_freqs , np . real ( self . model_responses_H [ : , i , j ] ) , ' - ' , lw = 2 , color = ' k ' , label = ' Fit ' )
plt . title ( f " Response i= { i + 1 } , j= { j + 1 } " )
plt . ylabel ( " Real Part " )
plt . legend ( loc = " best " )
plt . subplot ( 2 , 2 , 4 )
plt . plot ( self . freqs , np . imag ( self . H [ : , i , j ] ) , ' o ' , ms = 4 , color = ' red ' , label = ' Input Samples ' )
plt . plot ( self . model_responses_freqs , np . imag ( self . model_responses_H [ : , i , j ] ) , ' - ' , lw = 2 , color = ' k ' , label = ' Fit ' )
plt . title ( f " Response i= { i + 1 } , j= { j + 1 } " )
plt . ylabel ( " Imag Part " )
plt . legend ( loc = " best " )
plt . tight_layout ( )
plt . savefig ( f " model_response_ { i + 1 } { j + 1 } .png " )
print ( f " Saved model_response_ { i + 1 } { j + 1 } .png " )
def get_model_responses ( self , freqs ) :
self . model_responses_freqs = freqs
self . model_responses_H = self . model . get_model_responses ( freqs )
return self . model_responses_H
def noise ( n : complex , coeff : float = 0.05 ) :
noise_r = rnd . gauss ( - coeff * n . real , coeff * n . real )
noise_i = rnd . gauss ( - coeff * n . imag , coeff * n . imag )
@@ -318,7 +496,7 @@ if __name__ == "__main__":
network = rf . Network ( f " /tmp/paramer/simulation/ { id } / { id } .s2p " )
# network = rf.data.ring_slot
ports = network . nports
K = 5
K = 100
full_freqences = network . f [ start_point : ]
noised_sampled_points = network . y [ start_point : , : , : ] . reshape ( - 1 , ports , ports )
@@ -329,111 +507,119 @@ if __name__ == "__main__":
H , freqs = auto_select_multple_ports ( noised_sampled_points , full_freqences , max_points = 20 )
poles = generate_starting_poles ( 2 , beta_min = 1e4 , beta_max = freqs [ - 1 ] * 1.1 )
vf = VFUtils ( npoles_cplx = 2 , freqs = freqs , H = H , model = MultiPortOrthonormalBasis , iterations = K )
model = vf . fit ( )
vf . plot_metrics ( )
model_responses = vf . get_model_responses ( full_freqences )
vf . plot_model_responses ( )
# # Original plot functions
Dt_1 = np . ones ( ( len ( freqs ) , 1 ) , np . complex128 )
# Levi step (no weighting):
basis = MultiPortOrthonormalBasis( H , freqs , poles = poles )
Dt = basis . Dt
poles = basis . next_poles
# Dt_1 = np.ones((len(freqs),1),np. complex128)
# # Levi step (no weighting):
# basis = MultiPortOrthonormalBasis(H,freqs,poles= poles)
# Dt = basis. Dt
# poles = basis. next_poles
print( " Levi step (no weighting):" )
print( " A: " , basis . A )
print( " B: " , basis . B )
print( " C: " , basis . Cw )
print( " D: " , basis . D )
print( " next_pozles:" , basis . next_poles )
print( " Dt: " , Dt , " norm: " , np . linalg . norm ( Dt ) )
# print(" Levi step (no weighting):" )
# print("A:",basis.A )
# print("B:",basis.B )
# print("C:",basis.C )
# print("D:",basis.D )
# print(" next_pozles:",basis. next_poles)
# print("Dt:",Dt, "norm:",np.linalg.norm(Dt) )
# SK weighting (optional, after first pass):
least_squares_condition = [ ]
least_squares_rms_error = [ ]
eigenval_condition = [ ]
eigenval_rms_error = [ ]
for i in range ( K ) :
basis = MultiPortOrthonormalBasis( H , freqs , poles = poles , weights = Dt )
Dt_1 = Dt
Dt = basis . Dt
poles = basis . next_poles
print( f " SK Iteration { i + 1 } / { K } " )
print( " A: " , basis . A )
print( " B: " , basis . B )
print( " C: " , basis . Cw )
print( " D: " , basis . D )
print( " z: " , basis . next_poles )
print( " Dt: " , Dt )
print( " Dt/Dt-1 " , np . linalg . norm ( Dt ) / np . linalg . norm ( Dt_1 ) )
least_squares_condition. append( basis . least_squares_condition )
least_squares_rms_error. append( basis . least_squares_rms_error )
eigenval_condition. append( basis . eigenval_condition )
eigenval_rms_error. append( basis . eigenval_rms_error )
# # SK weighting (optional, after first pass):
# least_squares_condition = [ ]
# least_squares_rms_error = [ ]
# eigenval_condition = [ ]
# eigenval_rms_error = [ ]
# for i in range(K) :
# basis = MultiPortOrthonormalBasis(H,freqs,poles=poles,weights=Dt )
# Dt_1 = Dt
# Dt = basis. Dt
# poles = basis. next_poles
# print(f" SK Iteration {i+1}/{K}" )
# print("A:",basis.A )
# print("B:",basis.B )
# print("C:",basis.C )
# print("D:",basis.D )
# print("z:",basis. next_poles)
# print("Dt:",Dt )
# print("Dt/Dt-1",np.linalg.norm(Dt) / np.linalg.norm(Dt_1) )
# least_squares_condition. append(basis. least_squares_condition)
# least_squares_rms_error. append(basis. least_squares_rms_error)
# eigenval_condition. append(basis. eigenval_condition)
# eigenval_rms_error. append(basis. eigenval_rms_error)
# H11_evaluated = basis.evaluate_pole_residue(network.f[1:],poles,basis.C[0])
H_evaluated = basis . evaluate ( full_freqences , w0 = basis . w0 )
fitted_points = H_evaluated
sliced_freqences = freqs
# # H11_evaluated = basis.evaluate_pole_residue(network.f[1:],poles,basis.C[0])
# H_evaluated = basis.get_model_responses(full_freqences )
# fitted_points = H_evaluated
# sliced_freqences = freqs
input_points = H
for i in range ( ports ) :
for j in range ( ports ) :
fig, axes = plt . subplots ( 3 , 2 , figsize = ( 15 , 16 ) , sharex= False )
ax00 = axes [ 0 ] [ 0 ]
ax00. plot ( full_freqences , np . abs ( sampled_points [ : , i , j ] ) , ' o ' , ms = 4 , color = ' red ' , label = ' Samples' )
ax00. plot ( full_freqences , np . abs ( fitted_points [ : , i , j ] ) , ' - ' , lw = 2 , color = ' k ' , label = ' Fit ' )
ax00. plot ( sliced_freqences, np . abs ( input_points [ : , i , j ] ) , ' x ' , ms = 4 , color = ' blue ' , label = ' Input Samples' )
ax00. set_title( f " Response i= { i + 1 } , j= { j + 1 } " )
ax00. set_ylabel( " Magnitude" )
ax00. legend( loc = " best " )
# input_points = H
# for i in range(ports) :
# for j in range(ports) :
# fig, axes = plt.subplots(3, 2, figsize=(15, 16), sharex= False)
# ax00 = axes[0][0]
# ax00.plot(full_freqences, np.abs(sampled_points[:,i,j]), 'o', ms=4, color='red', label=' Samples' )
# ax00.plot(full_freqences, np.abs(fitted_points[:,i,j]), '-', lw=2, color='k', label='Fit' )
# ax00.plot( sliced_freqences, np.abs(input_points[:,i,j]), 'x', ms=4, color='blue', label=' Input Samples' )
# ax00. set_title(f"Response i={i+1}, j={j+1}" )
# ax00. set_ylabel(" Magnitude" )
# ax00. legend(loc="best" )
ax01 = axes [ 0 ] [ 1 ]
ax01. set_title( f " Response i= { i + 1 } , j= { j + 1 } " )
ax01. set_ylabel( " Phase (deg)" )
ax01. plot ( full_freqences , np . angle ( sampled_points [ : , i , j ] , deg = True ) , ' o ' , ms = 4 , color = ' red ' , label = ' Samples' )
ax01. plot ( full_freqences , np . angle ( fitted_points [ : , i , j ] , deg = True ) , ' - ' , lw = 2 , color = ' k ' , label = ' Fit ' )
ax01. plot ( sliced_freqences, np . angle ( input_points [ : , i , j ] , deg = True ) , ' x ' , ms = 4 , color = ' blue ' , label = ' Input Samples' )
ax01. legend( loc = " best " )
# ax01 = axes[0][1 ]
# ax01. set_title(f"Response i={i+1}, j={j+1}" )
# ax01. set_ylabel(" Phase (deg)" )
# ax01.plot(full_freqences, np.angle(sampled_points[:,i,j],deg=True), 'o', ms=4, color='red', label=' Samples' )
# ax01.plot(full_freqences, np.angle(fitted_points[:,i,j],deg=True), '-', lw=2, color='k', label='Fit' )
# ax01.plot( sliced_freqences, np.angle(input_points[:,i,j],deg=True), 'x', ms=4, color='blue', label=' Input Samples' )
# ax01. legend(loc="best" )
# ax00 = axes[0][0]
# ax00.plot(full_freqences, np.real(sampled_points[:,i,j]), 'o', ms=4, color='red', label='Samples')
# ax00.plot(full_freqences, np.real(fitted_points[:,i,j]), '-', lw=2, color='k', label='Fit')
# ax00.plot(sliced_freqences, np.real(input_points[:,i,j]), 'x', ms=4, color='blue', label='Input Samples')
# ax00.set_title(f"Response i={i+1}, j={j+1}")
# ax00.set_ylabel("Real Part")
# ax00.legend(loc="best")
# # ax00 = axes[0][0]
# # ax00.plot(full_freqences, np.real(sampled_points[:,i,j]), 'o', ms=4, color='red', label='Samples')
# # ax00.plot(full_freqences, np.real(fitted_points[:,i,j]), '-', lw=2, color='k', label='Fit')
# # ax00.plot(sliced_freqences, np.real(input_points[:,i,j]), 'x', ms=4, color='blue', label='Input Samples')
# # ax00.set_title(f"Response i={i+1}, j={j+1}")
# # ax00.set_ylabel("Real Part")
# # ax00.legend(loc="best")
# ax01 = axes[0][1]
# ax01.set_title(f"Response i={i+1}, j={j+1}")
# ax01.set_ylabel("Imag Part")
# ax01.plot(full_freqences, np.imag(sampled_points[:,i,j]), 'o', ms=4, color='red', label='Samples')
# ax01.plot(full_freqences, np.imag(fitted_points[:,i,j]), '-', lw=2, color='k', label='Fit')
# ax01.plot(sliced_freqences, np.imag(input_points[:,i,j]), 'x', ms=4, color='blue', label='Input Samples')
# ax01.legend(loc="best")
# # ax01 = axes[0][1]
# # ax01.set_title(f"Response i={i+1}, j={j+1}")
# # ax01.set_ylabel("Imag Part")
# # ax01.plot(full_freqences, np.imag(sampled_points[:,i,j]), 'o', ms=4, color='red', label='Samples')
# # ax01.plot(full_freqences, np.imag(fitted_points[:,i,j]), '-', lw=2, color='k', label='Fit')
# # ax01.plot(sliced_freqences, np.imag(input_points[:,i,j]), 'x', ms=4, color='blue', label='Input Samples')
# # ax01.legend(loc="best")
ax10 = axes [ 1 ] [ 0 ]
ax10. plot ( least_squares_condition, label = ' Least Squares Condition' )
ax10. set_title( " least_squares_condition" )
ax10. set_ylabel( " Magnitude" )
ax10. legend( loc = " best " )
# ax10 = axes[1][0 ]
# ax10.plot( least_squares_condition, label=' Least Squares Condition' )
# ax10. set_title(" least_squares_condition" )
# ax10. set_ylabel(" Magnitude" )
# ax10. legend(loc="best" )
ax11 = axes [ 1 ] [ 1 ]
ax11. plot ( least_squares_rms_error, label = ' Least Squares RMS Error' )
ax11. set_title( " least_squares_rms_error" )
ax11. set_ylabel( " Magnitude" )
ax11. legend( loc = " best " )
# ax11 = axes[1][1 ]
# ax11.plot( least_squares_rms_error, label=' Least Squares RMS Error' )
# ax11. set_title(" least_squares_rms_error" )
# ax11. set_ylabel(" Magnitude" )
# ax11. legend(loc="best" )
ax20 = axes [ 2 ] [ 0 ]
ax20. plot ( eigenval_condition, label = ' Eigenvalue Condition' )
ax20. set_title( " eigenval_condition" )
ax20. set_ylabel( " Magnitude" )
ax20. legend( loc = " best " )
# ax20 = axes[2][0 ]
# ax20.plot( eigenval_condition, label=' Eigenvalue Condition' )
# ax20. set_title(" eigenval_condition" )
# ax20. set_ylabel(" Magnitude" )
# ax20. legend(loc="best" )
ax21 = axes [ 2 ] [ 1 ]
ax21. plot ( eigenval_rms_error, label = ' Eigenvalue RMS Error' )
ax21. set_title( " eigenval_rms_error" )
ax21. set_ylabel( " Magnitude" )
ax21. legend( loc = " best " )
fig. tight_layout( )
plt. savefig( f " MultiplePortQR_port_{ i + 1 } { j + 1 } .png " )
print( f " Saved MultiplePortQR_port_{ i + 1 } { j + 1 } .png " )
# ax21 = axes[2][1 ]
# ax21.plot( eigenval_rms_error, label=' Eigenvalue RMS Error' )
# ax21. set_title(" eigenval_rms_error" )
# ax21. set_ylabel(" Magnitude" )
# ax21. legend(loc="best" )
# fig. tight_layout( )
# plt. savefig(f" MultiplePortQR_port_{i+1}{j+1}.png" )
# print(f" Saved MultiplePortQR_port_{i+1}{j+1}.png" )