def plot_rates(spike_trains, population=None, node_groups=None, times=None, smoothing=False, smoothing_params=None, title=None, show=True, save_as=None):
    'Calculate and plot the rates of each node in a SpikeTrains object or SONATA Spike-Trains file. If start and stop\n    times are not specified from the "times" parameter, will try to parse values from the timestamps data.\n\n    If you want to only display a subset of nodes and/or group together different nodes (by node_id) by dot colors and\n    labels then you can use the node_groups, which should be a list of dicts::\n\n        plot_rates(\'/path/to/my/spike.h5\',\n                    node_groups=[{\'node_ids\': range(0, 70), \'c\': \'b\', \'label\': \'pyr\'},\n                                 {\'node_ids\': range(70, 100), \'c\': \'r\', \'label\': \'inh\'}])\n\n    :param spike_trains: SpikeTrains object or path to a (SONATA) spikes file.\n    :param population: string. If a spikes-file contains more than one population of nodes, use this to determine which\n        nodes to actually plot. If only one population exists and population=None then the function will find it by\n        default.\n    :param node_groups: None or list of dicts. Used to group sets of nodes by labels and color. Each grouping should\n        be a dictionary with a \'node_ids\' key with a list of the ids. You can also add \'label\' and \'c\' keys for\n        label and color. If None all nodes will be labeled and colored the same.\n    :param times: (float, float). Used to set start and stop time. If not specified will try to find values from spiking\n        data.\n    :param smoothing: Bool or function. Used to smooth the data. By default (False) no smoothing will be done. If True\n        will using a moving average smoothing function. Or use a function pointer.\n    :param smoothing_params: dict, parameters when using a function pointer smoothing value.\n    :param title: str, Use to add a title. Default no tile\n    :param show:  bool to display or not display plot. default True.\n    :param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not\n        save plot.\n    :return: matplotlib figure.Figure object\n    '
    spike_trains = __get_spike_trains(spike_trains=spike_trains)
    pop = __get_population(spike_trains=spike_trains, population=population)
    (node_groups, selected_ids) = __get_node_groups(spike_trains=spike_trains, node_groups=node_groups, population=pop)
    smoothing_params = (smoothing_params or {})
    if isinstance(smoothing, types.FunctionType):
        smoothing_fnc = partial(smoothing, **smoothing_params)
    elif smoothing:
        smoothing_fnc = partial(moving_average, **smoothing_params)
    else:
        smoothing_fnc = (lambda d: d)
    spikes_df = spike_trains.to_dataframe(population=pop, with_population_col=False)
    spikes_df = spikes_df[spikes_df['node_ids'].isin(selected_ids)]
    if (times is not None):
        recording_interval = (times[1] - times[0])
        spikes_df = spikes_df[((spikes_df['timestamps'] >= times[0]) & (spikes_df['timestamps'] <= times[1]))]
    else:
        recording_interval = (np.max(spikes_df['timestamps']) - np.min(spikes_df['timestamps']))
    (fig, axes) = plt.subplots()
    show_legend = False
    for node_grp in node_groups:
        show_legend = (show_legend or ('label' in node_grp))
        grp_ids = node_grp.pop('node_ids')
        grp_spikes = spikes_df[spikes_df['node_ids'].isin(grp_ids)]
        spike_rates = (grp_spikes.groupby('node_ids').size() / (recording_interval / 1000.0))
        axes.plot(np.array(spike_rates.index), smoothing_fnc(spike_rates), '.', **node_grp)
    axes.set_ylabel('Firing Rates (Hz)')
    axes.set_xlabel('node_ids')
    if show_legend:
        axes.legend()
    if title:
        axes.set_title(title)
    if save_as:
        plt.savefig(save_as)
    if show:
        plt.show()
    return fig
Calculate and plot the rates of each node in a SpikeTrains object or SONATA Spike-Trains file. If start and stop
times are not specified from the "times" parameter, will try to parse values from the timestamps data.

If you want to only display a subset of nodes and/or group together different nodes (by node_id) by dot colors and
labels then you can use the node_groups, which should be a list of dicts::

    plot_rates('/path/to/my/spike.h5',
                node_groups=[{'node_ids': range(0, 70), 'c': 'b', 'label': 'pyr'},
                             {'node_ids': range(70, 100), 'c': 'r', 'label': 'inh'}])

:param spike_trains: SpikeTrains object or path to a (SONATA) spikes file.
:param population: string. If a spikes-file contains more than one population of nodes, use this to determine which
    nodes to actually plot. If only one population exists and population=None then the function will find it by
    default.
