2021年11月30日 星期二

AEDT設計屬性匯出及匯入

 exportDesignProperties.py

import clr
clr.AddReference("System.Windows.Forms")

from System.Windows.Forms import DialogResult, SaveFileDialog
dialog = SaveFileDialog()
dialog.Title = "Export Design Properties"
dialog.Filter = "csv file (*.csv)|*.csv"

if dialog.ShowDialog() == DialogResult.OK:
csv_path = dialog.FileName
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()

data = []
for key in oDesign.GetProperties('LocalVariableTab', "LocalVariables"):
value = oDesign.GetPropertyValue('LocalVariableTab', "LocalVariables", key)
data.append((key, value))

with open(csv_path, 'w') as f:
for key, value in data:
f.writelines('{}, {}\n'.format(key, value))
else:
pass

importDesignProperties.py

import clr
clr.AddReference("System.Windows.Forms")
from System.Windows.Forms import DialogResult, OpenFileDialog

dialog = OpenFileDialog()
dialog.Multiselect = False
dialog.Title = "HFSS ffd to csv converter"
dialog.Filter = "csv file (*.csv)|*.csv"

if dialog.ShowDialog() == DialogResult.OK:
csv_path = dialog.FileName

with open(csv_path) as f:
text = f.readlines()

data = []
for line in text:
try:
key, value = line.split(',')[0:2]
data.append((key, value))
except:
pass

oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
for key, value in data:
oDesign.ChangeProperty(
[
"NAME:AllTabs",
[
"NAME:LocalVariableTab",
[
"NAME:PropServers",
"LocalVariables"
],
[
"NAME:ChangedProps",
[
"NAME:{}".format(key),
"Value:=" , value
]
]
]
])
else:
pass

2021年11月26日 星期五

輸出變數及使用該變數的物件名稱

輸出變數及使用該變數的物件名稱

import os, re

oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.SetActiveEditor("3D Modeler")

oDesktop.ClearMessages("", "", 2)

properties = oDesign.GetProperties('LocalVariableTab', "LocalVariables")
prj_path = os.path.join(oProject.GetPath(), oProject.GetName() + '.aedt')
design_name = oDesign.GetName()

with open(prj_path) as f:
text = f.readlines()

models = []
for n, line in enumerate(text):
if "$begin 'HFSSModel'" in line:
model = []
elif "$end 'HFSSModel'" in line:
models.append(model)
del (model)

try:
model.append(line)
except:
pass

data = {}
for model in models:
if design_name not in model[2]:
continue
for prop_name in properties:
for line in model:
m = re.search("Name=(.*)", line)
if m:
obj = m.group(1).replace("'", '')
continue

if prop_name in line and '=' in line and 'obj' in locals():
try:
if obj not in data[prop_name]:
data[prop_name] += [obj]
except:
data[prop_name] = [obj]

for i, v in data.items():
AddWarningMessage(str(i) + ': ' + str(v))


2021年11月20日 星期六

輸出License使用狀況

 可以讀取ANSYS License Server的logs_backup目錄並輸出一段期間License的使用狀況

import os
import codecs
import logging
from datetime import datetime, timedelta

FORMAT = '%(asctime)s %(levelname)s: %(message)s'
logging.basicConfig(filename='simulation.log', filemode='w')

path = r'D:\demo\logs_backup'
data = []
pair = {}
Nin, Nout = 0, 0
for file in os.listdir(path):
with codecs.open(os.path.join(path, file), 'r', 'utf-8', errors='ignore') as f:
text = f.readlines()

for line in text:
if len(line.strip()) == 0:
continue

if '(lmgrd) TIMESTAMP' in line:
date = datetime.strptime(line.strip().split()[-1], '%m/%d/%Y')

if 'date' not in locals():
continue

x = line.strip().split()[0]

if not x.count(':') == 2:
continue

time = datetime.strptime(x, '%H:%M:%S').time()
ts = datetime.combine(date, time)

if 't0' not in locals():
t0 = ts
continue
else:
if (ts - t0).total_seconds() < 0:
date += timedelta(days=1)
t0 = datetime.combine(date, time)

try:
time_stamp, _, status, increment, userandserver, pid = line.strip().split()[0:6]
if status not in ['OUT:', 'IN:']:
raise Exception
except:
continue

