GCAL Collector

This notebook demonstrates how you can collect measurements and analyze data over development using the Collector class.


In [ ]:
%reload_ext topo.misc.ipython
%view webm:5

Defining the data to be collected


In [ ]:
import topo
from topo.analysis import Collector
from topo.submodel.gcal import ModelGCAL, ArraySpec

Hypercolumn distance estimation requires ``scipy.optimize``


In [ ]:
from topo.analysis.command import measure_or_pref
from imagen.analysis import fft_power_spectrum
from featuremapper.analysis.pinwheels import PinwheelAnalysis
from featuremapper.analysis.hypercolumns import PowerSpectrumAnalysis

from holoviews import Points

We will now define the GCAL model specification:


In [ ]:
topo.sim.model = ModelGCAL(cortex_density=47)
gcal = topo.sim.model.specification

Collector can be configured to collect Sheet and Projection activities, Projection weights, the output of featuremapper measurements, array data (here the V1 homeostatic threshold) and can be instructed to analyze any of these sources with the analyze method:


In [ ]:
c = Collector()

# Projection activities
c.Activity.LGNOnAfferent =  c.collect(gcal.projections.V1.LGNOnAfferent)
c.Activity.LGNOffAfferent = c.collect(gcal.projections.V1.LGNOffAfferent)

# OR preference measurement
c.collect(measure_or_pref)
# Sheet activities
c.Activity.Retina =         c.collect(gcal.sheets.Retina)
c.Activity.V1 =             c.collect(gcal.sheets.V1)
# Connection fields
c.CFs.LGNOnAfferent =       c.collect(gcal.projections.V1.LGNOnAfferent,  grid=True)
c.CFs.LGNOffAfferent =      c.collect(gcal.projections.V1.LGNOffAfferent, grid=True)
# Homeostatic threshold
c.HomeostaticThreshold.V1 = c.collect(ArraySpec('V1.output_fns[0].t'), 
                                                value='Homeostatic Threshold')
# Analysis
c.FFTPowerSpectrum.V1 =     c.analyze(c.ref.OrientationPreference.V1, fft_power_spectrum)
c.Pinwheels.V1 =            c.analyze(c.ref.OrientationPreference.V1
                                    * c.ref.OrientationSelectivity.V1, PinwheelAnalysis)
c.FFTAnalysis.V1 =          c.analyze(c.ref.Pinwheels.V1, PowerSpectrumAnalysis)

Now to instantiate and load the model:


In [ ]:
topo.sim()

Finally, we define the measurement times and run the collector:


In [ ]:
times = [500*i for i in range(31)]
print("Collection will start at iteration %d and end on iteration %d" % (min(times), max(times)))

In [ ]:
data = c(times=times)

Sheet and projection activities

Here are both the projection activities (top row) and sheet activies (bottom row)


In [ ]:
data.Activity.grid().cols(2)

Connection fields (weights)

Here are the weights on the ON surround and OFF surround RGC+LGN projections:


In [ ]:
data.CFs.LGNOnAfferent + data.CFs.LGNOffAfferent

On minus OFF visualization

Here is a visualization of the OFF weights subtracted from the ON weights:


In [ ]:
on_minus_off = (data.CFs.LGNOnAfferent * data.CFs.LGNOffAfferent)
on_minus_off.title = 'ON-OFF CFs'
on_minus_off

OR map and weights over development

  • The central map is an polar, orientation + selectivity orientation map.
  • The top histogram shows the distribution of orientation preferences across the map.
  • The star markers on the map show the positions from which the ON-OFF weights (on the left) are sampled.
  • The left side shows ON-OFF weights projecting to the V1 sheet.

In [ ]:
%view 150

In [ ]:
%%opts Points color='w' marker='*' s=100 edgecolors='k'
annotated_map = (data.OrientationPreference.V1 
                 * data.OrientationSelectivity.V1  
                 * Points(on_minus_off[0,-0.3:0.3].keys()))
annotated_map << on_minus_off[0,-0.3:0.3] <<  data.OrientationPreference.V1.hist(adjoin=False)

Homeostatic threshold

This is a visualization of the homeostatic threshold array (output function on the V1 sheet) over development:


In [ ]:
data.HomeostaticThreshold.V1.hist()

Orientation and Phase Preference and Selectivity

This animations shows how preference and selectivity evolve over development:


In [ ]:
%view 100

In [ ]:
OR_HCS = data.OrientationPreference.V1 * data.OrientationSelectivity.V1
phase_HCS = data.PhasePreference.V1 * data.PhaseSelectivity.V1
top_row = OR_HCS + data.OrientationPreference.V1.hist() + data.OrientationSelectivity.V1.hist() 
bottom_row =  phase_HCS + data.PhasePreference.V1.hist() + data.PhaseSelectivity.V1.hist()
(top_row + bottom_row).cols(3)

Pinwheel and hypercolumn analysis

The next plot shows analysis of a single (low resolution) GCAL simulation following the methods described in Stevens et al. (2013):

@article{Stevens2013,
   author = {Stevens, Jean-Luc R. and Law, Judith S. and
   Antol\'{i}k, J\'{a}n and Bednar, James A.},
   title = {Mechanisms for Stable, Robust, and Adaptive
   Development of Orientation Maps in the Primary Visual Cortex},
   journal = {The Journal of Neuroscience},
   volume = {33}, 
   number = {40}, 
   pages = {15747-15766}, 
   year = {2013}, 
   doi = {10.1523/JNEUROSCI.1037-13.2013}, 
   url = {http://www.jneurosci.org/content/33/40/15747.full}
}

The plot shows pinwheel and hypercolumn analysis for the GCAL model over development:

  • Top left - Orientation map annotated with pinwheel locations and real (white) and imaginary contours (black) in the polar representation. Adjoined plot shows orientation preference distribution.
  • Top right - Fourier power spectrum of the orientation preference map.
  • Bottom left - Collapsed 1D FFT power spectrum histogram and corresponding fit as described in the supplementary materials of Kaschube et al. 2010.
  • Bottom right - Hypercolumn and pinwheel density analysis:

    • cycles: The number of cycles for a hypercolumn in the anaysed map.
    • k_delta: The difference between the maximum power bin and the fitted maximum.
    • kmax: The wavenumber bin with the highest power.
    • rho: The pinwheel density.
    • rho metric: The map metric based on the pinwheel density.
    • units_per_hc : The number of units (samples) per hypercolumn.

In [ ]:
((data.Pinwheels.V1.hist(index=0) + data.FFTPowerSpectrum.V1) + data.FFTAnalysis.V1).cols(2)

We can collate the values of the pinwheel density over time to see how the pinwheel density changes over development. This graph is shown on the left of the figure below. There is a clear drop to zero at iteration 10000 which we can see is due to a failure of the fitting procedure at this time (shown on the right):


In [ ]:
data.FFTAnalysis.V1[0,1].sample(['rho']).collate('Time') + data.FFTAnalysis.V1[0,0,10000,:]

In the GCAL paper ten, high-quality simulations were run over a wide range of contrasts (with the borders trimmed to eliminate edge effects) so that a decent estimate of the pinwheel density could be obtained for the GCAL model as a whole.