diff --git a/plotstyle.py b/plotstyle.py index 0bfe3ee..23206a4 100644 --- a/plotstyle.py +++ b/plotstyle.py @@ -354,6 +354,7 @@ def common_format(): mpl.rcParams['ytick.direction'] = 'out' mpl.rcParams['xtick.major.width'] = 1.25 mpl.rcParams['ytick.major.width'] = 1.25 + mpl.rcParams['axes.facecolor'] = 'none' if 'axes.prop_cycle' in mpl.rcParams: mpl.rcParams['axes.prop_cycle'] = cycler(color=[colors['blue'], colors['red'], colors['orange'], colors['green'], diff --git a/pointprocesses/lecture/firingrates.py b/pointprocesses/lecture/firingrates.py index 2ee4c17..eacda7e 100644 --- a/pointprocesses/lecture/firingrates.py +++ b/pointprocesses/lecture/firingrates.py @@ -35,7 +35,6 @@ def plot_isi_rate(spike_times, max_t=30, dt=1e-4): ax1.set_xlim(0, 5) ax2.plot(time, rate, label="instantaneous rate, trial 1") ax2.set_ylabel('Firing rate', 'Hz') - ax2.legend() ax3.fill_between(time, avg_rate+rate_std, avg_rate-rate_std, color="dodgerblue", alpha=0.5, label="standard deviation") @@ -144,39 +143,47 @@ def plot_comparison(spike_times, bin_width, sigma, max_t=30., dt=1e-4): time, inst_rate = get_instantaneous_rate(times) time, binn_rate = get_binned_rate(times, bin_width) - fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, figsize=cm_size(figure_width, 2.0*figure_height)) + fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, figsize=cm_size(figure_width, 1.8*figure_height)) fig.subplots_adjust(**adjust_fs(fig, left=6.0, right=1.5, bottom=3.0, top=1.0)) + ax1.show_spines('b') ax1.vlines(times[times < (100000*dt)], ymin=0, ymax=1, color=colors['blue'], lw=1.5) - ax1.set_ylabel('Spikes') + #ax1.set_ylabel('Spikes') + ax1.text(-0.105, 0.5, 'Spikes', transform=ax1.transAxes, + rotation='vertical', va='center') ax1.set_xlim(2.5, 3.5) - ax1.set_ylim(0, 1) - ax1.set_yticks([0, 1]) + ax1.set_ylim(-0.2, 1) ax1.set_xticks([2.5, 2.75, 3.0, 3.25, 3.5]) ax1.set_xticklabels([]) - ax2.plot(time, inst_rate, color=colors['orange'], lw=1.5, label="instantaneous rate") - ax2.legend() - ax2.set_ylabel('Rate', 'Hz') + ax2.plot(time, inst_rate, color=colors['orange'], lw=2) + ax2.text(1.0, 1.0, 'instantaneous rate', transform=ax2.transAxes, ha='right') + #ax2.set_ylabel('Rate', 'Hz') + ax2.text(-0.105, 0.5, axis_label('Rate', 'Hz'), transform=ax2.transAxes, + rotation='vertical', va='center') ax2.set_xlim(2.5, 3.5) ax2.set_ylim(0, 300) ax2.set_yticks(np.arange(0, 400, 100)) ax2.set_xticks([2.5, 2.75, 3.0, 3.25, 3.5]) ax2.set_xticklabels([]) - ax3.plot(time, binn_rate, color=colors['orange'], lw=1.5, label="binned rate") - ax3.set_ylabel('Rate', 'Hz') - ax3.legend() + ax3.plot(time, binn_rate, color=colors['orange'], lw=2) + ax3.text(1.0, 1.0, 'binned rate', transform=ax3.transAxes, ha='right') + #ax3.set_ylabel('Rate', 'Hz') + ax3.text(-0.105, 0.5, axis_label('Rate', 'Hz'), transform=ax3.transAxes, + rotation='vertical', va='center') ax3.set_xlim(2.5, 3.5) ax3.set_ylim(0, 300) ax3.set_yticks(np.arange(0, 400, 100)) ax3.set_xticks([2.5, 2.75, 3.0, 3.25, 3.5]) ax3.set_xticklabels([]) - ax4.plot(time, conv_rate, color=colors['orange'], lw=1.5, label="convolved rate") + ax4.plot(time, conv_rate, color=colors['orange'], lw=2) + ax4.text(1.0, 1.0, 'convolved rate', transform=ax4.transAxes, ha='right') ax4.set_xlabel('Time', 's') - ax4.set_ylabel('Rate', 'Hz') - ax4.legend() + #ax4.set_ylabel('Rate', 'Hz') + ax4.text(-0.105, 0.5, axis_label('Rate', 'Hz'), transform=ax4.transAxes, + rotation='vertical', va='center') ax4.set_xlim(2.5, 3.5) ax4.set_xticks([2.5, 2.75, 3.0, 3.25, 3.5]) ax4.set_ylim(0, 300) diff --git a/pointprocesses/lecture/isimethod.py b/pointprocesses/lecture/isimethod.py index 1fe81bb..750b840 100644 --- a/pointprocesses/lecture/isimethod.py +++ b/pointprocesses/lecture/isimethod.py @@ -1,9 +1,10 @@ import numpy as np import matplotlib.pyplot as plt +import matplotlib.gridspec as gridspec from plotstyle import * -fig_size = cm_size(figure_width, 1.2*figure_height) +fig_size = cm_size(figure_width, figure_height) def create_spikes(nspikes=11, duration=0.5, seed=1000): @@ -27,11 +28,12 @@ def gaussian(sigma, dt): def setup_axis(spikes_ax, rate_ax): - spikes_ax.show_spines('b') + spikes_ax.show_spines('') spikes_ax.set_yticks([]) spikes_ax.set_ylim(-0.2, 1.0) spikes_ax.text(-0.1, 0.5, 'Spikes', transform=spikes_ax.transAxes, rotation='vertical', va='center') spikes_ax.set_xlim(-1, 500) + spikes_ax.set_xticklabels([]) #spikes_ax.set_xticklabels(np.arange(0., 600, 100)) spikes_ax.show_spines('lb') @@ -54,10 +56,12 @@ def plot_bin_method(): bins = np.arange(0, 0.55, 0.05) count, _ = np.histogram(spike_times, bins) - + fig = plt.figure(figsize=fig_size) - spikes_ax = plt.subplot2grid((7,1), (0,0), rowspan=3, colspan=1) - rate_ax = plt.subplot2grid((7,1), (3,0), rowspan=4, colspan=1) + spec = gridspec.GridSpec(nrows=2, ncols=1, height_ratios=[3, 4], hspace=0.2, + **adjust_fs(fig, left=5.5, right=1.5, top=1.5)) + spikes_ax = fig.add_subplot(spec[0, 0]) + rate_ax = fig.add_subplot(spec[1, 0]) setup_axis(spikes_ax, rate_ax) for ti in spike_times: @@ -71,7 +75,7 @@ def plot_bin_method(): ha='center') rate = count / 0.05 - rate_ax.step(1000.0*bins, np.hstack((rate, rate[-1])), color=colors['orange'], where='post') + rate_ax.step(1000.0*bins, np.hstack((rate, rate[-1])), color=colors['orange'], lw=2, where='post') fig.savefig("binmethod.pdf") plt.close() @@ -89,8 +93,10 @@ def plot_conv_method(): rate = np.roll(rate, -1) fig = plt.figure(figsize=fig_size) - spikes_ax = plt.subplot2grid((7,1), (0,0), rowspan=3, colspan=1) - rate_ax = plt.subplot2grid((7,1), (3,0), rowspan=4, colspan=1) + spec = gridspec.GridSpec(nrows=2, ncols=1, height_ratios=[3, 4], hspace=0.2, + **adjust_fs(fig, left=5.5, right=1.5, top=1.5)) + spikes_ax = fig.add_subplot(spec[0, 0]) + rate_ax = fig.add_subplot(spec[1, 0]) setup_axis(spikes_ax, rate_ax) for ti in spike_times: @@ -109,9 +115,11 @@ def plot_isi_method(): spike_times = create_spikes() fig = plt.figure(figsize=fig_size) - spikes_ax = plt.subplot2grid((7,1), (0,0), rowspan=3, colspan=1) - rate = plt.subplot2grid((7,1), (3,0), rowspan=4, colspan=1) - setup_axis(spikes_ax, rate) + spec = gridspec.GridSpec(nrows=2, ncols=1, height_ratios=[3, 4], hspace=0.2, + **adjust_fs(fig, left=5.5, right=1.5, top=1.5)) + spikes_ax = fig.add_subplot(spec[0, 0]) + rate_ax = fig.add_subplot(spec[1, 0]) + setup_axis(spikes_ax, rate_ax) spike_times = np.hstack((0.005, spike_times)) for i in range(1, len(spike_times)): @@ -119,13 +127,13 @@ def plot_isi_method(): t = 1000*spike_times[i] spikes_ax.plot([t_start, t_start], [0., 1.], color=colors['blue'], lw=2) spikes_ax.annotate(s='', xy=(t_start, 0.5), xytext=(t,0.5), arrowprops=dict(arrowstyle='<->'), color=colors['red']) - spikes_ax.text(0.5*(t_start+t), 0.75, + spikes_ax.text(0.5*(t_start+t), 1.05, "{0:.0f}".format((t - t_start)), color=colors['red'], ha='center') #spike_times = np.hstack((0, spike_times)) i_rate = 1./np.diff(spike_times) - rate.step(1000*spike_times, np.hstack((i_rate, i_rate[-1])),color=colors['orange'], lw=2, where="post") + rate_ax.step(1000*spike_times, np.hstack((i_rate, i_rate[-1])),color=colors['orange'], lw=2, where="post") fig.savefig("isimethod.pdf") diff --git a/pointprocesses/lecture/pointprocesses-chapter.tex b/pointprocesses/lecture/pointprocesses-chapter.tex index e71ae61..897a5ac 100644 --- a/pointprocesses/lecture/pointprocesses-chapter.tex +++ b/pointprocesses/lecture/pointprocesses-chapter.tex @@ -2,6 +2,8 @@ \input{../../header} +\renewcommand{\exercisesolutions}{here} % 0: here, 1: chapter, 2: end + \lstset{inputpath=../code} \graphicspath{{figures/}} diff --git a/pointprocesses/lecture/pointprocesses.tex b/pointprocesses/lecture/pointprocesses.tex index 5ec4abf..f6e0945 100644 --- a/pointprocesses/lecture/pointprocesses.tex +++ b/pointprocesses/lecture/pointprocesses.tex @@ -175,7 +175,7 @@ with itself and is always 1. Implement a function \varcode{isiserialcorr()} that takes a vector of interspike intervals as input argument and calculates the serial correlation. The function should further plot the serial - correlation. \pagebreak[4] + correlation. \end{exercise} @@ -223,7 +223,7 @@ that is given in Hertz window. The function should take two input arguments: (i) a cell-array of vectors containing the spike times in seconds observed in a number of trials, and (ii) the duration of the time window that - is used to evaluate the counts.\pagebreak[4] + is used to evaluate the counts. \end{exercise} @@ -340,13 +340,11 @@ closely. \begin{figure}[tp] \includegraphics[width=\columnwidth]{firingrates} - \titlecaption{Estimating the time-dependent firing - rate.}{\textbf{A)} Rasterplot showing the spiking activity of a - neuron. \textbf{B)} Firing rate calculated from the - \emph{instantaneous rate}. \textbf{C)} classical PSTH with the - \emph{binning} method. \textbf{D)} Firing rate estimated by - \emph{convolution} of the activity with a Gaussian - kernel.}\label{psthfig} + \titlecaption{Estimating time-dependent firing rates.}{Rasterplot + showing one trial of spiking activity of a neuron (top). + \emph{Instantaneous rate}, classical PSTH estimatd with the + \emph{binning} method and by \emph{convolution} of the spike train + with a Gaussian kernel (bottom).}\label{psthfig} \end{figure} @@ -354,11 +352,11 @@ closely. \begin{figure}[tp] \includegraphics[width=\columnwidth]{isimethod} - \titlecaption{Instantaneous firing rate.}{Sketch of the recorded - spiketrain (top). Arrows illustrate the interspike intervals and - number give the intervals in milliseconds. The inverse of the - interspike interval is the \emph{instantaneous firing - rate}.}\label{instratefig} + \titlecaption{Instantaneous firing rate.}{The recorded spiketrain + (top). Arrows illustrate the interspike intervals and numbers + give the intervals in milliseconds. The inverse of the interspike + intervals is the \emph{instantaneous firing rate} + (bottom).}\label{instratefig} \end{figure} A very simple method for estimating the time-dependent firing rate is @@ -414,12 +412,12 @@ methods make an assumption about the relevant observation time-scale \begin{figure}[tp] \includegraphics[width=\columnwidth]{binmethod} - \titlecaption{Estimating the PSTH using the binning method.}{ The - same spiketrain as shown in \figref{instratefig} is used - here. Vertical gray lines indicate the borders between adjacent - bins in which the number of action potentials is counted (red - numbers). The firing rate is then the histogram normalized to the - binwidth.}\label{binpsthfig} + \titlecaption{Estimating the PSTH using the binning method.}{The + same spiketrain as shown in \figref{instratefig} (top). Vertical + gray lines indicate the borders between adjacent bins in which the + number of action potentials is counted (red numbers). The firing + rate is then the histogram normalized to the binwidth + (bottom).}\label{binpsthfig} \end{figure} The \entermde[firing rate!binning @@ -440,7 +438,6 @@ estimation Changes that happen within a bin cannot be resolved. Thus chosing a bin width implies an assumption about the relevant time-scale. -\pagebreak[4] \begin{exercise}{binnedRate.m}{} Implement a function that estimates the firing rate using the binning method. The method should take the spike-times as an @@ -452,12 +449,12 @@ time-scale. \begin{figure}[tp] \includegraphics[width=\columnwidth]{convmethod} \titlecaption{Estimating the firing rate using the convolution - method.}{The same spiketrain as in \figref{instratefig}. The - convolution of the spiketrain with a convolution kernel basically - replaces each spike event with the kernel (top). A Gaussian kernel - is used here, but other kernels are also possible. If the kernel - is properly normalized the firing rate results directly form the - superposition of the kernels.}\label{convratefig} + method.}{The same spiketrain as in \figref{instratefig} (top). The + convolution of the spiketrain with a kernel replaces each spike + event with the kernel (red). A Gaussian kernel is used here, but + other kernels are also possible. If the kernel is properly + normalized the firing rate results directly form the superposition + of the kernels (bottom).}\label{convratefig} \end{figure} With the \entermde[firing rate!convolution @@ -484,7 +481,6 @@ width defines, similar to the bin width of the binning method, the temporal resolution of the method and thus makes assumptions about the relevate time-scale. -\pagebreak[4] \begin{exercise}{convolutionRate.m}{} Implement the function that estimates the firing rate using the convolution method. The method takes the spiketrain, the temporal @@ -512,16 +508,15 @@ snippets are then averaged (\figref{stafig}). \begin{figure}[t] \includegraphics[width=\columnwidth]{sta} - \titlecaption{Spike-triggered average of a P-type electroreceptors + \titlecaption{Spike-triggered average of a P-type electroreceptor and the stimulus reconstruction.}{The neuron was driven by a - \enterm{white-noise} stimulus (blue curve, right panel). The STA - (left) is the average stimulus that surrounds the times of the - recorded action potentials (40\,ms before and 20\,ms after the - spike). Using the STA as a convolution kernel for convolving the - spiketrain we can reconstruct the stimulus from the neuronal - response. In this way we can get an impression of the stimulus - features that are encoded in the neuronal response (right - panel).}\label{stafig} + \enterm{white-noise} stimulus (blue, right). The STA (left) is the + average stimulus that surrounds the times of the recorded action + potentials (40\,ms before and 20\,ms after the spike). Using the + STA as a kernel for convolving the spiketrain we can reconstruct + the stimulus from the neuronal response. In this way we can get an + impression of the stimulus features that are linearly encoded in + the neuronal response (orange, right).}\label{stafig} \end{figure} From the STA we can extract several pieces of information about the