2021年9月27日 星期一

一次啟動多個Stramlit App

main.py為主頁面,透過main.py可以連接到不同App。

run.bat

set PATH=C:\Users\mlin\AppData\Local\Programs\Python\Python38\Scripts

start streamlit run .\main.py --server.port 8050
start streamlit run .\case1.py --server.port 8051
start streamlit run .\case2.py --server.port 8052
start streamlit run .\case3.py --server.port 8053

main.py

import os
import streamlit as st
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.connect(("8.8.8.8", 80))
ip = s.getsockname()[0]
s.close()

st.title('main')
st.markdown(f'[case1](http://{ip}:8051)')
st.markdown(f'[case2](http://{ip}:8052)')
st.markdown(f'[case3](http://{ip}:8053)')

2021年9月21日 星期二

如何用Streamlit做出具備動畫效果的網頁

透過st.empty(),只要以下幾行程式碼就可以做出數學運算的動畫網頁。有趣的是,這個計算是在伺服器完成運算並主動刷新使用者頁面,類似推播的功能。而非由使用者端刷新頁面。

import streamlit as st
import numpy as np
import matplotlib.pyplot as plt

plt.figure(figsize=(6,6))
st.title('Animation')
t = 0
x, y = [], []
n = st.number_input('w:', value=5)
start = st.button('Start!')
container = st.empty()

if start:
while(True):
plt.clf()
plt.title(f't={round(t,2)}')

x.append(np.sin(t))
y.append(np.cos(n*t))

plt.xlim(-1.2,1.2)
plt.ylim(-1.2,1.2)
plt.plot(x, y, color='red')
container.pyplot(plt)
t+=0.02




2021年9月20日 星期一

建立有滑桿,多欄位,Latex方程式的互動式網頁

只要25行,就可以輕鬆建立一個精美的拍頻訊號互動式頁面,布置在任一台電腦上面,就可以從遠端登入網頁使用。

import streamlit as st
import numpy as np
import matplotlib.pyplot as plt

st.title('Beat Signal Demo')

c1, c2 = st.columns(2)
with c1:
a1 = st.slider('A1', 0.0, 1.0, 0.5)
f1 = st.slider('f1(Hz)', 0, 100, 10)

with c2:
a2 = st.slider('A2', 0.0, 1.0, 0.5)
f2 = st.slider('f2(Hz)', 0, 100, 20)

time = np.arange(0, 1, 0.001)
x1 = a1 * np.sin(2*np.pi*f1*time)
x2 = a2 * np.sin(2*np.pi*f2*time)

st.latex('f(t) = A1\cdot sin(2\pi f_1 t) + A2\cdot sin(2\pi f_2 t)')
plt.plot(time, x1+x2)
plt.ylabel('f(t)',)
plt.xlabel('t(sec)',)

st.pyplot(plt)


(圖一)互動式網頁介面


2021年9月18日 星期六

上傳檔案到遠端streamlit網頁伺服器

如果要上傳snp, brd, aedtz, gds, zip, png等檔案到遠端伺服器用自動化程式加以處理,以下程式碼可以產生檔案上傳按鈕,選擇檔案即可上傳到伺服器特定路徑存檔。另外也可以選擇副檔名篩選出檔案類型,並選擇檔案下載。

import streamlit as st
from os import listdir
from os.path import isfile, join

folder_path = 'D:/Downloads'

st.header('上傳檔案')
with st.form(key='my_form', clear_on_submit=True):
files = st.file_uploader("上傳檔案", accept_multiple_files=True, )

if st.form_submit_button(label='Submit'):
for file in files:
with open(join(folder_path, file.name), 'wb') as f:
f.write(file.getbuffer())

st.header('下載檔案')
password = st.text_input('Password', type="password")
if password == '1234':
ext = []
files = listdir(folder_path)
for f in files:
if isfile(join(folder_path, f)):
ext.append(f.split('.')[-1])

ext = list(set(ext))
x = st.selectbox("extensions", ext, 0)
filename = st.selectbox('file', [i for i in files if i.endswith(x)])

with open(join(folder_path, filename), 'rb') as f:
data = f.read()
st.download_button('download', data, filename)
(圖一)上傳/下載檔案頁面


以Streamlit建立網頁GUI背景呼叫Nexxim.exe執行RC電路模擬

延續上一篇介紹的內容,本範例套用Streamlit模組,不到10行程式碼(st.XXX)便可以建立RC電路模擬GUI。使用者輸入R, C,按下執行模擬鍵,一秒便可以顯示S21分布圖。也可以從遠端設備登入網頁執行模擬工作。如圖二。

# -*- coding: utf-8 -*-
import os
import streamlit as st
import random
import matplotlib.pyplot as plt
from datetime import datetime



