LTspice を CLI で動かして PyLTSpice で結果を読みだして gnuplot で表示する

こういう人向け

- なんでもコマンドラインから動かしたくなる.
- LTspice のグラフ表示はイマイチだと思う.
- いまだに gnuplot で満足だ.

例として [別記事](https://qiita.com/t-kuwa/items/9a7f1319009853555ee7) で紹介しているオペアンプのオープンループ特性のシミュレーションを、コマンドラインから実行し、結果の raw file を PyLTSpice を使って読みだして、gnuplot でボード線図にプロットしてみます。

まずは回路図。
LTspice の回路図 (*.asc) は、テキストとして読めるのですが、例となる回路図はこんな感じです。

```openloop.asc
Version 4
SHEET 1 880 680
WIRE 256 -16 112 -16
WIRE 272 -16 256 -16
WIRE 272 16 272 -16
WIRE 112 144 112 -16
WIRE 144 144 112 144
WIRE 256 160 208 160
WIRE 272 160 272 96
WIRE 272 160 256 160
WIRE 144 176 64 176
WIRE 64 224 64 176
FLAG 176 384 0
FLAG 272 384 0
FLAG 64 304 0
FLAG 256 160 vo
FLAG 256 -16 vi
FLAG 176 304 vcc
FLAG 176 128 vcc
FLAG 176 192 vee
FLAG 272 304 vee
SYMBOL Opamps\\OP07 176 96 R0
SYMATTR InstName U1
SYMBOL voltage 176 288 R0
WINDOW 123 0 0 Left 0
WINDOW 39 0 0 Left 0
SYMATTR InstName V1
SYMATTR Value 15
SYMBOL voltage 272 288 R0
WINDOW 123 0 0 Left 0
WINDOW 39 0 0 Left 0
SYMATTR InstName V2
SYMATTR Value -15
SYMBOL voltage 64 208 R0
WINDOW 123 0 0 Left 0
WINDOW 39 0 0 Left 0
SYMATTR InstName V3
SYMATTR Value 0
SYMBOL voltage 272 0 R0
WINDOW 123 24 124 Left 2
WINDOW 39 0 0 Left 0
SYMATTR InstName V4
SYMATTR Value 0
SYMATTR Value2 AC 1
TEXT 358 200 Left 2 !.ac dec 20 1 10meg
```
この回路をシミュレーションすると、openloop.raw という解析結果ができるのですが、こちらは直接は読めないので、読み出すために、以下のような Python script を用意します。
```rawread.py
#! py -3
import sys
import math
import cmath
import os
from contextlib import redirect_stdout
from PyLTSpice.LTSpice_RawRead import LTSpiceRawRead

if len(sys.argv) < 2:
    print('usage : %s raw_filenmae' % sys.argv[0])
    exit()
else:
    file = sys.argv[1]

with redirect_stdout(open(os.devnull, 'w')):
    raw = LTSpiceRawRead(file)

fr = raw.get_trace('frequency')
vi = raw.get_trace('V(vi)')
vo = raw.get_trace('V(vo)')

N = len(fr)
for i in range(N):
    (a, p) = cmath.polar(vo[i] / vi[i])
    print('%f %f %f' % (abs(fr[i]), 20*math.log10(a), p*180/math.pi))
```
結果から、周波数と、V(vo)/V(vi) の振幅(dB)と位相(°)を抜き出して表示しています。LTSpiceRawRead が余計なコンソール出力するようなので、redirect_stdout で抑制してます。

ボード線図をプロットするための gnuplot script はこんなの。
```bode.plt
set terminal postscript eps enhanced color size 8cm,4cm font "Times:Bold,10"
set output "openloop.eps"

set multiplot

set border lw 2
set logscale x

set xrange [1:1e+7]
set yrange [-80:120]
set ytics -80,20,120
set format x ""
unset xlabel
set ylabel "Gain [dB]" offset 1.0,0
unset key
set mxtics 10
set grid xtics mxtics
set grid ytics
set lmargin screen 0.10
set rmargin screen 0.95
set tmargin screen 0.95
set bmargin screen 0.58
plot "data.txt" using 1:2 with lines lw 2 lc rgbcolor "#C05050"

set xrange [1:1e+7]
set yrange [-90:180]
set ytics -90,30,180
set format x
set xlabel "Frequency [Hz]"
set ylabel "Phase [degree]" offset 1.0,0
unset key
set mxtics 10
set grid xtics mxtics
set grid ytics
set lmargin screen 0.10
set rmargin screen 0.95
set tmargin screen 0.53
set bmargin screen 0.16
plot "data.txt" using 1:3 with lines lw 2 lc rgbcolor "#C05050"

unset multiplot
```
文字とかグリッドとかマージンとか、細かい設定は好みで。

で、これらを実行する shell script は（私の場合は Cygwin の bash terminal で実行しましたが、cmd や powershell でも似たようなもの)...
```run.sh
#!/usr/bin/bash
export PATH={XVIIx64へのパス}:$PATH

XVIIx64 -netlist openloop.asc
XVIIx64 -b openloop.net

./rawread.py openloop.raw > data.txt
gnuplot bode.plt
```
LTspice は一度回路図を spice netlist に変換してから、バッチモードで解析するようです。
run.sh 一発で以下のようなグラフができました。
![openloop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3455249/c5ef15d8-71a5-914f-5a56-7e6002153a9f.png)