Source code for netpyne.plotting.plotSpikeHist

# Generate a spike histogram

from netpyne import __gui__

if __gui__:
    import matplotlib.patches as mpatches
import numpy as np
from ..analysis.utils import exception
from ..analysis.tools import loadData
from .plotter import HistPlotter


[docs] @exception def plotSpikeHist( histData=None, axis=None, timeRange=None, popNumCells=None, popLabels=None, popColors=None, binSize=5, histType='step', stacked=False, cumulative=False, log=False, density=False, legend=True, colorList=None, returnPlotter=False, **kwargs ): """Function to produce a histogram plot of cell spiking NetPyNE Options --------------- include : str, int, list Cells and/or NetStims to return information from. *Default:* ``['allCells', 'eachPop']`` includes average of all cells and each population of cells *Options:* (1) ``'all'`` includes all cells and all NetStims, (2) ``'allNetStims'`` includes all NetStims but no cells, (3) a *str* which matches a popLabel includes all cells in that pop, (4) a *str* which matches a NetStim name includes that NetStim, (5) an *int* includes the cell with that global identifier (GID), (6) a *list* of *ints* includes the cells with those GIDS, (7) a *list* with two items, the first of which is a *str* matching a popLabel and the second of which is an *int* (or a *list* of *ints*), includes the relative cell(s) from that population (e.g. (``['popName', [0, 1]]``) includes the first two cells in popName. sim : NetPyNE sim object The *sim object* from which to get data. *Default:* ``None`` uses the current NetPyNE sim object Parameters ---------- histData : list, tuple, dict, str The data necessary to plot the raster (spike times and spike indices, at minimum). *Default:* ``None`` uses ``analysis.prepareRaster`` to produce ``rasterData`` using the current NetPyNE sim object. *Options:* if a *list* or a *tuple*, the first item must be a *list* of spike times and the second item must be a *list* the same length of spike indices (the id of the cell corresponding to that spike time). Optionally, a third item may be a *list* of *ints* representing the number of cells in each population (in lieu of ``popNumCells``). Optionally, a fourth item may be a *list* of *strs* representing the population names (in lieu of ``popLabels``). If a *dict* it must have keys ``'spkTimes'`` and ``'spkInds'`` and may optionally include ``'popNumCells'`` and ``'popLabels'``. If a *str* it must represent a file path to previously saved data. axis : matplotlib axis The axis to plot into, allowing overlaying of plots. *Default:* ``None`` produces a new figure and axis. timeRange : list Time range to include in the raster: ``[min, max]``. *Default:* ``None`` uses the entire simulation popNumCells : list A *list* of *ints* representing the number of cells in each population. *Default:* ``None`` puts all cells into a single population. popLabels : list A *list* of *strs* of population names. Must be the same length as ``popNumCells``. *Default:* ``None`` uses generic names. popColors : dict A *dict* of ``popLabels`` and their desired color. *Default:* ``None`` draws from the NetPyNE default colorList. binSize : int Size of bin in ms to use for spike histogram. *Default:* ``5`` histType : str Type of histogram to plot ('step', 'stepfilled', 'bar', 'barstacked') *Default:* ``'step'`` stacked : bool Whether to stack populations on top of each other *Default:* ``False`` cumulative : bool Whether each bin is cumulative *Default:* ``False`` log : bool Whether to use a log axis *Default:* ``False`` density : bool Whether to normalize data *Default:* ``False`` legend : bool Whether or not to add a legend to the plot. *Default:* ``True`` adds a legend. colorList : list A *list* of colors to draw from when plotting. *Default:* ``None`` uses the default NetPyNE colorList. returnPlotter : bool Whether to return the figure or the NetPyNE MetaFig object. *Default:* ``False`` returns the figure. Plot Options ------------ showFig : bool Whether to show the figure. *Default:* ``False`` saveFig : bool Whether to save the figure. *Default:* ``False`` overwrite : bool whether to overwrite existing figure files. *Default:* ``True`` overwrites the figure file *Options:* ``False`` adds a number to the file name to prevent overwriting legendKwargs : dict a *dict* containing any or all legend kwargs. These include ``'title'``, ``'loc'``, ``'fontsize'``, ``'bbox_to_anchor'``, ``'borderaxespad'``, and ``'handlelength'``. rcParams : dict a *dict* containing any or all matplotlib rcParams. To see all options, execute ``import matplotlib; print(matplotlib.rcParams)`` in Python. Any options in this *dict* will be used for this current figure and then returned to their prior settings. title : str the axis title xlabel : str label for x-axis ylabel : str label for y-axis linewidth : int line width Returns ------- freqPlot : *matplotlib figure* By default, returns the *figure*. If ``returnPlotter`` is ``True``, instead returns the NetPyNE MetaFig. """ # If there is no input data, get the data from the NetPyNE sim object if histData is None: if 'sim' not in kwargs: from .. import sim else: sim = kwargs['sim'] histData = sim.analysis.prepareSpikeHist(timeRange=timeRange, binSize=binSize, **kwargs) # Ensure that include is a list if it is in kwargs if 'include' in kwargs: include = kwargs['include'] else: include = ['eachPop', 'allCells'] print('Plotting spike histogram...') # If input is a file name, load data from the file if type(histData) == str: histData = loadData(histData) # If input is a dictionary, pull the data out of it if type(histData) == dict: spkTimes = histData['spkTimes'] spkInds = histData['spkInds'] if not popNumCells: popNumCells = histData.get('popNumCells') if not popLabels: popLabels = histData.get('popLabels') numNetStims = histData.get('numNetStims', 0) axisArgs = histData.get('axisArgs') legendLabels = histData.get('legendLabels') # If input is a list or tuple, the first item is spike times, the second is spike indices elif type(histData) == list or type(histData) == tuple: spkTimes = histData[0] spkInds = histData[1] axisArgs = None legendLabels = None # If there is a third item, it should be popNumCells if not popNumCells: try: popNumCells = histData[2] except: pass # If there is a fourth item, it should be popLabels if not popLabels: try: popLabels = histData[3] except: pass # If there is no info about pops, generate info for a single pop if not popNumCells: popNumCells = [max(spkInds)] if popLabels: popLabels = [str(popLabels[0])] else: popLabels = ['population'] # If there is info about pop numbers, but not labels, generate the labels elif not popLabels: popLabels = ['pop_' + str(index) for index, pop in enumerate(popNumCells)] # If there is info about pop numbers and labels, make sure they are the same size if len(popNumCells) != len(popLabels): raise Exception( 'In plotSpikeHist, popNumCells (' + str(len(popNumCells)) + ') and popLabels (' + str(len(popLabels)) + ') must be the same size' ) # Replace 'eachPop' with list of pops if 'eachPop' in include: include.remove('eachPop') for popLabel in popLabels: include.append(popLabel) # Create a dictionary with the color for each pop if not colorList: from .plotter import colorList popColorsTemp = {popLabel: colorList[ipop % len(colorList)] for ipop, popLabel in enumerate(popLabels)} if popColors: popColorsTemp.update(popColors) popColors = popColorsTemp # Create a list to link cells to their populations indPop = [] popGids = [] for popLabel, popNumCell in zip(popLabels, popNumCells): popGids.append(np.arange(len(indPop), len(indPop) + int(popNumCell))) indPop.extend(int(popNumCell) * [popLabel]) # Create a dictionary to link cells to their population cellGids = list(set(spkInds)) gidPops = {cellGid: indPop[cellGid] for cellGid in cellGids} # Set the time range appropriately if 'timeRange' in histData: timeRange = histData['timeRange'] if timeRange is None: timeRange = [0, np.ceil(max(spkTimes))] # Bin the data using Numpy histoData = np.histogram(spkTimes, bins=np.arange(timeRange[0], timeRange[1], binSize)) histoBins = histoData[1] histoCount = histoData[0] # Create a dictionary with the inputs for a histogram plot plotData = {} plotData['x'] = spkTimes plotData['bins'] = histoBins plotData['range'] = histData.get('range', None) plotData['density'] = density plotData['weights'] = histData.get('weights', None) plotData['cumulative'] = cumulative plotData['bottom'] = histData.get('bottom', None) plotData['histtype'] = histType plotData['align'] = histData.get('align', 'mid') plotData['orientation'] = histData.get('orientation', 'vertical') plotData['rwidth'] = histData.get('rwidth', None) plotData['log'] = log plotData['color'] = histData.get('color', None) plotData['linewidth'] = 1.0 plotData['alpha'] = histData.get('alpha', None) plotData['label'] = histData.get('label', None) plotData['stacked'] = stacked plotData['data'] = histData.get('data', None) # If a kwarg matches a histogram input key, use the kwarg value instead of the default for kwarg in list(kwargs.keys()): if kwarg in plotData: plotData[kwarg] = kwargs[kwarg] kwargs.pop(kwarg) # Create a dictionary to hold axis inputs if not axisArgs: axisArgs = {} axisArgs['title'] = 'Histogram Plot of Spiking' axisArgs['xlabel'] = 'Time (ms)' axisArgs['ylabel'] = 'Number of Spikes' axisArgs['xlim'] = timeRange axisArgs['ylim'] = None # If a kwarg matches an axis input key, use the kwarg value instead of the default for kwarg in list(kwargs.keys()): if kwarg in axisArgs.keys(): axisArgs[kwarg] = kwargs[kwarg] kwargs.pop(kwarg) # create Plotter object histPlotter = HistPlotter(data=plotData, kind='histogram', axis=axis, **axisArgs, **kwargs) metaFig = histPlotter.metafig # Set up a dictionary of population colors if not popColors: colorList = colorList popColors = {popLabel: colorList[ipop % len(colorList)] for ipop, popLabel in enumerate(popLabels)} # Create the labels and handles for the legend # (use rectangles instead of markers because some markers don't show up well) labels = [] handles = [] # Remove the sum of all population spiking when stacking if stacked or histType == 'barstacked': if 'allCells' in include: include.remove('allCells') # Deal with the sum of all population spiking (allCells) if 'allCells' not in include: histPlotter.x = [] histPlotter.color = [] else: histPlotter.x = [histPlotter.x] allCellsColor = 'black' if 'allCellsColor' in kwargs: allCellsColor = kwargs['allCellsColor'] histPlotter.color = [allCellsColor] labels.append('All cells') handles.append(mpatches.Rectangle((0, 0), 1, 1, fc=allCellsColor)) # Handle individual pops and grouped pops for subset in include: # if it's a single population if type(subset) not in [list, tuple]: for popIndex, popLabel in enumerate(popLabels): if popLabel == subset: # Get GIDs for this population currentGids = popGids[popIndex] # Use GIDs to get a spiketimes list for this population try: spkinds, spkts = list( zip(*[(spkgid, spkt) for spkgid, spkt in zip(spkInds, spkTimes) if spkgid in currentGids]) ) except: spkinds, spkts = [], [] # Append the population spiketimes list to histPlotter.x histPlotter.x.append(spkts) # Append the population color to histPlotter.color histPlotter.color.append(popColors[popLabel]) # Append the legend labels and handles if legendLabels: labels.append(legendLabels[popIndex]) else: labels.append(popLabel) handles.append(mpatches.Rectangle((0, 0), 1, 1, fc=popColors[popLabel])) # if it's a group of populations else: allGids = [] groupLabel = None groupColor = None for popIndex, popLabel in enumerate(popLabels): if popLabel in subset: # Get GIDs for this population currentGids = popGids[popIndex] allGids.extend(currentGids) if not groupLabel: groupLabel = popLabel else: groupLabel += ', ' + popLabel if not groupColor: groupColor = popColors[popLabel] # Use GIDs to get a spiketimes list for this population try: spkinds, spkts = list( zip(*[(spkgid, spkt) for spkgid, spkt in zip(spkInds, spkTimes) if spkgid in allGids]) ) except: spkinds, spkts = [], [] # Append the population spiketimes list to histPlotter.x histPlotter.x.append(spkts) # Append the population color to histPlotter.color histPlotter.color.append(groupColor) # Append the legend labels and handles labels.append(groupLabel) handles.append(mpatches.Rectangle((0, 0), 1, 1, fc=groupColor)) # Set up the default legend settings legendKwargs = {} legendKwargs['title'] = 'Populations' legendKwargs['bbox_to_anchor'] = (1.025, 1) legendKwargs['loc'] = 2 legendKwargs['borderaxespad'] = 0.0 legendKwargs['handlelength'] = 0.5 legendKwargs['fontsize'] = 'small' # add legend if legend: # Add the legend histPlotter.addLegend(handles, labels, **legendKwargs, **kwargs) # Adjust the plot to make room for the legend rightOffset = 0.8 maxLabelLen = max([len(label) for label in popLabels]) histPlotter.fig.subplots_adjust(right=(rightOffset - 0.012 * maxLabelLen)) # Generate the figure histPlot = histPlotter.plot(**axisArgs, **kwargs) # Default is to return the figure, but you can also return the plotter if returnPlotter: return metaFig else: return histPlotter