-
Notifications
You must be signed in to change notification settings - Fork 8
Schemdraw
Pythonを使って回路図などを描けて,png, pdf, svgへの出力もできる.自由度が高いので重宝している.
ドキュメントに必要なことは書いてある.回路の記述はここらへんが参考.
with schemdraw.Drawin() as d:のスコープでd += しなくても書いてある順にパーツが置かれていく.態々as dとしているのはconfigとかpush, pop, holdとか,あとでsaveするため.
Pythonの仕様としてwith ~ asで変数を指定してもスコープでの死活概念がないので,スコープ外でsaveできる.(スコープ内の方が綺麗だがsaveは分けておいた方が見付けやすい)
Pythonの環境にはとりあえず, Jupyter Lab, matplotlib, matplotlib-fontja, schemdrawがあれば十分.
このドキュメントではWindowsで,Wordの数式フォントのCambria(Math)と日本語を無理矢理使う設定を示しておく.Cambriaなttfはそこらじゅうに落ちているのでmatplotlibでttfを読ませることもできるが,ライセンス的にダメと思われるので注意(macだとWordをインストールしてもシステムフォントに組込まれない)
up, down, left, right, thetaとかで指定すれば,次に新たに指定するまでその向きが継続されるが,書かなければ書かないで可読性が落ちる.
ドキュメントに書かれている通りで,スコープの頭でd.config(unit=2)とすると通常より短かめの記述になる(デフォルトは3)が,fontsize, 絶対量記述には反映しないので,あとからサイズ変更すると基本的に書き直しに近い作業になる.(ので,長さの指定はd.unit*0.5)のように相対値にしておくと良い)パーツそのもののサイズを変えたい場合はscale, scalex, scaleyで倍率を指定する.特にLについては貧相なのでやや盛った方が見易い.
R, L, Cとかのパーツはstart, end, centerがアンカーとして存在し,他の特殊なパーツについてはドキュメント参照
- at: パーツ名またはパーツ名.アンカーのような感じでスタート地点を指定できる
- anchor: 置くパーツのどのアンカーに繋げるかの指定
- to, tox, toy: どこまでかの指定.tox, toyはそれぞれx, y座標のみ合わせる.
中身はMatplotlibなので,その数式記述と同じで数式だけならr'$ $'で囲まれた中にLaTeX記述をする.
詳細はドキュメント参照
- loc: どこに置くか.'top'がデフォで'bottom','left','right'がある.あとはアンカー名.
- ofst: オフセット量.tuppleで書けばdx,dyだがパーツを置く向き依存なので,取り敢えず書いてから考える.
- rotate: Trueにするとパーツに沿ってラベルが置かれる.
- fontsize: そのラベルだけサイズを変えたいとき.全体は
d.configで指定する. - color: 文字の色指定
push, popの中での記述か,with d.hold():のスコープでの記述.後者の方がネストするので見易いっちゃ見易い.
import schemdraw
import schemdraw.elements as elm
import matplotlib.pyplot as plt
plt.rcParams["text.usetex"]=False # Wordと同じ数式フォントにするためFalse
import matplotlib.pyplot as plt
import matplotlib
import matplotlib_fontja # IPAexGothicが仕込まれるらしい
plt.rcParams['font.family']='serif'
plt.rcParams['mathtext.fontset'] = 'custom'
plt.rcParams['mathtext.rm'] = 'Cambria' # Cambria だけでMathの方と一致
plt.rcParams['mathtext.it'] = 'Cambria:italic'
plt.rcParams['mathtext.bfit'] = 'Cambria:bold:italic'
plt.rcParams['mathtext.bf'] = 'Cambria:bold'
schemdraw.config(font='IPAexGothic') # 無理矢理日本語にする
with schemdraw.Drawing() as d:
d.config(fontsize=18.0)
R1 = elm.ResistorIEC().linestyle('--').color('red').right().label('抵抗').dot()
d.push() # 1 命令の脇道
elm.Line().up(d.unit*0.5)
elm.Resistor().right().label('push,popで並列回路')
elm.Line().down(d.unit*0.5)
elm.Dot()
d.pop() # 1 の直前から再開
R2 = elm.ResistorIEC().right().label(r'$R_2=1\Omega$')
C1 = elm.Capacitor().right().label(r'$\dot{Z}=-j8\Omega$').dot()
d.push() # 2
topLn = elm.Line().right()
L0 = elm.Inductor().down().label('標準だと$L$は貧相',loc='bottom',rotate=True,ofst=(-0.8,0.3))
botLn = elm.Line().left().dot()
d.pop() # 2
I0 = elm.SourceI().down().reverse().label(r'$2\angle 45^\circ \rm A$',loc='top',rotate=True)
E0 = elm.SourceSin().left()
elm.Dot(open=True).label(r'$\rm a$')
Gap = elm.Gap().left(d.unit*0.5).label('ギャップも作れる',ofst=(0,0.8))
elm.Dot(open=True).label(r'$\rm b$',loc='right')
with d.hold(): # push,popの代わり
elm.Line().up(d.unit*0.4)
elm.ResistorIEC().scale(0.4).left(d.unit*0.2)
elm.Inductor().flip().scalex(0.4).left(d.unit*0.2)
elm.ResistorIEC().scalex(0.4).scaley(0.3).left(d.unit*0.2).label('scale,scalex,scaleyで調整',fontsize=10,ofst=(0,-0.3))
elm.ResistorIEC().scale(0.3).left(d.unit*0.2)
elm.Capacitor().scale(0.4).left(d.unit*0.1)
elm.Line().down(d.unit*0.4).dot()
L1 = elm.Inductor().scaley(2).scalex(1.3).flip().label(r'$j21\Omega$')
elm.Dot()
elm.Ground()
dLn = elm.Line().theta(135).label('任意角の線も可',rotate=True,loc='bottom',ofst=(0,0.5),color='blue')
elm.Line().toy(R1.start).label('toy')
elm.Line().tox(R1.start).label('tox')
elm.CurrentLabel(top=False,length=d.unit*0.5).at(R2).label('名前があればatで指定できる')
elm.CurrentLabel(length=d.unit*0.25, top=False).at(E0).label(r'$\bfit E_{\bf 0}$',ofst=0)
elm.LoopCurrent(elm_list=[topLn,L0,botLn,I0],direction='ccw',theta1=-125,theta2=125,pad=0.4).label('閉路1')
elm.CurrentLabelInline(ofst=0).at(dLn).label(r'Inline $\dot{I}_1$',rotate=True)
elm.Dot(radius=0.05).at(L0.NW) # 極性のドットはLのアンカー NW, NEを使う
d.save('schemdraw01.png')
d.save('schemdraw01_300.png',dpi=300)
d.save('schemdraw01.pdf')
d.save('schemdraw01.svg')
Transformerとしてパーツはあるのだが半円4つしかなく,線を引き込む必要があったり全部アンカー基準で書く必要があり可読性が悪くなるうえ,d.unitガン無視の寸法(高さ1.6),1次2次の間隔が狭いのでMや極性や弧が書きにくいといった扱いにくさ.
なので普通のInductor置いてGapで間開けて2次側記述した方が読みやすかったりする.
import schemdraw
import schemdraw.elements as elm
import matplotlib.pyplot as plt
plt.rcParams["text.usetex"]=False # Wordと同じ数式フォントにするためFalse
import matplotlib.pyplot as plt
import matplotlib
import matplotlib_fontja # IPAexGothicが仕込まれるらしい
plt.rcParams['font.family']='serif'
plt.rcParams['mathtext.fontset'] = 'custom'
plt.rcParams['mathtext.rm'] = 'Cambria' # Cambria だけでMathの方と一致
plt.rcParams['mathtext.it'] = 'Cambria:italic'
plt.rcParams['mathtext.bfit'] = 'Cambria:bold:italic'
plt.rcParams['mathtext.bf'] = 'Cambria:bold'
schemdraw.config(font='IPAexGothic') # 無理矢理日本語にする
with schemdraw.Drawing() as d:
d.config(fontsize=18.0)
elm.SourceSin().reverse().up()
elm.ResistorIEC().right()
elm.Line().down(0.7)
T0 = elm.Transformer(core=False).anchor('p1').right() # p1に接続
bbT0 = T0.get_bbox()
print(bbT0)
# 位置決めにはBounding Boxを取得して相対値にする手段もある
elm.Label(r'$M$',fontsize=14).at(T0.p1,dx=(bbT0.xmax-bbT0.xmin)/3,dy=0.6)
elm.Arc2().at(T0.p1,dx=0.1,dy=0.2).to(T0.s1,dx=-0.1,dy=0.2)
elm.Dot(radius=0.04).at(T0.p1,dx=0.2,dy=0.1)
elm.Dot(radius=0.04).at(T0.s2,dx=-0.2,dy=-0.1)
elm.Line().at(T0.p2).down(0.7) # p2から書き始める
elm.Line().left()
elm.Line().down(0.7).at(T0.s2) # s2から書き始める
elm.Line().right()
elm.SourceSin().up().reverse()
elm.ResistorIEC().left()
elm.Line().down(0.7)BBox(xmin=-3.2162452993532734e-17, ymin=0.0, xmax=0.75, ymax=1.6)

