import os import numpy as np import matplotlib.pyplot as plt from scipy.interpolate import griddata from datetime import datetime from matplotlib.colors import LogNorm from matplotlib.ticker import LogFormatter from matplotlib import ticker, cm import workspace as ws import read_results def show_slice( ax, filename, axis, where, method='nearest', rsx=100, rsy=100, rsz=100, window=(0., 1.), nlevels=100, vmin=None, vmax=None, extend='neither', logscale=False, save=False, zorder=0, **kwargs ): """ Opens a file 'filename' and shows the data at a slice perpendicular to the 'axis' axis at a relative position 'where', where 'where' ranges from 0. to 1. """ # Keyword arguments if len(kwargs) >= 2: xyzunits = kwargs['xyzunits'] vunits = kwargs['vunits'] else: xyzunits = '' vunits = '' try: cmap = kwargs['cmap'] except KeyError: cmap = plt.cm.jet try: show_data_points = kwargs['show_data_points'] except KeyError: show_data_points = False try: show_intp_points = kwargs['show_intp_points'] except KeyError: show_intp_points = False # Set colors for bad values if False: cmap.set_under(color='black') cmap.set_over(color='black') if False: cmap.set_bad(color='black') # Load data data = np.loadtxt(filename, delimiter=',') x = data[:,0] y = data[:,1] z = data[:,2] v = data[:,3] # Sides xspan = x.max() - x.min() yspan = y.max() - y.min() zspan = z.max() - z.min() # Window wl, wr = window # Crop the window limits just in case wl = max(wl, 0.) wl = min(wl, 1.) wr = max(wr, 0.) wr = min(wr, 1.) # Regular mesh xi_ = np.linspace(x.min(), x.max(), rsx) yi_ = np.linspace(y.min(), y.max(), rsy) zi_ = np.linspace(z.min(), z.max(), rsz) if axis == 'x': # Indices for the windows wl_i = int(rsx * wl) wr_i = int(rsx * wr) # Create the mask for the data xleft = x.min() + xspan * wl xrght = x.min() + xspan * wr mask = np.ma.masked_where((x >= xleft) & (x <= xrght), x).mask # Crop the corresponding array for the regular mesh xi_ = xi_[wl_i:wr_i] elif axis == 'y': # Indices for the windows wl_i = int(rsy * wl) wr_i = int(rsy * wr) # Create the mask for the data yleft = y.min() + yspan * wl yrght = y.min() + yspan * wr mask = np.ma.masked_where((y >= yleft) & (y <= yrght), y).mask # Crop the corresponding array for the regular mesh yi_ = yi_[wl_i:wr_i] elif axis == 'z': # Indices for the windows wl_i = int(rsz * wl) wr_i = int(rsz * wr) # Create the mask for the data zleft = z.min() + zspan * wl zrght = z.min() + zspan * wr mask = np.ma.masked_where((z >= zleft) & (z <= zrght), z).mask # Crop the corresponding array for the regular mesh zi_ = zi_[wl_i:wr_i] # 'mesh' the regular mesh xi, yi, zi = np.meshgrid(xi_, yi_, zi_) # Mask data x = x[mask] y = y[mask] z = z[mask] v = v[mask] # Interpolation t0 = datetime.now() vi = griddata((x,y,z), v, (xi,yi,zi), method=method) t1 = datetime.now() print('Time needed: %f s'%((t1 - t0).total_seconds())) # Figure # Levels for colouring vi_mkd_cpd = np.ma.masked_where(np.isnan(vi), vi).compressed() vmin_, vmax_ = vi_mkd_cpd.min(), vi_mkd_cpd.max() if vmax is None: vmax = vmax_ if vmin is None: vmin = vmin_ # levels_i = np.linspace(vmin, vmax, nlevels) # Avoid an error due to a flat level list if vmin == vmax: vmin -= 0.1 vmax += 0.1 # Re-build the levels print('Limits:', vmin, vmax) levels_i = np.linspace(vmin, vmax, nlevels) loglevels = np.logspace( np.log10(min(np.abs(vmin), np.abs(vmax))), np.log10(max(np.abs(vmin), np.abs(vmax))), nlevels ) # Minimum and maximum exponents min_exp = int(np.log10(min(np.abs(vmin), np.abs(vmax)))) max_exp = int(np.log10(max(np.abs(vmin), np.abs(vmax)))) + 1 # Ticks for the colorbar in case it's logscale cbticks = 10. ** np.arange(min_exp, max_exp + 1, 1) cbticks_ = cbticks.tolist() for i in range(2, 10, 1): cbticks_ = cbticks_ + (float(i) * cbticks).tolist() cbticks_.sort() # print(cbticks_, min_exp, max_exp) cbticklabels = [] for c in cbticks_: if c in (20, 50, 100, 200, 500, 1000): cbticklabels.append('%i'%c) else: cbticklabels.append('') if axis == 'x': s = int(where * rsx) - wl_i if not logscale: cf = ax.contourf( yi[:, s, :], zi[:, s, :], vi[:, s, :], levels_i, cmap=cmap, extend=extend, zorder=zorder ) else: cf = ax.contourf( yi[:, s, :], zi[:, s, :], np.abs(vi[:, s, :]), loglevels, cmap=cmap, norm=LogNorm( vmin=min(np.abs(vmin), np.abs(vmax)), vmax=max(np.abs(vmin), np.abs(vmax)) ), # locator=ticker.LogLocator(), zorder=zorder ) if show_data_points: ax.plot(y, z, 'k.', markersize=0.6) if show_intp_points: ax.scatter(yi, zi, c='k', s=1) ax.set_title('x = %f'%xi[s, s, s] + ' ' + xyzunits) ax.set_xlabel('y (' + xyzunits + ')') ax.set_ylabel('z (' + xyzunits + ')') elif axis == 'y': s = int(where * rsy) - wl_i if not logscale: cf = ax.contourf( xi[s, :, :], zi[s, :, :], vi[s, :, :], levels_i, cmap=cmap, extend=extend, zorder=zorder ) else: cf = ax.contourf( xi[s, :, :], zi[s, :, :], np.abs(vi[s, :, :]), loglevels, cmap=cmap, norm=LogNorm( vmin=min(np.abs(vmin), np.abs(vmax)), vmax=max(np.abs(vmin), np.abs(vmax)) ), # locator=ticker.LogLocator(), zorder=zorder ) if show_data_points: ax.plot(x, z, 'k.', markersize=0.6) if show_intp_points: ax.scatter(xi, zi, c='k', s=1) ax.set_title('y = %f'%yi[s, s, s] + ' ' + xyzunits) ax.set_xlabel('x (' + xyzunits + ')') ax.set_ylabel('z (' + xyzunits + ')') elif axis == 'z': s = int(where * rsz) - wl_i if not logscale: cf = ax.contourf( xi[:, :, s], yi[:, :, s], vi[:, :, s], levels_i, cmap=cmap, extend=extend, zorder=zorder ) else: cf = ax.contourf( xi[:, :, s], yi[:, :, s], np.abs(vi[:, :, s]), loglevels, cmap=cmap, norm=LogNorm( vmin=min(np.abs(vmin), np.abs(vmax)), vmax=max(np.abs(vmin), np.abs(vmax)) ), # locator=ticker.LogLocator(), zorder=zorder ) if show_data_points: ax.plot(x, y, 'k.', markersize=0.6) if show_intp_points: ax.scatter(xi, yi, c='k', s=1) ax.set_title('z = %f'%zi[s, s, s] + ' ' + xyzunits) ax.set_xlabel('x (' + xyzunits + ')') ax.set_ylabel('y (' + xyzunits + ')') ax.set_aspect('equal') if logscale: l_f = LogFormatter(10, labelOnlyBase=False) # cb = plt.colorbar(cf, ticks=cbticks_, format=l_f) cb = plt.colorbar(cf, format=l_f) # cb = plt.colorbar(cf, ticks=cbticks) # cb = plt.colorbar(cf) cb.set_ticks(cbticks_) # cb.set_ticklabels(cbticklabels) # cb.set_norm(LogNorm()) # print(cbticklabels) else: cb = plt.colorbar(cf, ax=ax) cb.set_label(vunits) def z_slice(ax, filename, folder, z, t, tarray): """ This slicing function uses a much more efficient method to interpolate along the z-axiz """ # This is from a xyz file # Load data data = np.loadtxt(filename, delimiter=',') x = data[:,0] y = data[:,1] z_ = data[:,2] v = data[:,3] # Set the cables xy_all = np.array(list(zip(x, y))) xy_unique = np.unique(xy_all, axis=0) nc = len(xy_unique) data_intp = np.zeros(nc) # Construct zprofile for i, xy in enumerate(xy_unique): # Select the corresponding rows rows = np.where((xy == xy_all).all(axis=1))[0] # Sort z_ just in case # argsort = np.argsort(z_[rows]) # z_.sort() # Sort v accordingly # Not yet # v.sort(argsort) # Select z_ z__ = z_[rows] z_lower = z__[np.where(z__ < z)] z__minus_z = np.abs(z__ - z) z_lower_minus_z = np.abs(z_lower - z).min() here = np.where(z__minus_z == z_lower_minus_z)[0][0] # Interpolate v__ = v[rows] data_intp[i] = (z__minus_z[here + 1] * v__[here] + z__minus_z[here] * v__[here + 1]) / (z__[here + 1] - z__[here]) # if v[here] < -100.: # Show result ax.scatter(xy_unique[:, 0], xy_unique[:, 1], c=data_intp, s=10, cmap=plt.cm.jet_r) ax.set_aspect('equal') # KEEP THE CODE BELOW, DON'T DELETE IT. # It works only when there are results if False: # Read results data, zprofile, xyr = read_results.read_results(folder) xx_, yy_, rr_ = xyr nc = len(data) data_intp = np.zeros(nc) for i in range(nc): # Choose data try: data_ = data[i]['vext[0]'] except KeyError: data_ = data[i]['vext[1]'] # Find the zprofile[i] value lying just below z zpr = np.array(zprofile[i].values()) zpr_minus_z = np.abs(zpr - z) here = np.where(zpr_minus_z == zpr_minus_z.min()) # Interpolate v it = np.where(tarray == t)[0][0] v = data_[:, it] # data_intp[i] = (zpr_minus_z[here] * v[here] + zpr_minus_z[here + 1] * v[here + 1]) / (zpr[here + 1] - zpr[here]) data_intp[i] = (zpr_minus_z[here + 1] * v[here] + zpr_minus_z[here] * v[here + 1]) / (zpr[here + 1] - zpr[here]) # Show result ax.scatter(xx_, yy_, c=data_intp) return xy_unique, data_intp def axons_activity(time, data, tlims): """ Show axons' activity """ labels = {'Sti': 'Stimulation point', 'Rec': 'Recording point'} colors = {'Sti': 'k', 'Rec': 'b'} fig, ax = plt.subplots() # Potential for vecs in data: for k, vv in vecs.items(): ax.plot(time, vv, colors[k]) ax.set_xlim(tlims[0], tlims[1]) ax.set_xlabel('t (ms)') ax.set_ylabel('Vm (mV)') ax.set_title('Axons Vm (mV)') plt.savefig(os.path.join(ws.folders["data/results"], 'images/Axons.png')) def cross_sec_results(data): """ Cross-section of the nerve and results """ # Map of axons act_axs = [] k = 0 # Count it as having an AP if Vm is above 20 mV for i, v in enumerate(data): # Don't use the stimulation point to check if there is an AP, because # the stimulation artefact can give a false positive. # v = v['Sti'] # Use instead the recording position. This is in better accordance to # Raspopovic & al. (2011), who say that the AP needs to travel the whole # length for the axon to be tagged as activated v = v['Rec'] if v.max() > -30.: act_axs.append(True) else: act_axs.append(False) # Figure fig, ax = plt.subplots() zorder = 0 # Triangulation ws.nvt.draw_contours(ax, c='k', zorder=zorder) ws.nvt.draw_axons_and_points(ax, c='k', act_axons=act_axs, zorder=zorder) ws.nvt.draw_triangulation(ax, c='darkgrey', lw=0.4, zorder=zorder) zorder += 1 # Scatter all points in black x, y = ws.nvt.x, ws.nvt.y ax.scatter(x, y, c='k', s=1, zorder=zorder) df2 # Arrange figure xleft = x.min() xrght = x.max() ybot = y.min() ytop = y.max() margin = 100 ax.set_xlim(xleft - margin, xrght + margin) ax.set_ylim(ybot - margin, ytop + margin) ax.set_aspect('equal') ax.set_xlabel('x') ax.set_ylabel('y') title_ups = 'Tessellated nerve and current injections' title_len = 'Length (z-axis): %0.00f um'%ws.length title_inj = 'Injected current(s): %0.00f uA'%(ws.icamp * 1.e-3) title = title_ups + '\n' + title_len + '\n' + title_inj ax.set_title(title) # Field ws.nvt.pd.draw(ax, colour='dimgrey', alpha=1., linestyle='-', linewidth=.5, markers=None, title=title, zorder=zorder) fig.tight_layout() fig.savefig(os.path.join(ws.folders["data/results"], 'images/Nerve_and_tessellation.png'))