gcal allΒΆ

GCAL model with multiple maps

This tutorial shows how to use the GCAL model to explore the development of preferences for a wide variety of feature maps, including retinotopy, orientation, ocular dominance, disparity, motion direction, spatial frequency, and color. Each of these are called "dimensions", which are controlled by the dims parameter. For instance, dims=['xy','or'] works the same as the regular GCAL Orientation Map Tutorial, because it specifies that the only dimensions that will be varied on the input are xy (spatial position, leading to a retinotopic map) and or (orientation, leading to an orientation map). The other dimensions can be supplied similarly below. Throughout this tutorial, there will be sections that apply only to particular dimensions; these will be skipped automatically if that dimension has not been selected.

For some dimensions, there are very many different ways they could be modelled, both for the input patterns and for the neural model. For instance, the motion direction dimension (e.g. dims=['xy','or','dr']) uses oriented Gaussian patterns swept perpendicularly to their orientation axis, but many other types of motion exist and could be added as options. Similarly, at the neural level, there are many ways to allow neurons to have a preference for motion direction, but here by default it is done by adding multiple lagged projections to V1, such that V1 receives input from various different times in the past.

See Fischer (2014) for a discussion of the various dimensions supported.

Imports

In [1]:
%reload_ext topo.misc.ipython
%timer start
Executing user startup file /var/lib/buildbot/docs/.topographicarc
Timer start: 2015/05/13 18:03:35

In [2]:
import topo
from topo.command import load_snapshot, save_snapshot, save_script_repr

from topo.analysis import Collector
from featuremapper.analysis.raster import fft_power, vectorfield
from featuremapper.analysis.pinwheels import PinwheelAnalysis
from featuremapper.analysis.hypercolumns import PowerSpectrumAnalysis

import holoviews
from holoviews import Layout, HoloMap, Points, Image, RGB

from topo.submodel.color import ModelGCALColor

import time, os 

Define the model

In [3]:
# Uncomment to see all of the options available for use below
#%params ModelGCALColor
In [4]:
simulations = { 
    # Parameters to match published simulations
    "fischer:ms14 fig6.1":      dict(dims=['xy','or'],cortex_density=141),
    "fischer:ms14 fig6.2-3":    dict(dims=['xy','or','od'],cortex_density=141),
    "fischer:ms14 fig6.5-6":    dict(dims=['xy','or','dy'],cortex_density=141),
    "fischer:ms14 fig6.7-8":    dict(dims=['xy','or','od','dy'],cortex_density=141),
    "fischer:ms14 fig6.9-11":   dict(dims=['xy','or','dr'],num_inputs=1,
                                     speed=3.0/24.0,aff_lr=0.1/4.0,
                                     aff_strength=1.5,cortex_density=141),

    "fischer:ms14 fig6.12-13":  dict(dims=['xy','or','cr'],dataset='FoliageA',
                                     strength_factor=0.75,color_strength=0.3,
                                     cone_scale=[0.80,0.75,0.80]),

    "fischer:ms14 fig6.14":     dict(dims=['xy','or','od','cr'],dataset='FoliageA',
                                     strength_factor=0.75,color_strength=0.3,
                                     cone_scale=[0.80,0.75,0.80]), # Estimated

    "fischer:ms14 fig6.15-16b": dict(dims=['xy','or','sf'],dataset='FoliageA'), # Estimated
    "fischer:ms14 fig6.16c":    dict(dims=['xy','or','sf'],dataset='FoliageA',
                                     sf_spacing=2.5,sf_channels=3,gain_control_SF=True),

    # Other potentially useful simulations
    "retinotopic map":          dict(dims=['xy']),
    "all maps":                 dict(dims=['xy','or','od','dy','cr','sf','dr'],dataset='FoliageA'),
    "all maps but sf":          dict(dims=['xy','or','od','dy','cr','dr']),
}

# Special parameters overriding those above, if desired, e.g. to reduce time and memory requirements
overrides = dict(cortex_density=48)# cortex_density was 63 for most fisher:ms14 simulations

# Choose desired simulation here
params = dict(simulations["fischer:ms14 fig6.7-8"],**overrides)
In [5]:
topo.sim.model = ModelGCALColor(**params)
In [6]:
gcal=topo.sim.model.setup() 
In [7]:
times=[10000] # Determines total duration of simulation, plus frequency of generating plots, e.g. [100,1000,10000]