可読性はこっちの方が遥かに良いが,Inductorが小さいのでscale調整が必要
import schemdraw
import schemdraw.elements as elm
import matplotlib.pyplot as plt
plt.rcParams["text.usetex"]=False # Wordと同じ数式フォントにするためFalse
import matplotlib.pyplot as plt
import matplotlib
import matplotlib_fontja # IPAexGothicが仕込まれるらしい
plt.rcParams['font.family']='serif'
plt.rcParams['mathtext.fontset'] = 'custom'
plt.rcParams['mathtext.rm'] = 'Cambria' # Cambria だけでMathの方と一致
plt.rcParams['mathtext.it'] = 'Cambria:italic'
plt.rcParams['mathtext.bfit'] = 'Cambria:bold:italic'
plt.rcParams['mathtext.bf'] = 'Cambria:bold'
schemdraw.config(font='IPAexGothic') # 無理矢理日本語にする
with schemdraw.Drawing() as d:
d.config(fontsize=18.0)
elm.SourceSin().reverse().up()
elm.ResistorIEC().right()
L1 = elm.Inductor().scalex(1.6).scaley(2).down()
elm.Line().left()
elm.Dot(radius=0.04).at(L1.NE,dx=-0.3)
with d.hold(): # 2次側
elm.Gap().at(L1.start).right(d.unit*0.5) # L1.startの横から書き始める
L2 = elm.Inductor().scalex(1.6).scaley(2).flip().down()
elm.Line().right()
elm.SourceSin().up().reverse()
elm.ResistorIEC().left()
elm.Dot(radius=0.04).at(L2.NW,dx=0.3)
elm.Label(r'$M$',fontsize=14).at(L1.NW,dy=0.7,dx=0.1)
elm.Arc2().at(L1.NW,dx=-0.5,dy=0.1).to(L2.NW,dx=0.5,dy=0.1)
用意されている以外の何かを作ろうとすると面倒で,検流計を作ろうとしても文字をド真ん中に置くという方法が無い.locでcenterアンカー使っても,align指定しても無理
ギャラリーにブリッジ回路はあるが,MeterArrowでお茶濁し.
with schemdraw.Drawing() as d:
d.config(fontsize=24.0)
elm.Source().label('D',loc='center',halign='center')
elm.MeterArrow()
ホイートストンだけ用意されている. Wheatstone classを加工しても書けるがやってる事は根性で書くだけなので複雑になれば労力は自前で用意するのと変わらなそう.
以下根性で書いた場合.長さの帳尻をsqrt(2)でやるか,tox, toyを使うかというところ.
入れ子になるとwith d.hold():も見易いかというと微妙.
import schemdraw
import schemdraw.elements as elm
import matplotlib.pyplot as plt
plt.rcParams["text.usetex"]=False # Wordと同じ数式フォントにするためFalse
import matplotlib.pyplot as plt
import matplotlib
import matplotlib_fontja # IPAexGothicが仕込まれるらしい
plt.rcParams['font.family']='serif'
plt.rcParams['mathtext.fontset'] = 'custom'
plt.rcParams['mathtext.rm'] = 'Cambria' # Cambria だけでMathの方と一致
plt.rcParams['mathtext.it'] = 'Cambria:italic'
plt.rcParams['mathtext.bfit'] = 'Cambria:bold:italic'
plt.rcParams['mathtext.bf'] = 'Cambria:bold'
schemdraw.config(font='IPAexGothic') # 無理矢理日本語にする
with schemdraw.Drawing() as d:
len_a = 0.2*d.unit
len_obj= 0.6*d.unit
len_b = 0.15*d.unit
d.config(fontsize=18.0)
lr = elm.Line().down()
v1 = elm.SourceSin().left(d.unit*1.41).flip()
elm.Line().up()
elm.Dot()
with d.hold():
Z1 = elm.ResistorIEC().theta(45).label(r'$R_1$',ofst=0).dot()
with d.hold():
elm.Source().down(d.unit*1.414).label('D',ofst=(0.05,0.7))
elm.Dot()
elm.Line().length(len_a).theta(-45).dot()
with d.hold():
elm.Line().length(len_b).theta(45)
Z31 = elm.ResistorIEC().length(d.unit*0.5).theta(-45).label(r'$R_3$',ofst=0)
elm.Line().length(len_b).theta(-135).dot()
elm.Line().length(len_b).theta(-135)
Z32 = elm.Capacitor().length(d.unit*0.5).theta(-45).label(r'$C_3$','bottom',ofst=(0.7,0.35))
elm.Line().length(len_b).theta(45)
elm.Line().tox(lr.start).theta(-45)
elm.Dot()
Z2 = elm.ResistorIEC().theta(-45).label(r'$R_2$','bottom',ofst=0)
elm.Dot()
Z4 = elm.Capacitor().theta(45).length(d.unit*0.4).label(r'$C_4$','bottom',ofst=0)
elm.ResistorIEC().tox(lr.start).theta(45).label(r'$R_4$',loc='bottom',ofst=(-0.4,0))
elm.CurrentLabel(length=0.75).at(v1).label(r'$\dot{V}(\omega)$',ofst=0)
- 3ds_max
- Android
- Books
- Caffe
- Canvas
- Chainer
- CloudCompare
- colinux
- colmap
- Cygwin
- DeepLearning
- DICOM
- dlib
- docker
- Everun
- Excel
- EyeX
- FANN
- FDS
- Felica
- FreeBSD
- FreeNAS
- GAlib
- gnuplot
- JetsonNano
- JetsonTK1
- JetsonTX2
- Kinect
- LAPACK
- LaTeX
- LTspice
- M5Stack
- MacOSX
- MATLAB
- Memo
- MicroEnableIII
- Mono
- MSVC
- nano
- nvidia-docker
- ODE
- Open3D
- OpenCV
- OpenCVSharp
- OpenMVG
- OpenOffice
- OpenVSLAM
- OSG
- ParaView
- PCL
- Phidgets
- PlaidML
- PLplot
- POVRay
- PowerPoint
- Python
- R
- RaspberryPi
- Realsense
- ROS
- RSJ2011
- Ruby
- Scilab
- SHOGUN
- SUSE
- SVM
- Tensorflow
- TrueCrypt
- Ubuntu
- uEye
- Unix
- VMWarePlayer
- Vim
- VTK
- Windows
- WSL2
- 文書作成
- 文献調査
- 立体映像
- 論文メモ