# Monitors (Brian 1 –> 2 conversion)

## Monitoring spiking activity

The main class to record spiking activity is `SpikeMonitor` which is created in the same way as in Brian 1. However, the internal storage and retrieval of spikes is different. In Brian 1, spikes were stored as a list of pairs `(i, t)`, the index and time of each spike. In Brian 2, spikes are stored as two arrays `i` and `t`, storing the indices and times. You can access these arrays as attributes of the monitor, there’s also a convenience attribute `it` that returns both at the same time. The following table shows how the spike indices and times can be retrieved in various forms in Brian 1 and Brian 2:

Brian 1 | Brian 2
--- | ---

    mon = SpikeMonitor(group)
    #... do the run
    list_of_pairs = mon.spikes
    index_list, time_list = zip(*list_of_pairs)
    index_array = array(index_list)
    time_array = array(time_list)
    # time_array is unitless in Brian 1

    mon = SpikeMonitor(group)
    #... do the run
    list_of_pairs = zip(*mon.it)
    index_list = list(mon.i)
    time_list = list(mon.t)
    index_array, time_array = mon.i, mon.t
    # time_array has units in Brian 2

You can also access the spike times for individual neurons. In Brian 1, you could directly index the monitor which is no longer allowed in Brian 2. Instead, ask for a dictionary of spike times and index the returned dictionary:

Brian 1 | Brian 2
--- | ---

    # dictionary of spike times for each neuron:
    spike_dict = mon.spiketimes
    # all spikes for neuron 3:
    spikes_3 = spike_dict[3] #  (no units)
    spikes_3 = mon[3] #  alternative (no units)

    # dictionary of spike times for each neuron:
    spike_dict = mon.spike_trains()
    # all spikes for neuron 3:
    spikes_3 = spike_dict[3]  # with units

In Brian 2, `SpikeMonitor` also provides the functionality of the Brian 1 classes `SpikeCounter` and `PopulationSpikeCounter`. If you are only interested in the counts and not in the individual spike events, use `record=False` to save the memory of storing them:

Brian 1 | Brian 2
--- | ---

    counter = SpikeCounter(group)
    pop_counter = PopulationSpikeCounter(group)
    #... do the run
    # Number of spikes for neuron 3:
    count_3 = counter[3]
    # Total number of spikes:
    total_spikes = pop_counter.nspikes

    counter = SpikeMonitor(group, record=False)

    #... do the run
    # Number of spikes for neuron 3
    count_3 = counter.count[3]
    # Total number of spikes:
    total_spikes = counter.num_spikes

Currently Brian 2 provides no functionality to calculate statistics such as correlations or histograms online, there is no equivalent to the following classes that existed in Brian 1: `AutoCorrelogram`, `CoincidenceCounter`, `CoincidenceMatrixCounter`, `ISIHistogramMonitor`, `VanRossumMetric`. You will therefore have to be calculate the corresponding statistiacs manually after the simulation based on the information stored in the `SpikeMonitor`. If you use the default Runtime code generation, you can also create a new Python class that calculates the statistic online (see this example from a Brian 2 tutorial).

## Monitoring variables

Single variables are recorded with a `StateMonitor` in the same way as in Brian 1, but the times and variable values are accessed differently:

Brian 1 | Brian 2
--- | ---

    mon = StateMonitor(group, 'v',
                       record=True)
    # ... do the run
    # plot the trace of neuron 3:
    plot(mon.times/ms, mon[3]/mV)
    # plot the traces of all neurons:
    plot(mon.times/ms, mon.values.T/mV)

    mon = StateMonitor(group, 'v',
                       record=True)
    # ... do the run
    # plot the trace of neuron 3:
    plot(mon.t/ms, mon[3].v/mV)
    # plot the traces of all neurons:
    plot(mon.t/ms, mon.v.T/mV)

Further differences:

- `StateMonitor` now records in the `'start'` scheduling slot by default. This leads to a more intuitive correspondence between the recorded times and the values: in Brian 1 (where `StateMonitor` recorded in the `'end'` slot) the recorded value at 0ms was not the initial value of the variable but the value after integrating it for a single time step. The disadvantage of this new default is that the very last value at the end of the last time step of a simulation is not recorded anymore. However, this value can be manually added to the monitor by calling `StateMonitor.record_single_timestep`.

- To not record every time step, use the `dt` argument (as for all other classes) instead of specifying a number of `timesteps`.

- Using `record=False` does no longer provide mean and variance of the recorded variable.

In contrast to Brian 1, `StateMonitor` can now record multiple variables and therefore replaces Brian 1’s `MultiStateMonitor`:

Brian 1 | Brian 2
--- | ---

    mon = MultiStateMonitor(group, ['v', 'w'],
                            record=True)
    # ... do the run
    # plot the traces of v and w for neuron 3:
    plot(mon['v'].times/ms, mon['v'][3]/mV)
    plot(mon['w'].times/ms, mon['w'][3]/mV)

    mon = StateMonitor(group, ['v', 'w'],
                       record=True)
    # ... do the run
    # plot the traces of v and w for neuron 3:
    plot(mon.t/ms, mon[3].v/mV)
    plot(mon.t/ms, mon[3].w/mV)

To record variable values at the times of spikes, Brian 2 no longer provides a separate class as Brian 1 did (`StateSpikeMonitor`). Instead, you can use `SpikeMonitor` to record additional variables (in addition to the neuron index and the spike time):

Brian 1 | Brian 2
--- | ---

    # We assume that "group" has a varying threshold
    mon = StateSpikeMonitor(group, 'v')
    # ... do the run
    # plot the mean v at spike time for each neuron
    mean_values = [mean(mon.values('v', idx))
                    for idx in range(len(group))]

    plot(mean_values/mV, 'o')

    # We assume that "group" has a varying threshold
    mon = SpikeMonitor(group, variables='v')
    # ... do the run
    # plot the mean v at spike time for each neuron
    values = mon.values('v')
    mean_values = [mean(values[idx])
                   for idx in range(len(group))]
    plot(mean_values/mV, 'o')

Note that there is no equivalent to `StateHistogramMonitor`, you will have to calculate the histogram from the recorded values or write your own custom monitor class.