2021年4月5日 星期一

將HFSS個別輸出的遠場圖更名為port的名稱

import os

path = 'd:/demo_FFD'

with open(os.path.join(path, 'exportelement.txt')) as f:
text = f.readlines()

for line in text[1:]:
try:
port_name, file_name = line.strip().split()
port_name = port_name.split(':')[0]
os.rename('{}/{}.ffd'.format(path, file_name),
'{}/{}.ffd'.format(path, port_name))
except:
pass


2021年4月4日 星期日

一次畫出IBIS當中所有[Model]的[Rising Waveform]跟[Falling Waveform]

 指定IBIS檔案路徑,執行以下腳本即可。

# -*- coding: utf-8 -*-
"""
Created on Sun Apr 4 09:23:17 2021

@author: mlin
"""
import matplotlib.pyplot as plt


def plotWaveform(model_name, waveform):
plt.figure(figsize=(7, 4))
plt.clf()
header = []
_time_, _typ_, _min_, _max_ = [], [], [], []
for i in waveform:
if '=' in i:
header.append(i.strip())
continue
if '|' in i:
continue
try:
_time, _typ, _min, _max = i.strip().split()
_time_.append(float(_time.lower().replace('ps', 'e-12').replace('ns', 'e-9').replace('us', 'e-6')))
_typ_.append(
float(_typ.lower().replace('nv', 'e-9').replace('uv', 'e-6').replace('mv', 'e-3').replace('v', '')))
_min_.append(
float(_min.lower().replace('nv', 'e-9').replace('uv', 'e-6').replace('mv', 'e-3').replace('v', '')))
_max_.append(
float(_max.lower().replace('nv', 'e-9').replace('uv', 'e-6').replace('mv', 'e-3').replace('v', '')))
except:
pass
plt.plot(_time_, _typ_, 'g')
plt.plot(_time_, _min_, 'b')
plt.plot(_time_, _max_, 'r')
plt.title('{}\n{}\n{}\n{}'.format(model_name, ';'.join(header[0:3]), ';'.join(header[3:6]), ';'.join(header[6:9])))
plt.xlabel('Time(sec)')
plt.ylabel('Waveform(v)')
plt.grid()
plt.show()


data = {}
container = None
with open('D:\OneDrive - ANSYS, Inc/Models/IBIS/tpz015lg.ibs') as f:
for i in f:
if i.startswith('[Model]'):
_, model_name = i.strip().split()
data[model_name] = {}
continue

if i.startswith('['):
container = None

if '[rising waveform]' in i.lower():
try:
data[model_name]['rising_waveform'].append([])
except:
data[model_name]['rising_waveform'] = [[]]
finally:
container = data[model_name]['rising_waveform'][-1]
continue

if '[falling waveform]' in i.lower():
try:
data[model_name]['falling_waveform'].append([])
except:
data[model_name]['falling_waveform'] = [[]]
finally:
container = data[model_name]['falling_waveform'][-1]
continue

try:
container.append(i)
except:
pass

for model in data:
try:
for i in data[model]['rising_waveform']:
plotWaveform(model, i)
except:
pass
for model in data:
try:
for i in data[model]['falling_waveform']:
plotWaveform(model, i)
except:
pass
[圖一]畫出所有[Model]的[Rising Waveform]跟[Falling Waveform]


2021年3月28日 星期日

如何在Linux上加密IronPython Script

1. 首先編寫要加密的模組(e.g. test.py),模組當中內容可為函數或物件,如圖一。

2. 在Linux當中,需加入mono指令配合ipy64.exe來執行pyc.py以加密模組檔test.py最後輸出test.dll到個人home目錄底下,如圖二。

3. 撰寫工具tool.py檔,透過clr引用test.dll檔案。注意tool.py是不加密的,如圖三。

4. 在AEDT當中測試tool.py,如圖四。

(圖一) 在test.py模組定義函式myadd()

(圖二) 加密test.py 並輸出 test.dll

(圖三) clr匯入test.dll模組,並使用test模組當中的myadd()函式

(圖四) 執行測試無誤





2021年3月13日 星期六

如何用命令列啟動script?

本範例可以用bat檔啟動視窗,視窗可以保持在最上層,但是又可以操作AEDT環境。兩者可以平行操作。不像之前的toolkit會鎖定AEDT環境。總共有三個檔案,以下為程式範例:

run.bat

SET PATH=C:\Program Files\AnsysEM\AnsysEM20.2\Win64\common\IronPython\
ipy64 test.py
pause

test.xaml
<Window 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Template Window" Height="144.165" Width="300" ResizeMode="NoResize" WindowStartupLocation="CenterScreen" Background="#FFEAEBFF" Topmost="True">
<Grid>
<Button Content="Execute" HorizontalAlignment="Right" Height="36" Margin="0,0,10,10" VerticalAlignment="Bottom" Width="93" Click="Button_Click"/>
<TextBox x:Name="input_tb" HorizontalAlignment="Right" Height="27" Margin="0,10,10,0" TextWrapping="Wrap" VerticalAlignment="Top" Width="214" VerticalContentAlignment="Center"/>
<Label Content="Value:" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="55"/>
</Grid>
</Window>

