Instruction:
How would you implement a function in Python 3 that
plots the data for the given two time points.

Response:
def IV(abf,T1,T2,plotToo=True,color='b'):
    """
    Given two time points (seconds) return IV data.
    Optionally plots a fancy graph (with errorbars)
    Returns [[AV],[SD]] for the given range.
    """
    rangeData=abf.average_data([[T1,T2]]) #get the average data per sweep
    AV,SD=rangeData[:,0,0],rangeData[:,0,1] #separate by average and SD
    Xs=abf.clampValues(T1) #get clamp values at time point T1
    if plotToo:
        new(abf) #do this so it's the right shape and size

        # plot the original sweep
        pylab.subplot(221)
        pylab.title("sweep data")
        pylab.xlabel("time (s)")
        pylab.ylabel("Measurement (%s)"%abf.units)
        sweep(abf,'all',protocol=False)
        pylab.axis([None,None,np.min(rangeData)-50,np.max(rangeData)+50])
        pylab.axvspan(T1,T2,alpha=.1,color=color) #share measurement region
        pylab.margins(0,.1)

        # plot the data zoomed in
        pylab.subplot(223)
        pylab.title("measurement region")
        pylab.xlabel("time (s)")
        pylab.ylabel("Measurement (%s)"%abf.units)
        sweep(abf,'all',protocol=False)
        pylab.axis([T1-.05,T2+.05,np.min(rangeData)-50,np.max(rangeData)+50])
        pylab.axvspan(T1,T2,alpha=.1,color=color) #share measurement region
        pylab.margins(0,.1)

        # plot the protocol
        pylab.subplot(222)
        pylab.title("protocol")
        pylab.xlabel("time (s)")
        pylab.ylabel("Command (%s)"%abf.unitsCommand)
        sweep(abf,'all',protocol=True)
        pylab.axvspan(T1,T2,alpha=.1,color=color) #share measurement region
        pylab.margins(0,.1)

        # plot the I/V
        pylab.subplot(224)
        pylab.grid(alpha=.5)
        pylab.title("command / measure relationship")
        pylab.xlabel("Command (%s)"%abf.unitsCommand)
        pylab.ylabel("Measurement (%s)"%abf.units)
        pylab.errorbar(Xs,AV,SD,capsize=0,marker='.',color=color)
        if abf.units=="pA":
            pylab.axhline(0,alpha=.5,lw=2,color='r',ls="--")
            pylab.axvline(-70,alpha=.5,lw=2,color='r',ls="--")
        else:
            pylab.axhline(-70,alpha=.5,lw=2,color='r',ls="--")
            pylab.axvline(0,alpha=.5,lw=2,color='r',ls="--")
        pylab.margins(.1,.1)
    annotate(abf)
    return AV,SD


Instruction:
Explain what the following Python 3 code does
def comments(abf,minutes=False):
    if not len(abf.commentTimes):
        return
    for i in range(len(abf.commentTimes)):
        t,c = abf.commentTimes[i],abf.commentTags[i]
        if minutes:
            t=t/60
        pylab.axvline(t,lw=1,color='r',ls="--",alpha=.5)
        X1,X2,Y1,Y2=pylab.axis()
        Y2=Y2-abs(Y2-Y1)*.02
        pylab.text(t,Y2,c,size=8,color='r',rotation='vertical',
                   ha='right',va='top',weight='bold',alpha=.5)
        if minutes:
            pylab.xlabel("minutes")
        else:
            pylab.xlabel("seconds")

Response: draw vertical lines at comment points. Defaults to seconds.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def dual(ABF):
    new(ABF)
    pylab.subplot(211)
    pylab.title("Input A (channel 0)")
    ABF.channel=0
    sweep(ABF)
    pylab.subplot(212)
    pylab.title("Input B (channel 1)")
    ABF.channel=1
    sweep(ABF)

