def mplot_ANU(ax, fnames, path='', labels='', colors='', corr=False, shiftup=0, plot=True, xvar='eV', norm=False, logy=True, eps=False, cutoffs=(0, -1)): # prepare the ground if path != 'current': path_full = genSZ.device() + path elif path == 'current': path = Path().absolute() path_ori = Path().absolute() os.chdir(path_full) num_files = len(fnames) if labels == '': # make labels the filenames, if no labels labels = [] for f in fnames: labels.append(os.path.splitext(f)[0]) if colors == '' or colors == 1: # the colours feature colorRev = False colors = [ None ] * num_files # so that the plotting section doesn't throw an error elif colors == -1: colorRev = True colors = [None] * num_files elif type(colors) == list: colorRev = False else: raise TypeError( 'The colors have to be in list format. The number of colors specificed have to equal the number of PL spectra' ) # if colors are specified, they will override this if colorRev == True: mpl.rcParams['axes.prop_cycle'] = plt.cycler( color=plt.cm.rainbow(np.linspace(1, 0.1, num_files))) else: mpl.rcParams['axes.prop_cycle'] = plt.cycler( color=plt.cm.rainbow(np.linspace(0.1, 1, num_files))) # Adjust for correction if corr == True or corr == False: corr = [corr] * num_files elif type(corr) != list or len(corr) != num_files: raise NameError( 'Please ensure variable corr is of type bool or list, and has the same number of elements as files to be processed. Lists use sq brackets []' ) # Adjust for shiftup if type(shiftup) == int or type(shiftup) == float: shiftup = np.full(num_files, shiftup) elif shiftup != list or len(shiftup) != num_files: raise NameError( 'Please ensure variable corr is of type int, float, or list, and has the same number of elements as files to be processed. Lists use sq brackets []' ) # load data # data = np.empty((0,0)) # for f in fnames: # i = fnames.index(f) # data = np.concatenate((data,load_corr_ANU(f,path=path,corr=corr[i],shiftup=shiftup[i]))) # print(data) data = [] for f in fnames: i = fnames.index(f) data.append( load_corr_ANU(f, path=path, corr=corr[i], shiftup=shiftup[i], cutoffs=cutoffs)) data = list( zip(*data) ) # transpose the list of lists, and make it a list of lists instead of a list of tuples so I can call elements eV = data[0] PL = data[1] PLn = data[2] wvl = data[3] PL_wvl = data[4] PLn_wvl = data[5] # return to original directory os.chdir(path_ori) #x-axis wvl or eV? if xvar == 'wvl': xax = wvl xlabel = r'$ \rm Wavelength~[nm] $' PL_plot = PL_wvl if norm == True: PL_plot = PLn_wvl elif xvar == 'eV': xax = eV xlabel = r'$ \rm Emission~Energy~[eV] $' PL_plot = PL if norm == True: PL_plot = PLn else: raise Exception('The x-axis must be in wvl or eV') # Do we plot? if plot == False: return (eV, PL, PLn, wvl, PL_wvl, PLn_wvl) elif plot != True: raise NameError('The variable plot must be a boolean') # Why, I shall plot, of course if logy == False: for i in range(num_files): ax.plot(xax[i], PL_plot[i], label=labels[i], color=colors[i], lw=1) elif logy == True: for i in range(num_files): # print(np.shape(PL_plot[1])) if type(eps) == float or type(eps) == int: # apply epsilon cutting y = np.where( PL_plot[i] > eps, PL_plot[i], eps ) # account for possible length differences between lines in PL_plot ax.semilogy(xax[i], y, label=labels[i], color=colors[i], lw=1) else: ax.semilogy(xax[i], PL_plot[i], label=labels[i], color=colors[i], lw=1) else: raise Exception('The plot must be linear or semilogy') ax.set_xlabel(xlabel) ax.legend() ax.set_ylabel(r'$ \rm PL~Intensity~[AU] $') plt.tight_layout() return (eV, PL, PLn, wvl, PL_wvl, PLn_wvl)
def load_corr_ANU(fname, path='', corr=False, shiftup=0, cutoffs=(0, -1)): # Go to the target directory if path != 'current': path = genSZ.device() + path else: path = Path().absolute() path_ori = Path().absolute() os.chdir(path) # load the correction coefficients # np.seterr(invalid='ignore') # invalid (probably NaN) values exist in the below operation. use this to override the warning. Corresponding expression below sets it back corr_InGaAs = np.loadtxt( genSZ.device() + 'Modules/Correction base files/ANU QE/no laser corrected.txt' )[:, 1] / np.loadtxt(genSZ.device() + 'Modules/Correction base files/ANU QE/no laser.txt')[:, 1] corr_Si = np.loadtxt( genSZ.device() + 'Modules/Correction base files/ANU QE/Si corrected.txt' )[:, 1] / np.loadtxt( genSZ.device() + 'Modules/Correction base files/ANU QE/Si uncorrected.txt')[:, 1] # np.seterr(invalid='warn') # load and return to the original path wvl, PL = np.loadtxt(fname, unpack=True) os.chdir(path_ori) if np.any(wvl) > 1200: detector = 'InGaAs' else: detector = 'Si' PL = PL + shiftup if corr == True: if detector == 'InGaAs': PL = PL * corr_InGaAs elif detector == 'Si': PL = PL * corr_Si elif corr != False: raise NameError('The correction variable must be True or False') PL_wvl = PL dw = np.gradient(wvl) dw = dw / dw.max() eV = conSZ.nm2eV / wvl PL = PL_wvl / (eV**2 * dw) PL = PL[cutoffs[0]:cutoffs[1]] PL_wvl = PL_wvl[cutoffs[0]:cutoffs[1]] eV = eV[cutoffs[0]:cutoffs[1]] wvl = wvl[cutoffs[0]:cutoffs[1]] PLn = PL / PL.max() PLn_wvl = PL_wvl / PL_wvl.max() return (eV, PL, PLn, wvl, PL_wvl, PLn_wvl)
def imap(filename, path, times, Nx, Ny, dx, dy, dark='PL0.csv', detector='InGaAs', cutoff=0): # go to required directory if path != 'current': path = genSZ.device() + path else: path = Path().absolute() path_ori = Path().absolute() os.chdir(path) # set up map x = np.linspace(0, Nx * dx, Nx) y = np.linspace(0, Ny * dy, Ny) extent = (x.min(), x.max(), y.min(), y.max()) # Import map and PL0 PL0, noise = np.loadtxt(dark, skiprows=80, usecols=(6, 7), delimiter=',', unpack=True) PL = np.loadtxt(filename) PL = PL[:, 2:] # Spectrum corrections setup: QE, wvl to eV, averaging wvl path = genSZ.device( ) + 'Modules/' # make sure that it's using the QE files in the Modules folder if detector == "InGaAs": wvl, QE = np.loadtxt(path + 'QE_InGaAs.csv', unpack=True, delimiter=',', skiprows=1, usecols=(0, 1)) elif detector == "Si": # wvl, QE = np.loadtxt(path+'QE_Si.csv', unpack=True, # delimiter = ',', skiprows=1, usecols = (0, 1)) wvl, QE = np.loadtxt( path + 'QE_Si_Avantes.csv', unpack=True, # the calibration using the lamp delimiter=',', skiprows=1, usecols=(0, 3)) PL = PL[:, 138:2041] PL0 = PL0[138:2041] noise = noise[138:2041] # end of Avantes calibration else: raise NameError('Detector must be string named InGaAs or Si') Nw = len(wvl) dw = np.gradient( wvl ) # for elements in a 1D array it will output half the difference between the elements proceeding and following that element dw = dw / dw.max() eV = conSZ.nm2eV / wvl # spectral corrections PL_eV = (PL - times * PL0) / (QE * eV**2 * dw) PL_wvl = (PL - times * PL0) / (QE * dw) # reshape the data: 2D -> 3D PL_eV = np.reshape(PL_eV, (Nx, Ny, Nw)) PL_eV[1::2, :, :] = PL_eV[1::2, ::-1, :] PL_eV = np.flipud(PL_eV) PL_eV = np.rot90(PL_eV, 3) PL_wvl = np.reshape(PL_wvl, (Nx, Ny, Nw)) PL_wvl[1::2, :, :] = PL_wvl[1::2, ::-1, :] PL_wvl = np.flipud(PL_wvl) PL_wvl = np.rot90(PL_wvl, 3) # Cut-off data where needed if cutoff < 0: PL_eV = PL_eV[:, :, :cutoff] PL_wvl = PL_wvl[:, :, :cutoff] PL0 = PL0[:cutoff] eV = eV[:cutoff] wvl = wvl[:cutoff] elif cutoff >= 0: PL_eV = PL_eV[:, :, cutoff:] PL_wvl = PL_wvl[:, :, cutoff:] PL0 = PL0[cutoff:] eV = eV[cutoff:] wvl = wvl[cutoff:] # go back to previous directory os.chdir(path_ori) return PL_wvl, PL_eV, wvl, eV, PL0, noise, extent
def load_correct_0d(filename, detector, times, xvar='eV', delimiter=',', cutoff=0): #load data. unpack transposes the ndarray output PL0, PL = np.loadtxt(filename, skiprows=80, usecols=(4, 6), delimiter=delimiter, unpack=True) info = pd.read_csv(filename, delimiter=delimiter, usecols=(0, 1), index_col='Name', header=0, names=['Name', 'Value']) t_int = np.float(info.loc['intigration times(ms)']) n_avg = np.float(info.loc['average number']) # Spectrum corrections setup path = genSZ.device( ) + 'Modules/' # make sure that it's using the QE files in the Modules folder if detector == "InGaAs": wvl, QE = np.loadtxt(path + 'QE_InGaAs.csv', unpack=True, delimiter=',', skiprows=1, usecols=(0, 1)) elif detector == "Si": # wvl, QE = np.loadtxt(path+'QE_Si.csv', unpack=True, # delimiter = ',', skiprows=1, usecols = (0, 1)) wvl, QE = np.loadtxt( path + 'QE_Si_Avantes.csv', unpack=True, # the calibration using the lamp delimiter=',', skiprows=1, usecols=(0, 3)) PL = PL[138:2041] PL0 = PL0[138:2041] else: raise NameError('Detector must be string named InGaAs or Si') dw = np.gradient( wvl ) # for elements in a 1D array it will output half the difference between the elements proceeding and following that element dw = dw / dw.max() eV = conSZ.nm2eV / wvl if xvar == 'eV': PL = (PL - times * PL0) / (QE * eV**2 * dw) elif xvar == 'wvl': PL = (PL - times * PL0) / (QE * dw) else: raise Exception('The x-axis must be in wvl or eV') # Cut-off data where needed if cutoff < 0: PL = PL[:cutoff] PL0 = PL0[:cutoff] eV = eV[:cutoff] wvl = wvl[:cutoff] elif cutoff >= 0: PL = PL[cutoff:] PL0 = PL0[cutoff:] eV = eV[cutoff:] wvl = wvl[cutoff:] return PL, wvl, eV, PL0, t_int, n_avg
def mplot(filenames, times, path='', labels='', detector='Si', plot=True, xvar='eV', norm=False, logy=True, colors='', delimiter=',', cutoff=0, ratio=0, offset=False): # prepare the ground if path != 'current': path = genSZ.device() + path elif path == 'current': path = Path().absolute() path_ori = Path().absolute() os.chdir(path) if detector == 'Si': # which detector # length=2048-np.abs(cutoff) # this is for the default Si calibration with blackbody at 400C, which uRob rarely uses and is therefore not optimal length = 1903 - np.abs( cutoff ) # this is measured with a lamp, the bottom turrent position #6 which I think is probably empty elif detector == "InGaAs": length = 512 - np.abs(cutoff) else: raise NameError('The detector must be Si or InGaAs') num_files = len( filenames) #the number of files this function will need to process if labels == '': # make labels the filenames, if no labels labels = [] for f in filenames: labels.append(os.path.splitext(f)[0]) if colors == '' or colors == 1: # the colours feature colorRev = False colors = [None] * num_files elif colors == -1: colorRev = True colors = [None] * num_files elif type(colors) == list: colorRev = False else: raise TypeError( 'The colors have to be in list format. The number of colors specificed have to equal the number of PL spectra' ) # try: if colorRev == True: mpl.rcParams['axes.prop_cycle'] = plt.cycler( color=plt.cm.rainbow(np.linspace(1, 0.1, num_files))) else: mpl.rcParams['axes.prop_cycle'] = plt.cycler( color=plt.cm.rainbow(np.linspace(0.1, 1, num_files))) # except: # pass if type(times) == float or type( times) == int: # allowing customisation of the times variable mul = np.empty((num_files, length)) for i in range(len(mul)): mul[i] = times elif len(times) != num_files: raise Exception( 'The times variable must be a float, or an array with the same length as the filenames array' ) #load the data PL = np.empty((num_files, length)) wvl = np.empty((num_files, length)) eV = np.empty((num_files, length)) PL0 = np.empty((num_files, length)) t_int = np.empty((num_files, 1)) n_avg = np.empty((num_files, 1)) for f in filenames: i = filenames.index(f) PL[i], wvl[i], eV[i], PL0[i], t_int[i], n_avg[i] = load_correct_0d( filename=f, times=times, detector=detector, xvar=xvar, delimiter=delimiter, cutoff=cutoff) # return to original directory os.chdir(path_ori) # account for possible different integration times or multipliers if ratio == 0: pass elif type(ratio) == int or type(ratio) == float: for i in range(num_files): PL[i] = PL[i] / ratio elif len(ratio) == num_files: for i in range(num_files): PL[i] = PL[i] / ratio[i] else: raise Exception( 'The ratio variable must be zero, or have length 1, or an array with the same length as the filenames array' ) # Do we plot? if plot == False: return PL, wvl, eV, PL0, t_int, n_avg elif plot != True: raise NameError('The variable plot must be a boolean') # prep the data for plotting PL_plot = np.empty((num_files, length)) xax = np.empty((num_files, length)) if norm == True: #possible normalisation for i in range(num_files): PL_plot[i] = PL[i] / PL[i].max() elif norm == False: PL_plot = PL else: raise NameError( 'You must specify whether the graph should be normalised') if xvar == 'wvl': #x-axis wavelength or energy? xax = wvl xlabel = r'$ \rm Wavelength~[nm] $' elif xvar == 'eV': xax = eV xlabel = r'$ \rm Emission~Energy~[eV] $' else: raise Exception('The x-axis must be in wvl or eV') # plot, both the semilogy and the linear plot if logy == True: eps = 0.3 PL_plot = np.flip(PL_plot, axis=0) PL_plot = np.where(PL_plot > eps, PL_plot, eps) if type(offset) == int or type(offset) == float: for i in range(num_files): PL_plot[i] = PL_plot[i] * offset**i for i in range(num_files): plt.semilogy(xax[i], PL_plot[i], label=labels[i], color=colors[i], lw=1) elif logy == False: if type(offset) == int or type(offset) == float: for i in range(num_files): PL_plot[i] = PL_plot[i] + offset * i for i in range(num_files): plt.plot(xax[i], PL_plot[i], label=labels[i], color=colors[i], lw=1) else: raise Exception( 'The plot must be linear or semilogy, the variable must be a Boolean' ) plt.xlabel(xlabel) plt.legend() plt.ylabel(r'$ \rm PL~Intensity~[AU] $') plt.tight_layout() return PL, wvl, eV, PL0, t_int, n_avg