diff --git a/MakeIndividualIVs.py b/MakeIndividualIVs.py index 18ddceb..baf5b6a 100644 --- a/MakeIndividualIVs.py +++ b/MakeIndividualIVs.py @@ -1,213 +1,212 @@ # -*- coding: utf-8 -*- import numpy as np import Functions as uf import os import matplotlib.pyplot as plt import matplotlib from tkinter import Tk from tkinter.filedialog import askopenfilenames from matplotlib.font_manager import FontProperties import platform import csv import argparse from pprint import pprint import LoadData #Set font properties fontP = FontProperties() fontP.set_size('small') props = dict(boxstyle='round', facecolor='wheat', alpha=0.5) matplotlib.rcParams['pdf.fonttype'] = 42 matplotlib.rcParams['ps.fonttype'] = 42 #Set units formatting from matplotlib.ticker import EngFormatter Res = EngFormatter(unit='Ω', places=2) Cond = EngFormatter(unit='S', places=2) SpesCond = EngFormatter(unit='S/m', places=2) size = EngFormatter(unit='m', places=2) if (platform.system()=='Darwin'): Tk().withdraw() os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "python" to true' ''') # Define default parameters for size fitting expname = 'All' Parameters = { 'Type': 'Nanopore', # Nanopore, Nanocapillary, NanocapillaryShrunken 'reversePolarity': 0, 'specificConductance': 10.5, # 10.5 S/m for 1M KCl 'delay': 3, # seconds for reading current # Nanopore 'poreLength': 20e-9, # Nanocapillary 'taperLength': 3.3e-3, 'innerDiameter': 0.2e-3, 'taperLengthShaft': 543e-9, 'innerDiameterShaft': 514e-9, # Fit option 'CurveFit': 'PolyFit', # PolyFit YorkFit 'fittingMethod': 'mean' # expFit, mean } def GetParameters(): print("Usage:") print("run(filenames,newParameters={},verbose=False, noPlot=False") print('Returns poresize in m') print() print("Default Parameters:") pprint(Parameters) def run(filenames, newParameters={}, verbose=False, noPlot=False): """ Function used to call all the necessary other functions to make I-V curves. It takes a list of filenames as necessary argument. For each data file, a corresponding I-V curve will be generated. It iterates on the filenames in the list and calls the corresponding MakeIVData from Functions module. Parameters ---------- filenames : list of strings Full paths to data files. newParameters : dict Contains the default parameters for the analysis. verbose : bool, optional False by default. If True, it will display a simple figure with the shape of the signal. noPlot : bool, optional False by default. If True it will disable the plotting """ for key in newParameters: Parameters[key]=newParameters[key] Type = Parameters['Type'] CurveFit = Parameters['CurveFit'] specificConductance = Parameters['specificConductance'] for filename in filenames: os.chdir(os.path.dirname(filename)) #print(filename) # Make Dir to save images output = LoadData.OpenFile(filename, verbose=verbose) if Parameters['reversePolarity']: print('Polarity Reversed!!!!') - output['i1']= -output['i1'] - output['v1']= -output['v1'] + output['i1'] = -output['i1'] + output['v1'] = -output['v1'] directory = (str(os.path.split(filename)[0]) + os.sep + expname + '_SavedImages') if not os.path.exists(directory): os.makedirs(directory) AllData = uf.MakeIVData(output, approach=Parameters['fittingMethod'], delay = Parameters['delay'])#, UseVoltageRange = [-0.4, 0.4]) if AllData == 0: print('!!!! No Sweep in: ' + filename) continue if output['graphene']: currents = ['i1', 'i2'] else: currents = ['i1'] for current in currents: - print(current) Slope = AllData[current][CurveFit]['Slope'] Yintercept = AllData[current][CurveFit]['Yintercept'] if Type == 'Nanopore': poreLength = Parameters['poreLength'] poresize = uf.CalculatePoreSize(np.abs(Slope), poreLength, specificConductance) textstr = 'Nanopore Size\n\nSpecific Conductance: {}\nLength: {}\n\nConductance: {}\nDiameter: {}' \ .format(SpesCond.format_data(specificConductance), size.format_data(poreLength), Cond.format_data(Slope), size.format_data(poresize)) elif Type == 'Nanocapillary': taperLength = Parameters['taperLength'] innerDiameter = Parameters['innerDiameter'] poresize = uf.CalculateCapillarySize(np.abs(Slope), innerDiameter, taperLength, specificConductance) textstr = 'Nanocapillary Size\n\nSpecific Conductance: {}\nTaper lenghth {}:\nInner diameter: {}:\n\nConductance: {}\nDiameter: {}'. \ format(SpesCond.format_data(specificConductance), size.format_data(taperLength), size.format_data(innerDiameter), Cond.format_data(Slope), size.format_data(poresize)) elif Type == 'NanocapillaryShrunken': taperLength = Parameters['taperLength'] innerDiameter = Parameters['innerDiameter'] taperLengthShaft = Parameters['taperLengthShaft'] innerDiameterShaft = Parameters['innerDiameterShaft'] poresize = uf.CalculateShrunkenCapillarySize(np.abs(Slope), innerDiameter, taperLength, specificConductance, taperLengthShaft, innerDiameterShaft) textstr = 'Shrunken Nanocapillary Size\n\nSpecific Conductance: {}\nTaper length: {}\nInner diameter: {}\nTaper length at shaft: {}' \ '\nInner Diameter at shaft: {}:\n\nConductance: {}\nDiameter: {}'. \ format(SpesCond.format_data(specificConductance), size.format_data(taperLength), size.format_data(innerDiameter), size.format_data(taperLengthShaft), size.format_data(innerDiameterShaft), Cond.format_data(Slope), size.format_data(poresize)) if not noPlot: figIV = plt.figure(2, figsize=(10, 7)) ax1IV = figIV.add_subplot(111) ax1IV.text(0.05, 0.95, textstr, transform=ax1IV.transAxes, fontsize=12, verticalalignment='top', bbox=dict(boxstyle='round', facecolor='wheat', alpha=0.5)) ind = np.argsort(AllData[current]['Voltage']) ax1IV.errorbar(AllData[current]['Voltage'][ind], AllData[current]['Mean'][ind], yerr=AllData[current]['SE'][ind], fmt='o', color='b') ax1IV.plot(AllData[current]['Voltage'][ind], np.polyval([Slope,Yintercept], AllData[current]['Voltage'][ind]), color='r') ax1IV.set_title(str(os.path.split(filename)[1])+ '\nR=' + Res.format_data(1/Slope) + ', G=' + Cond.format_data(Slope)) ax1IV.set_ylabel('Current ' + current) ax1IV.set_xlabel('Voltage') ax1IV.xaxis.set_major_formatter(EngFormatter(unit='V')) ax1IV.yaxis.set_major_formatter(EngFormatter(unit='A')) figIV.savefig(directory + os.sep + str(os.path.split(filename)[1]) + Type + '_' + current + 'IV.pdf', transparent=True) x = AllData[current]['Voltage'][ind] y = AllData[current]['Mean'][ind] csvfile = directory + os.sep + str(os.path.split(filename)[1]) + Type + '_' + current + '_IV.csv' with open(csvfile, 'w') as output: writer=csv.writer(output, lineterminator='\n') for i in range(len(x)): writer.writerow([x[i], y[i]]) - #plt.show() + plt.show() figIV.clear() #return poresize #else: #return poresize if __name__=='__main__': parser = argparse.ArgumentParser() parser.add_argument('-i', '--input', help='input file') parser.add_argument('-c', '--coeff', help='Coefficients for calculating pore size', nargs='+') parser args = parser.parse_args() inputData=args.input if inputData==None: inputData=askopenfilenames() else: inputData={inputData} newParameters={} if args.coeff is not None: if len(args.coeff) % 2 == 0: for i in range(0, len(args.coeff), 2): if i <= len(args.coeff): newParameters[str(args.coeff[i])]=args.coeff[i+1] run(inputData,newParameters) if (platform.system()=='Darwin'): Tk().withdraw() root=Tk() root.update() \ No newline at end of file diff --git a/Plotting/EventPlots.py b/Plotting/EventPlots.py index a6c5c76..e0135c2 100644 --- a/Plotting/EventPlots.py +++ b/Plotting/EventPlots.py @@ -1,779 +1,779 @@ import numpy as np import matplotlib import matplotlib.pyplot as plt import matplotlib.patches as patches from matplotlib.ticker import EngFormatter from matplotlib.widgets import CheckButtons, Button import argparse import platform import shelve import os import Functions import LoadData import NanoporeClasses as NC from bokeh.models import Legend,LegendItem,Range1d from bokeh.palettes import Spectral4 from bokeh.plotting import figure, output_file, show, output_notebook from bokeh.layouts import row, column, gridplot from holoviews.plotting import bokeh from holoviews.operation import histogram import holoviews as hv from holoviews import opts import seaborn as sns sns.set() hv.extension('bokeh') #needed for plotting in jupyter from bokeh.resources import INLINE import bokeh.io bokeh.io.output_notebook(INLINE) Amp = EngFormatter(unit='A', places=2) Time = EngFormatter(unit='s', places=2) Volt = EngFormatter(unit='V', places=2) Cond = EngFormatter(unit='S', places=2) # Extract y and tau out of events def extractytau(filteredevents, showCurrent, normalized = False): if showCurrent or normalized: if normalized: yVals = [event.currentDrop/event.baseline for event in filteredevents] else: yVals = [event.currentDrop for event in filteredevents] tau = [event.eventLength for event in filteredevents] else: yVals = [event.currentDrop / event.voltage for event in filteredevents if event.voltage > 0] tau = [event.eventLength for event in filteredevents if event.voltage > 0] return tau, yVals def PlotGTau(eventClass, xLim = None, yLim = None, showCurrent = False, normalized = False, showLog=False, showNonFitted=False): """ Function used to produce scatter plots and histograms of the events. The figure produced has 3 subplots: Up: Histogram with the number of events per event length Right: Histogram with the number of events per conductance drop [nS] Center: Scatter-plot of all the events wiht in on x-coordinates the event length [s] and in y-coordinates the conductance drop [nS]. In the plots, the events were distributed into the 3 types of events: CUSUM-fitted in red ('Real' type) Impulse in blue ('Impulse' type) Non-fitted in green ('Rough' type) Parameters ---------- eventClass : AllEvents object All the events to be plotted. xLim : 2D list, optional limits on x axis yLim : 2D list, optional limits on y axis showCurrent : bool, optional False by default. If True, it will change the SI unit in the y-axis from siemens [S] to ampers [A]. So instead of units in conductance drop, it will have current drop. normalized : bool, optional False by default. If True, it will change in the y-axis the unit from siemens [S] to normalized current drop without unit. showLog : bool, optional False by default. If True, it will change the axis to logarithmic showNonFitted: bool, optional False by default. If True, it will show non fitted events """ # categorize events in three types # CUSUM fitted events CUSUMEvents = eventClass.GetEventTypes('CUSUM') if len(CUSUMEvents) == 0: CUSUMEvents = eventClass.GetEventTypes('Real') # Non-fitted events if showNonFitted: nonFittedEvents = eventClass.GetEventTypes('Rough') else: nonFittedEvents = [] # Impulse events impulseEvents = eventClass.GetEventTypes('Impulse') # select min max events = [event for event in eventClass.events if showCurrent or event.voltage is not 0] allTau, allYVals = extractytau(events, showCurrent, normalized) maxy = 1 if normalized else 1.1 * np.percentile(allYVals, 99) minx = 0.9 * np.percentile(allTau, 1) if showLog else 0 brx = (minx, 1.1 * np.percentile(allTau, 99)) if xLim is None else tuple(xLim) bry = (0, maxy) if yLim is None else tuple(yLim) br = dict() br['x'] = brx br['y'] = bry showlogHist = dict() showlogHist['x'] = showLog showlogHist['y'] = False xlabel = 'Dwell time (s)' - ylabel = 'Current drop (A)' + ylabel = 'Current drop (A)' if showCurrent else 'Conductance drop (S)' tau1, yVals1 = extractytau(impulseEvents, showCurrent, normalized) points = hv.Points((tau1, yVals1), label='impulse') tau2, yVals2 = extractytau(CUSUMEvents, showCurrent, normalized) points2 = hv.Points((tau2, yVals2), label='CUSUM') tau3, yVals3 = extractytau(nonFittedEvents, showCurrent, normalized) points3 = hv.Points((tau3, yVals3), label='non-fitted') xhist, yhist = (histogram(points3, bin_range=br[dim], dimension=dim, log=(showlogHist[dim] and len(tau3) > 0),normed=False) * histogram(points2, bin_range=br[dim], dimension=dim, log=(showlogHist[dim] and len(tau2) > 0),normed=False) * histogram(points, bin_range=br[dim], dimension=dim, log=(showlogHist[dim] and len(tau1) > 0),normed=False) for dim in 'xy') return ((points3 * points2 * points).opts(logx=showLog, xlabel=xlabel, ylabel=ylabel, width=500, height=500, xlim=brx, ylim=bry) << yhist.opts( width=200) << xhist.opts(height=150, logx=showLog)).opts( opts.Histogram(xlabel='', ylabel='', alpha=0.3, show_legend=False)) def PlotG_tau(translocationEvents, fig=None, savefile=None, showCurrent=False, normalized=False, showCUSUM=True, showLog=False): """ Function used to produce scatter plots and histograms of the events. The figure produced has 3 subplots: Up: Histogram with the number of events per event length Right: Histogram with the number of events per conductance drop [nS] Center: Scatter-plot of all the events wiht in on x-coordinates the event length [s] and in y-coordinates the conductance drop [nS]. In the plots, the events were distributed into the 3 types of events: CUSUM-fitted in red ('Real' type) Non-fitted in blue ('Rough' type) Impulse in green ('Impulse' type) Parameters ---------- events : AllEvents object All the events to be plotted. savefile : str, optional Full path to file where the plots will be saved. showCurrent : bool, optional False by default. If True, it will change the SI unit in the y-axis from siemens [S] to ampers [A]. So instead of units in conductance drop, it will have current drop. normalized : bool, optional False by default. If True, it will change in the y-axis the unit from siemens [S] to normalized current drop without unit. showCUSUM : bool, optional True by default. """ # categorize events in three types # CUSUM fitted events CUSUMEvents = translocationEvents.GetEventTypes('CUSUM') if len(CUSUMEvents) == 0: CUSUMEvents = translocationEvents.GetEventTypes('Real') # Non-fitted events nonFittedEvents = translocationEvents.GetEventTypes('Rough') # Impulse events impulseEvents = translocationEvents.GetEventTypes('Impulse') catEvents = (CUSUMEvents, nonFittedEvents, impulseEvents) # Save figure def SavePlot(event): # Check if directory exists directory = os.path.dirname(savefile) if showCurrent: fig.savefig(directory + os.sep + 'PlotITau.pdf', transparent=True) else: fig.savefig(directory + os.sep + 'PlotGTau.pdf', transparent=True) def ShowLog(event): name = axScatter.xaxis._scale.name bshowlog.label.set_text('Show ' + name) axScatter.set_xscale('linear') if name == 'log' else axScatter.set_xscale('log') # definitions for the axes left, width = 0.15, 0.55 bottom, height = 0.1, 0.6 left_h = left + width + 0.015 bottom_h = bottom + height + 0.015 rect_scatter = [left, bottom, width, height] rect_histx = [left, bottom_h, width, 0.2] rect_histy = [left_h, bottom, 0.2, height] # start with a rectangular Figure if fig is None: fig = plt.figure(1, figsize=(10, 8)) # define axes and link histogram to scatterplot axScatter = fig.add_axes(rect_scatter) axHistx = fig.add_axes(rect_histx, sharex=axScatter) axHisty = fig.add_axes(rect_histy, sharey=axScatter) # Checkboxes to turn on or off events rax = plt.axes([0.75, 0.73, 0.14, 0.15]) visBool = [True, False, True] labelsCheckBox = ('CUSUM-fitted', 'Not fitted', 'impulse') check = CheckButtons(rax, labelsCheckBox, visBool) # Link button to axes to preserve function rax._check = check bax = plt.axes([0.77, 0.9, 0.1, 0.03]) bnext = Button(bax, 'Save figure') bnext.on_clicked(SavePlot) # Link button to axes to preserve function bax._bnext = bnext baxl = plt.axes([0.77, 0.95, 0.1, 0.03]) txt = 'log' if showLog else 'linear' bshowlog = Button(baxl, 'Show ' + txt) bshowlog.on_clicked(ShowLog) # Link button to axes to preserve function bax._bshowlog = bshowlog # Show labels def setlabels(): plt.setp(axHistx.get_xticklabels(), visible=False) plt.setp(axHisty.get_yticklabels(), visible=False) axScatter.set_xlabel('Event length (s)') axScatter.xaxis.set_major_formatter(Time) if normalized: axScatter.set_ylabel('current drop (normalized)') else: if showCurrent: axScatter.set_ylabel('current drop (A)') axScatter.yaxis.set_major_formatter(Amp) else: axScatter.set_ylabel('Conductance drop (G)') axScatter.yaxis.set_major_formatter(Cond) # Set limits allEvents = [event for event in translocationEvents.events if showCurrent or event.voltage is not 0] bins = 100 extra = 0.1 # 0.1 = 10% allTau, allYVals = extractytau(allEvents, showCurrent) yClean = [y for y in allYVals if str(y) != 'nan'] taurangeHist = np.linspace(min(allTau), max(allTau), num=bins) yValsrangeHist = np.linspace(min(yClean), max(yClean), num=bins) # define colors of the 3 classes colors = ['tomato', 'lightgreen', 'skyblue'] linecolors = ['red', 'green', 'blue'] # the scatter plot: scatters = [None]*3 def PlotEvents(visBool): # clear axes axScatter.clear() axHistx.clear() axHisty.clear() nrEvents = 0 for i in range(len(catEvents)): # If checkbox is True, plot events if visBool[i]: # Extract Tau and Y events = catEvents[i] tau, yVals = extractytau(events, showCurrent) scatters[i] = axScatter.scatter(tau, yVals, color=colors[i], marker='o', s=30, linewidths=0.1, edgecolors=linecolors[i], picker=5, visible=visBool[i]) axHistx.hist(tau, bins=taurangeHist, color=colors[i], visible=visBool[i]) axHisty.hist(yVals, bins=yValsrangeHist, orientation='horizontal', color=colors[i], visible=visBool[i]) nrEvents += len(events) if showLog: axScatter.set_xscale('log') # set limits if len(allTau) > 0: tauRange = np.max(allTau) - np.min(allTau) yRange = np.max(yClean) - np.min(yClean) axScatter.set_xlim((np.max([np.min(allTau) - extra * tauRange, 1e-6]), np.max(allTau) + extra * tauRange)) axScatter.set_ylim((np.min(yClean) - extra * yRange, np.max(yClean) + extra * yRange)) setlabels() fig.suptitle('{} number of events'.format(nrEvents)) PlotEvents(visBool) # If click on checkbox, switch Boolean and replot events def func(label): for i in range(len(labelsCheckBox)): if label == labelsCheckBox[i]: visBool[i] = not visBool[i] PlotEvents(visBool) plt.draw() # When clicking on event def onpick(event): for i in range(len(catEvents)): if event.artist == scatters[i]: N = len(event.ind) if not N: return True figi = plt.figure(figsize=(10, 6)) for subplotnum, dataind in enumerate(event.ind): ax = figi.add_subplot(N, 1, subplotnum + 1) PlotEvent(catEvents[i][dataind], ax, savefile, showCUSUM) figi.show() return True fig.canvas.mpl_connect('pick_event', onpick) check.on_clicked(func) if not hasattr(fig, '_AnalysisUI__attached'): plt.show() def PlotGTauVoltage (eventClass, xLim=None, yLim=None, showCurrent=False, voltageLimits = None): bokeh.io.output_notebook(INLINE) #sort the voltages # categorize events in three types # CUSUM fitted events voltagesList = eventClass.GetAllVoltages() if voltageLimits is not None: voltagesList = [x for x in voltagesList if x>voltageLimits[0] and x=2: eventLength = event.eventLengthCUSUM currentDrop = event.currentDropCUSUM else: showCUSUM=False eventLength = event.eventLength currentDrop = event.currentDrop fn=filename_w_ext = os.path.basename(event.filename) if showCurrent: plotTitle = fn + '\n' + 'Event length: {}\nCurrent drop: {} with voltage {}'.format( Time.format_data(eventLength), Cond.format_data(currentDrop), Volt.format_data(event.voltage)) else: plotTitle = fn + '\n' + 'Event length: {}\nConductance drop: {} with voltage {}'.\ format(Time.format_data(eventLength), Cond.format_data(currentDrop/event.voltage),Volt.format_data(event.voltage)) ax.set_xlabel('time (s)') ax.set_ylabel('current (A)') if axisFormatter: ax.xaxis.set_major_formatter(Time) ax.yaxis.set_major_formatter(Amp) if plotTitleBool: plt.title(plotTitle) if showButtons: # Add buttons # Save button bax = plt.axes([0.77, 0.95, 0.15, 0.03]) bsave = Button(bax, 'Save figure') bsave.on_clicked(SavePlot) # Link button to axes to preserve function ax._bsave = bsave # Show original trace button bax2 = plt.axes([0.77, 0.9, 0.15, 0.03]) bfull = Button(bax2, 'Show original Trace') # Link button to axes to preserve function ax._bfull = bfull bfull.on_clicked(ShowFullTrace) #Plotting timeVals1 = np.linspace(0, len(event.before) / event.samplerate, num=len(event.before)) timeVals2 = np.linspace(0 + max(timeVals1), len(event.eventTrace) / event.samplerate + max(timeVals1), num=len(event.eventTrace)) timeVals3 = np.linspace(0 + max(timeVals2), len(event.after) / event.samplerate + max(timeVals2), num=len(event.after)) ax.plot(np.append(timeVals1,timeVals2[0]), np.append(event.before,event.eventTrace[0]), color='tomato') ax.plot(timeVals2, event.eventTrace, color='mediumslateblue') ax.plot(np.append(timeVals2[-1],timeVals3), np.append(event.eventTrace[-1],event.after), color='tomato') if showCUSUM: timeVals = np.linspace(0, len(event.segmentedSignal) / event.samplerate, num=len(event.segmentedSignal)) if hasattr(event,'mcbefore') and hasattr(event,'mcafter') and hasattr(event,'mctrace'): ax.plot(timeVals1, event.mcbefore,'--', color='tomato') x=np.append(np.append(timeVals1[-1],timeVals2),timeVals3[0]) y=np.append(np.append(event.mcbefore[-1],event.mctrace),event.mcafter[0]) ax.plot(x, y, color='yellow') ax.plot(timeVals3, event.mcafter,'--', color='tomato') else: ax.plot(timeVals,event.segmentedSignal, color='yellow') #,timeVals3[0],event.mcafter[0] else: beforeBaseline=np.full(len(event.before), event.baseline) ax.plot(timeVals1,beforeBaseline, '--', color='tomato') afterBaseline = np.full(len(event.after), event.baseline) ax.plot(timeVals3,afterBaseline, '--', color='tomato') meanTrace = np.full(len(event.eventTrace), event.baseline-event.currentDrop) ax.plot(timeVals2,meanTrace, '--', color='mediumslateblue') if 'fig' in locals(): plt.show() def ShowEventInTrace_SignalPreloaded(FullTrace, AllData, eventnumber, ax, line = None, firstCall = True, dscorrection = None): times = np.linspace(0, len(FullTrace) / AllData.events[eventnumber].samplerate, num=len(FullTrace)) if line: line.set_ydata(FullTrace) line.set_xdata(times) if firstCall: ax.set_xlim(np.min(times), np.max(times)) ax.set_ylim(np.min(FullTrace), np.max(FullTrace)) print('updated lines') else: ax.plot(times, FullTrace, zorder=1) print('Updated plot') ax.set_xlabel('time (s)') ax.set_ylabel('current (A)') # Create a Rectangle patch if dscorrection: if hasattr(AllData.events[eventnumber], 'changeTimes') and len(AllData.events[eventnumber].changeTimes) > 2: start_i = (AllData.events[eventnumber].beginEventCUSUM - len(AllData.events[eventnumber].before)) / AllData.events[eventnumber].samplerate * dscorrection end_i = (AllData.events[eventnumber].endEventCUSUM + len(AllData.events[eventnumber].after)) / AllData.events[eventnumber].samplerate * dscorrection else: start_i = (AllData.events[eventnumber].beginEvent - len(AllData.events[eventnumber].before)) / AllData.events[eventnumber].samplerate * dscorrection end_i = (AllData.events[eventnumber].endEvent + len(AllData.events[eventnumber].after)) / AllData.events[eventnumber].samplerate * dscorrection else: if hasattr(AllData.events[eventnumber], 'changeTimes') and len(AllData.events[eventnumber].changeTimes) > 2: start_i = (AllData.events[eventnumber].beginEventCUSUM - len(AllData.events[eventnumber].before)) / \ AllData.events[eventnumber].samplerate end_i = (AllData.events[eventnumber].endEventCUSUM + len(AllData.events[eventnumber].after)) / \ AllData.events[eventnumber].samplerate else: start_i = (AllData.events[eventnumber].beginEvent - len(AllData.events[eventnumber].before)) / \ AllData.events[eventnumber].samplerate end_i = (AllData.events[eventnumber].endEvent + len(AllData.events[eventnumber].after)) / AllData.events[ eventnumber].samplerate minE = np.min(np.append(np.append(AllData.events[eventnumber].eventTrace, AllData.events[eventnumber].before), AllData.events[eventnumber].after)) maxE = np.max(np.append(np.append(AllData.events[eventnumber].eventTrace, AllData.events[eventnumber].before), AllData.events[eventnumber].after)) rect = patches.Rectangle((start_i, minE - 0.1 * (maxE - minE)), end_i - start_i, maxE + 0.2 * (maxE - minE) - minE, linestyle='--', linewidth=1, edgecolor='r', facecolor='none', zorder=10) # Add the patch to the Axes print(ax.patches.clear()) ax.add_patch(rect) def ShowEventInTrace(event, lowPass = 1e3): """ Function used to show the event with it's location framed in red in the original full signal trace in blue. Parameters ---------- event : TranslocationEvent object Event to be plotted. LowPass low pass filter, default set to 1 kHz """ filename = event.filename loadedData = LoadData.OpenFile(filename, lowPass, True) fig, ax = plt.subplots(figsize=(10, 6)) if loadedData['samplerate'] > lowPass: output = Functions.LowPass(loadedData['i1'], loadedData['samplerate'], lowPass) FullTrace = output['data'] samplerate = output['samplerate'] else: FullTrace = loadedData['i1'] samplerate = loadedData['samplerate'] times = np.linspace(0, len(FullTrace) / samplerate, num=len(FullTrace)) ax.plot(times, FullTrace, zorder=1) ax.set_xlabel('time (s)') ax.set_ylabel('current (A)') ax.xaxis.set_major_formatter(Time) ax.yaxis.set_major_formatter(Amp) # Create a Rectangle patch if hasattr(event,'changeTimes') and len(event.changeTimes)>2: start_i = (event.beginEventCUSUM - len(event.before))/event.samplerate end_i = (event.endEventCUSUM + len(event.after))/event.samplerate else: start_i = (event.beginEvent - len(event.before))/event.samplerate end_i = (event.endEvent + len(event.after))/event.samplerate minE=np.min(np.append(np.append(event.eventTrace,event.before),event.after)) maxE=np.max(np.append(np.append(event.eventTrace,event.before),event.after)) rect = patches.Rectangle((start_i, minE-0.1*(maxE-minE)), end_i-start_i, maxE+0.2*(maxE-minE)-minE, linestyle='--', linewidth=1, edgecolor='r', facecolor='none',zorder=10) # Add the patch to the Axes ax.add_patch(rect) plt.title(os.path.basename(filename)) plt.show() def PlotCurrentTrace(currentTrace, samplerate): """ Function used in TranslocationEvent class methods in the NanoporeClasses module to plot events. It will plot the TranslocationEvent's currrentTrace passed in argument. Parameters ---------- currentTrace : list of float Data points in current to be plotted. samplerate : float Sampling frequency of the data acquisition. """ timeVals = np.linspace(0, len(currentTrace) / samplerate, num=len(currentTrace)) fig,ax=plt.subplots(figsize=(10, 6)) ax.plot(timeVals, currentTrace) ax.set_xlabel('time (s)') ax.set_ylabel('current (A)') ax.xaxis.set_major_formatter(Time) ax.yaxis.set_major_formatter(Amp) plt.show() def PlotCurrentTraceBaseline(before, currentTrace, after, samplerate, plotTitle=''): """ Function used in TranslocationEvent class methods in the NanoporeClasses module to plot events. It will plot TranslocationEvent's currentTrace and the surrounding baseline (after and before) passed in argument. Parameters ---------- before : list of float Data points in current of the baseline trace before the event. currentTrace : list of float Data points in current of the event trace. after : list of float Data points in current of the baseline trace after the event. samplerate : float Sampling frequency of the data aquisition. plotTitle : str, optional Plot title. """ timeVals1 = np.linspace(0, len(before) / samplerate, num=len(before)) timeVals2 = np.linspace(0 + max(timeVals1), len(currentTrace) / samplerate + max(timeVals1), num=len(currentTrace)) timeVals3 = np.linspace(0 + max(timeVals2), len(after) / samplerate + max(timeVals2), num=len(after)) #plt.figure(figsize=(10, 6)) fig,ax=plt.subplots(figsize=(10, 6)) ax.plot(timeVals1, before, color='red') ax.plot(timeVals2, currentTrace) ax.plot(timeVals3, after, color='red') ax.set_xlabel('time (s)') ax.set_ylabel('current (A)') ax.xaxis.set_major_formatter(Time) ax.yaxis.set_major_formatter(Amp) if plotTitle: plt.title(plotTitle) plt.show() if __name__=='__main__': from tkinter import Tk from tkinter.filedialog import askopenfilenames, askdirectory matplotlib.use('TkAgg') if (platform.system() == 'Darwin'): root = Tk() root.withdraw() if (platform.system() == 'Darwin'): os.system('''/usr/bin/osascript -e 'tell app "Finder" to set frontmost of process "python" to true' ''') parser = argparse.ArgumentParser() parser.add_argument('-i', '--input', help='Input file') args = parser.parse_args() inputData = args.input if inputData == None: inputData = askopenfilenames(filetypes=[('data files', '*.dat')]) #for Mac systems, replace 'Data*.dat' with >> '*.dat' #if inputData: # inputData=os.path.splitext(inputData[0])[0] if (platform.system() == 'Darwin'): root.update() translocationEvents = NC.AllEvents() if inputData: for filename in inputData: shelfFile = shelve.open(os.path.splitext(filename)[0]) translocationEventstemp = shelfFile['TranslocationEvents'] shelfFile.close() translocationEvents.AddEvent(translocationEventstemp) PlotG_tau(translocationEvents, savefile=inputData)