Define plotting and analysis

In [8]:
save_plots=False # Set this to true if you want .png files saved externally
In [9]:
dim_or='or' in topo.sim.model.dims
dim_od='od' in topo.sim.model.dims
dim_dy='dy' in topo.sim.model.dims
dim_dr='dr' in topo.sim.model.dims
dim_sf='sf' in topo.sim.model.dims
dim_cr='cr' in topo.sim.model.dims

twoeyes = dim_od or dim_dy
In [10]:
c = Collector()

# Projection activities
for proj in gcal.projections:
     if proj.dest.level=='V1' and proj.src.level=='LGN':
         c.set_path('Activity'+'.'+proj.parameters['name'],
                    c.collect(gcal.projections[('V1', proj.parameters['name'])]))
In [11]:
# Preference map measurements
from topo.analysis.command import measure_or_pref, \
    measure_od_pref, measure_phasedisparity, measure_dr_pref, \
    measure_sine_pref, measure_hue_pref

if(dim_or and not dim_sf and not dim_dr): c.collect(measure_or_pref)
if(twoeyes): c.collect(measure_od_pref)
if(dim_dy):  c.collect(measure_phasedisparity)
if(dim_dr):  c.collect(measure_dr_pref)
if(dim_sf):  c.collect(measure_sine_pref)
if(dim_cr):  c.collect(measure_hue_pref)
In [12]:
# Sheet activities
for sheet_item in gcal.sheets:
    if sheet_item.level=='Retina' or sheet_item.level=='V1':
        c.set_path('Activity'+'.'+str(sheet_item), c.collect(gcal.sheets[str(sheet_item)]))

for proj in gcal.projections:
     if proj.dest.level=='V1' and proj.src.level=='LGN':
         c.set_path('CFs'+'.'+proj.parameters['name'],
                    c.collect(gcal.projections[('V1', proj.parameters['name'])],grid=True))
            
# Analysis
c.FFTPowerSpectrum.V1 = c.analyze(c.ref.OrientationPreference.V1, fft_power)
c.Pinwheels.V1 =            c.analyze(c.ref.OrientationPreference.V1
                                      * c.ref.OrientationSelectivity.V1, PinwheelAnalysis)
c.FFTAnalysis.V1 =          c.analyze(c.ref.OrientationPreference.V1, PowerSpectrumAnalysis)

Example input patterns

In [13]:
color_example = dim_cr and topo.sim.model.dataset!='Gaussian'

# Monochrome training patterns:
gcal.training_patterns.LeftRetina.anim(50) + \
gcal.training_patterns.RightRetina.anim(50) if twoeyes else \
gcal.training_patterns.Retina.anim(50) if not color_example else None
Out[13]:
Time:

In [14]:
# Color training patterns:
if color_example:
    eyes = [gcal.sheets.LeftRetina,gcal.sheets.RightRetina] if twoeyes else [gcal.sheets.Retina]
    animated_RGB = []
    for (e,eye) in enumerate(eyes):
        rgb_inputs = {i: gen[:] for i, gen in enumerate(eye.parameters['input_generator'].generators)}
        animated_RGB.append(HoloMap(rgb_inputs, key_dimensions=['Time']))
    Layout(animated_RGB)

Training the network (slow!)

In [15]:
print("Collection will start at iteration %d and end on iteration %d" % (min(times), max(times)))
Collection will start at iteration 10000 and end on iteration 10000

In [16]:
data = c(times=times)
WARNING:root:Time: 010000.00 PowerSpectrumAnalysis: Slicing data to nearest odd dimensions for centered FFT.

100% measurement progress 00:00:24

Results

Activity patterns

In [17]:
data.Activity.V1
Out[17]:
In [18]:
data.Activity.display('all')
Out[18]:

On-Off connection fields

In [19]:
%output size=150
In [20]:
eyes = ['Left','Right'] if twoeyes else ['']
sfs = ['','SF2'] if dim_sf else ['']

on_minus_off = []
for (e,eye) in enumerate(eyes):
    for l in gcal['lags']:
        for (s,sf) in enumerate(sfs):
            luminosityname = "RedGreenBlueRedGreenBlue" if dim_cr and s==0 else ""
            plot=(data.CFs[eye+luminosityname+"LGNOnAfferent" +sf+("" if l==0 else "Lag"+str(l))] * 
                  data.CFs[eye+luminosityname+"LGNOffAfferent"+sf+("" if l==0 else "Lag"+str(l))])
            plot.title = (("" if l==0 else "Lag"+str(l)) +" "+sf + eye + ' ' + luminosityname + ' ON-OFF CFs').strip()
            on_minus_off += [plot]