Response: Plot two channels of current sweep ( top / bottom.


Instruction:
Implement a Python 3 function for
loading a particular sweep then plot it. If sweep is None or False, just plot current dataX/dataY. If rainbow, it'll make it color coded prettily.

Response:
def sweep(ABF,sweep=None,rainbow=True,alpha=None,protocol=False,color='b',
               continuous=False,offsetX=0,offsetY=0,minutes=False,
               decimate=None,newFigure=False):
    """
    Load a particular sweep then plot it.
    If sweep is None or False, just plot current dataX/dataY.
    If rainbow, it'll make it color coded prettily.
    """
    if len(pylab.get_fignums())==0 or newFigure:
        new(ABF,True)
    if offsetY>0:
        pylab.grid(None)

    # figure which sweeps to plot
    if sweep is None:
        sweeps=[ABF.currentSweep]
        if not ABF.currentSweep:
            sweeps=[0]
    elif sweep=="all":
        sweeps=range(0,ABF.sweeps)
    elif type(sweep) in [int,float]:
        sweeps=[int(sweep)]
    elif type(sweep) is list:
        sweeps=sweep
    else:
        print("DONT KNOW WHAT TO DO WITH THIS SWEEPS!!!\n",type(sweep),sweep)

    #figure out offsets:
    if continuous:
        offsetX=ABF.sweepInterval

    # determine the colors to use
    colors=[color]*len(sweeps) #detault to blue
    if rainbow and len(sweeps)>1:
        for i in range(len(sweeps)):
            colors[i]=ABF.colormap[i]
    if alpha is None and len(sweeps)==1:
        alpha=1
    if rainbow and alpha is None:
        alpha=.5

    # correct for alpha
    if alpha is None:
        alpha=1

    # conversion to minutes?
    if minutes == False:
        minutes=1
    else:
        minutes=60
        pylab.xlabel("minutes")

    ABF.decimateMethod=decimate
    # do the plotting of each sweep
    for i in range(len(sweeps)):
        ABF.setSweep(sweeps[i])
        if protocol:
            pylab.plot((np.array(ABF.protoX)/ABF.rate+offsetX*i)/minutes,
                       ABF.protoY+offsetY*i,
                       alpha=alpha,color=colors[i])
        else:
            pylab.plot((ABF.dataX+offsetX*i)/minutes,
                       ABF.dataY+offsetY*i,alpha=alpha,color=colors[i])
    ABF.decimateMethod=None
    pylab.margins(0,.02)


Instruction:
How would you explain what the following Python 3 function does
def annotate(abf):
    msg="SWHLab %s "%str(swhlab.VERSION)
    msg+="ID:%s "%abf.ID
    msg+="CH:%d "%abf.channel
    msg+="PROTOCOL:%s "%abf.protoComment
    msg+="COMMAND: %d%s "%(abf.holding,abf.units)
    msg+="GENERATED:%s "%'{0:%Y-%m-%d %H:%M:%S}'.format(datetime.datetime.now())
    pylab.annotate(msg,(.001,.001),xycoords='figure fraction',ha='left',
                   va='bottom',color='#999999',family='monospace',size=8,
                   weight='bold')
    if abf.nADC>1:
        msg="Ch %d/%d"%(abf.channel+1,abf.nADC)
        pylab.annotate(msg,(.01,.99),xycoords='figure fraction',ha='left',
                       va='top',color='#FF0000',family='monospace',size=12,
                       weight='bold')

Response: stamp the bottom with file info.


Instruction:
Explain what the following Python 3 code does
def new(ABF,forceNewFigure=False,title=None,xlabel=None,ylabel=None):
    if len(pylab.get_fignums()) and forceNewFigure==False:
        #print("adding to existing figure")
        return
    pylab.figure(figsize=(8,6))
    pylab.grid(alpha=.5)
    pylab.title(ABF.ID)
    pylab.ylabel(ABF.units)
    pylab.xlabel("seconds")
    if xlabel:
        pylab.xlabel(xlabel)
    if ylabel:
        pylab.ylabel(ylabel)
    if title:
        pylab.title(title)
    annotate(ABF)

Response: make a new matplotlib figure with default dims and DPI.


Instruction:
Explain what the following Python 3 code does
def save(abf,fname=None,tag=None,width=700,close=True,facecolor='w',
              resize=True):
    """
    Save the pylab figure somewhere.
    If fname==False, show it instead.
    Height force > dpi force
    if a tag is given instead of a filename, save it alongside the ABF
    """
    if len(pylab.gca().get_lines())==0:
        print("can't save, no figure!")
        return
    if resize:
        pylab.tight_layout()
        pylab.subplots_adjust(bottom=.1)
    annotate(abf)
    if tag:
        fname = abf.outpath+abf.ID+"_"+tag+".png"
    inchesX,inchesY = pylab.gcf().get_size_inches()
    dpi=width/inchesX
    if fname:
        if not os.path.exists(abf.outpath):
            os.mkdir(abf.outpath)
        print(" <- saving [%s] at %d DPI (%dx%d)"%(os.path.basename(fname),dpi,inchesX*dpi,inchesY*dpi))
        pylab.savefig(fname,dpi=dpi,facecolor=facecolor)
    else:
        pylab.show()
    if close:
        pylab.close()

Response: Save the current ABF to a file.


Instruction:
Can you implement a function in Python 3 that
tries to load a custom swhlab module from a local path.

Response:
def tryLoadingFrom(tryPath,moduleName='swhlab'):
    """if the module is in this path, load it from the local folder."""
    if not 'site-packages' in swhlab.__file__:
        print("loaded custom swhlab module from",
              os.path.dirname(swhlab.__file__))
        return # no need to warn if it's already outside.
    while len(tryPath)>5:
        sp=tryPath+"/swhlab/" # imaginary swhlab module path
        if os.path.isdir(sp) and os.path.exists(sp+"/__init__.py"):
            if not os.path.dirname(tryPath) in sys.path:
                sys.path.insert(0,os.path.dirname(tryPath))
            print("#"*80)
            print("# WARNING: using site-packages swhlab module")
            print("#"*80)
        tryPath=os.path.dirname(tryPath)
    return


Instruction:
Can you tell what is the following Python 3 function doing
def update(self, tids, info):
        outputs_dir = os.path.join(info['root_directory'], 'streams')
        pattern = '%s_*_tid_*{tid}.o.{tid}*' % info['batch_name']
        flist = os.listdir(outputs_dir)
        try:
            outputs = []
            for tid in tids:
                matches = fnmatch.filter(flist, pattern.format(tid=tid))
                if len(matches) != 1:
                    self.warning("No unique output file for tid %d" % tid)
                contents = open(os.path.join(outputs_dir, matches[0]),'r').read()
                outputs.append(self.output_extractor(contents))

            self._next_val = self._update_state(outputs)
            self.trace.append((outputs, self._next_val))
        except:
            self.warning("Cannot load required output files. Cannot continue.")
            self._next_val = StopIteration

Response: This method updates the state of the iterator.


Instruction:
Can you create a Python 3 function that
shows the current set of available key - values.

Response:
def show(self):
        """
        When dynamic, not all argument values may be available.
        """
        copied = self.copy()
        enumerated = [el for el in enumerate(copied)]
        for (group_ind, specs) in enumerated:
            if len(enumerated) > 1: print("Group %d" % group_ind)
            ordering = self.constant_keys + self.varying_keys
            # Ordered nicely by varying_keys definition.
            spec_lines = [', '.join(['%s=%s' % (k, s[k]) for k in ordering]) for s in specs]
            print('\n'.join(['%d: %s' % (i,l) for (i,l) in enumerate(spec_lines)]))

        print('Remaining arguments not available for %s' % self.__class__.__name__)


Instruction:
Can you generate the documentation for the following Python 3 function
def _trace_summary(self):
        for (i, (val, args)) in enumerate(self.trace):
            if args is StopIteration:
                info = "Terminated"
            else:
                pprint = ','.join('{' + ','.join('%s=%r' % (k,v)
                         for (k,v) in arg.items()) + '}' for arg in args)
                info = ("exploring arguments [%s]" % pprint )

            if i == 0: print("Step %d: Initially %s." % (i, info))
            else:      print("Step %d: %s after receiving input(s) %s." % (i, info.capitalize(), val))

Response:
Summarizes the trace of the values used to update the DynamicArgs
        and the arguments subsequently returned.


Instruction:
How would you explain what the following Python 3 function does
def proto_0111(theABF):
    abf=ABF(theABF)
    abf.log.info("analyzing as an IC ramp")

    # AP detection
    ap=AP(abf)
    ap.detect()

    # also calculate derivative for each sweep
    abf.derivative=True

    # create the multi-plot figure
    plt.figure(figsize=(SQUARESIZE,SQUARESIZE))
    ax1=plt.subplot(221)
    plt.ylabel(abf.units2)
    ax2=plt.subplot(222,sharey=ax1)
    ax3=plt.subplot(223)
    plt.ylabel(abf.unitsD2)
    ax4=plt.subplot(224,sharey=ax3)

    # put data in each subplot
    for sweep in range(abf.sweeps):
        abf.setsweep(sweep)
        ax1.plot(abf.sweepX,abf.sweepY,color='b',lw=.25)
        ax2.plot(abf.sweepX,abf.sweepY,color='b')
        ax3.plot(abf.sweepX,abf.sweepD,color='r',lw=.25)
        ax4.plot(abf.sweepX,abf.sweepD,color='r')

    # modify axis
    for ax in [ax1,ax2,ax3,ax4]: # everything
        ax.margins(0,.1)
        ax.grid(alpha=.5)
    for ax in [ax3,ax4]: # only derivative APs
        ax.axhline(-100,color='r',alpha=.5,ls="--",lw=2)
    for ax in [ax2,ax4]: # only zoomed in APs
        ax.get_yaxis().set_visible(False)
    if len(ap.APs):
        firstAP=ap.APs[0]["T"]
        ax2.axis([firstAP-.25,firstAP+.25,None,None])
        ax4.axis([firstAP-.01,firstAP+.01,None,None])

    # show message from first AP
    if len(ap.APs):
        firstAP=ap.APs[0]
        msg="\n".join(["%s = %s"%(x,str(firstAP[x])) for x in sorted(firstAP.keys()) if not "I" in x[-2:]])
        plt.subplot(221)
        plt.gca().text(0.02, 0.98, msg, transform= plt.gca().transAxes, fontsize=10, verticalalignment='top', family='monospace')

    # save it
    plt.tight_layout()
    frameAndSave(abf,"AP shape")
    plt.close('all')

Response: protocol: IC ramp for AP shape analysis


Instruction:
Make a summary of the following Python 3 code
def proto_gain(theABF,stepSize=25,startAt=-100):
    abf=ABF(theABF)
    abf.log.info("analyzing as an IC ramp")
    plot=ABFplot(abf)
    plot.kwargs["lw"]=.5
    plot.title=""
    currents=np.arange(abf.sweeps)*stepSize-startAt

    # AP detection
    ap=AP(abf)
    ap.detect_time1=.1
    ap.detect_time2=.7
    ap.detect()

    # stacked plot
    plt.figure(figsize=(SQUARESIZE,SQUARESIZE))

    ax1=plt.subplot(221)
    plot.figure_sweeps()

    ax2=plt.subplot(222)
    ax2.get_yaxis().set_visible(False)
    plot.figure_sweeps(offsetY=150)

    # add vertical marks to graphs:
    for ax in [ax1,ax2]:
        for limit in [ap.detect_time1,ap.detect_time2]:
            ax.axvline(limit,color='r',ls='--',alpha=.5,lw=2)

    # make stacked gain function
    ax4=plt.subplot(223)
    plt.ylabel("frequency (Hz)")
    plt.ylabel("seconds")
    plt.grid(alpha=.5)
    freqs=ap.get_bySweep("freqs")
    times=ap.get_bySweep("times")
    for i in range(abf.sweeps):
        if len(freqs[i]):
            plt.plot(times[i][:-1],freqs[i],'-',alpha=.5,lw=2,
                     color=plot.getColor(i/abf.sweeps))

    # make gain function graph
    ax4=plt.subplot(224)
    ax4.grid(alpha=.5)
    plt.plot(currents,ap.get_bySweep("median"),'b.-',label="median")
    plt.plot(currents,ap.get_bySweep("firsts"),'g.-',label="first")
    plt.xlabel("applied current (pA)")
    plt.legend(loc=2,fontsize=10)
    plt.axhline(40,color='r',alpha=.5,ls="--",lw=2)
    plt.margins(.02,.1)

    # save it
    plt.tight_layout()
    frameAndSave(abf,"AP Gain %d_%d"%(startAt,stepSize))
    plt.close('all')

    # make a second figure that just shows every sweep up to the first AP
    plt.figure(figsize=(SQUARESIZE,SQUARESIZE))
    plt.grid(alpha=.5)
    plt.ylabel("Membrane Potential (mV)")
    plt.xlabel("Time (seconds)")
    for sweep in abf.setsweeps():
        plt.plot(abf.sweepX2,abf.sweepY,color='b',alpha=.5)
        if np.max(abf.sweepY>0):
            break
    plt.tight_layout()
    plt.margins(0,.1)

    plt.axis([0,1,None,None])
    plt.title("%d pA Steps from Rest"%stepSize)
    frameAndSave(abf,"voltage response fromRest",closeWhenDone=False)
    plt.axis([1.5,2.5,None,None])
    plt.title("%d pA Steps from %d pA"%(stepSize,startAt))
    frameAndSave(abf,"voltage response hyperpol",closeWhenDone=False)
    plt.close('all')

Response: protocol: gain function of some sort. step size and start at are pA.


Instruction:
Write a Python 3 function for
protocolling : membrane test

Response:
def proto_0201(theABF):
    """protocol: membrane test."""
    abf=ABF(theABF)
    abf.log.info("analyzing as a membrane test")
    plot=ABFplot(abf)
    plot.figure_height,plot.figure_width=SQUARESIZE/2,SQUARESIZE/2
    plot.figure_sweeps()

    # save it
    plt.tight_layout()
    frameAndSave(abf,"membrane test")
    plt.close('all')


Instruction:
Can you implement a function in Python 3 that
protocols 2. 0. 1. 2. 1

Response:
def proto_0202(theABF):
    """protocol: MTIV."""
    abf=ABF(theABF)
    abf.log.info("analyzing as MTIV")
    plot=ABFplot(abf)
    plot.figure_height,plot.figure_width=SQUARESIZE,SQUARESIZE
    plot.title=""
    plot.kwargs["alpha"]=.6
    plot.figure_sweeps()

    # frame to uppwer/lower bounds, ignoring peaks from capacitive transients
    abf.setsweep(0)
    plt.axis([None,None,abf.average(.9,1)-100,None])
    abf.setsweep(-1)
    plt.axis([None,None,None,abf.average(.9,1)+100])

    # save it
    plt.tight_layout()
    frameAndSave(abf,"MTIV")
    plt.close('all')


Instruction:
How would you explain what the following Python 3 function does
def proto_0203(theABF):
    abf=ABF(theABF)
    abf.log.info("analyzing as a fast IV")
    plot=ABFplot(abf)
    plot.title=""
    m1,m2=.7,1
    plt.figure(figsize=(SQUARESIZE,SQUARESIZE/2))

    plt.subplot(121)
    plot.figure_sweeps()
    plt.axvspan(m1,m2,color='r',ec=None,alpha=.1)

    plt.subplot(122)
    plt.grid(alpha=.5)
    Xs=np.arange(abf.sweeps)*5-110
    Ys=[]
    for sweep in range(abf.sweeps):
        abf.setsweep(sweep)
        Ys.append(abf.average(m1,m2))
    plt.plot(Xs,Ys,'.-',ms=10)
    plt.axvline(-70,color='r',ls='--',lw=2,alpha=.5)
    plt.axhline(0,color='r',ls='--',lw=2,alpha=.5)
    plt.margins(.1,.1)
    plt.xlabel("membrane potential (mV)")

    # save it
    plt.tight_layout()
    frameAndSave(abf,"fast IV")
    plt.close('all')

Response: protocol : vast IV


Instruction:
Here you have a function in Python 3, explain what it does
def proto_0303(theABF):

    abf=ABF(theABF)
    abf.log.info("analyzing as a halorhodopsin (2s pulse)")

    # show average voltage
    proto_avgRange(theABF,0.2,1.2)
    plt.close('all')

    # show stacked sweeps
    plt.figure(figsize=(8,8))
    for sweep in abf.setsweeps():
        color='b'
        if sweep in np.array(abf.comment_sweeps,dtype=int):
            color='r'
        plt.plot(abf.sweepX2,abf.sweepY+100*sweep,color=color,alpha=.5)
    plt.margins(0,.01)
    plt.tight_layout()
    frameAndSave(abf,"IC ramps")
    plt.close('all')

    # do AP event detection
    ap=AP(abf)
    ap.detect_time1=2.3
    ap.detect_time2=8.3
    ap.detect()
    apCount=[]
    apSweepTimes=[]

    for sweepNumber,times in enumerate(ap.get_bySweep("times")):
        apCount.append(len(times))
        if len(times):
            apSweepTimes.append(times[0])
        else:
            apSweepTimes.append(0)

    # plot AP frequency vs time
    plt.figure(figsize=(8,8))

    ax1=plt.subplot(211)
    plt.grid(alpha=.4,ls='--')
    plt.plot(np.arange(len(apCount))*abf.sweepLength/60,apCount,'.-',ms=15)
    comment_lines(abf)
    plt.ylabel("AP Count")

    plt.subplot(212,sharex=ax1)
    plt.grid(alpha=.4,ls='--')
    plt.plot(np.arange(len(apCount))*abf.sweepLength/60,apSweepTimes,'.-',ms=15)
    comment_lines(abf)
    plt.ylabel("First AP Time (s)")
    plt.xlabel("Experiment Duration (minutes)")
    plt.tight_layout()
    frameAndSave(abf,"IC ramp freq")
    plt.close('all')

Response: protocol: repeated IC ramps.


Instruction:
Create a Python 3 function for
protocolling for repeated IC steps.

Response:
def proto_0304(theABF):
    """protocol: repeated IC steps."""

    abf=ABF(theABF)
    abf.log.info("analyzing as repeated current-clamp step")

    # prepare for AP analysis
    ap=AP(abf)

    # calculate rest potential
    avgVoltagePerSweep = [];
    times = []
    for sweep in abf.setsweeps():
        avgVoltagePerSweep.append(abf.average(0,3))
        times.append(abf.sweepStart/60)

    # detect only step APs
    M1,M2=3.15,4.15
    ap.detect_time1, ap.detect_time2 = M1,M2
    ap.detect()
    apsPerSweepCos=[len(x) for x in ap.get_bySweep()]

    # detect all APs
    M1,M2=0,10
    ap.detect_time1, ap.detect_time2 = M1,M2
    ap.detect()
    apsPerSweepRamp=[len(x) for x in ap.get_bySweep()]

    # make the plot of APs and stuff
    plt.figure(figsize=(8,8))

    plt.subplot(311)
    plt.grid(ls='--',alpha=.5)
    plt.plot(times,avgVoltagePerSweep,'.-')
    plt.ylabel("Rest Potential (mV)")
    comment_lines(abf)

    plt.subplot(312)
    plt.grid(ls='--',alpha=.5)
    plt.plot(times,apsPerSweepCos,'.-')
    plt.ylabel("APs in Step (#)")
    comment_lines(abf)

    plt.subplot(313)
    plt.grid(ls='--',alpha=.5)
    plt.plot(times,apsPerSweepRamp,'.-')
    plt.ylabel("APs in Sweep (#)")
    comment_lines(abf)

    plt.tight_layout()

    frameAndSave(abf,"cos ramp")
    plt.close('all')


Instruction:
Can you tell what is the following Python 3 function doing
def proto_avgRange(theABF,m1=None,m2=None):

    abf=ABF(theABF)
    abf.log.info("analyzing as a fast IV")
    if m1 is None:
        m1=abf.sweepLength
    if m2 is None:
        m2=abf.sweepLength

    I1=int(abf.pointsPerSec*m1)
    I2=int(abf.pointsPerSec*m2)

    Ts=np.arange(abf.sweeps)*abf.sweepInterval
    Yav=np.empty(abf.sweeps)*np.nan # average
    Ysd=np.empty(abf.sweeps)*np.nan # standard deviation
    #Yar=np.empty(abf.sweeps)*np.nan # area

    for sweep in abf.setsweeps():
        Yav[sweep]=np.average(abf.sweepY[I1:I2])
        Ysd[sweep]=np.std(abf.sweepY[I1:I2])
        #Yar[sweep]=np.sum(abf.sweepY[I1:I2])/(I2*I1)-Yav[sweep]

    plot=ABFplot(abf)
    plt.figure(figsize=(SQUARESIZE*2,SQUARESIZE/2))

    plt.subplot(131)
    plot.title="first sweep"
    plot.figure_sweep(0)
    plt.title("First Sweep\n(shaded measurement range)")
    plt.axvspan(m1,m2,color='r',ec=None,alpha=.1)

    plt.subplot(132)
    plt.grid(alpha=.5)
    for i,t in enumerate(abf.comment_times):
        plt.axvline(t/60,color='r',alpha=.5,lw=2,ls='--')
    plt.plot(Ts/60,Yav,'.',alpha=.75)
    plt.title("Range Average\nTAGS: %s"%(", ".join(abf.comment_tags)))
    plt.ylabel(abf.units2)
    plt.xlabel("minutes")
    plt.margins(0,.1)

    plt.subplot(133)
    plt.grid(alpha=.5)
    for i,t in enumerate(abf.comment_times):
        plt.axvline(t/60,color='r',alpha=.5,lw=2,ls='--')
    plt.plot(Ts/60,Ysd,'.',alpha=.5,color='g',ms=15,mew=0)
    #plt.fill_between(Ts/60,Ysd*0,Ysd,lw=0,alpha=.5,color='g')
    plt.title("Range Standard Deviation\nTAGS: %s"%(", ".join(abf.comment_tags)))
    plt.ylabel(abf.units2)
    plt.xlabel("minutes")
    plt.margins(0,.1)
    plt.axis([None,None,0,np.percentile(Ysd,99)*1.25])

    plt.tight_layout()
    frameAndSave(abf,"sweep vs average","experiment")
    plt.close('all')

Response: experiment: generic VC time course experiment


Instruction:
Can you tell what is the following Python 3 function doing
def analyze(fname=False,save=True,show=None):
    if fname and os.path.exists(fname.replace(".abf",".rst")):
        print("SKIPPING DUE TO RST FILE")
        return
    swhlab.plotting.core.IMAGE_SAVE=save
    if show is None:
        if cm.isIpython():
            swhlab.plotting.core.IMAGE_SHOW=True
        else:
            swhlab.plotting.core.IMAGE_SHOW=False
    #swhlab.plotting.core.IMAGE_SHOW=show
    abf=ABF(fname) # ensure it's a class
    print(">>>>> PROTOCOL >>>>>",abf.protocomment)
    runFunction="proto_unknown"
    if "proto_"+abf.protocomment in globals():
        runFunction="proto_"+abf.protocomment
    abf.log.debug("running %s()"%(runFunction))
    plt.close('all') # get ready
    globals()[runFunction](abf) # run that function
    try:
        globals()[runFunction](abf) # run that function
    except:
        abf.log.error("EXCEPTION DURING PROTOCOL FUNCTION")
        abf.log.error(sys.exc_info()[0])
        return "ERROR"
    plt.close('all') # clean up
    return "SUCCESS"

Response: try to analyze a file or ABF object


Instruction:
Here you have a function in Python 3, explain what it does
def processFolder(abfFolder):
    if not type(abfFolder) is str or not len(abfFolder)>3:
        return
    files=sorted(glob.glob(abfFolder+"/*.abf"))
    for i,fname in enumerate(files):
        print("\n\n\n### PROCESSING {} of {}:".format(i,len(files)),os.path.basename(fname))
        processAbf(fname,show=False)
    plt.show()
    return

Response: call processAbf for every ABF in a folder


Instruction:
Make a summary of the following Python 3 code
def processAbf(abfFname,saveAs=False,dpi=100,show=True):
    if not type(abfFname) is str or not len(abfFname)>3:
        return
    abf=swhlab.ABF(abfFname)
    plot=swhlab.plotting.ABFplot(abf)
    plot.figure_height=6
    plot.figure_width=10
    plot.subplot=False
    plot.figure(True)
    if abf.get_protocol_sequence(0)==abf.get_protocol_sequence(1) or abf.sweeps<2:
        # same protocol every time
        if abf.lengthMinutes<2:
            # short (probably a memtest or tau)
            ax1=plt.subplot(211)
            plot.figure_sweeps()
            plt.title("{} ({} sweeps)".format(abf.ID,abf.sweeps))
            plt.gca().get_xaxis().set_visible(False)
            plt.subplot(212,sharex=ax1)
            plot.figure_protocol()
            plt.title("")
        else:
            # long (probably a drug experiment)
            plot.figure_chronological()
    else:
        # protocol changes every sweep
        plots=[211,212] # assume we want 2 images
        if abf.units=='mV': # maybe it's something with APs?
            ap=swhlab.AP(abf) # go ahead and do AP detection
            ap.detect() # try to detect APs
            if len(ap.APs): # if we found some
                plots=[221,223,222,224] # get ready for 4 images
        ax1=plt.subplot(plots[0])
        plot.figure_sweeps()
        plt.title("{} ({} sweeps)".format(abf.ID,abf.sweeps))
        plt.gca().get_xaxis().set_visible(False)
        plt.subplot(plots[1],sharex=ax1)
        plot.figure_protocols()
        plt.title("protocol")
        if len(plots)>2:
            # assume we want to look at the first AP
            ax2=plt.subplot(plots[2])
            plot.rainbow=False
            plot.kwargs["color"]='b'
            plot.figure_chronological()
            plt.gca().get_xaxis().set_visible(False)
            plt.title("first AP magnitude")
            # velocity plot
            plt.subplot(plots[3],sharex=ax2)
            plot.abf.derivative=True
            plot.rainbow=False
            plot.traceColor='r'
            plot.figure_chronological()
            plt.axis([ap.APs[0]["T"]-.05,ap.APs[0]["T"]+.05,None,None])
            plt.title("first AP velocity")

    if saveAs:
        print("saving",os.path.abspath(saveAs))
        plt.savefig(os.path.abspath(saveAs),dpi=dpi)
        return
    if show:
        plot.show()

Response: Process an ABF and return a tuple of the ID and the image.


Instruction:
Make a summary of the following Python 3 code
def frameAndSave(abf,tag="",dataType="plot",saveAsFname=False,closeWhenDone=True):
    print("closeWhenDone",closeWhenDone)
    plt.tight_layout()
    plt.subplots_adjust(top=.93,bottom =.07)
    plt.annotate(tag,(.01,.99),xycoords='figure fraction',ha='left',va='top',family='monospace',size=10,alpha=.5)
    msgBot="%s [%s]"%(abf.ID,abf.protocomment)
    plt.annotate(msgBot,(.01,.01),xycoords='figure fraction',ha='left',va='bottom',family='monospace',size=10,alpha=.5)
    fname=tag.lower().replace(" ",'_')+".jpg"
    fname=dataType+"_"+fname
    plt.tight_layout()
    if IMAGE_SAVE:
        abf.log.info("saving [%s]",fname)
        try:
            if saveAsFname:
                saveAs=os.path.abspath(saveAsFname)
            else:
                saveAs=os.path.abspath(abf.outPre+fname)
            if not os.path.exists(abf.outFolder):
                os.mkdir(abf.outFolder)
            plt.savefig(saveAs)
        except Exception as E:
            abf.log.error("saving [%s] failed! 'pip install pillow'?",fname)
            print(E)
    if IMAGE_SHOW==True:
        if closeWhenDone==False:
            print("NOT SHOWING (because closeWhenDone==True and showing would mess things up)")
        else:
            abf.log.info("showing [%s]",fname)
            plt.show()
    if closeWhenDone:
        print("closing figure")
        plt.close('all')

Response: frame the current matplotlib plot with ABF info and optionally save it.


Instruction:
Given the following Python 3 function, write the documentation
def figure(self,forceNew=False):
        if plt._pylab_helpers.Gcf.get_num_fig_managers()>0 and forceNew is False:
            self.log.debug("figure already seen, not creating one.")
            return

        if self.subplot:
            self.log.debug("subplot mode enabled, not creating new figure")
        else:
            self.log.debug("creating new figure")
            plt.figure(figsize=(self.figure_width,self.figure_height))

Response: make sure a figure is ready.


Instruction:
Implement a Python 3 function for
saving the existing figure. does not close it.

Response:
def save(self,callit="misc",closeToo=True,fullpath=False):
        """save the existing figure. does not close it."""
        if fullpath is False:
            fname=self.abf.outPre+"plot_"+callit+".jpg"
        else:
            fname=callit
        if not os.path.exists(os.path.dirname(fname)):
            os.mkdir(os.path.dirname(fname))
        plt.savefig(fname)
        self.log.info("saved [%s]",os.path.basename(fname))
        if closeToo:
            plt.close()


Instruction:
Write a Python 3 function that can
add comments to an existing plot.

Response:
def comments(self,minutes=False):
        """
        Add comment lines/text to an existing plot. Defaults to seconds.
        Call after a plot has been made, and after margins have been set.
        """
        if self.comments==0:
            return
        self.log.debug("adding comments to plot")
        for i,t in enumerate(self.abf.comment_times):
            if minutes:
                t/=60.0
            plt.axvline(t,color='r',ls=':')
            X1,X2,Y1,Y2=plt.axis()
            Y2=Y2-abs(Y2-Y1)*.02
            plt.text(t,Y2,self.abf.comment_tags[i],color='r',rotation='vertical',
                     ha='right',va='top',weight='bold',alpha=.5,size=8,)


Instruction:
Create a Python 3 function for
creating a chronological plot of every sweep of an ABF file

Response:
def figure_chronological(self):
        """plot every sweep of an ABF file (with comments)."""
        self.log.debug("creating chronological plot")
        self.figure()
        for sweep in range(self.abf.sweeps):
            self.abf.setsweep(sweep)
            self.setColorBySweep()
            if self.abf.derivative:
                plt.plot(self.abf.sweepX,self.abf.sweepD,**self.kwargs)
            else:
                plt.plot(self.abf.sweepX,self.abf.sweepY,**self.kwargs)
        self.comments()
        self.decorate()


Instruction:
How would you explain what the following Python 3 function does
def figure_sweeps(self, offsetX=0, offsetY=0):
        self.log.debug("creating overlayed sweeps plot")
        self.figure()
        for sweep in range(self.abf.sweeps):
            self.abf.setsweep(sweep)
            self.setColorBySweep()
            plt.plot(self.abf.sweepX2+sweep*offsetX,
                     self.abf.sweepY+sweep*offsetY,
                     **self.kwargs)
        if offsetX:
            self.marginX=.05
        self.decorate()

Response: This function creates the overlayed sweeps plot for each sweep of an ABF file.


Instruction:
How would you explain what the following Python 3 function does
def figure_protocol(self):
        self.log.debug("creating overlayed protocols plot")
        self.figure()
        plt.plot(self.abf.protoX,self.abf.protoY,color='r')
        self.marginX=0
        self.decorate(protocol=True)

Response: create the overlayed sweep protocol plot


Instruction:
Can you create a Python 3 function that
creates overlayed protocols plot

Response:
def figure_protocols(self):
        """plot the protocol of all sweeps."""
        self.log.debug("creating overlayed protocols plot")
        self.figure()
        for sweep in range(self.abf.sweeps):
            self.abf.setsweep(sweep)
            plt.plot(self.abf.protoX,self.abf.protoY,color='r')
        self.marginX=0
        self.decorate(protocol=True)


Instruction:
Given the following Python 3 function, write the documentation
def fread(f,byteLocation,structFormat=None,nBytes=1):
    f.seek(byteLocation)
    if structFormat:
        val = struct.unpack(structFormat, f.read(struct.calcsize(structFormat)))
        val = val[0] if len(val)==1 else list(val)
        return val
    else:
        return f.read(nBytes)

Response: Reads a certain number of bytes from a file object f.


Instruction:
Implement a function in Python 3 to
read the header of an ABF file into memory.

Response:
def abf_read_header(fname, saveHeader=True):
    """
    Practice pulling data straight out of an ABF's binary header. Support only ABF2 (ClampEx an ClampFit 10).
    Use only native python libraries. Strive for simplicity and readability (to promote language portability).
    This was made by Scott Harden after a line-by-line analysis of axonrawio.py from the neo io library.
    Unlike NeoIO's format, I'm going to try to prevent nested dictionaries to keep things simple.
    """

    ### THESE OBJETS WILL BE FULL WHEN THIS FUNCTION IS COMPLETE
    header={} # information about the file format
    sections={} # contains byte positions (and block sizes) for header information
    strings=[] # a list of strings stored in the ABF header (protocol file, abf comment, and channel labels / units)
    protocol = {} # info about the ABF recording
    tags=[] # timed comments made during the abf as a list of lists [pos,comment,tagtype,voice]
    adcs=[] # ADC info as a list of dicts
    dacs=[] # DAC info as a list of dicts
    digitalOutputs=[] # one 0b00000000 code per epoch
    config={} # a concise collection of ABF info I think is useful. I intend only to return this object.

    ### READ THE FIRST PART OF THE FILE INTO MEMORY
    # TODO: figure out the most memory-effecient way to do this
    f=open(fname,'rb')
    config["abf_filename"]=os.path.abspath(fname) # full path to the abf file on disk
    config["abf_ID"]=os.path.basename(fname)[:-4] # abf filename without the ".abf"

    ### DECODE HEADER - this tells basic information about the file format
    for key, byte_location, fmt in headerDescriptionV2:
        header[key]=fread(f,byte_location,fmt)
    header['fFileSignature']=header['fFileSignature'].decode()

    ### DECODE SECTIONS - sections are where (byte location) in this file different data is stored
    for sectionNumber, sectionName in enumerate(sectionNames):
        uBlockIndex, uBytes, llNumEntries = fread(f,76+sectionNumber*16,"IIl")
        sections[sectionName] = [uBlockIndex,uBytes,llNumEntries]
    config["abf_sweep_start_time"]=header['uFileStartTimeMS']/1000/1000

    ### DECODE STRINGS - figure out where (byte location) strings are in this file
    # There are 20 strings. Protocol path, ABF comment, then alternating channel name and units.
    byte_location = sections['StringsSection'][0]*BLOCKSIZE
    string_size = sections['StringsSection'][1]
    strings_data = fread(f,byte_location,structFormat=None,nBytes=string_size)
    for key in [b'AXENGN', b'clampex', b'Clampex', b'CLAMPEX', b'axoscope']:
        if key in strings_data:
            for line in strings_data.split(key)[1].split(b'\x00')[1:-1]:
                strings.append(line.decode())
            config["abf_protocol_file"]=strings[0]
            config["abf_comment"]=strings[1]
            config["abf_channels"]=strings[2::2]
            config["abf_units"]=strings[3::2]
            break

    ### DECODE ADC INFO - a list of dictionaries, one per ADC employed
    for ADCsection in range(sections['ADCSection'][2]):
        thisADC={}
        byte_location=sections['ADCSection'][0]*BLOCKSIZE+sections['ADCSection'][1]*ADCsection
        for key, fmt in ADCInfoDescription:
            thisADC[key]=fread(f,byte_location,fmt)
            byte_location+=struct.calcsize(fmt)
        adcs.append(thisADC)

    ### PROTOCOL - info about the nature of the recording
    byte_location=sections['ProtocolSection'][0]*BLOCKSIZE
    for key, fmt in protocolInfoDescription:
        protocol[key]=fread(f,byte_location,fmt)
        byte_location+=struct.calcsize(fmt)
    protocol.pop('sUnused', None) # we don't need this

    ### TAGS (COMMMENTS) - those with a timestamp/comment (not those embedded in the protocol)
    #TODO: not sure what the tagtime units actually are. Byte positions? Block number?
    byte_location=sections['TagSection'][0]*BLOCKSIZE
    for i in range(sections['TagSection'][2]):
        thisTag=[]
        for key, fmt in TagInfoDescription:
            val=fread(f,byte_location,fmt)
            if type(val) is bytes:
                val=val.decode().strip()
            thisTag.append(val)
            byte_location+=struct.calcsize(fmt)
        tags.append(thisTag)

    ### DAC SECTIONS
    for dacNumber in range(sections['DACSection'][2]):
        thisDAC={}
        byte_location=sections['DACSection'][0]*BLOCKSIZE+sections['DACSection'][1]*dacNumber
        for key, fmt in DACInfoDescription:
            thisDAC[key]=fread(f,byte_location,fmt)
            byte_location+=struct.calcsize(fmt)
        thisDAC.pop('sUnused', None) # we don't need this
        if thisDAC['nWaveformEnable']==0: continue # don't record unused DACs
        dacs.append(thisDAC)

    ### EPOCHS PER DAC - this is what appear on the waveform tab
    epochs=[]
    for epochNumber in range(sections['EpochPerDACSection'][2]):
        thisEpoch={}
        byte_location=sections['EpochPerDACSection'][0]*BLOCKSIZE+sections['EpochPerDACSection'][1]*epochNumber
        for key, fmt in EpochInfoPerDACDescription:
            thisEpoch[key]=fread(f,byte_location,fmt)
            byte_location+=struct.calcsize(fmt)
        thisEpoch.pop('sUnused', None) # we don't need this
        epochs.append(thisEpoch)

    ### DIGITAL OUTPUTS - this is where digital outputs are stored. Returns binary string (7-0)
    # this does not exist in Neo IO. It was hacked-in by Scott Harden (github: swharden) to capture digital outputs.
    # let's just add the digital output string to the epochs array we already have started.
    byte_location=sections['EpochSection'][0]*BLOCKSIZE
    for epochNumber in range(sections['EpochSection'][0]):
        if epochNumber>=len(epochs):
            break # don't bother looking up unused epochs
        thisEpoch=epochs[epochNumber]
        for key, fmt in EpochSectionDescription:
            val=fread(f,byte_location,fmt)
            if key=='nEpochDigitalOutput':
                val=format(val, 'b').rjust(8,'0') # convert to a binary string (7->0)
            thisEpoch[key]=val
            byte_location+=struct.calcsize(fmt)
        thisEpoch.pop('sUnused', None) # we don't need this
        epochs[epochNumber]=thisEpoch

    ### WE ARE DONE READING THE FILE
    f.close()

    ### EXTRA CONFIG - cherry-pick just what I find useful and arrange it in a simple dictionary
    config["abfVersion"]=float("".join([str(x) for x in header['fFileVersionNumber']]))/100 # now a float
    config['signalNames']=config['abf_channels'][:len(adcs)] # don't need more than the number of channels
    config['signalUnits']=config['abf_units'][:len(adcs)] # don't need more than the number of channels
    config['comments']=[x[:2] for x in tags]
    config['nSweeps']=sections['SynchArraySection'][2]

    # Determine the recording date from the header
    YY = int(header['uFileStartDate'] / 10000)
    MM = int((header['uFileStartDate'] - YY * 10000) / 100)
    DD = int(header['uFileStartDate'] - YY * 10000 - MM * 100)
    hh = int(header['uFileStartTimeMS'] / 1000. / 3600.)
    mm = int((header['uFileStartTimeMS'] / 1000. - hh * 3600) / 60)
    ss = header['uFileStartTimeMS'] / 1000. - hh * 3600 - mm * 60
    ms = int((ss%1)*1e6)
    ss = int(ss)
    config['abf_datetime'] = datetime.datetime(YY, MM, DD, hh, mm, ss, ms)


Instruction:
How would you implement a function in Python 3 that
creates and save a two column frames HTML file.

Response:
def frames(fname=None,menuWidth=200,launch=False):
    """create and save a two column frames HTML file."""
    html="""
    <frameset cols="%dpx,*%%">
    <frame name="menu" src="index_menu.html">
    <frame name="content" src="index_splash.html">
    </frameset>"""%(menuWidth)
    with open(fname,'w') as f:
        f.write(html)
    if launch:
        webbrowser.open(fname)


Instruction:
Write a Python 3 function for
saving HTML to disk

Response:
def save(html,fname=None,launch=False):
    """wrap HTML in a top and bottom (with css) and save to disk."""
    html=html_top+html+html_bot
    html=html.replace("~GENAT~",swhlab.common.datetimeToString())
    if fname is None:
        fname = tempfile.gettempdir()+"/temp.html"
        launch=True
    fname=os.path.abspath(fname)
    with open(fname,'w') as f:
        f.write(html)

    global stylesheetSaved
    stylesheetPath=os.path.join(os.path.dirname(fname),"style.css")
    if not os.path.exists(stylesheetPath) or stylesheetSaved is False:
        with open(stylesheetPath,'w') as f:
            f.write(stylesheet)
            stylesheetSaved=True
    if launch:
        webbrowser.open(fname)


Instruction:
Write a Python 3 script for
renaming all files in a tree with the given character.

Response:
def clampfit_rename(path,char):
    """
    Given ABFs and TIFs formatted long style, rename each of them to prefix their number with a different number.

    Example: 2017_10_11_0011.abf
    Becomes: 2017_10_11_?011.abf
    where ? can be any character.
    """
    assert len(char)==1 and type(char)==str, "replacement character must be a single character"
    assert os.path.exists(path), "path doesn't exist"
    files = sorted(os.listdir(path))
    files = [x for x in files if len(x)>18 and x[4]+x[7]+x[10]=='___']
    for fname in files:
        fname2 = list(fname)
        fname2[11]=char
        fname2="".join(fname2)

        if fname==fname2:
            print(fname, "==", fname2)
        else:
            print(fname, "->", fname2)
#            fname=os.path.join(path,fname)
#            fname2=os.path.join(path,fname2)
#            if not os.path.exists(fname2):
#                os.rename(fname,fname2)
    return


Instruction:
Create a Python 3 function to
return a 1d gassuan array of a given size and sigma.

Response:
def kernel_gaussian(size=100, sigma=None, forwardOnly=False):
    """
    return a 1d gassuan array of a given size and sigma.
    If sigma isn't given, it will be 1/10 of the size, which is usually good.
    """
    if sigma is None:sigma=size/10
    points=np.exp(-np.power(np.arange(size)-size/2,2)/(2*np.power(sigma,2)))
    if forwardOnly:
        points[:int(len(points)/2)]=0
    return points/sum(points)


Instruction:
Write a Python 3 script for
giving a list of files return a dict organized by extension.

Response:
def filesByExtension(fnames):
    """given a list of files, return a dict organized by extension."""
    byExt={"abf":[],"jpg":[],"tif":[]} # prime it with empties
    for fname in fnames:
        ext = os.path.splitext(fname)[1].replace(".",'').lower()
        if not ext in byExt.keys():
            byExt[ext]=[]
        byExt[ext]=byExt[ext]+[fname]
    return byExt


Instruction:
Here you have a function in Python 3, explain what it does
def findCells(fnames):
    IDs=[]
    filesByExt = filesByExtension(fnames)
    for abfFname in filesByExt['abf']:
        ID=os.path.splitext(abfFname)[0]
        for picFname in filesByExt['jpg']+filesByExt['tif']:
            if picFname.startswith(ID):
                IDs.append(ID)
                break
    return smartSort(IDs)

Response: Given a list of files return a list of cells by their ID.


Instruction:
Make a summary of the following Python 3 code
def filesByCell(fnames,cells):
    byCell={}
    fnames=smartSort(fnames)
    days = list(set([elem[:5] for elem in fnames if elem.endswith(".abf")])) # so pythonic!
    for day in smartSort(days):
        parent=None
        for i,fname in enumerate([elem for elem in fnames if elem.startswith(day) and elem.endswith(".abf")]):
            ID=os.path.splitext(fname)[0]
            if len([x for x in fnames if x.startswith(ID)])-1:
                parent=ID
            if not parent in byCell:
                byCell[parent]=[]
            byCell[parent]=byCell[parent]+[fname]
    return byCell

Response: given files and cells return a dict of files grouped by cell.


Instruction:
Can you implement a function in Python 3 that
populates class properties relating to files in the folder.

Response:
def folderScan(self,abfFolder=None):
        """populate class properties relating to files in the folder."""
        if abfFolder is None and 'abfFolder' in dir(self):
            abfFolder=self.abfFolder
        else:
            self.abfFolder=abfFolder
        self.abfFolder=os.path.abspath(self.abfFolder)
        self.log.info("scanning [%s]",self.abfFolder)
        if not os.path.exists(self.abfFolder):
            self.log.error("path doesn't exist: [%s]",abfFolder)
            return
        self.abfFolder2=os.path.abspath(self.abfFolder+"/swhlab/")
        if not os.path.exists(self.abfFolder2):
            self.log.error("./swhlab/ doesn't exist. creating it...")
            os.mkdir(self.abfFolder2)
        self.fnames=os.listdir(self.abfFolder)
        self.fnames2=os.listdir(self.abfFolder2)
        self.log.debug("./ has %d files",len(self.fnames))
        self.log.debug("./swhlab/ has %d files",len(self.fnames2))
        self.fnamesByExt = filesByExtension(self.fnames)
        if not "abf" in self.fnamesByExt.keys():
            self.log.error("no ABF files found")
        self.log.debug("found %d ABFs",len(self.fnamesByExt["abf"]))

        self.cells=findCells(self.fnames) # list of cells by their ID
        self.log.debug("found %d cells"%len(self.cells))

        self.fnamesByCell = filesByCell(self.fnames,self.cells) # only ABFs
        self.log.debug("grouped cells by number of source files: %s"%\
            str([len(self.fnamesByCell[elem]) for elem in self.fnamesByCell]))


Instruction:
Can you implement a function in Python 3 that
generates list of cells with links and links. keep this simple.

Response:
def html_index(self,launch=False,showChildren=False):
        """
        generate list of cells with links. keep this simple.
        automatically generates splash page and regnerates frames.
        """
        self.makePics() # ensure all pics are converted
        # generate menu
        html='<a href="index_splash.html" target="content">./%s/</a><br>'%os.path.basename(self.abfFolder)
        for ID in smartSort(self.fnamesByCell.keys()):
            link=''
            if ID+".html" in self.fnames2:
                link='href="%s.html" target="content"'%ID
            html+=('<a %s>%s</a><br>'%(link,ID)) # show the parent ABF (ID)
            if showChildren:
                for fname in self.fnamesByCell[ID]:
                    thisID=os.path.splitext(fname)[0]
                    files2=[x for x in self.fnames2 if x.startswith(thisID) and not x.endswith(".html")]
                    html+='<i>%s</i>'%thisID # show the child ABF
                    if len(files2):
                        html+=' (%s)'%len(files2) # show number of supporting files
                    html+='<br>'
                html+="<br>"
        style.save(html,self.abfFolder2+"/index_menu.html")
        self.html_index_splash() # make splash page
        style.frames(self.abfFolder2+"/index.html",launch=launch)


Instruction:
Write a Python 3 function that can
generate HTML for a single given cell.

Response:
def html_single_basic(self,ID):
        """
        generate ./swhlab/xxyxxzzz.html for a single given abf.
        Input can be an ABF file path of ABF ID.
        """
        if not ID in self.cells:
            self.log.error("ID [%s] not seen!",ID)
            return
        htmlFname=os.path.abspath(self.abfFolder2+"/"+ID+".html")
        html="
Data for ID %s
"%ID
        npics=0
        for childID in [os.path.splitext(x)[0] for x in self.fnamesByCell[ID]]:
            pics=[x for x in self.fnames2 if x.startswith(childID) and os.path.splitext(x)[1].lower() in [".png",".jpg"]]
            html+="%s
"%(os.path.abspath(self.abfFolder+'/'+childID+".abf"))
            for i,pic in enumerate(pics):
                html+=''%(pic,pic)
                npics+=1
            html+="

"
        style.save(html,htmlFname)
        self.log.info("created %s containing %d pictures",htmlFname,npics)


Instruction:
How would you code a function in Python 3 to
generate a data view for every ABF in the project folder.

Response:
def html_singleAll(self,template="basic"):
        """generate a data view for every ABF in the project folder."""
        for fname in smartSort(self.cells):
            if template=="fixed":
                self.html_single_fixed(fname)
            else:
                self.html_single_basic(fname)


Instruction:
Can you generate the documentation for the following Python 3 function
def makePics(self):
        rescanNeeded=False
        for fname in smartSort(self.fnames):
            if fname in self.fnames2:
                continue
            ext=os.path.splitext(fname)[1].lower()
            if ext in [".jpg",".png"]:
                if not fname in self.abfFolder2:
                    self.log.debug("copying %s",fname)
                    shutil.copy(os.path.join(self.abfFolder,fname),os.path.join(self.abfFolder2,fname))
                    rescanNeeded=True
            if ext in [".tif",".tiff"]:
                if not fname+".jpg" in self.fnames2:
                    self.log.debug("converting %s",fname)
                    swhlab.swh_image.TIF_to_jpg(os.path.join(self.abfFolder,fname),saveAs=os.path.join(self.abfFolder2,fname+".jpg"))
                    rescanNeeded=True
        if rescanNeeded:
            self.log.debug("new pics, so a rescan is needed...")
            self.log.debug("REBUILDING ALL RECOMMENDED!!!!!!!!!!!")
            self.folderScan()

Response: convert every. image we find to a. swhlab image


Instruction:
Can you implement a function in Python 3 that
uses to determine gain function.

Response:
def proto_01_12_steps025(abf=exampleABF):
    """IC steps. Use to determine gain function."""
    swhlab.ap.detect(abf)
    standard_groupingForInj(abf,200)

    for feature in ['freq','downslope']:
        swhlab.ap.plot_values(abf,feature,continuous=False) #plot AP info
        swhlab.plot.save(abf,tag='A_'+feature)

    swhlab.plot.gain(abf) #easy way to do a gain function!
    swhlab.plot.save(abf,tag='05-gain')


Instruction:
Can you generate a brief explanation for the following Python 3 code
def proto_02_03_IVfast(abf=exampleABF):
    av1,sd1=swhlab.plot.IV(abf,.6,.9,True)
    swhlab.plot.save(abf,tag='iv1')
    Xs=abf.clampValues(.6) #generate IV clamp values
    abf.saveThing([Xs,av1],'iv')

Response: Generate fast sweeps 1 step per sweep for clean IV without fast currents.


Instruction:
Write a Python 3 function for
repeating membrane tests likely with drug added. Maybe IPSCs. Maybe IPSCs. Maybe IPSCs. Maybe IPSCs. Maybe IPSCs. Maybe IPSCs. Maybe IPSCs. Maybe IPSCs. Maybe IPSCs. Maybe IPSCs. Maybe IPSCs.

Response:
def proto_04_01_MTmon70s2(abf=exampleABF):
    """repeated membrane tests, likely with drug added. Maybe IPSCs."""
    standard_inspect(abf)
    swhlab.memtest.memtest(abf)
    swhlab.memtest.checkSweep(abf)
    swhlab.plot.save(abf,tag='check',resize=False)
    swhlab.memtest.plot_standard4(abf)
    swhlab.plot.save(abf,tag='memtests')


Instruction:
Given the following Python 3 function, write the documentation
def proto_VC_50_MT_IV(abf=exampleABF):
    swhlab.memtest.memtest(abf) #do membrane test on every sweep
    swhlab.memtest.checkSweep(abf) #see all MT values
    swhlab.plot.save(abf,tag='02-check',resize=False)

    av1,sd1=swhlab.plot.IV(abf,1.2,1.4,True,'b')
    swhlab.plot.save(abf,tag='iv')
    Xs=abf.clampValues(1.2) #generate IV clamp values
    abf.saveThing([Xs,av1],'01_iv')

Response: combination of membrane test and IV steps.


Instruction:
Write a Python 3 function for
increasing ramps in (? pA steps.

Response:
def proto_IC_ramp_gain(abf=exampleABF):
    """increasing ramps in (?) pA steps."""
    standard_inspect(abf)
    swhlab.ap.detect(abf)

    swhlab.ap.check_AP_raw(abf) #show overlayed first few APs
    swhlab.plot.save(abf,tag="01-raw",resize=False)
    swhlab.ap.check_AP_deriv(abf) #show overlayed first few APs
    swhlab.plot.save(abf,tag="02-deriv")
    swhlab.ap.check_AP_phase(abf) #show overlayed first few APs
    swhlab.plot.save(abf,tag="03-phase")

    swhlab.ap.plot_values(abf,'freq',continuous=True) #plot AP info
    pylab.subplot(211)
    pylab.axhline(40,color='r',lw=2,ls="--",alpha=.2)
    swhlab.plot.save(abf,tag='04-freq')

    swhlab.ap.plot_values(abf,'downslope',continuous=True) #plot AP info
    pylab.subplot(211)
    pylab.axhline(-100,color='r',lw=2,ls="--",alpha=.2)
    swhlab.plot.save(abf,tag='04-downslope')


Instruction:
How would you code a function in Python 3 to
index images in folder.

Response:
def indexImages(folder,fname="index.html"):
    """OBSOLETE WAY TO INDEX A FOLDER.""" #TODO: REMOVE
    html="<html><body>"
    for item in glob.glob(folder+"/*.*"):
        if item.split(".")[-1] in ['jpg','png']:
            html+="<h3>%s</h3>"%os.path.basename(item)
            html+='<img src="%s">'%os.path.basename(item)
            html+='<br>'*10
    html+="</html></body>"
    f=open(folder+"/"+fname,'w')
    f.write(html)
    f.close
    print("indexed:")
    print("  ",os.path.abspath(folder+"/"+fname))
    return


Instruction:
Given the following Python 3 function, write the documentation
def save(self, *args, **kwargs):
        current_activable_value = getattr(self, self.ACTIVATABLE_FIELD_NAME)
        is_active_changed = self.id is None or self.__original_activatable_value != current_activable_value
        self.__original_activatable_value = current_activable_value

        ret_val = super(BaseActivatableModel, self).save(*args, **kwargs)

        # Emit the signals for when the is_active flag is changed
        if is_active_changed:
            model_activations_changed.send(self.__class__, instance_ids=[self.id], is_active=current_activable_value)
        if self.activatable_field_updated:
            model_activations_updated.send(self.__class__, instance_ids=[self.id], is_active=current_activable_value)

        return ret_val

Response: A custom save method that handles figuring out when something is activated or deactivated.


Instruction:
Write a Python 3 function for
deleting an activatable object.

Response:
def delete(self, force=False, **kwargs):
        """
        It is impossible to delete an activatable model unless force is True. This function instead sets it to inactive.
        """
        if force:
            return super(BaseActivatableModel, self).delete(**kwargs)
        else:
            setattr(self, self.ACTIVATABLE_FIELD_NAME, False)
            return self.save(update_fields=[self.ACTIVATABLE_FIELD_NAME])


Instruction:
Can you write a function in Python 3 where it
writes to file_handle if supplied othewise print output

Response:
def show(self, args, file_handle=None, **kwargs):
        "Write to file_handle if supplied, othewise print output"
        full_string = ''
        info = {'root_directory':     '<root_directory>',
                'batch_name':         '<batch_name>',
                'batch_tag':          '<batch_tag>',
                'batch_description':  '<batch_description>',
                'launcher':        '<launcher>',
                'timestamp_format':   '<timestamp_format>',
                'timestamp':          tuple(time.localtime()),
                'varying_keys':       args.varying_keys,
                'constant_keys':      args.constant_keys,
                'constant_items':     args.constant_items}

        quoted_cmds = [ subprocess.list2cmdline(
                [el for el in self(self._formatter(s),'<tid>',info)])
                        for s in args.specs]

        cmd_lines = ['%d: %s\n' % (i, qcmds) for (i,qcmds)
                     in enumerate(quoted_cmds)]
        full_string += ''.join(cmd_lines)
        if file_handle:
            file_handle.write(full_string)
            file_handle.flush()
        else:
            print(full_string)


Instruction:
Explain what the following Python 3 code does
def update(self):
        launches = []
        for path in os.listdir(self.output_dir):
            full_path = os.path.join(self.output_dir, path)
            if os.path.isdir(full_path):
                launches.append(self._get_launch_info(full_path))
        self.launches = sorted(launches)

Response: Update the launch information for the current user.


Instruction:
Create a Python 3 function for
returning the root directory name given the timestamp.

Response:
def get_root_directory(self, timestamp=None):
        """
        A helper method that supplies the root directory name given a
        timestamp.
        """
        if timestamp is None: timestamp = self.timestamp
        if self.timestamp_format is not None:
            root_name =  (time.strftime(self.timestamp_format, timestamp)
                          + '-' + self.batch_name)
        else:
            root_name = self.batch_name

        path = os.path.join(self.output_directory,
                                *(self.subdir+[root_name]))
        return os.path.abspath(path)


Instruction:
Make a summary of the following Python 3 code
def _append_log(self, specs):
        self._spec_log += specs # This should be removed
        log_path = os.path.join(self.root_directory, ("%s.log" % self.batch_name))
        core.Log.write_log(log_path, [spec for (_, spec) in specs], allow_append=True)

Response: Append the log to the log file.


Instruction:
Can you generate the documentation for the following Python 3 function
def _record_info(self, setup_info=None):
        info_path = os.path.join(self.root_directory, ('%s.info' % self.batch_name))

        if setup_info is None:
            try:
                with open(info_path, 'r') as info_file:
                    setup_info = json.load(info_file)
            except:
                setup_info = {}

            setup_info.update({'end_time' : tuple(time.localtime())})
        else:
            setup_info.update({
                'end_time' : None,
                'metadata' : self.metadata
                })

        with open(info_path, 'w') as info_file:
            json.dump(setup_info, info_file, sort_keys=True, indent=4)

Response: Record the current state of the cluster.


Instruction:
Can you create a Python 3 function that
prints a succinct summary of the Launcher configuration.

Response:
def summary(self):
        """
        A succinct summary of the Launcher configuration.  Unlike the
        repr, a summary does not have to be complete but must supply
        key information relevant to the user.
        """
        print("Type: %s" % self.__class__.__name__)
        print("Batch Name: %r" % self.batch_name)
        if self.tag:
            print("Tag: %s" % self.tag)
        print("Root directory: %r" % self.get_root_directory())
        print("Maximum concurrency: %s" % self.max_concurrency)
        if self.description:
            print("Description: %s" % self.description)


Instruction:
Write a Python 3 function that can
run qdel command to remove all remaining jobs using the job_timestamp of the current job. Returns exit - code of qdel.

Response:
def qdel_batch(self):
        """
        Runs qdel command to remove all remaining queued jobs using
        the <batch_name>* pattern . Necessary when StopIteration is
        raised with scheduled jobs left on the queue.
        Returns exit-code of qdel.
        """
        p = subprocess.Popen(['qdel', '%s_%s*' % (self.batch_name,
                                                  self.job_timestamp)],
                             stdout=subprocess.PIPE)
        (stdout, stderr) = p.communicate()
        return p.poll()


Instruction:
Can you tell what is the following Python 3 function doing
def _launch_process_group(self, process_commands, streams_path):
        processes = []
        for cmd, tid in process_commands:
            job_timestamp = time.strftime('%H%M%S')
            basename = "%s_%s_tid_%d" % (self.batch_name, job_timestamp, tid)
            stdout_path = os.path.join(streams_path, "%s.o.%d" % (basename, tid))
            stderr_path = os.path.join(streams_path, "%s.e.%d" % (basename, tid))
            process = { 'tid' : tid,
                        'cmd' : cmd,
                        'stdout' : stdout_path,
                        'stderr' : stderr_path }
            processes.append(process)

        # To make the JSON filename unique per group, we use the last tid in
        # this group.
        json_path = os.path.join(self.root_directory, self.json_name % (tid))
        with open(json_path, 'w') as json_file:
            json.dump(processes, json_file, sort_keys=True, indent=4)

        p = subprocess.Popen([self.script_path, json_path, self.batch_name,
                              str(len(processes)), str(self.max_concurrency)])
        if p.wait() != 0:
            raise EnvironmentError("Script command exit with code: %d" % p.poll())

Response: Launches the process group.


Instruction:
Make a summary of the following Python 3 code
def cross_check_launchers(self, launchers):
        if len(launchers) == 0: raise Exception('Empty launcher list')
        timestamps = [launcher.timestamp for launcher in launchers]

        if not all(timestamps[0] == tstamp for tstamp in timestamps):
            raise Exception("Launcher timestamps not all equal. "
                            "Consider setting timestamp explicitly.")

        root_directories = []
        for launcher in launchers:
            command = launcher.command
            args = launcher.args
            command.verify(args)
            root_directory = launcher.get_root_directory()
            if os.path.isdir(root_directory):
                raise Exception("Root directory already exists: %r" % root_directory)
            if root_directory in root_directories:
                raise Exception("Each launcher requires a unique root directory")
            root_directories.append(root_directory)

Response: Cross - checks the launchers and returns a list of root directories that are needed for the launcher.


Instruction:
Make a summary of the following Python 3 code
def _launch_all(self, launchers):
        for launcher in launchers:
            print("== Launching  %s ==" % launcher.batch_name)
            launcher()
        return True

Response: Launches all available launchers.


Instruction:
Make a summary of the following Python 3 code
def _review_all(self, launchers):
        # Run review of launch args if necessary
        if self.launch_args is not None:
            proceed = self.review_args(self.launch_args,
                                       show_repr=True,
                                       heading='Meta Arguments')
            if not proceed: return False

        reviewers = [self.review_args,
                     self.review_command,
                     self.review_launcher]

        for (count, launcher) in enumerate(launchers):

            # Run reviews for all launchers if desired...
            if not all(reviewer(launcher) for reviewer in reviewers):
                print("\n == Aborting launch ==")
                return False
            # But allow the user to skip these extra reviews
            if len(launchers)!= 1 and count < len(launchers)-1:
                skip_remaining = self.input_options(['Y', 'n','quit'],
                                 '\nSkip remaining reviews?', default='y')

                if skip_remaining == 'y':          break
                elif skip_remaining == 'quit':     return False

        if self.input_options(['y','N'], 'Execute?', default='n') != 'y':
            return False
        else:
            return self._launch_all(launchers)

Response: Runs the review process for all the launchers.


Instruction:
Can you tell what is the following Python 3 function doing
def input_options(self, options, prompt='Select option', default=None):
        check_options = [x.lower() for x in options]
        while True:
            response = input('%s [%s]: ' % (prompt, ', '.join(options))).lower()
            if response in check_options: return response.strip()
            elif response == '' and default is not None:
                return default.lower().strip()

Response: Helper to prompt user for input on the commandline.


Instruction:
How would you code a function in Python 3 to
save the data to a file.

Response:
def save(self, filename,  metadata={}, **data):
        """
        The implementation in the base class simply checks there is no
        clash between the metadata and data keys.
        """
        intersection = set(metadata.keys()) & set(data.keys())
        if intersection:
            msg = 'Key(s) overlap between data and metadata: %s'
            raise Exception(msg  % ','.join(intersection))


Instruction:
Can you create a Python 3 function that
returns the full path for saving the file.

Response:
def _savepath(self, filename):
        """
        Returns the full path for saving the file, adding an extension
        and making the filename unique as necessary.
        """
        (basename, ext) = os.path.splitext(filename)
        basename = basename if (ext in self.extensions) else filename
        ext = ext if (ext in self.extensions) else self.extensions[0]
        savepath = os.path.abspath(os.path.join(self.directory,
                                                 '%s%s' % (basename, ext)))
        return (tempfile.mkstemp(ext, basename + "_", self.directory)[1]
                if self.hash_suffix else savepath)


Instruction:
Can you implement a function in Python 3 that
returns a boolean indicating whether the filename has an anonacus related extension for this class.

Response:
def file_supported(cls, filename):
        """
        Returns a boolean indicating whether the filename has an
        appropriate extension for this class.
        """
        if not isinstance(filename, str):
            return False
        (_, ext) = os.path.splitext(filename)
        if ext not in cls.extensions:
            return False
        else:
            return True


Instruction:
Create a Python 3 function for
saving the data in the specified file.

Response:
def save(self, filename, imdata, **data):
        """
        Data may be either a PIL Image object or a Numpy array.
        """
        if isinstance(imdata, numpy.ndarray):
            imdata = Image.fromarray(numpy.uint8(imdata))
        elif isinstance(imdata, Image.Image):
            imdata.save(self._savepath(filename))


Instruction:
Implement a Python 3 function for
returning the timestamp of the file modified

Response:
def fileModifiedTimestamp(fname):
    """return "YYYY-MM-DD" when the file was modified."""
    modifiedTime=os.path.getmtime(fname)
    stamp=time.strftime('%Y-%m-%d', time.localtime(modifiedTime))
    return stamp


Instruction:
Can you implement a function in Python 3 that
loads the results file into a dict of active folders with days as keys.

Response:
def loadResults(resultsFile):
    """returns a dict of active folders with days as keys."""
    with open(resultsFile) as f:
        raw=f.read().split("\n")
    foldersByDay={}
    for line in raw:
        folder=line.split('"')[1]+"\\"
        line=[]+line.split('"')[2].split(", ")
        for day in line[1:]:
            if not day in foldersByDay:
                foldersByDay[day]=[]
            foldersByDay[day]=foldersByDay[day]+[folder]
    nActiveDays=len(foldersByDay)
    dayFirst=sorted(foldersByDay.keys())[0]
    dayLast=sorted(foldersByDay.keys())[-1]
    dayFirst=datetime.datetime.strptime(dayFirst, "%Y-%m-%d" )
    dayLast=datetime.datetime.strptime(dayLast, "%Y-%m-%d" )
    nDays = (dayLast - dayFirst).days + 1
    emptyDays=0
    for deltaDays in range(nDays):
        day=dayFirst+datetime.timedelta(days=deltaDays)
        stamp=datetime.datetime.strftime(day, "%Y-%m-%d" )
        if not stamp in foldersByDay:
            foldersByDay[stamp]=[]
            emptyDays+=1
    percActive=nActiveDays/nDays*100
    print("%d of %d days were active (%.02f%%)"%(nActiveDays,nDays,percActive))
    return foldersByDay


Instruction:
Make a summary of the following Python 3 code
def HTML_results(resultsFile):
    foldersByDay=loadResults(resultsFile)

    # optionally skip dates before a certain date
#    for day in sorted(list(foldersByDay.keys())):
#        if time.strptime(day,"%Y-%m-%d")<time.strptime("2016-05-01","%Y-%m-%d"):
#            del foldersByDay[day]

    # Create a header
    html="
Active Folder Report (updated TIMESTAMP)
"
    html+="
When a file is created (or modified) its parent folder is marked active for that day."
    html+="
This page reports all folders which were active in the last several years. "
    html+="
A single folder can be active for more than one date."
    html=html.replace("TIMESTAMP",(time.strftime('%Y-%m-%d', time.localtime())))
    html+="
"*5

    # create menu at the top of the page
    html+="
Active Folder Dates
"
    html+=""
    lastMonth=""
    lastYear=""
    for day in sorted(list(foldersByDay.keys())):
        month=day[:7]
        year=day[:4]
        if year!=lastYear:
            html+="

%s "%year
            lastYear=year
        if month!=lastMonth:
            html+="
%s: "%month
            lastMonth=month
        html+="%s, "%(day,day[8:])
    html+="
"*5
    html=html.replace(",
","
")
    html+=""

    # create the full list of folders organized by active date
    html+="
Active Folders
"
    for day in sorted(list(foldersByDay.keys())):
        dt=datetime.datetime.strptime(day, "%Y-%m-%d" )
        classPrefix="weekday"
        if int(dt.weekday())>4:
            classPrefix="weekend"
        html+=""%(day,day)
        title="%s (%s)"%(day,DAYSOFWEEK[dt.weekday()])
        html+="
%s
"%(classPrefix,title)
        html+="
"%(classPrefix)
        # define folders to skip
        for folder in foldersByDay[day]:
            if "\\References\\" in folder:
                continue
            if "\\MIP\\" in folder:
                continue
            if "LineScan-" and "\\analysis\\" in folder:
                continue
            if "trakem2" in folder:
                continue
            if "SWHlab-" in folder:
                continue
            if "\\swhlab" in folder:
                continue
            html+="%s
"%folder
        html+="
"
    fnameSave=resultsFile+".html"
    html=html.replace("D:\\X_Drive\\","X:\\")
    with open(fnameSave,'w') as f:
        f.write(HTML_TEMPLATE.replace("",""+html))
    print("saved",fnameSave)

Response: generates HTML report of active folders and days.


Instruction:
Implement a Python 3 function for
giving some data Y break it into chunks and return just the quiet ones.

Response:
def quietParts(data,percentile=10):
    """
    Given some data (Y) break it into chunks and return just the quiet ones.
    Returns data where the variance for its chunk size is below the given percentile.
    CHUNK_POINTS should be adjusted so it's about 10ms of data.
    """
    nChunks=int(len(Y)/CHUNK_POINTS)
    chunks=np.reshape(Y[:nChunks*CHUNK_POINTS],(nChunks,CHUNK_POINTS))
    variances=np.var(chunks,axis=1)
    percentiles=np.empty(len(variances))
    for i,variance in enumerate(variances):
        percentiles[i]=sorted(variances).index(variance)/len(variances)*100
    selected=chunks[np.where(percentiles<=percentile)[0]].flatten()
    return selected


Instruction:
Can you generate the documentation for the following Python 3 function
def ndist(data,Xs):
    sigma=np.sqrt(np.var(data))
    center=np.average(data)
    curve=mlab.normpdf(Xs,center,sigma)
    curve*=len(data)*HIST_RESOLUTION
    return curve

Response:
return the normal
    distribution curve as a Y point at each of those Xs


Instruction:
Make a summary of the following Python 3 code
def abfinfo(self,printToo=False,returnDict=False):
        info="\n### ABF INFO ###\n"
        d={}
        for thingName in sorted(dir(self)):
            if thingName in ['cm','evIs','colormap','dataX','dataY',
                             'protoX','protoY']:
                continue
            if "_" in thingName:
                continue
            thing=getattr(self,thingName)
            if type(thing) is list and len(thing)>5:
                continue
            thingType=str(type(thing)).split("'")[1]
            if "method" in thingType or "neo." in thingType:
                continue
            if thingName in ["header","MT"]:
                continue
            info+="%s <%s> %s\n"%(thingName,thingType,thing)
            d[thingName]=thing
        if printToo:
            print()
            for line in info.split("\n"):
                if len(line)<3:
                    continue
                print("   ",line)
            print()
        if returnDict:
            return d
        return info

Response: show basic info about ABF class variables.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def headerHTML(self,fname=None):
        if fname is None:
            fname = self.fname.replace(".abf","_header.html")
        html=""
        html+="
abfinfo() for %s.abf
"%self.ID
        html+=self.abfinfo().replace("<","<").replace(">",">").replace("\n","
")
        html+="
Header for %s.abf
"%self.ID
        html+=pprint.pformat(self.header, indent=1)
        html=html.replace("\n",'
').replace(" "," ")
        html=html.replace(r"\x00","")
        html+=""
        print("WRITING HEADER TO:")
        print(fname)
        f=open(fname,'w')
        f.write(html)
        f.close()

Response: read the ABF header and save it HTML formatted.


Instruction:
Implement a function in Python 3 to
generate colormap for all sweeps

Response:
def generate_colormap(self,colormap=None,reverse=False):
        """use 1 colormap for the whole abf. You can change it!."""
        if colormap is None:
            colormap = pylab.cm.Dark2
        self.cm=colormap
        self.colormap=[]
        for i in range(self.sweeps): #TODO: make this the only colormap
            self.colormap.append(colormap(i/self.sweeps))
        if reverse:
            self.colormap.reverse()


Instruction:
Can you generate a brief explanation for the following Python 3 code
def setSweep(self,sweep=0,force=False):
        if sweep is None or sweep is False:
            sweep=0
        if sweep<0:
            sweep=self.sweeps-sweep #-1 means last sweep
            if sweep<0: #still!
                sweep=0 #first sweep
        if sweep>(self.sweeps-1):
            print(" !! there aren't %d sweeps. Reverting to last (%d) sweep."%(sweep,self.sweeps-1))
            sweep=self.sweeps-1
        sweep=int(sweep)
        try:
            if self.currentSweep==sweep and force==False:
                return
            self.currentSweep=sweep
            self.dataY = self.block.segments[sweep].analogsignals[self.channel]
            self.dataY = np.array(self.dataY)

            B1,B2=self.baseline
            if B1==None:
                B1=0
            else:
                B1=B1*self.rate
            if B2==None:
                B2==self.sweepSize
            else:
                B2=B2*self.rate

                self.dataY-=np.average(self.dataY[self.baseline[0]*self.rate:self.baseline[1]*self.rate])
            self.sweep_genXs()
            self.sweep_decimate()
            self.generate_protocol(sweep=sweep)
            self.dataStart = self.sweepInterval*self.currentSweep
        except Exception:
            print("#"*400,"\n",traceback.format_exc(),'\n',"#"*400)
        return self.dataX,self.dataY

Response: Load X and Y data for a particular sweep.


Instruction:
Write a Python 3 script to
generate sweepX to match sweepY

Response:
def sweep_genXs(self):
        """generate sweepX (in seconds) to match sweepY"""
        if self.decimateMethod:
            self.dataX=np.arange(len(self.dataY))/self.rate
            self.dataX*=self.decimateBy
            return
        if self.dataX is None or len(self.dataX)!=len(self.dataY):
            self.dataX=np.arange(len(self.dataY))/self.rate


Instruction:
Implement a function in Python 3 to
decimate data using one of the following methods: 'avg','max','min','fast' They're self explainatory. 'fast' just plucks the n'th data point.

Response:
def sweep_decimate(self):
        """
        decimate data using one of the following methods:
            'avg','max','min','fast'
        They're self explainatory. 'fast' just plucks the n'th data point.
        """
        if len(self.dataY)<self.decimateBy:
            return
        if self.decimateMethod:
            points = int(len(self.dataY)/self.decimateBy)
            self.dataY=self.dataY[:points*self.decimateBy]
            self.dataY = np.reshape(self.dataY,(points,self.decimateBy))
            if self.decimateMethod=='avg':
                self.dataY = np.average(self.dataY,1)
            elif self.decimateMethod=='max':
                self.dataY = np.max(self.dataY,1)
            elif self.decimateMethod=='min':
                self.dataY = np.min(self.dataY,1)
            elif self.decimateMethod=='fast':
                self.dataY = self.dataY[:,0]
            else:
                print("!!! METHOD NOT IMPLIMENTED YET!!!",self.decimateMethod)
            self.dataX = np.arange(len(self.dataY))/self.rate*self.decimateBy


Instruction:
Write a Python 3 function that can
return self.dataY around a time point. All units are seconds. if thisSweep==False, the time point is considered to be experiment time and an appropriate sweep may be selected. i.e., with 10 second sweeps and timePint=35, will select the 5s mark of the third sweep

Response:
def get_data_around(self,timePoints,thisSweep=False,padding=0.02,msDeriv=0):
        """
        return self.dataY around a time point. All units are seconds.
        if thisSweep==False, the time point is considered to be experiment time
            and an appropriate sweep may be selected. i.e., with 10 second
            sweeps and timePint=35, will select the 5s mark of the third sweep
        """
        if not np.array(timePoints).shape:
            timePoints=[float(timePoints)]
        data=None
        for timePoint in timePoints:
            if thisSweep:
                sweep=self.currentSweep
            else:
                sweep=int(timePoint/self.sweepInterval)
                timePoint=timePoint-sweep*self.sweepInterval
            self.setSweep(sweep)
            if msDeriv:
                dx=int(msDeriv*self.rate/1000) #points per ms
                newData=(self.dataY[dx:]-self.dataY[:-dx])*self.rate/1000/dx
            else:
                newData=self.dataY
            padPoints=int(padding*self.rate)
            pad=np.empty(padPoints)*np.nan
            Ic=timePoint*self.rate #center point (I)
            newData=np.concatenate((pad,pad,newData,pad,pad))
            Ic+=padPoints*2
            newData=newData[Ic-padPoints:Ic+padPoints]
            newData=newData[:int(padPoints*2)] #TODO: omg so much trouble with this!
            if data is None:
                data=[newData]
            else:
                data=np.vstack((data,newData))#TODO: omg so much trouble with this!
        return data


Instruction:
Can you generate the documentation for the following Python 3 function
def generate_protocol(self,sweep=None):
        #TODO: make a line protocol that's plottable
        if sweep is None:
            sweep = self.currentSweep
        if sweep is None:
            sweep = 0
        if not self.channel in self.header['dictEpochInfoPerDAC'].keys():
            self.protoX=[0,self.sweepSize]
            self.protoY=[self.holding,self.holding]
            self.protoSeqX=self.protoX
            self.protoSeqY=self.protoY
            return
        proto=self.header['dictEpochInfoPerDAC'][self.channel]
        self.protoX=[] #plottable Xs
        self.protoY=[] #plottable Ys
        self.protoX.append(0)
        self.protoY.append(self.holding)
        for step in proto:
            dX = proto[step]['lEpochInitDuration']
            Y = proto[step]['fEpochInitLevel']+proto[step]['fEpochLevelInc']*sweep
            self.protoX.append(self.protoX[-1])
            self.protoY.append(Y) #go to new Y
            self.protoX.append(self.protoX[-1]+dX) #take it to the new X
            self.protoY.append(Y) #update the new Y #TODO: fix for ramps

        if self.header['listDACInfo'][0]['nInterEpisodeLevel']: #nInterEpisodeLevel
            finalVal=self.protoY[-1] #last holding
        else:
            finalVal=self.holding #regular holding
        self.protoX.append(self.protoX[-1])
        self.protoY.append(finalVal)
        self.protoX.append(self.sweepSize)
        self.protoY.append(finalVal)

        for i in range(1,len(self.protoX)-1): #correct for weird ABF offset issue.
            self.protoX[i]=self.protoX[i]+self.offsetX
        self.protoSeqY=[self.protoY[0]]
        self.protoSeqX=[self.protoX[0]]
        for i in range(1,len(self.protoY)):
            if not self.protoY[i]==self.protoY[i-1]:
                self.protoSeqY.append(self.protoY[i])
                self.protoSeqX.append(self.protoX[i])
        if self.protoY[0]!=self.protoY[1]:
            self.protoY.insert(1,self.protoY[0])
            self.protoX.insert(1,self.protoX[1])
            self.protoY.insert(1,self.protoY[0])
            self.protoX.insert(1,self.protoX[0]+self.offsetX/2)

        self.protoSeqY.append(finalVal)
        self.protoSeqX.append(self.sweepSize)

        self.protoX=np.array(self.protoX)
        self.protoY=np.array(self.protoY)

Response: Generate the protocol for the current sweep.


Instruction:
Write a Python 3 function that can
clamp the values of the command values at a time point.

Response:
def clampValues(self,timePoint=0):
        """
        return an array of command values at a time point (in sec).
        Useful for things like generating I/V curves.
        """
        Cs=np.zeros(self.sweeps)
        for i in range(self.sweeps):
            self.setSweep(i) #TODO: protocol only = True
            for j in range(len(self.protoSeqX)):
                if self.protoSeqX[j]<=timePoint*self.rate:
                    Cs[i]=self.protoSeqY[j]
        return Cs


Instruction:
Create a Python 3 function to
guess the protocol of the current ISO - 8601 entry.

Response:
def guess_protocol(self):
        """
        This just generates a string to define the nature of the ABF.
        The ultimate goal is to use info about the abf to guess what to do with it.
            [vc/ic]-[steps/fixed]-[notag/drugs]-[2ch/1ch]
            This represents 2^4 (18) combinations, but is easily expanded.
        """
        clamp="ic"
        if self.units=="pA":
            clamp="vc"
        command="fixed"
        if self.sweeps>1:
            self.setSweep(0)
            P0=str(self.protoX)+str(self.protoY)
            self.setSweep(1)
            P1=str(self.protoX)+str(self.protoY)
            if not P0==P1:
                command="steps"
        tags="notag"
        if len(self.commentSweeps):
            tags="drugs"
        ch="1ch"
        if self.nADC>1:
            ch="2ch"
        guess="-".join([clamp,command,tags,ch])
        return guess


Instruction:
Write a Python 3 function for
giving an array of sweeps, return X,Y,Err average. This returns *SWEEPS* of data, not just 1 data point.

Response:
def average_sweep(self,T1=0,T2=None,sweeps=None,stdErr=False):
        """
        given an array of sweeps, return X,Y,Err average.
        This returns *SWEEPS* of data, not just 1 data point.
        """
        T1=T1*self.rate
        if T2 is None:
            T2 = self.sweepSize-1
        else:
            T2 = T2*self.rate
        if sweeps is None:
            sweeps = range(self.sweeps)
        Ys=np.empty((len(sweeps),(T2-T1)))
        for i in range(len(sweeps)):
            self.setSweep(sweeps[i])
            Ys[i]=self.dataY[T1:T2]
        Av = np.average(Ys,0)
        Es = np.std(Ys,0)
        Xs = self.dataX[T1:T2]
        if stdErr: #otherwise return stdev
            Es = Es/np.sqrt(len(sweeps))
        return Xs,Av,Es


Instruction:
Create a Python 3 function to
return a numpy array of average data for every sweep

Response:
def average_data(self,ranges=[[None,None]],percentile=None):
        """
        given a list of ranges, return single point averages for every sweep.
        Units are in seconds. Expects something like:
            ranges=[[1,2],[4,5],[7,7.5]]
        None values will be replaced with maximum/minimum bounds.
        For baseline subtraction, make a range baseline then sub it youtself.
            returns datas[iSweep][iRange][AVorSD]
        if a percentile is given, return that percentile rather than average.
            percentile=50 is the median, but requires sorting, and is slower.
        """
        ranges=copy.deepcopy(ranges) #TODO: make this cleaner. Why needed?
        # clean up ranges, make them indexes
        for i in range(len(ranges)):
            if ranges[i][0] is None:
                ranges[i][0] = 0
            else:
                ranges[i][0] = int(ranges[i][0]*self.rate)
            if ranges[i][1] is None:
                ranges[i][1] = -1
            else:
                ranges[i][1] = int(ranges[i][1]*self.rate)

        # do the math
        datas=np.empty((self.sweeps,len(ranges),2)) #[sweep][range]=[Av,Er]
        for iSweep in range(self.sweeps):
            self.setSweep(iSweep)
            for iRange in range(len(ranges)):
                I1=ranges[iRange][0]
                I2=ranges[iRange][1]
                if percentile:
                    datas[iSweep][iRange][0]=np.percentile(self.dataY[I1:I2],percentile)
                else:
                    datas[iSweep][iRange][0]=np.average(self.dataY[I1:I2])
                datas[iSweep][iRange][1]=np.std(self.dataY[I1:I2])
        return datas


Instruction:
How would you explain what the following Python 3 function does
def filter_gaussian(self,sigmaMs=100,applyFiltered=False,applyBaseline=False):
        if sigmaMs==0:
            return self.dataY
        filtered=cm.filter_gaussian(self.dataY,sigmaMs)
        if applyBaseline:
            self.dataY=self.dataY-filtered
        elif applyFiltered:
            self.dataY=filtered
        else:
            return filtered

Response: RETURNS filtered trace. Desn t filter it in place.


Instruction:
Create a Python 3 function for
saving any object as a file

Response:
def saveThing(self,thing,fname,overwrite=True,ext=".pkl"):
        """save any object as /swhlab4/ID_[fname].pkl"""
        if not os.path.exists(os.path.dirname(self.outpre)):
            os.mkdir(os.path.dirname(self.outpre))
        if ext and not ext in fname:
            fname+=ext
        fname=self.outpre+fname
        if overwrite is False:
            if os.path.exists(fname):
                print(" o- not overwriting [%s]"%os.path.basename(fname))
                return
        time1=cm.timethis()
        pickle.dump(thing, open(fname,"wb"),pickle.HIGHEST_PROTOCOL)
        print(" <- saving [%s] %s (%.01f kB) took %.02f ms"%(\
              os.path.basename(fname),str(type(thing)),
              sys.getsizeof(pickle.dumps(thing, -1))/1e3,
              cm.timethis(time1)))


Instruction:
Write a Python 3 function for
loading any object from a file

Response:
def loadThing(self,fname,ext=".pkl"):
        """save any object from /swhlab4/ID_[fname].pkl"""
        if ext and not ext in fname:
            fname+=ext
        fname=self.outpre+fname
        time1=cm.timethis()
        thing = pickle.load(open(fname,"rb"))
        print(" -> loading [%s] (%.01f kB) took %.02f ms"%(\
              os.path.basename(fname),
              sys.getsizeof(pickle.dumps(thing, -1))/1e3,
              cm.timethis(time1)))
        return thing


Instruction:
Can you write a function in Python 3 where it
deletes all the files in the system

Response:
def deleteStuff(self,ext="*",spareInfo=True,spare=["_info.pkl"]):
        """delete /swhlab4/ID_*"""
        print(" -- deleting /swhlab4/"+ext)
        for fname in sorted(glob.glob(self.outpre+ext)):
            reallyDelete=True
            for item in spare:
                if item in fname:
                    reallyDelete=False
            if reallyDelete:
                os.remove(fname)


Instruction:
Make a summary of the following Python 3 code
def validate_activatable_models():
    for model in get_activatable_models():
        # Verify the activatable model has an activatable boolean field
        activatable_field = next((
            f for f in model._meta.fields
            if f.__class__ == models.BooleanField and f.name == model.ACTIVATABLE_FIELD_NAME
        ), None)
        if activatable_field is None:
            raise ValidationError((
                'Model {0} is an activatable model. It must define an activatable BooleanField that '
                'has a field name of model.ACTIVATABLE_FIELD_NAME (which defaults to is_active)'.format(model)
            ))

        # Ensure all foreign keys and onetoone fields will not result in cascade deletions if not cascade deletable
        if not model.ALLOW_CASCADE_DELETE:
            for field in model._meta.fields:
                if field.__class__ in (models.ForeignKey, models.OneToOneField):
                    if field.remote_field.on_delete == models.CASCADE:
                        raise ValidationError((
                            'Model {0} is an activatable model. All ForeignKey and OneToOneFields '
                            'must set on_delete methods to something other than CASCADE (the default). '
                            'If you want to explicitely allow cascade deletes, then you must set the '
                            'ALLOW_CASCADE_DELETE=True class variable on your model.'
                        ).format(model))

Response: Validates that the ActivatableModel s fields are not None and that all foreign keys and OneToOneFields that will be deleted will not cause cascading deletions to occur.


Instruction:
Here you have a function in Python 3, explain what it does
def to_table(args, vdims=[]):
    "Helper function to convet an Args object to a HoloViews Table"
    if not Table:
        return "HoloViews Table not available"
    kdims = [dim for dim in args.constant_keys + args.varying_keys
             if dim not in vdims]
    items = [tuple([spec[k] for k in kdims+vdims])
             for spec in args.specs]
    return Table(items, kdims=kdims, vdims=vdims)

Response: Helper function to convet an Args object to a HoloViews Table


Instruction:
Make a summary of the following Python 3 code
def pprint_args(self, pos_args, keyword_args, infix_operator=None, extra_params={}):
        if infix_operator and not (len(pos_args)==2 and keyword_args==[]):
            raise Exception('Infix format requires exactly two'
                            ' positional arguments and no keywords')
        (kwargs,_,_,_) = self._pprint_args
        self._pprint_args = (keyword_args + kwargs, pos_args, infix_operator, extra_params)

Response:
Method to define the positional arguments and keyword order
        for pretty printing.


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _pprint(self, cycle=False, flat=False, annotate=False, onlychanged=True, level=1, tab = '   '):
        (kwargs, pos_args, infix_operator, extra_params) = self._pprint_args
        (br, indent)  = ('' if flat else '\n', '' if flat else tab * level)
        prettify = lambda x: isinstance(x, PrettyPrinted) and not flat
        pretty = lambda x: x._pprint(flat=flat, level=level+1) if prettify(x) else repr(x)

        params = dict(self.get_param_values())
        show_lexsort = getattr(self, '_lexorder', None) is not None
        modified = [k for (k,v) in self.get_param_values(onlychanged=onlychanged)]
        pkwargs = [(k, params[k])  for k in kwargs if (k in modified)] + list(extra_params.items())
        arg_list = [(k,params[k]) for k in pos_args] + pkwargs

        lines = []
        if annotate: # Optional annotating comment
            len_ckeys, len_vkeys = len(self.constant_keys), len(self.varying_keys)
            info_triple = (len(self),
                           ', %d constant key(s)' % len_ckeys if len_ckeys else '',
                           ', %d varying key(s)'  % len_vkeys if len_vkeys else '')
            annotation = '# == %d items%s%s ==\n' % info_triple
            lines = [annotation]

        if show_lexsort: lines.append('(')
        if cycle:
            lines.append('%s(...)' % self.__class__.__name__)
        elif infix_operator:
            level = level - 1
            triple = (pretty(params[pos_args[0]]), infix_operator, pretty(params[pos_args[1]]))
            lines.append('%s %s %s' % triple)
        else:
            lines.append('%s(' % self.__class__.__name__)
            for (k,v) in arg_list:
                lines.append('%s%s=%s' %  (br+indent, k, pretty(v)))
                lines.append(',')
            lines = lines[:-1] +[br+(tab*(level-1))+')'] # Remove trailing comma

        if show_lexsort:
            lines.append(').lexsort(%s)' % ', '.join(repr(el) for el in self._lexorder))
        return ''.join(lines)

Response: Pretty printer that prints all the modified keywords and the modified keywords and optionally annotates the top of the repr with a comment.


Instruction:
Create a Python 3 function to
format the elements of an argument set appropriately

Response:
def spec_formatter(cls, spec):
        " Formats the elements of an argument set appropriately"
        return type(spec)((k, str(v)) for (k,v) in spec.items())


Instruction:
Can you generate a brief explanation for the following Python 3 code
def _collect_by_key(self,specs):
        # Collect (key, value) tuples as list of lists, flatten with chain
        allkeys = itertools.chain.from_iterable(
            [[(k, run[k]) for k in run] for run in specs])
        collection = defaultdict(list)
        for (k,v) in allkeys: collection[k].append(v)
        return collection

Response: Collect the keys of the log entries in the specs dictionary.


Instruction:
Write a Python 3 script to
return the Cartesian product of the two sets of specifications.

Response:
def _cartesian_product(self, first_specs, second_specs):
        """
        Takes the Cartesian product of the specifications. Result will
        contain N specifications where N = len(first_specs) *
        len(second_specs) and keys are merged.
        Example: [{'a':1},{'b':2}] * [{'c':3},{'d':4}] =
        [{'a':1,'c':3},{'a':1,'d':4},{'b':2,'c':3},{'b':2,'d':4}]
        """
        return  [ dict(zip(
                          list(s1.keys()) + list(s2.keys()),
                          list(s1.values()) + list(s2.values())
                      ))
                 for s1 in first_specs for s2 in second_specs ]


Instruction:
Make a summary of the following Python 3 code
def summary(self):
        print("Items: %s" % len(self))
        varying_keys = ', '.join('%r' % k for k in self.varying_keys)
        print("Varying Keys: %s" % varying_keys)
        items = ', '.join(['%s=%r' % (k,v)
                           for (k,v) in self.constant_items])
        if self.constant_items:
            print("Constant Items: %s" % items)

Response: A succinct summary of the argument specifier.


Instruction:
Can you generate the documentation for the following Python 3 function
def _build_specs(self, specs, kwargs, fp_precision):
        if specs is None:
            overrides = param.ParamOverrides(self, kwargs,
                                             allow_extra_keywords=True)
            extra_kwargs = overrides.extra_keywords()
            kwargs = dict([(k,v) for (k,v) in kwargs.items()
                           if k not in extra_kwargs])
            rounded_specs = list(self.round_floats([extra_kwargs],
                                                   fp_precision))

            if extra_kwargs=={}: return [], kwargs, True
            else:                return rounded_specs, kwargs, False

        return list(self.round_floats(specs, fp_precision)), kwargs, True

Response: Builds the list of specs and kwargs for the resource.


Instruction:
Can you write a function in Python 3 where it
returns unique items in a sequence.

Response:
def _unique(self, sequence, idfun=repr):
        """
        Note: repr() must be implemented properly on all objects. This
        is implicitly assumed by Lancet when Python objects need to be
        formatted to string representation.
        """
        seen = {}
        return [seen.setdefault(idfun(e),e) for e in sequence
                if idfun(e) not in seen]


Instruction:
How would you code a function in Python 3 to
print the available argument values in the human - readable format.

Response:
def show(self, exclude=[]):
        """
        Convenience method to inspect the available argument values in
        human-readable format. The ordering of keys is determined by
        how quickly they vary.

        The exclude list allows specific keys to be excluded for
        readability (e.g. to hide long, absolute filenames).
        """
        ordering = self.constant_keys + self.varying_keys
        spec_lines = [', '.join(['%s=%s' % (k, s[k]) for k in ordering
                                 if (k in s) and (k not in exclude)])
                      for s in self.specs]
        print('\n'.join(['%d: %s' % (i,l) for (i,l) in enumerate(spec_lines)]))


Instruction:
Here you have a function in Python 3, explain what it does
def lexsort(self, *order):
        if order == []:
            raise Exception("Please specify the keys for sorting, use"
                            "'+' prefix for ascending,"
                            "'-' for descending.)")

        if not set(el[1:] for el in order).issubset(set(self.varying_keys)):
            raise Exception("Key(s) specified not in the set of varying keys.")

        sorted_args = copy.deepcopy(self)
        specs_param = sorted_args.params('specs')
        specs_param.constant = False
        sorted_args.specs = self._lexsorted_specs(order)
        specs_param.constant = True
        sorted_args._lexorder = order
        return sorted_args

Response: Returns a new instance of the command with the same arguments as this one but with the same arguments.