Claude CodeにSpiceネットリストを入れて、回路図を書かせたいので、pythonでトランジスタを描く方法を探したところ、以下の記事がHitしました。
https://qiita.com/goldengate94704/items/60c55f0f0710b5e4c8a3
この記事が書かれたのが2021年で、その後APIが変わってしまったようで、動くように修正したので、公開します。
import schemdraw
import schemdraw.elements as elm
from schemdraw.segments import *
reswidth = 1.0 / 6 # Full (inner) length of resistor is 1.0 data unit
fets = reswidth*2
fetw = reswidth*4
feth = reswidth*5
fetl = feth/2
fetgap = reswidth*1.5
fetr = reswidth*0.7 # Radius of "not" bubble
class PMOS(elm.Element):
def __init__(self, *d, bulk: bool=False, **kwargs):
super().__init__(*d, **kwargs)
self.segments.append(Segment([(0, 0), (0, -fetl)]))
self.segments.append(Segment([(0, -fetl), (-fets, -fetl)], arrow='->', arrowwidth=0.15, arrowlength=0.2))
self.segments.append(Segment([(-fets, -fetl-fetw),(0, -fetl-fetw),(0, -2*fetl-fetw)]))
self.segments.append(Segment([(-fets, -fets),(-fets, -fets-feth)],lw=4))
self.segments.append(Segment([(-fets-fetgap, -fetl),(-fets-fetgap, -fetl-fetw)],lw=4))
self.segments.append(Segment([(-fets-fetgap-fetr, -fetl-fetw/2),(-fets-fetgap-fetl-fetr, -fetl-fetw/2)]))
self.anchors['drain'] = (0, -2*fetl-fetw)
self.anchors['source'] = (0, 0)
self.anchors['gate'] = (-fets-fetgap-fetl-fetr, -fetl-fetw/2)
self.params['drop'] = (0, -2*fetl-fetw)
self.params['lblloc'] = 'rgt'
if bulk:
self.segments.append(Segment([(-fets, -fetl-fetw/2),(0, -fetl-fetw/2)], arrow='->', arrowwidth=0.2))
self.anchors['bulk'] = (0, -fetl-fetw/2)
class NMOS(elm.Element):
def __init__(self, *d, bulk: bool=False, **kwargs):
super().__init__(*d, **kwargs)
self.segments.append(Segment([(0, 0), (0, -fetl), (-fets, -fetl)]))
self.segments.append(Segment([(-fets, -fetl-fetw),(0, -fetl-fetw)], arrow='->', arrowwidth=0.15, arrowlength=0.2))
self.segments.append(Segment([(0, -fetl-fetw),(0, -2*fetl-fetw)]))
self.segments.append(Segment([(-fets, -fets),(-fets, -fets-feth)],lw=4))
self.segments.append(Segment([(-fets-fetgap, -fetl),(-fets-fetgap, -fetl-fetw)],lw=4))
self.segments.append(Segment([(-fets-fetgap-fetr, -fetl-fetw/2),(-fets-fetgap-fetl-fetr, -fetl-fetw/2)]))
self.anchors['source'] = (0, -2*fetl-fetw)
self.anchors['drain'] = (0, 0)
self.anchors['gate'] = (-fets-fetgap-fetl-fetr, -fetl-fetw/2)
self.params['drop'] = (0, -2*fetl-fetw)
self.params['lblloc'] = 'rgt'
if bulk:
self.segments.append(Segment([(0, -fetl-fetw/2),(-fets, -fetl-fetw/2)], arrow='->', arrowwidth=0.2))
self.anchors['bulk'] = (0, -fetl-fetw/2)
d = schemdraw.Drawing()
d += (pmos01 := PMOS().label('pmos01', fontsize=9,ofst=(0.1,0)))
d += elm.Line().left().at(pmos01.gate).length(0).label('$V_{b}$', 'left')
d += elm.Line().up().at(pmos01.source).length(0.75).label('$V_{dd}$', 'right',ofst=(0,-0.75))
d += elm.Vdd()
d += (dot01 := elm.Line().down().at(pmos01.drain).length(0.5))
d += elm.Dot().at(dot01.end)
d += elm.Line().right().length(0.5).label('$V_{out}$', 'right')
d += (net01 := elm.Line().at(dot01.end).down().length(0.5))
d += (nmos01 := NMOS().label('nmos01', fontsize=9,ofst=(0.1,0)).at(net01.end).anchor('drain').theta(0))
d += elm.Line().right().at(nmos01.gate).length(0.5).label('$V_{in}$', 'left')
d += elm.Line().down().at(nmos01.source).length(0.5)
d += elm.Ground()
d.draw()
# d.save('schematic01.jpg')
