TAKEC

大学院生の覚書

circuitikzを用いた回路図作成

回路図を書くソフトを色々探したが、結局latexで図を描画するパッケージであるtikzのcircuitikzライブラリを用いている。 f:id:takecccc:20170621151816p:plain

\documentclass[border=1mm]{standalone}
\usepackage[dvipdfmx]{graphicx}
\usepackage{circuitikz}
\usetikzlibrary{calc}

\begin{document}
\begin{circuitikz}
    \draw
    (0,0) node [op amp] (opamp1) {}
    (5,0) node [op amp] (opamp2) {}
    (10,0) node [op amp] (opamp3) {}
    (opamp1.-) to[R,-o,label=$R_3$] ++(-2,0) coordinate (V1) {}
    (V1) node[left] {$V_1$}

    (opamp1.out) to[R,label=$R_4$] ($(opamp2.-)!(opamp1.out)!(opamp2.+)$) -| (opamp2.-)
    (opamp2.out) to[R,label=$R_5$] ($(opamp3.-)!(opamp2.out)!(opamp3.+)$) -| (opamp3.-)
    (opamp3.out) to[short,-o] ++(1,0) coordinate (V2) {}
    (V2) node[right] {$V_2$}

    (opamp1.+) -- ++(0,-1) node[ground] {}
    (opamp2.+) -- ++(0,-1) node[ground] {}
    (opamp3.+) -- ++(0,-1) node[ground] {}

    (opamp1.-) ++(0,4) coordinate (p1) {}
    (p1) ++ (10,0) coordinate (p1') {}
    ($(p1)!(opamp3.out)!(p1')$) coordinate (p2) {}

    (opamp1.-) to[short,*-] (p1)  to[R,label=$R_2$] (p2) to[short,-*] (opamp3.out)

    (opamp1.-) ++(0,1.5) coordinate (p3) {}
    (p3) ++ (5,0) coordinate(p3') {}
    ($(p3)!(opamp1.out)!(p3')$) coordinate (p4) {}
    (p3) to[C,*-*,label=$C_1$] (p4) to[short,*-*] (opamp1.out)

    (opamp1.-) ++(0,3) coordinate (p5) {}
    (p5) ++ (5,0) coordinate(p5') {}
    ($(p5)!(opamp1.out)!(p5')$) coordinate (p6) {}
    (p5) to[R,*-,label=$R_1$] (p6) -- (p4)

    (opamp2.-) ++(0,1.5) coordinate (p7) {}
    (p7) ++ (5,0) coordinate (p7') {}
    ($(p7)!(opamp2.out)!(p7')$) coordinate (p8) {}
    (opamp2.-) to[short,*-] (p7) to[C,label=$C_2$] (p8) to[short,-*] (opamp2.out)

    (opamp3.-) ++(0,1.5) coordinate (p9) {}
    (p9) ++ (5,0) coordinate (p9') {}
    ($(p9)!(opamp3.out)!(p9')$) coordinate (p10) {}
    (opamp3.-) to[short,*-] (p9) to[R,-*,label=$R_5$] (p10)
    ;
\end{circuitikz}
\end{document}

画像のランキング付け

写真を撮影した際、似たような写真がたくさんあって一番いいのはどれか悩んだことがあった。 ランダムに2枚並べて表示し、どちらの方がより良いか選択していけば良い写真を選択できると思い、 pythonで簡単に作成した。

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
        QApplication, QWidget, QLabel, QHBoxLayout, QVBoxLayout,
        QGraphicsView, QGraphicsScene, QGraphicsItem
        )
from PyQt5.QtGui import (QPixmap)
import glob
import random
import csv

imgPath = './data/Resize/*.PNG'
dataPath = './result.csv'

class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        self.title = 'Image rank'
        self.initUI()
        self.left = 50
        self.top = 50
        self.width = 1200
        self.height = 480
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)
        self.getImgList()
        self.setNextPix()
    def initUI(self):
        print("initUI")
        self.view1 = QGraphicsView()
        self.scene1 = QGraphicsScene(self.view1)
        self.view1.setScene(self.scene1)
        self.label1 = QLabel("Label1")

        self.view2 = QGraphicsView()
        self.scene2 = QGraphicsScene(self.view2)
        self.view2.setScene(self.scene2)
        self.label2 = QLabel("Label2")

        self.hlayout = QHBoxLayout()
        self.vlayout1 = QVBoxLayout()
        self.vlayout2 = QVBoxLayout()
        self.vlayout1.addWidget(self.view1)
        self.vlayout1.addWidget(self.label1)
        self.vlayout2.addWidget(self.view2)
        self.vlayout2.addWidget(self.label2)
        self.hlayout.addLayout(self.vlayout1)
        self.hlayout.addLayout(self.vlayout2)
        self.setLayout(self.hlayout)
        self.show()

    def resizeEvent(self, e):
        self.resizeView()

    def resizeView(self):
        self.view1.fitInView(self.scene1.sceneRect(), Qt.KeepAspectRatio)
        self.view2.fitInView(self.scene2.sceneRect(), Qt.KeepAspectRatio)

    def getImgList(self):
        self.imgFiles = glob.glob(imgPath)
        if(len(self.imgFiles)<2):
            print("can't compare")
            exit()
        self.ranking = []
        for i in range(0, len(self.imgFiles)):
            self.ranking.append( [0, self.imgFiles[i]] )
        #print(self.ranking)

    def setNextPix(self):
        while True:
            self.n1 = random.randint(0,len(self.imgFiles)-1)
            self.n2 = random.randint(0,len(self.imgFiles)-1)
            if self.n1 != self.n2:
                break
        #print(self.n1,self.imgFiles[self.n1],self.n2,self.imgFiles[self.n2])
        self.scene1.clear()
        self.pixmap1 = QPixmap(self.imgFiles[self.n1])
        self.scene1.addPixmap(self.pixmap1)
        self.label1.setText(self.imgFiles[self.n1])
        self.scene2.clear()
        self.pixmap2 = QPixmap(self.imgFiles[self.n2])
        self.scene2.addPixmap(self.pixmap2)
        self.label2.setText(self.imgFiles[self.n2])
        self.resizeView()

    def keyPressEvent(self, e):
        if( e.key() == Qt.Key_Q ):
            self.ranking.sort(key=lambda x:x[0], reverse=True)
            with open(dataPath, 'w') as f:
                writer = csv.writer(f, lineterminator='\n')
                writer.writerows(self.ranking)
            self.close()

        if( e.key() == Qt.Key_H or e.key() == Qt.Key_L or e.key() == Qt.Key_M):
            if( e.key() == Qt.Key_H ): # left
                self.ranking[self.n1][0] += 1
            if( e.key() == Qt.Key_L ): # right
                self.ranking[self.n2][0] += 1
            self.setNextPix()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    print("create MainWindow")
    main_window = MainWindow()
    print("exec")
    sys.exit(app.exec_())

matplotlib で画像を保存

matplotlib で作成したグラフを保存する。

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

N = 256
n = np.linspace(0,N,N,False)
#w = 2*np.pi*n/(N-1)
w = 2*np.pi*n/N
# 7 term Blackman-Harris
window = (
        0.27105140069342
        -0.43329793923448*np.cos(w)
        +0.21812299954311*np.cos(2*w)
        -0.06592544638803*np.cos(3*w)
        +0.01081174209837*np.cos(4*w)
        -0.00077658482522*np.cos(5*w)
        +0.00001388721735*np.cos(6*w)
        )

# グラフのサイズを指定(1in=2.54cm)
fig = plt.figure(figsize=(8,2))
ax = fig.gca()
ax.set_xlim((0,2*np.pi))
ax.set_xticks(np.linspace(0, 2*np.pi, 11))
ax.set_xticklabels(["{0:.1f}$\pi$".format(x/np.pi) for x in ax.get_xticks()])
ax.set_xlabel("Phase [rad]")
ax.set_ylim((0,1))
ax.set_yticks([y for y in np.linspace(0, 1, 11)])
ax.set_ylabel("coefficient")
ax.minorticks_on()
ax.tick_params(which='both', direction='in', color="#3333ee", labelcolor="#000000", zorder=1.8)
ax.grid(True,which='major')
ax.fill( w, window, zorder=2 )
fig.savefig("figure.svg", dpi=300, facecolor='None', edgecolor='None', transparent=True, format="svg")
# pdf,ps,rgba,pgf,svgz,svg,raw,eps,png

f:id:takecccc:20170223005819p:plain

ついでに EMF がほしい場合は Inkscape を使って SVG から変換可能。

d.hatena.ne.jp

for %%A in (%*) do "C:\Program Files\Inkscape\inkscape.exe" -z -f %%A --export-emf %%~dpnA.emf

python内から呼び出す場合は

import numpy as np
import matplotlib
import matplotlib.pyplot as plt
import subprocess

N = 256
filename = "figure.svg"
n = np.linspace(0,N,N,False)
#w = 2*np.pi*n/(N-1)
w = 2*np.pi*n/N
# 7 term Blackman-Harris
window = (
        0.27105140069342
        -0.43329793923448*np.cos(w)
        +0.21812299954311*np.cos(2*w)
        -0.06592544638803*np.cos(3*w)
        +0.01081174209837*np.cos(4*w)
        -0.00077658482522*np.cos(5*w)
        +0.00001388721735*np.cos(6*w)
        )

# グラフのサイズを指定(1in=2.54cm)
fig = plt.figure(figsize=(8,2))
ax = fig.gca()
ax.set_xlim((0,2*np.pi))
ax.set_xticks(np.linspace(0, 2*np.pi, 11))
ax.set_xticklabels(["{0:.1f}$\pi$".format(x/np.pi) for x in ax.get_xticks()])
ax.set_xlabel("Phase [rad]")
ax.set_ylim((0,1))
ax.set_yticks([y for y in np.linspace(0, 1, 11)])
ax.set_ylabel("coefficient")
ax.minorticks_on()
ax.tick_params(which='both', direction='in', color="#3333ee", labelcolor="#000000", zorder=1.8)
ax.grid(True,which='major')
ax.fill( w, window, zorder=2 )
fig.savefig(filename, dpi=300, facecolor='None', edgecolor='None', transparent=True)
# pdf,ps,rgba,pgf,svgz,svg,raw,eps,png

subprocess.call('"C:\Program Files\Inkscape\inkscape.exe" -z -f '+filename+' --export-emf '+filename+'.emf', shell=True)

pythonでCSVファイルのプロット

CSVファイルからグラフをプロットする際にpythonは便利である。 グラフ描画用パッケージmatplotlibと数値計算パッケージnumpyを用いる。

CSVから numpy.loadtxt で ndarray として読み込む。

numpy.loadtxt — NumPy v1.12 Manual

次のようなファイルがある場合

0,0.000000e+00,0.000000,+0.00000000,0
1,1.000000e+00,1.000000,+0.38268343,0.146447
2,2.000000e+00,4.000000,+0.70710678,0.5
3,3.000000e+00,9.000000,+0.92387953,0.853553
4,4.000000e+00,16.000000,+1.00000000,1
5,5.000000e+00,25.000000,+0.92387953,0.853553
6,6.000000e+00,36.000000,+0.70710678,0.5
7,7.000000e+00,49.000000,+0.38268343,0.146447
8,8.000000e+00,64.000000,+0.00000000,1.49976e-32
9,9.000000e+00,81.000000,-0.38268343,0.146447
10,1.000000e+01,100.000000,-0.70710678,0.5
11,1.100000e+01,121.000000,-0.92387953,0.853553
12,1.200000e+01,144.000000,-1.00000000,1
13,1.300000e+01,169.000000,-0.92387953,0.853553
14,1.400000e+01,196.000000,-0.70710678,0.5
15,1.500000e+01,225.000000,-0.38268343,0.146447
import numpy as np
import matplotlib.pyplot as plt

data = np.loadtxt("data.csv", delimiter=",", usecols=(0,3))
print(data)

plt.plot(data[:,0],data[:,1])
plt.show()

f:id:takecccc:20170222220600p:plain

ただし、次のように日本語等が含まれている場合

#latin-1で表せない文字を含む場合
0,0.000000e+00,0.000000,+0.00000000,0
1,1.000000e+00,1.000000,+0.38268343,0.146447
2,2.000000e+00,4.000000,+0.70710678,0.5
3,3.000000e+00,9.000000,+0.92387953,0.853553
4,4.000000e+00,16.000000,+1.00000000,1
5,5.000000e+00,25.000000,+0.92387953,0.853553
6,6.000000e+00,36.000000,+0.70710678,0.5
7,7.000000e+00,49.000000,+0.38268343,0.146447
8,8.000000e+00,64.000000,+0.00000000,1.49976e-32
9,9.000000e+00,81.000000,-0.38268343,0.146447
10,1.000000e+01,100.000000,-0.70710678,0.5
11,1.100000e+01,121.000000,-0.92387953,0.853553
12,1.200000e+01,144.000000,-1.00000000,1
13,1.300000e+01,169.000000,-0.92387953,0.853553
14,1.400000e+01,196.000000,-0.70710678,0.5
15,1.500000e+01,225.000000,-0.38268343,0.146447
UnicodeDecodeError: 'cp932' codec can't decode byte 0x84 in position 22: illegal multibyte sequence

といったエラーが発生する。 日本語等を無視して読み込みたい場合は

import numpy as np
import matplotlib.pyplot as plt

with open("data_jp.csv", "rb") as f:
    data = np.loadtxt(f, delimiter=",", usecols=(0,3))
print(data)

plt.plot(data[:,0],data[:,1])
plt.show()

と一度バイナリファイルとして開くと読み込める。

PythonでCSVファイルを保存

numpyで計算した値をCSVファイルに保存したい場合 numpy.savetxt が便利 numpy.savetxt — NumPy v1.12 Manual

ただし、日本語等 latin-1 で表せない文字列は保存できない。

import numpy as np

N = 16
x = np.linspace(0,N,N,False)
y0 = x
y1 = x**2
y2 = np.sin(2*np.pi*x/N)
y3 = np.sin(2*np.pi*x/N)**2
savedata = np.c_[x,y0,y1,y2,y3]
print(savedata)

np.savetxt("data1.csv", savedata, fmt='%d,%e,%f,%+02.8f,%g')
np.savetxt("data2.csv",savedata,
    delimiter=',',
    newline='\r\n',
    header='x x x^2 sin(x) sin(x)^2')
0,0.000000e+00,0.000000,+0.00000000,0
1,1.000000e+00,1.000000,+0.38268343,0.146447
2,2.000000e+00,4.000000,+0.70710678,0.5
3,3.000000e+00,9.000000,+0.92387953,0.853553
4,4.000000e+00,16.000000,+1.00000000,1
5,5.000000e+00,25.000000,+0.92387953,0.853553
6,6.000000e+00,36.000000,+0.70710678,0.5
7,7.000000e+00,49.000000,+0.38268343,0.146447
8,8.000000e+00,64.000000,+0.00000000,1.49976e-32
9,9.000000e+00,81.000000,-0.38268343,0.146447
10,1.000000e+01,100.000000,-0.70710678,0.5
11,1.100000e+01,121.000000,-0.92387953,0.853553
12,1.200000e+01,144.000000,-1.00000000,1
13,1.300000e+01,169.000000,-0.92387953,0.853553
14,1.400000e+01,196.000000,-0.70710678,0.5
15,1.500000e+01,225.000000,-0.38268343,0.146447
# x x x^2 sin(x) sin(x)^2
0.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00,0.000000000000000000e+00
1.000000000000000000e+00,1.000000000000000000e+00,1.000000000000000000e+00,3.826834323650897818e-01,1.464466094067262414e-01
2.000000000000000000e+00,2.000000000000000000e+00,4.000000000000000000e+00,7.071067811865475727e-01,5.000000000000001110e-01
3.000000000000000000e+00,3.000000000000000000e+00,9.000000000000000000e+00,9.238795325112867385e-01,8.535533905932737309e-01
4.000000000000000000e+00,4.000000000000000000e+00,1.600000000000000000e+01,1.000000000000000000e+00,1.000000000000000000e+00
5.000000000000000000e+00,5.000000000000000000e+00,2.500000000000000000e+01,9.238795325112867385e-01,8.535533905932737309e-01
6.000000000000000000e+00,6.000000000000000000e+00,3.600000000000000000e+01,7.071067811865475727e-01,5.000000000000001110e-01
7.000000000000000000e+00,7.000000000000000000e+00,4.900000000000000000e+01,3.826834323650898928e-01,1.464466094067263247e-01
8.000000000000000000e+00,8.000000000000000000e+00,6.400000000000000000e+01,1.224646799147353207e-16,1.499759782661857608e-32
9.000000000000000000e+00,9.000000000000000000e+00,8.100000000000000000e+01,-3.826834323650896152e-01,1.464466094067261304e-01
1.000000000000000000e+01,1.000000000000000000e+01,1.000000000000000000e+02,-7.071067811865474617e-01,4.999999999999998890e-01
1.100000000000000000e+01,1.100000000000000000e+01,1.210000000000000000e+02,-9.238795325112865164e-01,8.535533905932732868e-01
1.200000000000000000e+01,1.200000000000000000e+01,1.440000000000000000e+02,-1.000000000000000000e+00,1.000000000000000000e+00
1.300000000000000000e+01,1.300000000000000000e+01,1.690000000000000000e+02,-9.238795325112866275e-01,8.535533905932735088e-01
1.400000000000000000e+01,1.400000000000000000e+01,1.960000000000000000e+02,-7.071067811865476838e-01,5.000000000000002220e-01
1.500000000000000000e+01,1.500000000000000000e+01,2.250000000000000000e+02,-3.826834323650903924e-01,1.464466094067267132e-01