TFTiv.py ダウンロード/コピー
TFTiv.py
TFTiv.py
1import sys
2import re
3import numpy as np
4from numpy import sqrt, exp, sin, cos, tan, pi
5import numpy.linalg as LA
6import csv
7from matplotlib import pyplot as plt
8
9
10"""
11TFTのIds-Vgs-Vdsデータから飽和移動度を求める
12"""
13
14#===================================
15# physical constants
16#===================================
17pi = 3.14159265358979323846
18pi2 = 2.0 * pi
19h = 6.6260755e-34 # Js";
20hbar = 1.05459e-34 # "Js";
21c = 2.99792458e8 # m/s";
22e = 1.60218e-19 # C";
23e0 = 8.854418782e-12; # C<sup>2</sup>N<sup>-1</sup>m<sup>-2</sup>";
24kB = 1.380658e-23 # JK<sup>-1</sup>";
25me = 9.1093897e-31 # kg";
26R = 8.314462618 # J/K/mol
27a0 = 5.29177e-11 # m";
28
29
30#===================================
31# parameters
32#===================================
33infile = 'TransferCurve.csv'
34
35dg = 100.0e-9 # m
36erg = 11.9
37
38W = 300.0e-6 # m
39L = 50.0e-6
40
41Vds0 = 10.0 # V
42xfitmin = 1.90 # V
43xfitmax = 10.0
44
45#===================================
46# figure configuration
47#===================================
48fontsize = 12
49legend_fontsize = 6
50
51
52#=============================
53# other functions
54#=============================
55# 余計な文字が含まれている文字列から、
56# 浮動小数点に変換できる最初の文字列を切り出し、
57# 浮動小数点に変換して返す
58def pfloat(str, defval = None):
59# 文字列から、浮動小数点に使える文字が連続している部分を切り出す
60 m = re.search(r'([+\-eE\d\.]+)', str)
61# print("str, m=", str, m)
62# 一致した文字列を取得
63 valstr = m.group()
64 try:
65 return float(valstr)
66 except:
67 return defval
68
69def savecsv(outfile, header, datalist):
70 try:
71 print("Write to [{}]".format(outfile))
72 f = open(outfile, 'w')
73 except:
74# except IOError:
75 print("Error: Can not write to [{}]".format(outfile))
76 else:
77 fout = csv.writer(f, lineterminator='\n')
78 fout.writerow(header)
79# fout.writerows(data)
80 for i in range(0, len(datalist[0])):
81 a = []
82 for j in range(len(datalist)):
83 a.append(datalist[j][i])
84 fout.writerow(a)
85 f.close()
86
87def read_csv(fname):
88 print("")
89 with open(fname) as f:
90 fin = csv.reader(f)
91
92 labels = next(fin)
93 xlabel = labels[0]
94
95# label行が 空文字 の場合、データとしては読み込まない
96 ylabels = []
97 for i in range(1, len(labels)):
98 if labels[i] == '':
99 break
100 ylabels.append(labels[i])
101 ny = len(ylabels)
102# print("xlabel: ", xlabel)
103# print("ylabels: ", ylabels)
104# print("ny=", ny)
105
106 x = []
107 ylist = []
108 for i in range(ny):
109 ylist.append([])
110
111 for row in fin:
112 x.append(pfloat(row[0]))
113 for i in range(1, ny+1):
114 v = pfloat(row[i])
115 if v is not None:
116 ylist[i-1].append(v)
117 else:
118 ylist[i-1].append(None)
119
120 return xlabel, ylabels, x, ylist
121
122
123def main():
124 Cox = erg * e0 / dg #(F/m^2)
125 print("")
126 print("Cox = {:12.6g} [F/m^2]".format(Cox))
127
128 xlabel, ylabels, Vgs, IdsVgs = read_csv(infile)
129 nVgs = len(IdsVgs[0])
130 nVds = len(ylabels)
131 Vds = []
132 for i in range(nVds):
133 Vds.append(pfloat(ylabels[i]))
134 print("")
135 print("nVds=", nVds)
136 print("nVgs=", nVgs)
137 print("xlabel : ", xlabel)
138 print("ylabels: ", ylabels)
139 print("Vds: ", Vds)
140# for i in range(len(Idslist)):
141# print("")
142# print("Idslist[{}]: {}".format(i, Idslist[i]))
143
144# 出力特性 Ids - Vds をプロットするためのデータを作る
145 IdsVds = np.empty([nVgs, nVds])
146 for ig in range(nVgs):
147 for id in range(nVds):
148 IdsVds[ig][id] = IdsVgs[id][ig]
149
150# sqrt(Ids) - Vgsプロットをする Vds0 のデータ番号 iVds を探す
151# Vds[i] が小さい方から順に、Vds0 <= Vds[i] となる i を探すが、
152# 浮動小数点誤差があることを考慮し、Vds0 - 1.0e-3 <= Vds[i] とする
153 for i in range(nVds):
154 if Vds0 - 1.0e-3 <= Vds[i]:
155 iVds = i
156 break
157
158# sqrt(Ids) データを作る
159 print("")
160 print("Vds used: {} V (iVds = {})".format(Vds[iVds], iVds))
161 sqrtIds = []
162 for ig in range(nVgs):
163 sqrtIds.append(sqrt(IdsVgs[iVds][ig]))
164# print("sqrtIds=",sqrtIds)
165
166# 最小二乗法のデータ
167 xfit = []
168 yfit = []
169 for i in range(nVgs):
170 if xfitmin <= Vgs[i] <= xfitmax:
171 xfit.append(Vgs[i])
172 yfit.append(sqrtIds[i])
173 print("")
174 print("Least squares fitting:")
175 print("Vgs range: {} - {} V".format(xfitmin, xfitmax))
176 print("Vgs=", xfit)
177 print("Igs^(1/2)=", yfit)
178 ai = np.polyfit(xfit, yfit, 1)
179# y = ai[1] + ai[0]x
180# Vth = ai[1] / ai[0]
181 Vth = -ai[1] / ai[0]
182 grad = ai[0]
183 mu = grad * grad / (W * Cox / 2.0 / L)
184 print("Vth = {:6.4g} V".format(Vth))
185 print("dIgs^1/2/dVgs = {:12.4g} A^(1/2)/V".format(grad))
186 print("mu_sat = {} m^2/Vs = {} cm^2/Vs".format(mu, 1.0e4 * mu))
187
188 xcal = []
189 ycal = []
190 xx = xfitmin - 0.5
191 xcal.append(xx)
192 ycal.append(ai[1] + ai[0] * xx)
193 xx = max(Vgs)
194 xcal.append(xx)
195 ycal.append(ai[1] + ai[0] * xx)
196
197 print("")
198 print("plot")
199 fig = plt.figure(figsize = (12, 4))
200 ax1 = fig.add_subplot(1, 3, 1)
201 ax2 = fig.add_subplot(1, 3, 2)
202 ax3 = fig.add_subplot(1, 3, 3)
203
204# 伝達特性 Ids-Vgs のグラフ
205 for id in range(nVds):
206 ax1.plot(Vgs, IdsVgs[id], linewidth = 0.5, marker = 'o', markersize = 0.5,
207 label = 'Vds={} V'.format(Vds[id]))
208 for id in range(nVds):
209 ax1.plot(Vgs, IdsVgs[id], linewidth = 0.5, marker = 'o', markersize = 0.5,
210 label = 'Vds={} V'.format(Vds[id]))
211 ax1.set_xlabel('Vgs (V)')
212 ax1.set_ylabel("Ids (A)")
213 ax1.set_yscale('log')
214# ax1.set_xlim([-0.5, 0.5])
215# ax1.set_ylim([0.0, 0.5])
216 ax1.legend(loc = 'upper left', fontsize = legend_fontsize)
217
218# 出力特性 Ids-Vds のグラフ
219# 20点の Vgs を選び、そのうち、線形でIdsが見えるデータのみ表示する
220 nskip = int(nVgs / 20.0 + 1.0e-6)
221 for ig in range(0, nVgs, nskip):
222# 線形プロットで見えないほどIdsが小さいデータは表示しない
223 if max(IdsVds[ig]) < 1.0e-7:
224 continue
225 ax2.plot(Vds, IdsVds[ig], linewidth = 0.5, marker = 'o', markersize = 0.5,
226 label = 'Vgs={} V'.format(Vgs[ig]))
227 ax2.set_xlabel('Vds (V)')
228 ax2.set_ylabel("Ids (A)")
229# ax2.set_xlim([-0.5, 0.5])
230# ax2.set_ylim([0.0, 0.5])
231 ax2.legend(loc = 'upper left', fontsize = legend_fontsize)
232
233# Ids^(1/2) - Vgs グラフ
234 ax3.plot(Vgs, sqrtIds, linestyle = 'none', marker = 'o', markersize = 0.5)
235 ax3.plot(xcal, ycal, linestyle = '-', linewidth = 0.5)
236 ax3.set_xlabel('Vgs (V)')
237 ax3.set_ylabel("Ids$^{1/2}$ (A$^{1/2}$)")
238# ax2.set_xlim([-0.5, 0.5])
239# ax2.set_ylim([0.0, 0.5])
240# ax3.legend(loc = 'upper left', fontsize = legend_fontsize)
241
242 plt.tight_layout()
243
244 plt.pause(0.1)
245 print("Press ENTER to exit>>", end = '')
246 input()
247
248
249if (__name__ == '__main__'):
250 main()