TFTiv.py ダウンロード/コピー

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()