def PlotTracesAsGrids(df, index, viewRange, saveDir=None, colorfy=False, dpi=300, fig_size=None, adjustFigH=True, adjustFigW=True, nullRange=None, annotation='Simple', setFont='default',gridSpec='Vertical', scalebarAt='all', fontSize=10, linewidth=1.0, monoStim=False, stimReflectCurrent=True): "Export Multiple episodes arranged in a grid; default vertically""" if not colorfy: colorfy = ['k'] nchannels = len(viewRange.keys()) nepisodes = len(index) if isinstance(gridSpec, str): nrows, ncols = { 'ver': (nchannels*nepisodes, 1), 'hor': (1, nchannels*nepisodes), 'cha': (nchannels, nepisodes), 'epi': (nepisodes, nchannels) }.get(gridSpec[:3].lower(), (None, None)) if nrows is None: raise(ValueError('Unrecognized gridSpec: {}'.format(gridSpec))) else: raise(TypeError('Unrecognized type of argument: "gridSpec"')) fig, _ = plt.subplots(nrows=nrows, ncols=ncols, sharex=True) ax = fig.get_axes() # text annotation area textbox = [] viewRange_dict = {} row, col = 0,0 # keep track of axis used first_last_mat = [[],[]] for n, i in enumerate(index): zData = df['Data'][i] ts = zData.Protocol.msPerPoint channels = [] for c, m in enumerate(viewRange.keys()): # Draw plots X = zData.Time Y = getattr(zData, m[0])[m[1]] # null the trace if nullRange is not None: if isinstance(nullRange, list): Y = Y - np.mean(spk_window(Y, ts, nullRange)) else: # a single number Y = Y - Y[time2ind(nullRange, ts)] # window the plot X = spk_window(X, ts, viewRange[m][0]) Y = spk_window(Y, ts, viewRange[m][0]) # Stim channel reflects current channel if stimReflectCurrent and m[0]=='Stimulus': CurBase = spk_window(zData.Current[m[1]], ts, viewRange[m][0]) # use view range of stimulus on current CurBase = np.mean(spk_window(CurBase, ts, [0,50])) Y = Y + CurBase # do the plot ind = np.ravel_multi_index((row,col), (nrows, ncols), order='C') if n == 0: first_last_mat[0].append(ind) elif n == len(index)-1: first_last_mat[-1].append(ind) if m[0] in ['Voltage', 'Current'] or not monoStim: ax[ind].plot(X, Y, color=colorfy[n%len(colorfy)], lw=linewidth) else: ax[ind].plot(X, Y, color='k', lw=linewidth) # View range viewRange_dict[(row,col)] = list(m)+list(viewRange[m]) # Draw initial value InitVal = "{0:0.0f}".format(Y[0]) if m[0] == 'Voltage': InitVal += 'mV' elif m[0] == 'Current': InitVal += 'pA' elif m[0] == 'Stimulus': if stimReflectCurrent: InitVal += 'pA' else: InitVal = '' ax[ind].text(X[0]-0.03*(viewRange[m][0][1]-viewRange[m][0][0]), Y[0]-1, InitVal, ha='right', va='center', color=colorfy[n%len(colorfy)]) if m[1] not in channels: channels.append(m[1]) # update axis row, col = { 'ver': (row+1, col), 'hor': (row, col+1), 'cha': (row+1 if c<nrows-1 else 0, col+1 if c==nrows-1 else col), 'epi': (row+1 if c==ncols-1 else row, col+1 if c<ncols-1 else 0) }.get(gridSpec[:3].lower()) if annotation.lower() != 'none': final_notes = writeEpisodeNote(zData, viewRange[m][0], channels=channels, mode=annotation) # Draw more annotations textbox.append(TextArea(final_notes, minimumdescent=False, textprops=dict(color=colorfy[n%len(colorfy)]))) # Group all the episode annotation text if annotation.lower() != 'none': box = VPacker(children=textbox, align="left",pad=0, sep=2) annotationbox = AnchoredOffsetbox(loc=3, child=box, frameon=False, bbox_to_anchor=[1, 1.1]) ax[-1].add_artist(annotationbox) scalebar = [annotationbox] else: scalebar = [] # set axis for c, vr in enumerate(viewRange_dict.items()): l, r = vr ind = np.ravel_multi_index(l, (nrows, ncols), order='C') ax[ind].set_xlim(r[2]) ax[ind].set_ylim(r[3]) # Add scalebar if scalebarAt.lower()=='all' or (scalebarAt.lower()=='first' and ind in first_last_mat[0]) or (scalebarAt.lower()=='last' and ind in first_last_mat[-1]): scalebar.append(AddTraceScaleBar(xunit='ms', yunit='mV' if r[0]=='Voltage' else 'pA', ax=ax[ind])) else: # including 'none' TurnOffAxis(ax=ax[ind]) plt.subplots_adjust(hspace = .001) # temp = 510 + c temp = tic.MaxNLocator(3) ax[ind].yaxis.set_major_locator(temp) if (isinstance(setFont, str) and setFont.lower() in ['default', 'arial', 'helvetica']) or \ (isinstance(setFont, bool) and setFont): SetFont(ax, fig, fontsize=fontSize, fontname=os.path.join(__location__,'../resources/Helvetica.ttf')) else: SetFont(ax, fig, fontsize=fontSize, fontname=setFont) # save the figure if adjustFigW: fig_size = (fig_size[0]*ncols, fig_size[1]) if adjustFigH: fig_size = (fig_size[0], fig_size[1]*nrows) fig.set_size_inches(fig_size) # plt.subplots_adjust(hspace=-0.8) fig.savefig(saveDir, bbox_inches='tight', bbox_extra_artists=tuple(scalebar), dpi=dpi, transparent=True) # Close the figure after save plt.close(fig) if '.svg' in saveDir: svg2eps_ai(source_file=saveDir, target_file=saveDir.replace('.svg', '.eps')) return(ax)
def PlotTracesConcatenated(df, index, viewRange, saveDir, colorfy=False, dpi=300, fig_size=None, nullRange=None, hSpaceType='Fixed', hFixedSpace=0.10, adjustFigW=True, adjustFigH=True, trimH=(None,None), annotation='Simple', setFont='default', fontSize=10, linewidth=1.0, monoStim=False, stimReflectCurrent=True): """Export traces arranged horizontally. Good for an experiments acquired over multiple episodes. trimH: (t1, t2) trim off the beginning of first episode by t1 seconds, and the the end of the last episode by t2 seconds """ nchannels = len(viewRange.keys()) if not colorfy: colorfy=['k'] fig, _= plt.subplots(nrows=nchannels, ncols=1, sharex=True) ax = fig.get_axes() # text annotation area textbox = [] nullBase = dict() currentTime = 0 maxWindow = max(df['Duration']) for n, i in enumerate(index): #iterate over episodes zData = df['Data'][i] ts = zData.Protocol.msPerPoint channels = [] for c, m in enumerate(viewRange.keys()): # iterate over channels/streams # Draw plots X = zData.Time + currentTime Y = getattr(zData, m[0])[m[1]] # null the trace if nullRange is not None: if n == 0: # calculate nullBase if isinstance(nullRange, list): nullBase[(m[0],m[1])] = np.mean(spk_window(Y, ts, nullRange)) else: nullBase[(m[0],m[1])] = Y[time2ind(nullRange, ts)] Y = Y - nullBase[(m[0],m[1])] if n == 0 and trimH[0] is not None: X = spk_window(X, ts, (trimH[0], None)) Y = spk_window(X, ts, (trimH[0], None)) elif n + 1 == len(index) and trimH[1] is not None: X = spk_window(X, ts, (None, trimH[1])) Y = spk_window(X, ts, (None, trimH[1])) # Stim channel reflects current channel if stimReflectCurrent and m[0]=='Stimulus': CurBase = spk_window(zData.Current[m[1]], ts, viewRange[m][0]) # use view range of stimulus on current CurBase = np.mean(spk_window(CurBase, ts, [0,50])) Y = Y + CurBase # do the plot if m[0] in ['Voltage', 'Current'] or not monoStim: # temporary workaround ax[c].plot(X, Y, color=colorfy[n%len(colorfy)], lw=linewidth) else: ax[c].plot(X, Y, color='k', lw=linewidth) # Draw the initial value, only for the first plot if n == 0: InitVal = "{0:0.0f}".format(Y[0]) if m[0] == 'Voltage': InitVal += 'mV' elif m[0] == 'Current': InitVal += 'pA' elif m[0] == 'Stimulus': if stimReflectCurrent: InitVal += 'pA' else: InitVal = '' ax[c].text(X[0]-0.03*(viewRange[m][0][1]-viewRange[m][0][0]), Y[0]-1, InitVal, ha='right', va='center', color=colorfy[n%len(colorfy)]) if m[1] not in channels: channels.append(m[1]) if annotation.lower() != 'none': final_notes = writeEpisodeNote(zData, viewRange[m][0], channels=channels, mode=annotation) # Draw some annotations textbox.append(TextArea(final_notes, minimumdescent=False, textprops=dict(color=colorfy[n%len(colorfy)]))) # Set some spacing for the next episode if n+1 < len(index): if hSpaceType.lower() == 'fixed': currentTime = currentTime + (len(Y)-1)*ts + maxWindow * hFixedSpace / 100.0 elif hSpaceType.lower() in ['real time', 'realtime', 'rt']: currentTime = currentTime + (df['Data'][index[n+1]].Protocol.WCtime - zData.Protocol.WCtime)*1000 # Group all the episodes annotation text if annotation.lower() != 'none': box = VPacker(children=textbox, align="left",pad=0, sep=2) annotationbox = AnchoredOffsetbox(loc=3, child=box, frameon=False, bbox_to_anchor=[1, 1.1]) ax[-1].add_artist(annotationbox) scalebar = [annotationbox] else: scalebar = [] # set axis for c, vr in enumerate(viewRange.items()): ax[c].set_ylim(vr[1][1]) # Add scalebar scalebar.append(AddTraceScaleBar(xunit='ms', yunit='mV' if vr[0][0]=='Voltage' else 'pA', ax=ax[c])) plt.subplots_adjust(hspace = .001) temp = tic.MaxNLocator(3) ax[c].yaxis.set_major_locator(temp) # Set font if (isinstance(setFont, str) and setFont.lower() in ['default', 'arial', 'helvetica']) or \ (isinstance(setFont, bool) and setFont): SetFont(ax, fig, fontsize=fontSize, fontname=os.path.join(__location__,'../resources/Helvetica.ttf')) else: SetFont(ax, fig, fontsize=fontSize, fontname=setFont) # figure out and set the figure size if adjustFigW: fig_size = (np.ptp(ax[0].get_xlim()) / maxWindow * fig_size[0], fig_size[1]) if adjustFigH: fig_size = (fig_size[0], fig_size[1]*nchannels) fig.set_size_inches(fig_size) fig.savefig(saveDir, bbox_inches='tight', bbox_extra_artists=tuple(scalebar), dpi=dpi) # Close the figure after save plt.close(fig) # Convert svg file to eps if '.svg' in saveDir: svg2eps_ai(source_file=saveDir, target_file=saveDir.replace('.svg', '.eps')) return(ax)
def PlotTraces(df, index, viewRange, saveDir, colorfy=False, dpi=300, fig_size=None, adjustFigH=True, adjustFigW=True, nullRange=None, annotation='Simple', setFont='default', fontSize=10, linewidth=1.0, monoStim=False, stimReflectCurrent=True): """Export multiple traces overlapping each other""" # np.savez('R:/tmp.npz', df=df, index=index, viewRange=[viewRange], saveDir=saveDir, colorfy=colorfy) # return # set_trace() # Start the figure # viewRange= {(channel, stream):[[xmin,xmax],[ymin),ymax]]} nchannels = len(viewRange.keys()) if not fig_size: # if not specified size, set to (4, 4*nchannels) fig_size = (4, 4*nchannels) if not colorfy: colorfy=['k'] fig, _= plt.subplots(nrows=nchannels, ncols=1, sharex=True) ax = fig.get_axes() # text annotation area textbox = [] for n, i in enumerate(index): zData = df['Data'][i] ts = zData.Protocol.msPerPoint channels = [] for c, m in enumerate(viewRange.keys()): # Draw plots X = zData.Time Y = getattr(zData, m[0])[m[1]] # null the trace, but ignore arithmetic data since their data were already nulled if nullRange is not None and zData.Protocol.acquireComment != 'PySynapse Arithmetic Data': if isinstance(nullRange, list): Y = Y - np.mean(spk_window(Y, ts, nullRange)) else: # a single number Y = Y - Y[time2ind(nullRange, ts)] # window the plot X = spk_window(X, ts, viewRange[m][0]) Y = spk_window(Y, ts, viewRange[m][0]) # Stim channel reflects current channel if stimReflectCurrent and m[0]=='Stimulus': CurBase = spk_window(zData.Current[m[1]], ts, viewRange[m][0]) # use view range of stimulus on current CurBase = np.mean(spk_window(CurBase, ts, [0,50])) Y = Y + CurBase # do the plot if m[0] in ['Voltage', 'Current'] or not monoStim: ax[c].plot(X, Y, color=colorfy[n%len(colorfy)], lw=linewidth) else: ax[c].plot(X, Y, color='k', lw=linewidth) # Draw initial value InitVal = "{0:0.0f}".format(Y[0]) if m[0] == 'Voltage': InitVal += 'mV' elif m[0] == 'Current': InitVal += 'pA' elif m[0] == 'Stimulus': if stimReflectCurrent: InitVal += 'pA' else: InitVal = '' if m[1] not in channels: channels.append(m[1]) #kkks = viewRange[m][0][1]-viewRange[m][0][0] #set_trace() ax[c].text(X[0]-0.03*(viewRange[m][0][1]-viewRange[m][0][0]), Y[0]-1, InitVal, ha='right', va='center', color=colorfy[n%len(colorfy)]) if annotation.lower() != 'none': final_notes = writeEpisodeNote(zData, viewRange[m][0], channels=channels, mode=annotation) # Draw more annotations textbox.append(TextArea(final_notes, minimumdescent=False, textprops=dict(color=colorfy[n%len(colorfy)]))) # Group all the episode annotation text if annotation.lower() != 'none': box = VPacker(children=textbox, align="left",pad=0, sep=2) annotationbox = AnchoredOffsetbox(loc=3, child=box, frameon=False, bbox_to_anchor=[1, 1.1]) ax[-1].add_artist(annotationbox) scalebar = [annotationbox] else: scalebar = [] # set axis for c, vr in enumerate(viewRange.items()): l, r = vr ax[c].set_xlim(r[0]) ax[c].set_ylim(r[1]) # Add scalebar scalebar.append(AddTraceScaleBar(xunit='ms', yunit='mV' if l[0]=='Voltage' else 'pA', ax=ax[c])) plt.subplots_adjust(hspace = .001) # temp = 510 + c temp = tic.MaxNLocator(3) ax[c].yaxis.set_major_locator(temp) if (isinstance(setFont, str) and setFont.lower() in ['default', 'arial', 'helvetica']) or \ (isinstance(setFont, bool) and setFont): SetFont(ax, fig, fontsize=fontSize, fontname=os.path.join(__location__,'../resources/Helvetica.ttf')) else: SetFont(ax, fig, fontsize=fontSize, fontname=setFont) # save the figure if adjustFigH: fig_size = (fig_size[0], fig_size[1]*nchannels) fig.set_size_inches(fig_size) # plt.subplots_adjust(hspace=-0.8) fig.savefig(saveDir, bbox_inches='tight', bbox_extra_artists=tuple(scalebar), dpi=dpi, transparent=True) # Close the figure after save plt.close(fig) # Convert from svg to eps if '.svg' in saveDir: svg2eps_ai(source_file=saveDir, target_file=saveDir.replace('.svg', '.eps')) return(ax)
def PlotTracesAsGrids(df, index, viewRange, saveDir=None, colorfy=False, artists=None, dpi=300, fig_size=None, adjustFigH=True, adjustFigW=True, nullRange=None, annotation='Simple', setFont='default',gridSpec='Vertical', scalebarAt='all', fontSize=10, linewidth=1.0, monoStim=False, stimReflectCurrent=True): "Export Multiple episodes arranged in a grid; default vertically""" if not colorfy: colorfy = ['k'] nchannels = len(viewRange.keys()) nepisodes = len(index) if isinstance(gridSpec, str): nrows, ncols = { 'ver': (nchannels*nepisodes, 1), 'hor': (1, nchannels*nepisodes), 'cha': (nchannels, nepisodes), 'epi': (nepisodes, nchannels) }.get(gridSpec[:3].lower(), (None, None)) if nrows is None: raise(ValueError('Unrecognized gridSpec: {}'.format(gridSpec))) else: raise(TypeError('Unrecognized type of argument: "gridSpec"')) fig, _ = plt.subplots(nrows=nrows, ncols=ncols, sharex=True) ax = fig.get_axes() # text annotation area textbox = [] viewRange_dict = {} row, col = 0,0 # keep track of axis used first_last_mat = [[],[]] for n, i in enumerate(index): zData = df['Data'][i] ts = zData.Protocol.msPerPoint channels = [] for c, m in enumerate(viewRange.keys()): # Draw plots X = zData.Time Y = getattr(zData, m[0])[m[1]] # null the trace if nullRange is not None: if isinstance(nullRange, list): Y = Y - np.mean(spk_window(Y, ts, nullRange)) else: # a single number Y = Y - Y[time2ind(nullRange, ts)] # window the plot X = spk_window(X, ts, viewRange[m][0]) Y = spk_window(Y, ts, viewRange[m][0]) # Stim channel reflects current channel if stimReflectCurrent and m[0]=='Stimulus': CurBase = spk_window(zData.Current[m[1]], ts, viewRange[m][0]) # use view range of stimulus on current CurBase = np.mean(spk_window(CurBase, ts, [0,50])) Y = Y + CurBase # do the plot ind = np.ravel_multi_index((row,col), (nrows, ncols), order='C') if n == 0: first_last_mat[0].append(ind) elif n == len(index)-1: first_last_mat[-1].append(ind) if m[0] in ['Voltage', 'Current'] or not monoStim: ax[ind].plot(X, Y, color=colorfy[n%len(colorfy)], lw=linewidth, solid_joinstyle='bevel', solid_capstyle='butt') else: ax[ind].plot(X, Y, color='k', lw=linewidth, solid_joinstyle='bevel', solid_capstyle='butt') # View range viewRange_dict[(row,col)] = list(m)+list(viewRange[m]) # Draw initial value InitVal = "{0:0.0f}".format(Y[0]) if m[0] == 'Voltage': InitVal += 'mV' elif m[0] == 'Current': InitVal += 'pA' elif m[0] == 'Stimulus': if stimReflectCurrent: InitVal += 'pA' else: InitVal = '' ax[ind].text(X[0]-0.03*(viewRange[m][0][1]-viewRange[m][0][0]), Y[0]-1, InitVal, ha='right', va='center', color=colorfy[n%len(colorfy)]) if m[1] not in channels: channels.append(m[1]) # update axis row, col = { 'ver': (row+1, col), 'hor': (row, col+1), 'cha': (row+1 if c<nrows-1 else 0, col+1 if c==nrows-1 else col), 'epi': (row+1 if c==ncols-1 else row, col+1 if c<ncols-1 else 0) }.get(gridSpec[:3].lower()) if annotation.lower() != 'none': final_notes = writeEpisodeNote(zData, viewRange[m][0], channels=channels, mode=annotation) # Draw more annotations textbox.append(TextArea(final_notes, minimumdescent=False, textprops=dict(color=colorfy[n%len(colorfy)]))) # Group all the episode annotation text if annotation.lower() != 'none': box = VPacker(children=textbox, align="left",pad=0, sep=2) annotationbox = AnchoredOffsetbox(loc=3, child=box, frameon=False, bbox_to_anchor=[1, 1.1]) ax[-1].add_artist(annotationbox) scalebar = [annotationbox] else: scalebar = [] # set axis for c, vr in enumerate(viewRange_dict.items()): l, r = vr ind = np.ravel_multi_index(l, (nrows, ncols), order='C') ax[ind].set_xlim(r[2]) ax[ind].set_ylim(r[3]) # Add scalebar if scalebarAt.lower()=='all' or (scalebarAt.lower()=='first' and ind in first_last_mat[0]) or (scalebarAt.lower()=='last' and ind in first_last_mat[-1]): scalebar.append(AddTraceScaleBar(xunit='ms', yunit='mV' if r[0]=='Voltage' else 'pA', ax=ax[ind])) else: # including 'none' TurnOffAxis(ax=ax[ind]) plt.subplots_adjust(hspace = .001) # temp = 510 + c temp = tic.MaxNLocator(3) ax[ind].yaxis.set_major_locator(temp) # Draw annotation artist for each export DrawAnnotationArtists(artists, axs=[ax[ind]]) if (isinstance(setFont, str) and setFont.lower() in ['default', 'arial', 'helvetica']) or \ (isinstance(setFont, bool) and setFont): SetFont(ax, fig, fontsize=fontSize, fontname=os.path.join(__location__,'../resources/Helvetica.ttf')) else: SetFont(ax, fig, fontsize=fontSize, fontname=setFont) # save the figure if adjustFigW: fig_size = (fig_size[0]*ncols, fig_size[1]) if adjustFigH: fig_size = (fig_size[0], fig_size[1]*nrows) fig.set_size_inches(fig_size) # plt.subplots_adjust(hspace=-0.8) fig.savefig(saveDir, bbox_inches='tight', bbox_extra_artists=tuple(scalebar), dpi=dpi, transparent=True) # Close the figure after save plt.close(fig) if '.svg' in saveDir: svg2eps_ai(source_file=saveDir, target_file=saveDir.replace('.svg', '.eps')) return(ax)
def PlotTracesConcatenated(df, index, viewRange, saveDir, colorfy=False, artists=None, dpi=300, fig_size=None, nullRange=None, hSpaceType='Fixed', hFixedSpace=0.10, adjustFigW=True, adjustFigH=True, trimH=(None,None), annotation='Simple', setFont='default', fontSize=10, linewidth=1.0, monoStim=False, stimReflectCurrent=True): """Export traces arranged horizontally. Good for an experiments acquired over multiple episodes. trimH: (t1, t2) trim off the beginning of first episode by t1 seconds, and the the end of the last episode by t2 seconds """ nchannels = len(viewRange.keys()) if not colorfy: colorfy=['k'] fig, _= plt.subplots(nrows=nchannels, ncols=1, sharex=True) ax = fig.get_axes() # text annotation area textbox = [] nullBase = dict() currentTime = 0 maxWindow = max(df['Duration']) for n, i in enumerate(index): #iterate over episodes zData = df['Data'][i] ts = zData.Protocol.msPerPoint channels = [] for c, m in enumerate(viewRange.keys()): # iterate over channels/streams # Draw plots X = zData.Time + currentTime Y = getattr(zData, m[0])[m[1]] # null the trace if nullRange is not None: if n == 0: # calculate nullBase if isinstance(nullRange, list): nullBase[(m[0],m[1])] = np.mean(spk_window(Y, ts, nullRange)) else: nullBase[(m[0],m[1])] = Y[time2ind(nullRange, ts)] Y = Y - nullBase[(m[0],m[1])] if n == 0 and trimH[0] is not None: X = spk_window(X, ts, (trimH[0], None)) Y = spk_window(X, ts, (trimH[0], None)) elif n + 1 == len(index) and trimH[1] is not None: X = spk_window(X, ts, (None, trimH[1])) Y = spk_window(X, ts, (None, trimH[1])) # Stim channel reflects current channel if stimReflectCurrent and m[0]=='Stimulus': CurBase = spk_window(zData.Current[m[1]], ts, viewRange[m][0]) # use view range of stimulus on current CurBase = np.mean(spk_window(CurBase, ts, [0,50])) Y = Y + CurBase # do the plot if m[0] in ['Voltage', 'Current'] or not monoStim: # temporary workaround ax[c].plot(X, Y, color=colorfy[n%len(colorfy)], lw=linewidth, solid_joinstyle='bevel', solid_capstyle='butt') else: ax[c].plot(X, Y, color='k', lw=linewidth, solid_joinstyle='bevel', solid_capstyle='butt') # Draw the initial value, only for the first plot if n == 0: InitVal = "{0:0.0f}".format(Y[0]) if m[0] == 'Voltage': InitVal += 'mV' elif m[0] == 'Current': InitVal += 'pA' elif m[0] == 'Stimulus': if stimReflectCurrent: InitVal += 'pA' else: InitVal = '' ax[c].text(X[0]-0.03*(viewRange[m][0][1]-viewRange[m][0][0]), Y[0]-1, InitVal, ha='right', va='center', color=colorfy[n%len(colorfy)]) if m[1] not in channels: channels.append(m[1]) if annotation.lower() != 'none': final_notes = writeEpisodeNote(zData, viewRange[m][0], channels=channels, mode=annotation) # Draw some annotations textbox.append(TextArea(final_notes, minimumdescent=False, textprops=dict(color=colorfy[n%len(colorfy)]))) # Set some spacing for the next episode if n+1 < len(index): if hSpaceType.lower() == 'fixed': currentTime = currentTime + (len(Y)-1)*ts + maxWindow * hFixedSpace / 100.0 elif hSpaceType.lower() in ['real time', 'realtime', 'rt']: currentTime = currentTime + (df['Data'][index[n+1]].Protocol.WCtime - zData.Protocol.WCtime)*1000 # Group all the episodes annotation text if annotation.lower() != 'none': box = VPacker(children=textbox, align="left",pad=0, sep=2) annotationbox = AnchoredOffsetbox(loc=3, child=box, frameon=False, bbox_to_anchor=[1, 1.1]) ax[-1].add_artist(annotationbox) scalebar = [annotationbox] else: scalebar = [] # set axis for c, vr in enumerate(viewRange.items()): ax[c].set_ylim(vr[1][1]) # Add scalebar scalebar.append(AddTraceScaleBar(xunit='ms', yunit='mV' if vr[0][0]=='Voltage' else 'pA', ax=ax[c])) plt.subplots_adjust(hspace = .001) temp = tic.MaxNLocator(3) ax[c].yaxis.set_major_locator(temp) # Set font if (isinstance(setFont, str) and setFont.lower() in ['default', 'arial', 'helvetica']) or \ (isinstance(setFont, bool) and setFont): SetFont(ax, fig, fontsize=fontSize, fontname=os.path.join(__location__,'../resources/Helvetica.ttf')) else: SetFont(ax, fig, fontsize=fontSize, fontname=setFont) # figure out and set the figure size if adjustFigW: fig_size = (np.ptp(ax[0].get_xlim()) / maxWindow * fig_size[0], fig_size[1]) if adjustFigH: fig_size = (fig_size[0], fig_size[1]*nchannels) fig.set_size_inches(fig_size) fig.savefig(saveDir, bbox_inches='tight', bbox_extra_artists=tuple(scalebar), dpi=dpi) # Close the figure after save plt.close(fig) # Convert svg file to eps if '.svg' in saveDir: svg2eps_ai(source_file=saveDir, target_file=saveDir.replace('.svg', '.eps')) return(ax)
def PlotTraces(df, index, viewRange, saveDir, colorfy=False, artists=None, dpi=300, fig_size=None, adjustFigH=True, adjustFigW=True, nullRange=None, annotation='Simple', setFont='default', fontSize=10, linewidth=1.0, monoStim=False, stimReflectCurrent=True): """Export multiple traces overlapping each other""" # np.savez('R:/tmp.npz', df=df, index=index, viewRange=[viewRange], saveDir=saveDir, colorfy=colorfy) # return # set_trace() # Start the figure # viewRange= {(channel, stream):[[xmin,xmax],[ymin),ymax]]} nchannels = len(viewRange.keys()) if not fig_size: # if not specified size, set to (4, 4*nchannels) fig_size = (4, 4*nchannels) if not colorfy: colorfy=['k'] fig, _ = plt.subplots(nrows=nchannels, ncols=1, sharex=True) ax = fig.get_axes() # text annotation area textbox = [] for n, i in enumerate(index): zData = df['Data'][i] ts = zData.Protocol.msPerPoint channels = [] for c, m in enumerate(viewRange.keys()): # Draw plots X = zData.Time Y = getattr(zData, m[0])[m[1]] # null the trace, but ignore arithmetic data since their data were already nulled if nullRange is not None and zData.Protocol.acquireComment != 'PySynapse Arithmetic Data': if isinstance(nullRange, list): Y = Y - np.mean(spk_window(Y, ts, nullRange)) else: # a single number Y = Y - Y[time2ind(nullRange, ts)] # window the plot X = spk_window(X, ts, viewRange[m][0]) Y = spk_window(Y, ts, viewRange[m][0]) # Stim channel reflects current channel if stimReflectCurrent and m[0]=='Stimulus': CurBase = spk_window(zData.Current[m[1]], ts, viewRange[m][0]) # use view range of stimulus on current CurBase = np.mean(spk_window(CurBase, ts, [0,50])) Y = Y + CurBase # do the plot if m[0] in ['Voltage', 'Current'] or not monoStim: ax[c].plot(X, Y, color=colorfy[n%len(colorfy)], lw=linewidth, solid_joinstyle='bevel', solid_capstyle='butt') else: ax[c].plot(X, Y, color='k', lw=linewidth, solid_joinstyle='bevel', solid_capstyle='butt') # Draw initial value InitVal = "{0:0.0f}".format(Y[0]) if m[0] == 'Voltage': InitVal += 'mV' elif m[0] == 'Current': InitVal += 'pA' elif m[0] == 'Stimulus': if stimReflectCurrent: InitVal += 'pA' else: InitVal = '' if m[1] not in channels: channels.append(m[1]) #kkks = viewRange[m][0][1]-viewRange[m][0][0] #set_trace() ax[c].text(X[0]-0.03*(viewRange[m][0][1]-viewRange[m][0][0]), Y[0]-1, InitVal, ha='right', va='center', color=colorfy[n%len(colorfy)]) if annotation.lower() != 'none': final_notes = writeEpisodeNote(zData, viewRange[m][0], channels=channels, mode=annotation) # Draw more annotations textbox.append(TextArea(final_notes, minimumdescent=False, textprops=dict(color=colorfy[n%len(colorfy)]))) # Group all the episode annotation text if annotation.lower() != 'none': box = VPacker(children=textbox, align="left", pad=0, sep=2) annotationbox = AnchoredOffsetbox(loc=3, child=box, frameon=False, bbox_to_anchor=[1, 1.1]) ax[-1].add_artist(annotationbox) scalebar = [annotationbox] else: scalebar = [] # Draw annotation artists DrawAnnotationArtists(artists, axs=ax) # set axis for c, vr in enumerate(viewRange.items()): l, r = vr ax[c].set_xlim(r[0]) ax[c].set_ylim(r[1]) # Add scalebar scalebar.append(AddTraceScaleBar(xunit='ms', yunit='mV' if l[0]=='Voltage' else 'pA', ax=ax[c])) plt.subplots_adjust(hspace=.001) # temp = 510 + c temp = tic.MaxNLocator(3) ax[c].yaxis.set_major_locator(temp) if (isinstance(setFont, str) and setFont.lower() in ['default', 'arial', 'helvetica']) or \ (isinstance(setFont, bool) and setFont): SetFont(ax, fig, fontsize=fontSize, fontname=os.path.join(__location__,'../resources/Helvetica.ttf')) else: SetFont(ax, fig, fontsize=fontSize, fontname=setFont) # save the figure if adjustFigH: fig_size = (fig_size[0], fig_size[1]*nchannels) fig.set_size_inches(fig_size) # plt.subplots_adjust(hspace=-0.8) fig.savefig(saveDir, bbox_inches='tight', bbox_extra_artists=tuple(scalebar), dpi=dpi, transparent=True) # Close the figure after save plt.close(fig) # Convert from svg to eps if '.svg' in saveDir: svg2eps_ai(source_file=saveDir, target_file=saveDir.replace('.svg', '.eps')) return(ax)