:param node_groups: None or list of dicts. Used to group sets of nodes by labels and color. Each grouping should
    be a dictionary with a 'node_ids' key with a list of the ids. You can also add 'label' and 'c' keys for
    label and color. If None all nodes will be labeled and colored the same.
:param times: (float, float). Used to set start and stop time. If not specified will try to find values from spiking
    data.
:param smoothing: Bool or function. Used to smooth the data. By default (False) no smoothing will be done. If True
    will using a moving average smoothing function. Or use a function pointer.
:param smoothing_params: dict, parameters when using a function pointer smoothing value.
:param title: str, Use to add a title. Default no tile
:param show:  bool to display or not display plot. default True.
:param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not
    save plot.
:return: matplotlib figure.Figure object
def plot_rates(spike_trains, population=None, node_groups=None, times=None, smoothing=False, smoothing_params=None, title=None, show=True, save_as=None):
    'Calculate and plot the rates of each node in a SpikeTrains object or SONATA Spike-Trains file. If start and stop\n    times are not specified from the "times" parameter, will try to parse values from the timestamps data.\n\n    If you want to only display a subset of nodes and/or group together different nodes (by node_id) by dot colors and\n    labels then you can use the node_groups, which should be a list of dicts::\n\n        plot_rates(\'/path/to/my/spike.h5\',\n                    node_groups=[{\'node_ids\': range(0, 70), \'c\': \'b\', \'label\': \'pyr\'},\n                                 {\'node_ids\': range(70, 100), \'c\': \'r\', \'label\': \'inh\'}])\n\n    :param spike_trains: SpikeTrains object or path to a (SONATA) spikes file.\n    :param population: string. If a spikes-file contains more than one population of nodes, use this to determine which\n        nodes to actually plot. If only one population exists and population=None then the function will find it by\n        default.\n    :param node_groups: None or list of dicts. Used to group sets of nodes by labels and color. Each grouping should\n        be a dictionary with a \'node_ids\' key with a list of the ids. You can also add \'label\' and \'c\' keys for\n        label and color. If None all nodes will be labeled and colored the same.\n    :param times: (float, float). Used to set start and stop time. If not specified will try to find values from spiking\n        data.\n    :param smoothing: Bool or function. Used to smooth the data. By default (False) no smoothing will be done. If True\n        will using a moving average smoothing function. Or use a function pointer.\n    :param smoothing_params: dict, parameters when using a function pointer smoothing value.\n    :param title: str, Use to add a title. Default no tile\n    :param show:  bool to display or not display plot. default True.\n    :param save_as: None or str: file-name/path to save the plot as a png/jpeg/etc. If None or empty string will not\n        save plot.\n    :return: matplotlib figure.Figure object\n    '
    spike_trains = __get_spike_trains(spike_trains=spike_trains)
    pop = __get_population(spike_trains=spike_trains, population=population)
    (node_groups, selected_ids) = __get_node_groups(spike_trains=spike_trains, node_groups=node_groups, population=pop)
    smoothing_params = (smoothing_params or {})
    if isinstance(smoothing, types.FunctionType):
        smoothing_fnc = partial(smoothing, **smoothing_params)
    elif smoothing:
        smoothing_fnc = partial(moving_average, **smoothing_params)
    else:
        smoothing_fnc = (lambda d: d)
    spikes_df = spike_trains.to_dataframe(population=pop, with_population_col=False)
    spikes_df = spikes_df[spikes_df['node_ids'].isin(selected_ids)]
    if (times is not None):
        recording_interval = (times[1] - times[0])
        spikes_df = spikes_df[((spikes_df['timestamps'] >= times[0]) & (spikes_df['timestamps'] <= times[1]))]
    else:
        recording_interval = (np.max(spikes_df['timestamps']) - np.min(spikes_df['timestamps']))
    (fig, axes) = plt.subplots()
    show_legend = False
    for node_grp in node_groups:
        show_legend = (show_legend or ('label' in node_grp))
        grp_ids = node_grp.pop('node_ids')
        grp_spikes = spikes_df[spikes_df['node_ids'].isin(grp_ids)]
        spike_rates = (grp_spikes.groupby('node_ids').size() / (recording_interval / 1000.0))
        axes.plot(np.array(spike_rates.index), smoothing_fnc(spike_rates), '.', **node_grp)
    axes.set_ylabel('Firing Rates (Hz)')
    axes.set_xlabel('node_ids')
    if show_legend:
        axes.legend()
    if title:
        axes.set_title(title)
    if save_as:
        plt.savefig(save_as)
    if show:
        plt.show()
    return fig