def test_filelist(self): test_oect = oect.OECT(folder='tests/test_device/01') test_oect.filelist() assert (os.path.join('tests/test_device/01', 'uc1_kpf6_output_0.txt') in test_oect.files and os.path.join('tests/test_device/01', 'uc1_kpf6_output_1.txt') in test_oect.files and os.path.join('tests/test_device/01', 'uc1_kpf6_transfer_0.txt') in test_oect.files and test_oect.config[0] == os.path.join('tests/test_device/01', 'uc1_kpf6_config.cfg'))
def test_get_metadata(self): test_oect = oect.OECT(folder=os.getcwd()) test_file = 'tests/test_device/metadata_test/uc1_kpf6_output_0.txt' test_oect.get_metadata(test_file) assert (test_oect.Vg == -.5 and test_oect.W == 2000 and test_oect.L == 20)
def test_get_metadata_no_config(self): test_oect = oect.OECT(folder='tests/test_device/metadata_test') test_oect.make_config = True test_file = 'tests/test_device/metadata_test/uc1_kpf6_output_0.txt' test_oect.get_metadata(test_file) assert (test_oect.Vg == -.5 and test_oect.W == 4000 and test_oect.L == 10)
def test_filelist_noconfig(self): test_oect = oect.OECT(folder='tests/test_device/no_config') config_check = 'config.cfg' in os.listdir('tests/test_device/no_config') try: os.remove('tests/test_device/no_config/config.cfg') except: pass assert config_check
def test_set_params_defaults(self): test_oect = oect.OECT(folder=os.getcwd()) test_oect.set_params({}, {}, {}, {}) #try defaults assert (test_oect.options['gm_method'] == 'sg' and test_oect.options['Reverse'] == True and test_oect.options['Average'] == False and test_oect.options['V_low'] == False and test_oect.options['overwrite'] == False)
def loadOECT(path, dimDict, params=None, gm_plot=True, plot=True, options={}, verbose=True, text_browser=None): """ Wrapper function for processing OECT data params = {W: , L: , d: } for W, L, d of device USAGE: device1 = loadOECT(folder_name) """ if not path: path = file_open(caption='Select device subfolder') device = oect.OECT(path, dimDict, params, options) device.calc_gms() device.thresh() scaling = device.WdL # W *d / L if verbose: for key in device.gms: print( key, ': {:.2f}'.format( np.max(device.gms[key].values * 1e-2) / scaling), 'S/cm scaled') print(key, ': {:.2f}'.format(np.max(device.gms[key].values * 1000)), 'mS max') if (text_browser): text_browser.append(key + str(': {:.2f}'.format( np.max(device.gms[key].values * 1e-2) / scaling)) + 'S/cm scaled') text_browser.append(key + str(': {:.2f}'.format( np.max(device.gms[key].values * 1000))) + 'mS max') if plot: fig = oect_plot.plot_transfers_gm(device, gm_plot=gm_plot, leakage=True) fig.savefig(path + r'\transfer_leakage.tif', format='tiff') fig = oect_plot.plot_transfers_gm(device, gm_plot=gm_plot, leakage=False) fig.savefig(path + r'\transfer.tif', format='tiff') fig = oect_plot.plot_outputs(device, leakage=True) fig.savefig(path + r'\output_leakage.tif', format='tiff') fig = oect_plot.plot_outputs(device, leakage=False) fig.savefig(path + r'\output.tif', format='tiff') return device
def test_set_params(self): test_oect = oect.OECT(folder='tests/test_device/01') #called in init assert (test_oect.params['W'] == 4000.0 and test_oect.params['L'] == 20.0 and test_oect.params['d'] == 4e-8 and test_oect.params['Preread (ms)'] == 20000 and test_oect.params['First Bias (ms)'] == 120000 and test_oect.params['Vds (V)'] == 0 and test_oect.params['output_Preread (ms)'] == 5000 and test_oect.params['output_First Bias (ms)'] == 200 and test_oect.params['Output Vgs'] == 2 and test_oect.params['Vgs'] == [-0.5, -0.8])
def test_update_config(self): test_oect = oect.OECT(folder='tests/test_device/no_config') #config will be auto generated in init #default config will be made with values: # [Dimensions] # Width (um) = 2000 # Length (um) = 20 # [Transfer] # Preread (ms) = 30000.0 # First Bias (ms) = 120000.0 # Vds (V) = -0.6 # [Output] # Preread (ms) = 500.0 # First Bias (ms) = 200.0 # Output Vgs = 4 # Vgs (V) 0 = -0.1 # Vgs (V) 1 = -0.3 # Vgs (V) 2 = -0.5 # Vgs (V) 3 = -0.9 test_oect.W = 4000 test_oect.L = 10 test_oect.Vd = -1 test_oect.Vg_array = [0, .1, .2, .3, .4] test_oect.update_config() config = configparser.ConfigParser() config.read(test_oect.config) assert (config['Dimensions']['Width (um)'] == '4000' and config['Dimensions']['Length (um)'] == '10' and config['Transfer']['Vds (V)'] == '-1' and config['Output']['Preread (ms)'] == '500.0' and config['Output']['First Bias (ms)'] == '200.0' and config['Output']['Vgs (V) 0'] == '0' and config['Output']['Vgs (V) 1'] == '0.1' and config['Output']['Vgs (V) 2'] == '0.2' and config['Output']['Vgs (V) 3'] == '0.3' and config['Output']['Vgs (V) 4'] == '0.4') try: os.remove('tests/test_device/no_config/config.cfg') except: pass
def test_reverse_with_sweep(self): test_oect = oect.OECT(folder=os.getcwd()) a = np.arange(start=-1, stop=1.1, step=.1) b = np.arange(start=.9, stop=-1.1, step=-.1) v = np.concatenate((a, b)) assert len(v) // 2, True == test_oect._reverse(v)
import os import sys import pytest import configparser import numpy as np sys.path.insert(0, '..') import oect test_oect = oect.OECT(folder='test_device/no_config') print(os.path.isfile(os.path.join('test_device/no_config', 'config.cfg')))
def test_output_curve_wrong_col_names(self): test_oect = oect.OECT(folder=os.getcwd()) with pytest.raises(KeyError): test_file = 'tests/test_device/01/uc1_kpf6_output_0.txt' test_oect.get_metadata(test_file) test_oect.transfer_curve(test_file)
def test_set_params_not_dict(self): test_oect = oect.OECT(folder=os.getcwd()) with pytest.raises(IndexError) or pytest.raises(TypeError): test_oect.set_params([1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5], [1, 2, 3, 4, 5])
def test_all_outputs(self): test_oect = oect.OECT(folder='tests/test_device/01') #called in init assert test_oect.num_outputs == 4
def test_set_params_add(self): test_oect = oect.OECT(folder='tests/test_device/01', params={'test_param1': 100}, options={'test_option1': 200}) assert (test_oect.params['test_param1'] == 100 and test_oect.options['test_option1'] == 200)
def test_set_opts(self): test_oect = oect.OECT(folder='tests/test_device/options_test') #called in init assert (test_oect.options['Reverse'] == True and test_oect.options['Average'] == False and test_oect.options['gm_method'] == 'method' and test_oect.options['V_low'] == 10)
def average(dimDict={}, path='', thickness=40e-9, plot=True, text_browser=None): ''' averages data in this particular path (for folders 'avg') path: str string path to folder '.../avg'. Note Windows path are of form r'Path_name' thickness : float approximate film thickness. Standard polymers (for Raj) are ~40 nm plot : bool Whether to plot or not. Not plotting is very fast! Returns ------- pixels : dict of OECT Contains the various OECT class devices Id_Vg : pandas dataframe Contains the averaged Id vs Vg (drain current vs gate voltage, transfer) Id_Vd : pandas dataframe Contains the averaged Id vs Vg (drain current vs drain voltages, output) ''' if not path: path = file_open(caption='Select avg subfolder') print('Loading from', path) filelist = os.listdir(path) # removes all but the folders in pixel_names f = filelist[:] for k in filelist: try: sub_num = int(k) except: print('Ignoring', k) f.remove(k) filelist = f[:] del f paths = [os.path.join(path, name) for name in filelist] # removes random files instead of the sub-folders for p in paths: if not os.path.isdir(p): paths.remove(p) pixels = {} # loads all the folders for p, f in zip(paths, filelist): dv = loadOECT(dimDict, p, params={'d': thickness}, gm_plot=plot, plot=plot, text_browser=text_browser) pixels[f] = dv # average Id-Vg Id_Vg = [] first_pxl = pixels[list(pixels.keys())[0]] for dv in pixels: if not any(Id_Vg): Id_Vg = pixels[dv].transfers.values else: Id_Vg += pixels[dv].transfers.values Id_Vg /= len(pixels) Id_Vg = pd.DataFrame(data=Id_Vg) try: Id_Vg = Id_Vg.set_index(first_pxl.transfers.index) except: Id_Vg = Id_Vg.set_index(pixels[list(pixels.keys())[-1]]) # find gm of the average temp_dv = oect.OECT(dimDict, paths[0], {'d': thickness}) _gm_fwd, _gm_bwd = temp_dv._calc_gm(Id_Vg) Id_Vg['gm_fwd'] = _gm_fwd if not _gm_bwd.empty: Id_Vg['gm_bwd'] = _gm_bwd Id_Vg = Id_Vg.rename(columns={0: 'Id average'}) # fix a naming bug if temp_dv.reverse: Id_Vg.reverse = True Id_Vg.rev_point = temp_dv.rev_point # average Id-Vd at max Vd Id_Vd = [] # finds column corresponding to lowest voltage (most doping), but these are strings idx = np.argmin(np.array([float(i) for i in first_pxl.outputs.columns])) volt = first_pxl.outputs.columns[idx] for dv in pixels: if not any(Id_Vd): Id_Vd = pixels[dv].outputs[volt].values else: Id_Vd += pixels[dv].outputs[volt].values Id_Vd /= len(pixels) Id_Vd = pd.DataFrame(data=Id_Vd) try: Id_Vd = Id_Vd.set_index(pixels[list( pixels.keys())[0]].outputs[volt].index) except: Id_Vd = Id_Vd.set_index(pixels[list( pixels.keys())[-1]].outputs[volt].index) if plot: fig = oect_plot.plot_transfer_avg(Id_Vg, temp_dv.WdL) fig.savefig(path + r'\transfer_avg.tif', format='tiff') fig = oect_plot.plot_output_avg(Id_Vd) fig.savefig(path + r'\output_avg.tif', format='tiff') return pixels, Id_Vg, Id_Vd, temp_dv.WdL
def test_reverse_no_sweep(self): test_oect = oect.OECT(folder=os.getcwd()) v = np.arange(start=-1, stop=.1, step=.1) assert len(v) // 2, False == test_oect._reverse(v)
def test_all_transfers(self): test_oect = oect.OECT(folder='tests/test_device/01') #called in init assert test_oect.num_transfers == 2
def test_all_outputs_append(self): test_oect = oect.OECT(folder='tests/test_device/01') #called in init test_oect.all_outputs() #call again assert test_oect.num_outputs == 8