def main(): """Main function""" print "\nBatch importing .xlsx files..." print data_path, '\n' for f in files: print f # Loops through all transfer files if "IDVG.xlsx" in f: workbook = xlrd.open_workbook(f, logfile=open(os.devnull, 'w')) for dev in workbook.sheet_names(): if "Sheet" in dev: continue print " - device {:s}".format(dev) datasheet = workbook.sheet_by_name(dev) run_numbers = [str(int(x)) for x in datasheet.row_values(2) if x] for i, run in enumerate(run_numbers): print " - run {:s}".format(run) data = {} # File name for outputs outname = f[:-5] + '_' + dev + '_' + run # Constant parameters taken from header of .xlsx file vd1 = float(datasheet.cell_value(3, 6*i + 3)) vd2 = float(datasheet.cell_value(4, 6*i + 3)) chl = float(datasheet.cell_value(1, 1)) chw = float(datasheet.cell_value(0, 1)) tox = float(datasheet.cell_value(1, 3)) kox = float(datasheet.cell_value(0, 3)) ldr = float(datasheet.cell_value(1, 5)) lso = float(datasheet.cell_value(0, 5)) # Calculation of geometric capacitance ci = 8.85418782e-7*kox/tox # Extract data for h in colheads: data[h] = [] for row in range(datasheet.nrows - 9): for col, h in enumerate(colheads): if datasheet.cell_type(9 + row, 6*i + col) is 0: continue data[h].append(float(datasheet.cell_value(9 + row, 6*i + col))) p = len(data['VG'])/2 # Forward scan if sweepfwddirection: vg = np.array(data['VG'][:p]) id1 = np.array(data['ID1'][:p]) id2 = np.array(data['ID2'][:p]) ig1 = np.array(data['IG1'][:p]) ig2 = np.array(data['IG2'][:p]) else: vg = np.array(data['VG'][:p][::-1]) id1 = np.array(data['ID1'][:p][::-1]) id2 = np.array(data['ID2'][:p][::-1]) ig1 = np.array(data['IG1'][:p][::-1]) ig2 = np.array(data['IG2'][:p][::-1]) # Reverse scan if sweepfwddirection: vg_r = np.array(data['VG'][p:][::-1]) id1_r = np.array(data['ID1'][p:][::-1]) id2_r = np.array(data['ID2'][p:][::-1]) ig1_r = np.array(data['IG1'][p:][::-1]) ig2_r = np.array(data['IG2'][p:][::-1]) else: vg_r = np.array(data['VG'][p:]) id1_r = np.array(data['ID1'][p:]) id2_r = np.array(data['ID2'][p:]) ig1_r = np.array(data['IG1'][p:]) ig2_r = np.array(data['IG2'][p:]) # Smoothing Id for fitting id1_smoothed = mf.adjAvSmooth(abs(id1), N=1) id2_smoothed = mf.adjAvSmooth(abs(id2), N=1) id1_r_smoothed = mf.adjAvSmooth(abs(id1_r), N=1) id2_r_smoothed = mf.adjAvSmooth(abs(id2_r), N=1) # On-off ratio onoffratio1 = np.log10(max(id1[skipinit:-1])/min(abs(id1[skipinit:-1]))) onoffratio2 = np.log10(max(id2[skipinit:-1])/min(abs(id2[skipinit:-1]))) # Leakage ratio leakage_ratio1 = np.log10(abs(id1/ig1)) leakage_ratio2 = np.log10(abs(id2/ig2)) # Finding max saturation transconductance sqrtid2 = np.sqrt(id2_smoothed) sqrtid2_r = np.sqrt(id2_r_smoothed) diff_sqrt_id2_smoothed = np.array(mf.numDiff(sqrtid2, vg)) diff_sqrt_id2_r_smoothed = np.array(mf.numDiff(sqrtid2_r, vg_r)) tsmaxarg = np.argmax(diff_sqrt_id2_smoothed[skipinit:-1]) + skipinit tsmaxarg_r = np.argmax(diff_sqrt_id2_r_smoothed[skipinit:-1]) + skipinit # Saturation mobility (max transconductance) satmob_t = mobilitycorrection * (2*chl/(chw*ci))*(diff_sqrt_id2_smoothed)**2 satmob_r_t = mobilitycorrection * (2*chl/(chw*ci))*(diff_sqrt_id2_r_smoothed)**2 satmob_tmax = satmob_t[tsmaxarg] satmob_r_tmax = satmob_r_t[tsmaxarg_r] # Saturation threshold voltage (max transconductance) vthsat_tmax = vg[tsmaxarg] - sqrtid2[tsmaxarg]/diff_sqrt_id2_smoothed[tsmaxarg] vthsat_r_tmax = vg_r[tsmaxarg_r] - sqrtid2_r[tsmaxarg_r]/diff_sqrt_id2_r_smoothed[tsmaxarg_r] # Hysteresis hysteresissat = vthsat_tmax - vthsat_r_tmax # Calculate subthreshold slopes sts_sat = min(abs(1/np.array(mf.numDiff([np.log10(abs(x)) for x in id2_smoothed[skipinit:-1]], vg[skipinit:-1])))) sts_r_sat = min(abs(1/np.array(mf.numDiff([np.log10(abs(x)) for x in id2_r_smoothed[skipinit:-1]], vg_r[skipinit:-1])))) # Finding max linear transconductance diff_id1_smoothed = np.array(mf.numDiff(id1_smoothed, vg)) diff_id1_r_smoothed = np.array(mf.numDiff(id1_r_smoothed, vg_r)) tlmaxarg = np.argmax(diff_id1_smoothed[skipinit:-1]) + skipinit tlmaxarg_r = np.argmax(diff_id1_r_smoothed[skipinit:-1]) + skipinit # Linear mobility (max transconductance) linmob_t = mobilitycorrection * (chl/(chw*ci*vd1))*(diff_id1_smoothed) linmob_r_t = mobilitycorrection * (chl/(chw*ci*vd1))*(diff_id1_r_smoothed) linmob_tmax = linmob_t[tlmaxarg] linmob_r_tmax = linmob_r_t[tlmaxarg_r] # Linear threshold voltage (max transconductance) vthlin_tmax = vg[tlmaxarg] - id1_smoothed[tlmaxarg]/diff_id1_smoothed[tlmaxarg] vthlin_r_tmax = vg_r[tlmaxarg_r] - id1_r_smoothed[tlmaxarg_r]/diff_id1_r_smoothed[tlmaxarg_r] # Hysteresis hysteresislin = vthlin_tmax - vthlin_r_tmax # Calculate subthreshold slopes sts_lin = min(abs(1/np.array(mf.numDiff([np.log10(abs(x)) for x in id1_smoothed[skipinit:-1]], vg[skipinit:-1])))) sts_r_lin = min(abs(1/np.array(mf.numDiff([np.log10(abs(x)) for x in id1_r_smoothed[skipinit:-1]], vg_r[skipinit:-1])))) # Finds range of data that lies within the minimum+x% and the maximum-x% and also has a positive transconductance fitrange_id_lo = (1-rangefitbot/100.0)*min(sqrtid2[skipinit:-1]) + (rangefitbot/100.0)*max(sqrtid2[skipinit:-1]) fitrange_id_hi = (1-rangefittop/100.0)*max(sqrtid2[skipinit:-1]) + (rangefittop/100.0)*min(sqrtid2[skipinit:-1]) fitrange_bool = np.bitwise_and(np.bitwise_and(sqrtid2 > fitrange_id_lo, sqrtid2 < fitrange_id_hi), diff_sqrt_id2_smoothed > 0) # Checks that there are at least 3 data points to fit if sum(fitrange_bool) < 3: print " NOT ENOUGH DATA TO FIT" satmob_FITTED = np.nan vthsat_FITTED = np.nan r_value = np.nan else: # Linear Fitting to sqrt(Idrain) slope, intercept, r_value, p_value, std_err = stats.linregress(vg[fitrange_bool][skipinit:-1], sqrtid2[fitrange_bool][skipinit:-1]) fitline = slope*vg + intercept # Saturation mobility (from slope of sqrt(Idrain) fit) satmob_FITTED = mobilitycorrection * (2*chl/(chw*ci))*slope**2 # Threshold Voltage (from slope of sqrt(Idrain) fit) vthsat_FITTED = -intercept/slope # Plot sqrt(Isd) mf.quickPlot(outname+"_SQRTplot", data_path, [vg, sqrtid2, fitline], xlabel="VG [V]", ylabel="sqrt(Id) [A^0.5]", yrange=[0, 'auto']) # Output data data_summary.append([outname, satmob_tmax, vthsat_tmax, satmob_r_tmax, vthsat_r_tmax, linmob_tmax, vthlin_tmax, linmob_r_tmax, vthlin_r_tmax, hysteresislin, hysteresissat, onoffratio1, onoffratio2, leakage_ratio1[-skipinit], leakage_ratio2[-skipinit], sts_lin, sts_r_lin, sts_sat, sts_r_sat, satmob_FITTED, vthsat_FITTED, r_value**2]) # Ouput files mf.dataOutputHead(outname+"_transfer.txt", data_path, [np.array(data['VG']), abs(np.array(data['ID1'])), abs(np.array(data['ID2'])), abs(np.array(data['IG1'])), abs(np.array(data['IG2'])), np.concatenate((linmob_t, linmob_r_t[::-1])), np.concatenate((satmob_t, satmob_r_t[::-1]))], [["vg", "idlin", "idsat", "iglin", "igsat", "LINMOB", "SATMOB"]], format_d="%.3f\t %.5e\t %.5e\t %.5e\t %.5e\t %.5e\t %.5e\n", format_h="%s\t") # Plot transfer mf.quickPlot(outname+"_TRANSFERplot", data_path, [vg, id1_smoothed, id1_r_smoothed, abs(ig1), id2_smoothed, id2_r_smoothed, abs(ig2)], xlabel="VG [V]", ylabel="Id,g [A]", yscale="log", yrange=[1e-12, 1e-2], col=["r", "r", "r", "b", "b", "b"]) mf.dataOutputHead("SUMMARY.txt", data_path, map(list, zip(*data_summary)), summary_list_header, format_d="%s\t %.5e\t %.5f\t %.5e\t %.5f\t %.5e\t %.5f\t %.5e\t %.5f\t %.5f\t %.5f\t %.5f\t %.5f\t %.5f\t %.5f\t %.5f\t %.5f\t %.5f\t %.5f\t %.5e\t %.5f\t %.6f\n", format_h="%s\t") return
print "\n=================\n" r_list = np.log10(np.array(r_list)) # Takes log of resistances t_list = np.array(t_list) r_median = np.median(r_list) # Remove outliers that are an order of magnitude larger or smaller than the median r_list_trim = r_list[np.where((r_list < 10*r_median)&(r_list > 0.1*r_median))] # Compute means and standard errors r_av = np.mean(r_list_trim) r_stderr = np.std(r_list_trim)/np.sqrt(len(r_list_trim)) t_av = np.mean(t_list) t_stderr = np.std(t_list)/np.sqrt(len(t_list)) print "Median resistance: {:.4e}".format(r_median) print "Mean resistance: {:.4e} +/- {:.4e}".format(r_av, r_stderr) print "Mean transmission: {:.3f} +/- {:.3f}".format(t_av, t_stderr) print "\n=================\n" summary_list.append(["output_{:05d}".format(runnumber), nwlength, nwlength_sd, nwdiameter, agresistivity, nwresistance, nwanglekappa, nwdensity[l1], nwn, nwi, matrixrsheet, r_av, r_median, r_stderr, t_av, t_stderr]) mf.dataOutputHead("SUMMARY_{:d}.txt".format(int(time.time())), path, map(list, zip(*summary_list)), summary_list_header, format_d="%s\t %.3f\t %.3f\t %.4f\t %.3e\t %.4e\t %.3f\t %.4f\t %i\t %.3f\t %.3e\t %.4e\t %.4e\t %.4e\t %.3f\t %.3f\n", format_h="%s\t") print "DONE"
def main(): """Main function""" print "\nBatch importing .xlsx files..." print data_path, '\n' for f in files: print f # Loops through all transfer files if "IDVD.xlsx" in f: workbook = xlrd.open_workbook(f, logfile=open(os.devnull, 'w')) for dev in workbook.sheet_names(): if "Sheet" in dev: continue print " - device {:s}".format(dev) datasheet = workbook.sheet_by_name(dev) run_numbers = [str(int(x)) for x in datasheet.row_values(2) if x] stepvg = 0 for i, run in enumerate(run_numbers): print " - run {:s}".format(run) data = {} gdlin = [] gdsat = [] vg_list = [] # File name for outputs outname = f[:-5] + '_' + dev + '_' + run # Constant parameters taken from header vgmin = float(datasheet.cell_value(3, (stepvg + 2)*i + 1)) vgmax = float(datasheet.cell_value(4, (stepvg + 2)*i + 1)) stepvg_prev = stepvg stepvg = int(datasheet.cell_value(5, (stepvg + 2)*i + 1)) chl = float(datasheet.cell_value(1, 1)) chw = float(datasheet.cell_value(0, 1)) tox = float(datasheet.cell_value(1, 3)) kox = float(datasheet.cell_value(0, 3)) ldr = float(datasheet.cell_value(1, 5)) lso = float(datasheet.cell_value(0, 5)) ci = 8.85418782e-7*kox/tox colheads = ['VDS'] + ["ID{:d}".format(x + 1) for x in range(stepvg)] for h in colheads: data[h] = [] for row in range(datasheet.nrows - 11 - stepvg): for col, h in enumerate(colheads): if datasheet.cell_type(9 + row, (stepvg_prev + 2)*i + col) is 0: continue data[h].append(float(datasheet.cell_value(9 + row, (stepvg_prev + 2)*i + col))) vds = np.array(data['VDS']) output_list = [vds] for j in range(stepvg): ids = np.array(data["ID{:d}".format(j + 1)]) # Fits to first data points (given by fitrange) i.e. linear slope, intercept, r_value, p_value, std_err = stats.linregress(vds[:fitrange], ids[:fitrange]) gdlin.append(slope) # Fits to last data points (given by fitrange) i.e. saturation slope, intercept, r_value, p_value, std_err = stats.linregress(vds[-fitrange:], ids[-fitrange:]) gdsat.append(slope) # Update lists output_list.append(ids) vg_list.append(vgmin + j*(vgmax-vgmin)/(stepvg-1)) # Output data data_summary.append([outname, chl, chw]) # Ouput files mf.dataOutputGen(outname+"_output.txt", data_path, map(list, zip(*output_list))) mf.dataOutputHead(outname+"_gm.txt", data_path, [vg_list, gdlin, gdsat], [['VG', 'GDlin', 'GDsat']], format_d="%.2f\t %.5e\t %.5e\n", format_h="%s\t") mf.dataOutputHead("SUMMARY_OUT.txt", data_path, map(list, zip(*data_summary)), summary_list_header, format_d="%s\t %.1f\t %.1f\n", format_h="%s\t") return