Utility methods

This example shows some additional methods useful for examining the model and results.

from pathlib import Path
import matplotlib.pyplot as plt
import numpy as np
import macaqueretina as mr

mr.load_parameters()
print("\nRetina parameters:")
print(mr.config.retina_parameters)

print("\nVisual stimulus parameters:")
print(mr.config.visual_stimulus_parameters)

print("\nRun parameters:")
print(mr.config.simulation_parameters)

Count lines in codebase, relative to working directory

mr.project_utilities.countlines(Path("macaqueretina"))

Luminance and Photoisomerization calculator

I_cone = 4000  # photoisomerizations per second per cone
A_pupil = 9.0

luminance = mr.retina_math.get_luminance_from_photoisomerizations(
    I_cone, A_pupil=A_pupil
)
print(f"{luminance:.2f} cd/m2")
print(f"{luminance * A_pupil:.2f} trolands")

luminance = 128  # Luminance in cd/m2
A_pupil = 9.0

I_cone = mr.retina_math.get_photoisomerizations_from_luminance(
    luminance, A_pupil=A_pupil
)
print(f"{I_cone:.2f} photoisomerizations per second per cone")
print(f"{luminance * A_pupil:.2f} trolands")

Sample and view figure data from literature

# Example validation file, at
filename = "Derrington_1984b_Fig10B_magno_spatial.jpg"
filename_full = mr.config.git_repo_root_path.joinpath(
    r"retina/validation_data", filename
)

# Plot lowest and highest tick values in the image, use these as calibration points
min_X, max_X, min_Y, max_Y = (0.1, 10, 1, 100)  # Needs to be set for each figure
ds = mr.data_sampler(filename_full, min_X, max_X, min_Y, max_Y, logX=True, logY=True)

# ds.collect_and_save_points() # Will overwrite existing data file -- change filename or move existing file first
ds.quality_control()  # Show image with calibration and data points
# x_data, y_data = ds.get_data_arrays() # Get data arrays for further processing

plt.show()

For the rest, you need to run these once to create data files

mr.retina_constructor.construct()
mr.stimulus_factory.generate()

Load arbitrary data to workspace

filename = "my_responses.gz"
mr.retina_simulator.simulate(filename=filename)
filename_parents = mr.config.output_folder
filename_offspring = mr.config.retina_parameters.mosaic_file
filename = Path(filename_parents).joinpath(filename_offspring)

data = mr.data_io.load_data(filename)
print(type(data))
print(data.shape)

Show spikes from gz files

mr.retina_simulator.simulate(filename=filename)

filename_parents = mr.config.output_folder

# Build response filename from scratch
gc_type = mr.config.retina_parameters["gc_type"]
response_type = mr.config.retina_parameters["response_type"]
hashstr = mr.config.retina_parameters["retina_parameters_hash"]
filename_offspring =f"{gc_type}_{response_type}_{hashstr}_response_00.gz"
filename = Path(filename_parents).joinpath(filename_offspring)

mr.viz.show_spikes_from_gz_file(
    filename=filename,
    sweepname="spikes_0",  # "spikes_0", "spikes_1", ...
    savefigname=None,  
)
plt.show()

Show impulse response

mr.config.retina_parameters.gc_type = "parasol"  # "parasol", "midget"
mr.config.retina_parameters.response_type = "on"  # "on", "off"
mr.config.retina_parameters.spatial_model_type = "DOG"  # "DOG", "VAE"
mr.config.retina_parameters.temporal_model_type = (
    "fixed"  # "fixed", "dynamic", "subunit"
)
mr.retina_constructor.construct()

mr.config.simulation_parameters["contrasts_for_impulse"] = (1.0,)
mr.retina_simulator.simulate(impulse=True)
mr.viz.show_impulse_response_after_simulate(savefigname=None)

plt.show()

Show unity data

First, let's make a bigger retina.

mr.config.retina_parameters.ecc_limits_deg = [3.5, 6.5]
mr.config.retina_parameters.pol_limits_deg = [-15, 15]  
mr.retina_constructor.construct()

Then, get and show Unity region, i.e. where exactly one unit centre overlaps with the retina region. The uniformity index is the proportion of total unity region divided by total retina region.

mr.retina_simulator.simulate(unity=True)
mr.viz.show_unity(savefigname=None)

plt.show()