"""Module for calculating annotated region metrics from ISI data"""
import numpy as np
import logging
# These scaling factors are derived from experimental geometry using
# screen width 52.0 cm, screen height 32.0 cm (16:10 24 inch monitor)
# mouse 10.0 cm from center of monitor
ALTITUDE_SCALE = 0.322
AZIMUTH_SCALE = 0.383
[docs]def eccentricity(az, alt, az_center, alt_center):
"""Compute eccentricity
Parameters
----------
az : numpy.ndarray
Azimuth retinotopic map
alt : numpy.ndarray
Altitude retinotopic map
az_center : float
Azimuth value to use as center of eccentricity map
alt_center : float
Altitude value to use as center of eccentricity map
Returns
-------
numpy.ndarray
Eccentricity map
"""
daz = az - az_center
dalt = alt - alt_center
ecc = np.arctan(np.sqrt(np.square(np.tan(dalt)) +
np.square(np.tan(daz))/np.square(np.cos(dalt))))
return ecc
[docs]def retinotopy_metric(mask, isi_map):
"""Compute retinotopic metrics for a responding area
Parameters
----------
mask : numpy.ndarray
Mask representing the area over which to calculate metrics
isi_map : numpy.ndarray
Retinotopic map
Returns
-------
(float, float, float, float) tuple
min, max, range, bias of retinotopic map over masked region
"""
ind = np.where( mask > 0 )
vals = isi_map[ind]
maxv = np.degrees(np.max(vals))
minv = np.degrees(np.min(vals))
ret_range = float(maxv - minv)
ret_bias = float(abs(minv + maxv))
return float(minv), float(maxv), ret_range, ret_bias
[docs]def create_region_mask(image_shape, x, y, width, height, mask):
"""Create mask for region on retinotopic map
Parameters
----------
image_shape : tuple
(height, width) of retinotopic map
x : int
x offset of region mask within retinotopic map
y : int
y offset of region mask within retinotopic map
width : int
width of region mask
height : int
height of region mask
mask : list
region mask as a list of lists
Returns
-------
numpy.ndarray
Region mask
"""
bb = np.zeros((height,width), dtype=np.uint8)
bb[np.asarray(mask)] = 1
region_mask = np.zeros(image_shape, dtype=np.uint8)
region_mask[y:y + height,x:x + width] = bb
return region_mask
[docs]def get_metrics(altitude_phase, azimuth_phase, x=None, y=None, width=None,
height=None, mask=None, altitude_scale=ALTITUDE_SCALE,
azimuth_scale=AZIMUTH_SCALE):
"""Calculate annotated region metrics"""
altitude = altitude_phase * altitude_scale
azimuth = azimuth_phase * azimuth_scale
eccentricity_ret_zero = np.degrees(
eccentricity(azimuth, altitude, 0.0, 0.0))
result = {}
region_mask = create_region_mask(altitude.shape, x, y, width, height,
mask)
# compute centroid
centroid = [np.mean(x_value) for x_value in np.where(region_mask)]
result['y_centroid'] = centroid[0]
result['x_centroid'] = centroid[1]
# compute azimuth/altitude max,min,range and bias
az_min, az_max, az_range, az_bias = retinotopy_metric(region_mask,
azimuth)
alt_min, alt_max, alt_range, alt_bias = retinotopy_metric(region_mask,
altitude)
result['azimuth_min'] = az_min
result['azimuth_max'] = az_max
result['azimuth_range'] = az_range
result['azimuth_bias'] = az_bias
result['altitude_min'] = alt_min
result['altitude_max'] = alt_max
result['altitude_range'] = alt_range
result['altitude_bias'] = alt_bias
# eccentricity at centroid
cy = int(round(result['y_centroid']))
cx = int(round(result['x_centroid']))
result['eccentricity_at_centroid'] = float(eccentricity_ret_zero[cy,cx])
return result