zaskateam 님이 제공해 주신 팁입니다.
반복계산하는 프로그램의 수렴성을 테스트하기 위해서는 error rate를 텍스트로 출력해서 볼 수도 있지만, 그림으로 보면 더 명확해집니다. 이를 위해 간단한 팁을 올려 드립니다.
For 문으로 iteration 되는 프로그램에서 200 step마다 residue를 계산하여 residues.txt에 저장하려고 합니다. 반복이 되면서 쌓이는 데이터 중에 2000 step의 데이터만 plotting 하려 합니다. 저는 blt::stripchart를 사용했습니다. blt::graph에는 없는 기능들이 더 있습니다. 사용방법은 비슷합니다. 특히 -autorange, -shiftby를 사용하면 원하는 데이터만 plotting 할 수 있습니다.
제가 구현한 방법은 아래와 같습니다. 다른 분들은 아마 더 쉽게 할 수도 있을 것 같아요^^; Run을 클릭하면 아래의 cal_run을 호출합니다.
proc cal_run {} {
set pushd [pwd]
cd ju
...
set cmd "./win.exe"
blt::bgexec execstatus \
-onoutput ::StdoutMessage \
-keepnewline true \
$cmd &
...
cd $pushd
}
btl::bgexec에서 -onoutput 을 사용하면 콘솔에 stdout으로 나오는 데이터를 얻어올 수 있습니다. 저는 tkcon을 삽입해서 그 msg를 바로 뿌려주고, 거기에서 residue를 plotting 하는 함수를 콜 하도록 했습니다. 데이터가 파일로 출력되는 시간을 고려해 sleep을 좀 줬습니다. 그리고 see_residue가 1이면 실행되는 동안 plotting 하도록 했습니다. see_residue는 별것 아니고, 메뉴바에서 체크가 되면 1이 되도록 해서 필요하면 볼 수 있게 했습니다. 저는 defalut로 1을 줬습니다.
proc StdoutMessage {msg} {
global point_value
global xrange_value
global xshift_value
global see_residue
puts $msg
sleep 500
if {$see_residue == 1} {
graph_residue
}
# 200번마다 데이터가 출력되고 있음.
# 최종 2000번의 데이터만 출력하기 위해 shiftby값을 추가시킴
set xshift_value [expr $xshift_value + 200]
}
proc sleep {time} {
after $time set end 1
vwait end
}
그리고 중요한 blt::stripchart를 이용해 plotting하는 소스입니다.
proc graph_residue {} {
namespace import blt::*
namespace import -force blt::tile::*
global xrange_value
global xshift_value
global show_residue fr19
option add *bufferElements no
option add *bufferGraph yes
option add *Axis.lineWidth 1
option add *Axis*Rotate 90
option add *pixels 1.25m
option add *Stripchart.width 6i
if [winfo exist .show_residue] {
raise .show_residue
} else {
toplevel .show_residue
}
wm title .show_residue "Residues of Plasma Parameters"
if [winfo exist .show_residue.fr19] {
destroy .show_residue.fr19
}
set fr19 [frame .show_residue.fr19]
pack $fr19 -fill x
set rgraph [blt::stripchart $fr19.graph -title "Residues"]
pack $rgraph
# For 문으로 iteration 되는 프로그램에서
# 200 step마다 residue를 계산하여 residues.txt에 저장한다.
# 반복이 되면서 쌓이는 데이터 중에 2000 step의 데이터만 plotting 하려 한다.
# -autorange 2000
# -shiftby 는 초기값을 0으로 주고 데이터가 추가 될 때마다 그 증가량 만큼 증가시킴
# 그러면 나중에 나오는 데이터 2000 step만 plotting 된다.
$rgraph axis configure x -autorange 2000
$rgraph axis configure x -shiftby $xshift_value
# 축에 라벨 표시
$rgraph xaxis configure -title "Iteration (#)"
$rgraph yaxis configure -title "Residues"
# Grid 표시
$rgraph grid on
# Output 파일 갯수를 얻어온다
set outdata "./residues.txt"
set file [open $outdata r]
set i 1
while { [gets $file line] != -1 } {
incr i 1
}
close $file
# 배열에 할당함
set arr_num [expr $i-1]
vector x($arr_num) y0($arr_num) y1($arr_num) y2($arr_num)
set outdata "./residues.txt"
set file [open $outdata r]
set i 1
while { [gets $file line] != -1 } {
scan $line "%f %f %f %f %f" iter ni ne nN Te
set x($i-1) $iter
set y0($i-1) $ne
set y1($i-1) $nN
set y2($i-1) $Te
incr i 1
}
close $file
$rgraph element create ne -symbol square \
-color red \
-xdata x -ydata y0
$rgraph element create nN -symbol triangle \
-color green \
-xdata x -ydata y1
$rgraph element create Te -symbol cross \
-color blue \
-xdata x -ydata y2
$rgraph axis configure y -min {} -max {}
# 로그 스케일
$rgraph axis configure x -logscale yes
$rgraph axis configure y -logscale yes
}
마지막으로 아주 중요한 tip알려드립니다. 제가 이것 때문에 아주 고생했습니다.
win.exe 파일을 ./ju/win.exe에 두었습니다. 그래서 ./ju 폴더로 디렉터리를 변경한 후에 win.exe를 실행하도록 했습니다. 그리고 residues.txt파일도 ./ju/residue.txt에 출력되게 했습니다. 그러면 run을 눌러 win.exe가 실행되는 동안에는 ./ju 폴더로 이동한 상태죠. 따라서 plotting할 때, 데이터의 위치는 ./ju/residues.txt이 아닌 그냥 ./residues.txt이 됩니다. 이것 때문에 정말 삽질했습니다.
그럼 많은 도움이 되었으면 좋겠습니다.
'Tcl & Tk > 팁 (Tip)' 카테고리의 다른 글
피아노 코드 도우미 v0.925 (0) | 2025.03.12 |
---|---|
초 간단 웹 부라우저 (0) | 2025.03.12 |
읽어온 데이터를 BLT를 이용해서 2차원 그래프 그리기 (0) | 2025.03.12 |
Gnuplot + Tcl/Tk (0) | 2025.03.12 |
필요시만 스크롤바 보이게 하기 (0) | 2025.03.06 |