user, server = userandserver.split('@')
try:
if status == 'OUT:':
pair[(user, server, increment, pid)] = t0
elif status == 'IN:':
tout = pair[(user, server, increment, pid)]
tin = t0
data.append((user, increment, server, str(tout), str(tin), str(tin - tout)))
except:
logging.exception('')

with open('d:/demo/usage.csv', 'w') as f:
width = '{:12}\t{:30}\t{:30}\t{:25}\t{:25}\t{:25}\n'
title = ['USER', 'License', 'Machine', 'Tstart', 'Tstop', 'Duration']
f.writelines(width.format(*title))

for item in data:
f.writelines(width.format(*item))


2021年11月17日 星期三

使用ElementTree處理stack.xml

以下包含xml建立,讀取,改寫,存檔等動作:


import xml.etree.ElementTree as ET
tree = ET.parse('d:/demo/stackup1.xml')
x = tree.getroot()


y = x.find('./Stackup/ELayers/Layers')
for child in y:
print(child.get('Elevation'))
child.set('UnionPrimitives', 'true')
child.set('Material', 'Copper')
tree.write('d:/demo/stachkup2.xml')

2021年11月12日 星期五

計算選取物件的XYZ邊界

 選擇多個物件,執行下面script,即可輸出選取物件的XYZ邊界座標。

import ScriptEnv

ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.SetActiveEditor("3D Modeler")


def setModel(x):
objs = {True: [i for i in x if x[i]], False: [i for i in x if not x[i]]}
for b, o in objs.items():
if o:
oEditor.ChangeProperty(
[
"NAME:AllTabs",
[
"NAME:Geometry3DAttributeTab",
[
"NAME:PropServers",
] + o,
[
"NAME:ChangedProps",
[
"NAME:Model",
"Value:=" , b
]
]
]
])

def getBoundingBox(objs):
db = {}
for i in range(oEditor.GetNumObjects()):
name = oEditor.GetObjectName(i)
p = oEditor.GetPropertyValue('Geometry3DAttributeTab', name, 'Model')
db[name] = p

setModel({i :(i in oEditor.GetSelections()) for i in db.keys()})
result = oEditor.GetModelBoundingBox()
setModel(db)
return result

size = getBoundingBox(oEditor.GetSelections())
AddWarningMessage(str(size))




2021年11月10日 星期三

HFSS 3D Layout當中找出互連的物件群組

分層找出物理上互連的物件群組,針對沒有netname的物件也可以使用。這裡用到遞迴的函數。

import json
import ScriptEnv
ScriptEnv.Initialize("Ansoft.ElectronicsDesktop")
oDesktop.RestoreWindow()
oProject = oDesktop.GetActiveProject()
oDesign = oProject.GetActiveDesign()
oEditor = oDesign.GetActiveEditor()

objdic = {}
for layer in oEditor.GetStackupLayerNames():
objdic[layer] = oEditor.FilterObjectList('Type', '*', oEditor.FindObjects('Layer', layer))

result = {}
for layer in objdic:
for obj in objdic[layer]:
poly = oEditor.GetPolygon(obj)
x = oEditor.FindObjectsByPolygon(poly, layer)
if len(x) > 1:
result[obj] = x

def getConnect(key, g):
for i in result[key]:
if i not in g:
g.append(i)
getConnect(i, g)
else:
continue
return g

group = []
for obj in result:
x = getConnect(obj, [])
if sorted(x) not in group:
group.append(sorted(x))

with open('d:/demo/connect.json', 'w') as f:
json.dump(group, f, indent=4)
(圖一)輸出互連狀況


2021年11月9日 星期二

如何背景執行Python檔

如果我們想執行一隻Python程式,不會跳出任何視窗,只在背景模式執行,比方說監控電腦狀態並輸出log檔,可以使用pythonw.exe搭配start,就不會跳出任何視窗,範例如下。

test.bat

path=D:\myvenv\Scripts
start pythonw .\test.py

test.py

import os
import time
os.chdir(os.path.dirname(__file__))

while True:
with open('test.log', 'a') as f:
f.writelines(str(time.time()) + '\n')
time.sleep(1)

進一步我們可以將該程式(.bat)設定為開機執行。選擇該程式並按Windows鍵+R,跳出下面視窗再按確定即可。