test.py
# coding=UTF-8
import os, sys, re, clr, json, math, cmath

# 初始化環境,設定win64_path
win64_path = 'C:/Program Files/AnsysEM/AnsysEM20.2/Win64'
sys.path.append(win64_path)
sys.path.append(win64_path + '/PythonFiles/DesktopPlugin/')
sys.path.append(win64_path + '/common/IronPython/DLLs')

import ScriptEnv

ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
from Ansys.Ansoft.CoreCOMScripting.Util import COMUtil

# 初始化WPF視窗環境
clr.AddReference('IronPython.Wpf')
clr.AddReference('System.Drawing')
clr.AddReference('System.Windows.Forms')
import wpf
from System.Windows import Window
from System.Windows.Forms import OpenFileDialog, SaveFileDialog, FolderBrowserDialog, DialogResult

# 程式主體放在try段落當中,
try:
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.SetActiveEditor("3D Modeler")


def AddWarningMessage(info):
oDesktop.AddMessage(oProject.GetName(), oDesign.GetName(), 1, info)


class MyWindow(Window):
def __init__(self):
wpf.LoadComponent(self, 'test.xaml')
oDesktop.ClearMessages("", "", 2)

def Button_Click(self, sender, e):
AddWarningMessage(self.input_tb.Text)


MyWindow().ShowDialog()
except:
raise

# 程式執行成功與否,都能釋放AEDT專案
finally:
COMUtil.PInvokeProxyAPI.ReleaseCOMObjectScope(0)

(圖一)程式執行跳出視窗,同時仍能設定AEDT


2021年3月7日 星期日

奇異值分解(SVD, Singular Value Decomposition)

SVD是一個很有趣的技術。以下A為100x4矩陣,共400筆數值。做完SVD分解之後,可以拆成U:100x100, sigma:100x4, VT矩陣:4x4,乍看數量反而暴增(400 -> 10416)。然而只需保留矩陣的一小部分,(本範例四個奇異值只保留兩個來簡化矩陣,U1:100x2, sigma1:2x2, VT1:2x4,總數212),之後就可以透過矩陣乘法還原出原始的400筆數值,等於儲存資料量少了近一半(212/400=53%)。

SVD用在資料壓縮,機器學習等領域。網路上可以找到許多關於SVD的解說。。各位可以比較還原後的A1矩陣與A矩陣幾乎完全相同。SVD運算有點複雜,所幸Scipy已經提供了現成的函式可以使用。

# -*- coding: utf-8 -*-
"""
Created on Sun Mar 7 08:29:34 2021

@author: mlin
"""
import numpy as np
from numpy import linalg as la
A=np.array([[i+0,i+1,i+2, i+3] for i in range(100)])

#A矩陣(100x4)做奇異值分解分成三矩陣相乘
U,sigma,VT=la.svd(A)

#U(100x100)sigma(100x4),V(4x4)

print('_'*40)
U1 = U[:,:2]
#U1(100x2)

sigma1 = np.array([[sigma[0],0],[0, sigma[1]]])
#sigma1(2x2)

VT1 = VT[:2,:]
#VT1(2x4)

A1 = np.dot(np.dot(U1,sigma1), VT1)

2021年3月1日 星期一

使用優化來找出目標方程式最小值

參考https://www.youtube.com/watch?v=cXHvC_FGx24

目標方程式為四元(x1, x2, x3, x4)非線性方程式x1*x4*(x1+x2+x3)+x3。有兩條約束式,變數範圍1到5。求解滿足約束方程式的目標方程式最大值。

代碼:

# -*- coding: utf-8 -*-
import numpy as np
from scipy.optimize import minimize

def objective(x):
x1, x2, x3, x4 = x
return x1*x4*(x1+x2+x3)+x3

def constraint1(x):
x1, x2, x3, x4 = x
return x1*x2*x3*x4-25

def constraint2(x):
x1, x2, x3, x4 = x
return 40 - x1**2 - x2**2 - x3**2 - x4**2

bnds = ((1, 5), (1, 5), (1, 5), (1, 5))

con1 = {'type':'ineq', 'fun':constraint1}
con2 = {'type':'eq', 'fun':constraint2}

x0 = [1, 5, 5, 1]
sol = minimize(objective, x0, bounds = bnds, constraints=[con1, con2], tol=1e-6, options = {'maxiter':100, 'disp':True})
print(sol)

(圖一)優化結果

其中 x1, x3, x3, x4 = [1. , 4.7429961 , 3.82115462, 1.37940765],
最小值為17.01401724563517

2021年2月19日 星期五

如何在IronPython執行CPython運算

首先在環境變數引入AEDT內建的CPython路徑,再用system()執行python "xxx.py"即可。

 os.environ['PATH'] = oDesktop.GetExeDir() + "commonfiles/CPython/3_7/winx64/Release/python"

os.system('python "alignCS_Calculation.py"')