text = '''
.option PARHIER='local'
.option max_messages=1

* begin toplevel circuit

R1 Port1 Port2 {}
C2 0 Port2 {}
RPort1 Port1 0 PORTNUM=1 RZ=50 IZ=0
.PORT Port1 0 1 RPort1
RPort2 Port2 0 PORTNUM=2 RZ=50 IZ=0
.PORT Port2 0 2 RPort2

* end toplevel circuit
.LNA
+ LIN 10000 0 10000000000
+ FLAG='LNA'

.end'''


def readCSV(csv_name):
with open(csv_name) as f:
text = f.readlines()

freq = []
S11, S12, S21, S22 = [], [], [], []
for line in text[1:]:
_, f, s11_re, s11_im, s12_re, s12_im, s21_re, s21_im, s22_re, s22_im = line.split(',')
freq.append(float(f))
S11.append(complex(float(s11_re), float(s11_im)))
S12.append(complex(float(s12_re), float(s12_im)))
S21.append(complex(float(s21_re), float(s21_im)))
S22.append(complex(float(s22_re), float(s22_im)))
return freq, S21


st.header('RC電路S參數模擬')
R = st.number_input('電阻值(Ohm)')
C = st.number_input('電容值(pF)') * 1e-12
z = st.button('執行模擬')

n = datetime.now().timestamp()
if z:
with open('c:/demo/rc{}.cir'.format(n), 'w') as f:
f.write(text.format(R, C))

os.environ['path'] = 'C:\Program Files\AnsysEM\AnsysEM21.1\Win64'
os.system('nexxim c:/demo/rc{}.cir'.format(n))
os.system('sdf2csv c:/demo/rc{}.cir.sdf'.format(n))
with open('c:/demo/rc{}.cir.sdf.csv'.format(n)) as f:
text = f.readlines()

f, S21 = readCSV('c:/demo/rc{}.cir.sdf.csv'.format(n))
plt.figure(figsize=(4, 3))
plt.plot(f, [abs(i) for i in S21])
plt.grid()
plt.xlabel('freq(Hz)')
plt.ylabel('mag')
plt.xlim(0, 1e10)
plt.ylim(0, 1)
st.pyplot(plt)
print('Finished ID: {}'.format(n))
(圖一)網頁GUI

(圖二)由手機登入並執行模擬

2021年9月17日 星期五

如何用Streamlit設計網頁做為自動化程式介面

假設我們可以在網頁輸入參數,按下執行鍵,即可以讓遠端裝有EDA軟體的工作站執行模擬,並在模擬完成之後將結果回傳,這是不是很吸引人?只要區域網路內的任一台電腦,配備有瀏覽器,便可以透過網頁來執行模擬工作。這樣子的作法可以大大的提高EDA的使用效率,更可以讓更多不熟悉EDA操作的工程師也能正確的完成複雜的設定。

過往在開發網頁介面最大的困難是必須熟悉網頁框架,如Flask或Django。現在有了Streamlit,只要簡單的幾行程式碼便可以產生表單頁面,就算不熟悉HTML語法也可以輕鬆的完成介面的開發。這是一個相當新的技術,我將在之後的文章當中以實際例子來介紹,以下的程式碼是我們課堂練習過的計算機,用Streamlit模組只要下面幾行便可以生成頁面,可以遠端瀏覽器開啟使用。各位有興趣的可以先研究看看:

https://blog.jiatool.com/posts/streamlit/


import streamlit as st
from math import *

x = st.text_input('Simple Calculator', '1+1')
try:
st.write('Answer:', eval(x))
except:
'Invalid Formula!'


(圖一)網頁介面


2021年9月8日 星期三

如何背景執行電容Z11模擬並繪圖

當要檢查大量的電容Z11曲線,直接呼叫nexxim.exe執行AC模擬並繪圖會是一個比較有效率的做法。以下是處理單一一個電容的Python範例。加上迴圈可以一次處理大量的Z11計算及繪圖。

import os
import matplotlib.pyplot as plt
os.chdir(os.path.dirname(__file__))

netlist_template = r'''
.inc "{}"

x1 net_2 0 "{}"
I3 0 net_2 DC=0 AC 1 0

.LNA
+ 100000 100000000 10000
+ FLAG='LNA'

.print AC V(net_2)
.end'''

model_file = r'D:\demo\CL05A226MQ5QUN_Precise_DC0V_25degC_H.lib'
model_name = 'CL05A226MQ5QUN_Precise_DC0V_25degC'

netlist = netlist_template.format(model_file, model_name)
with open('./ZP.net', 'w') as f:
f.write(netlist)

os.environ['PATH'] = r'C:\Program Files\AnsysEM\AnsysEM21.2\Win64'
os.system("nexxim ZP.net")
os.system("sdf2csv ZP.net.sdf")

with open("ZP.net.sdf.csv") as f:
text = f.readlines()
data = []
for line in text[1:]:
try:
_, freq, Zre, Zim = line.strip().split(',')
data.append((float(freq), complex(float(Zre), float(Zim))))
except:
pass
freq, Z11 = zip(*data)
plt.plot(freq, [abs(i) for i in Z11])
plt.grid()
plt.show()
(圖一)Z11

(圖二)AEDT Designer的Z11