defaultproj=0
num_lags=len(gcal['lags'])

on_minus_off[0] if len(on_minus_off)==1 else sum(on_minus_off[1:],on_minus_off[0]).cols(num_lags if num_lags>1 else 4)
Out[20]:

Orientation map

In [21]:
%output size=150
In [22]:
%%opts Points (color='w' marker='*' s=100 edgecolors='k')
annotated_map = (data.OrientationPreference.V1 
                 * data.OrientationSelectivity.V1
                 * Points(on_minus_off[defaultproj][0,-0.3:0.3].keys())) if dim_or else None
annotated_map << on_minus_off[defaultproj][0,-0.3:0.3] << data.OrientationPreference.V1.hist(adjoin=False) if dim_or else None
Out[22]:

Ocularity map

In [23]:
%opts Image.Ocular_Preference (cmap="gray")
(data.OcularPreference.V1 << data.OcularPreference.V1.hist(adjoin=False)) + \
    (data.OcularSelectivity.V1 << data.OcularSelectivity.V1.hist(adjoin=False)) if twoeyes else None
Out[23]:
In [24]:
%%opts Contours (linewidth=5 color='k') Points (linewidth=2)
pins = data.Pinwheels.V1.select(Duration=max(gcal['lags'])+1,Time=times[-1]).get(3) if dim_or else None
od_contours = holoviews.operation.contours(data.OcularPreference.V1). \
    select(Duration=max(gcal['lags'])+1,Time=times[-1]).get(1) if twoeyes else None
data.OrientationPreference.V1.select(Duration=max(gcal['lags'])+1,Time=times[-1]) * pins * od_contours if twoeyes and dim_or else None
Out[24]:

Disparity map

In [25]:
data.PhasedisparityPreference.V1 * data.PhasedisparitySelectivity.V1 << data.PhasedisparityPreference.V1.hist(adjoin=False) \
    if dim_dy else None
Out[25]:

Direction map

Preference only

In [26]:
data.DirectionPreference.V1 << data.DirectionPreference.V1.hist(adjoin=False) if dim_dr else None

Preference + Selectivity

In [27]:
data.DirectionPreference.V1 * data.DirectionSelectivity.V1 << data.DirectionPreference.V1.hist(adjoin=False) \
    if dim_dr else None
In [28]:
%output size=300
In [29]:
%%opts VectorField [color_dim='angle'] (cmap='hsv' linewidth=1 edgecolors='k')
dir_vf = vectorfield(data.DirectionPreference.V1 * data.DirectionSelectivity.V1, rows=10, cols=10) if dim_dr else None

data.OrientationPreference.V1 * data.OrientationSelectivity.V1 * dir_vf << \
    data.OrientationPreference.V1.hist(adjoin=False) if dim_dr else None

Spatial frequency map

In [30]:
%output size=150
In [31]:
data.FrequencyPreference.V1 * data.FrequencySelectivity.V1 << data.FrequencyPreference.V1.hist(adjoin=False) \
    if dim_sf else None
In [32]:
%%opts Image.FrequencyPreference (cmap='gray')
data.FrequencyPreference.V1 << data.FrequencyPreference.V1.hist(adjoin=False) \
    if dim_sf else None

Color map

In [33]:
data.HuePreference.V1 * data.HueSelectivity.V1 << data.HuePreference.V1.hist(adjoin=False) \
    if dim_cr else None

Phase preference

In [34]:
%output size=100
In [35]:
if dim_or:
    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) if dim_or else None
Out[35]:

Orientation pinwheels + FFT analysis

In [36]:
%output size=120
In [37]:
if dim_or: 
    for t in times:
        data.FFTPowerSpectrum.V1.select(Duration=max(gcal['lags'])+1,Time=t) \
                .bounds=holoviews.core.boundingregion.BoundingBox(radius=20.0)
            
(data.FFTAnalysis.V1).display('all').cols(2) if dim_or else None
Out[37]:
In [38]:
%timer
Timer elapsed: 00:15:31

End of notebook


Download this notebook from GitHub (right-click to download).