Python 处理S-parameters (s4p file) 并提取SDD21差分插损的源码

1. 项目来源

供应商提供了两个产品的S参数文件(s4p 格式),需要对这两个S参数文件进行处理,提取出SDD21插损值,并与IEEE标准进行比较。

2. 实现方案

Python 对该 s4p 格式的S-parameters 文件进行处理,通过单端转差分的公式,获取SDD21参数
在这里插入图片描述

2.1 s4p 文件格式

这个s4p 文件表明,这是4端口的16个S参数。通过标准Touchstone 格式可知,该文件里 #HZ S RI R 50, 表示第一列是单位为Hz的频率,后面的参数是S参数,用实部,虚部表示,参考阻抗是50欧姆
在这里插入图片描述

2.2 单端转差分公式

从touchstone file format 可以得知,这个s4p 里是4端口网络的单端S参数。
在这里插入图片描述

因为Port 1 与 Port 3 组成一对差分线,Port 2 与 Port 4 组成一对差分线,则有
SDD11=0.5*(S11-S13-S31+S33)
SDD12=0.5*(S12-S14-S32+S34)
SDD21=0.5*(S21-S23-S41+S43)
SDD22=0.5*(S22-S24-S42+S44)
在这里SDD11是输入端回损,SDD12是差分线的反向隔离系数, SDD21是正向增益/插损,这里称为差分线的插入损耗特性,SDD22是输出端回损

2.3实数的加减法与实数到幅度(dB)的转换公式

(1)由于S 参数是以 实部+虚部方式表示,因此S参数的加减法遵循实数域的加法规则,即 实部与实部相加,虚部与虚部相加
(2)将实部与虚部转换为幅度(dB)与相位,则是通过:
magnitude[dB] = 20 * log(sqr(ReRe+ ImIm))
phase = arctan(Im / Re)

3. Python源码

在这里插入代码片

import numpy as np
import matplotlib.pyplot as plt
import math

Data_SFP = open("SFP+_HCB_wo_conn_18p5in_M_SMA_RevA.s4p").readlines()
Data_SFP28 = open("SFP28_HCB_wo_conn_12in_M_SMA_RevA.s4p").readlines()
        
with open('SFP_SDD21_data.txt',mode='w') as SFP_SDD21_data:

    for i in range(9,len(Data_SFP),5):
        Freq = float(Data_SFP[i].split()[0])/1000000
        SFP_SDD21_data.write(str(Freq))
        SFP_SDD21_data.write(" ")
        S21_R = Data_SFP[i+1].split()[0]
        S21_I = Data_SFP[i+1].split()[1]  
        S23_R = Data_SFP[i+1].split()[4]
        S23_I = Data_SFP[i+1].split()[5]
        S41_R = Data_SFP[i+3].split()[0]
        S41_I = Data_SFP[i+3].split()[1]
        S43_R = Data_SFP[i+3].split()[4]
        S43_I = Data_SFP[i+3].split()[5]

        SDD21_R=0.5*(float(S21_R)-float(S23_R)-float(S41_R)+float(S43_R))
        SDD21_I=0.5*(float(S21_I)-float(S23_I)-float(S41_I)+float(S43_I))
        SDD21=20*math.log10(math.sqrt(float(SDD21_R)*float(SDD21_R) + float(SDD21_I)*float(SDD21_I)))
        # print(Freq,S12_R, type(S12_R),S12_I, type(S12_I))
        SFP_SDD21_data.write(str(SDD21))
        SFP_SDD21_data.write("\n")        
        
with open('SFP28_SDD21_data.txt',mode='w') as SFP28_SDD21_data:

    for i in range(9,len(Data_SFP28),5):
        Freq = float(Data_SFP28[i].split()[0])/1000000
        SFP28_SDD21_data.write(str(Freq))
        SFP28_SDD21_data.write(" ")
        SDD21_R=0.5*(float(Data_SFP28[i+1].split()[0])-float(Data_SFP28[i+1].split()[4])-float(Data_SFP28[i+3].split()[0])+float(Data_SFP28[i+3].split()[4]))
        SDD21_I=0.5*(float(Data_SFP28[i+1].split()[1])-float(Data_SFP28[i+1].split()[5])-float(Data_SFP28[i+3].split()[1])+float(Data_SFP28[i+3].split()[5]))
        SDD21=20*math.log10(math.sqrt(float(SDD21_R)*float(SDD21_R) + float(SDD21_I)*float(SDD21_I)))
        SFP28_SDD21_data.write(str(SDD21))
        SFP28_SDD21_data.write("\n")    
        

SFP_SDD21_plot = np.loadtxt("SFP_SDD21_data.txt")
SFP28_SDD21_plot = np.loadtxt("SFP28_SDD21_data.txt")
SDD21_x=SFP_SDD21_plot[0:2500,0]  
SFP_SDD21_y=SFP_SDD21_plot[0:2500,1]
SFP28_SDD21_y=SFP28_SDD21_plot[:,1]

IEEE_86A_y=[]
IEEE_86A_ymax=[]
IEEE_86A_ymin=[]
for i in range(0,1500):
    IEEE_86A_y.append(float(-0.01-0.25*math.sqrt(float(SDD21_x[i])/1000)-0.0916*float(SDD21_x[i])/1000))
    if i<1110:
        IEEE_86A_ymax.append(float(-0.01-0.25*math.sqrt(float(SDD21_x[i])/1000)-0.0916*float(SDD21_x[i])/1000)*1.15)
        IEEE_86A_ymin.append(float(-0.01-0.25*math.sqrt(float(SDD21_x[i])/1000)-0.0916*float(SDD21_x[i])/1000)*0.85)  
    else:
        IEEE_86A_ymax.append(float(-0.01-0.25*math.sqrt(float(SDD21_x[i])/1000)-0.0916*float(SDD21_x[i])/1000)*1.25)
        IEEE_86A_ymin.append(float(-0.01-0.25*math.sqrt(float(SDD21_x[i])/1000)-0.0916*float(SDD21_x[i])/1000)*0.75)      
    
plt.plot(SDD21_x,SFP_SDD21_y,linewidth = 1,label='SFP+ HCB')
plt.plot(SDD21_x,SFP28_SDD21_y,linewidth = 1,label='SFP28 HCB')
plt.plot(SDD21_x[0:1500],IEEE_86A_y,linewidth = 1,label='SFF8431_Spec_Recomamnd')
plt.plot(SDD21_x[0:1500],IEEE_86A_ymax,linewidth = 1,label='SFF8431_Spec_Max',color="red")
plt.plot(SDD21_x[0:1500],IEEE_86A_ymin,linewidth = 1,label='SFF8431_Spec_Min',color="red")
plt.xlabel('Frequency (MHZ)', fontsize=12)
plt.ylabel(' SDD21(dB)', fontsize=12)
plt.xticks(fontsize = 12)
plt.yticks(fontsize = 12)
plt.legend()

plt.show()


4. 参考

  1. touchstone file format link
  2. 《ADS信号完整性仿真与实战》
  3. IEEE802.3 Standard
  • 4
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值