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
In [ ]:
import topo
from topo.analysis import Collector
from topo.submodel.gcal import ModelGCAL, ArraySpec
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)
Here are both the projection activities (top row) and sheet activies (bottom row)
In [ ]:
data.Activity.grid().cols(2)
Here are the weights on the ON surround and OFF surround RGC+LGN projections:
In [ ]:
data.CFs.LGNOnAfferent + data.CFs.LGNOffAfferent
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
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)
This is a visualization of the homeostatic threshold array (output function on the V1 sheet) over development:
In [ ]:
data.HomeostaticThreshold.V1.hist()
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)
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:
Bottom right - Hypercolumn and pinwheel density analysis:
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.