Skip to content

Commit

Permalink
Making physical spacing optional for drifting gratings + faster separ…
Browse files Browse the repository at this point in the history
…able FilterNet (#346)


* Making physical_spacing of moving gratings optional + faster separable FilterNet by ignoring zeros in the kernel.

* Changing the variable name + adding documentation
'physical_spacing' to 'degrees_per_pixel'.
  • Loading branch information
shixnya authored Feb 21, 2024
1 parent 39ebecf commit 4a9c230
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 10 deletions.
2 changes: 1 addition & 1 deletion bmtk/simulator/filternet/filtersimulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def add_movie(self, movie_type, params):

elif movie_type == 'graiting':
init_params = FilterSimulator.find_params(['row_size', 'col_size', 'frame_rate'], **params)
create_params = FilterSimulator.find_params(['gray_screen_dur', 'cpd', 'temporal_f', 'theta', 'contrast'],
create_params = FilterSimulator.find_params(['gray_screen_dur', 'cpd', 'temporal_f', 'theta', 'contrast', 'degrees_per_pixel'],
**params)

create_params['gray_screen_dur'] /= 1000.0
Expand Down
5 changes: 4 additions & 1 deletion bmtk/simulator/filternet/lgnmodel/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,10 @@ def evaluate(self, threshold=0):
# Convolve every frame in the movie with the spatial filter. First find the range of rows (range min and max)
# and columns in the filter that are above threshold, that way only portion of movie/filter are multiplied
# together
nonzero_inds = np.where(np.abs(full_spatial_kernel[0, :, :]) >= threshold)

# Using > instead of >= makes the code faster if there are many zeros in the
# spatial kernel. This will not affect the results.
nonzero_inds = np.where(np.abs(full_spatial_kernel[0, :, :]) > threshold)
rm, rM = nonzero_inds[0].min(), nonzero_inds[0].max()
cm, cM = nonzero_inds[1].min(), nonzero_inds[1].max()
convolution_answer_sep_spatial = (self.movie.data[:, rm:rM+1, cm:cM+1] *
Expand Down
15 changes: 8 additions & 7 deletions bmtk/simulator/filternet/lgnmodel/movie.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def __init__(self, row_size, col_size, frame_rate=1000.0):
self.frame_rate = float(frame_rate) # in Hz

def create_movie(self, t_min=0, t_max=1, gray_screen_dur=0, cpd=0.05, temporal_f=4, theta=45,
phase=0., contrast=1.0, row_size_new=None, col_size_new=None):
phase=0., contrast=1.0, degrees_per_pixel=None, row_size_new=None, col_size_new=None):
"""Create the grating movie with the desired parameters
:param t_min: start time in seconds
Expand All @@ -271,9 +271,10 @@ def create_movie(self, t_min=0, t_max=1, gray_screen_dur=0, cpd=0.05, temporal_f
assert contrast <= 1, "Contrast must be <= 1"
assert contrast > 0, "Contrast must be > 0"

physical_spacing = 1.0 / (float(cpd) * 10) # To make sure no aliasing occurs
self.row_range = np.linspace(0, self.row_size, int(self.row_size/physical_spacing), endpoint=True)
self.col_range = np.linspace(0, self.col_size, int(self.col_size/physical_spacing), endpoint=True)
if degrees_per_pixel is None: # default behavior when not specified
degrees_per_pixel = 1.0 / (float(cpd) * 10) # To make sure no aliasing occurs
self.row_range = np.linspace(0, self.row_size, int(self.row_size/degrees_per_pixel), endpoint=True)
self.col_range = np.linspace(0, self.col_size, int(self.col_size/degrees_per_pixel), endpoint=True)
numberFramesNeeded = int(round(self.frame_rate * (t_max - gray_screen_dur))) + 1
time_range = np.linspace(0, t_max - gray_screen_dur, numberFramesNeeded, endpoint=True)

Expand Down Expand Up @@ -316,9 +317,9 @@ def create_movie(self, t_looming=1, gray_screen_dur=0.5):
:param t_looming: duration of time looming
:param gray_screen_dur:
"""
physical_spacing = 1.0 # To make sure no aliasing occurs
self.row_range = np.linspace(0, self.row_size, int(self.row_size/physical_spacing), endpoint=True)
self.col_range = np.linspace(0, self.col_size, int(self.col_size/physical_spacing), endpoint=True)
degrees_per_pixel = 1.0 # To make sure no aliasing occurs
self.row_range = np.linspace(0, self.row_size, int(self.row_size/degrees_per_pixel), endpoint=True)
self.col_range = np.linspace(0, self.col_size, int(self.col_size/degrees_per_pixel), endpoint=True)
loomingFramesNeeded = int(round(self.frame_rate * t_looming))
grayScreenFrames = int(round(self.frame_rate * gray_screen_dur))
time_range = np.linspace(0, t_looming, loomingFramesNeeded, endpoint=True)
Expand Down
4 changes: 3 additions & 1 deletion docs/autodocs/source/filternet.rst
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ Plays a drifting grating across the screen
"temporal_f": 4.0,
"contrast": 0.8,
"theta": 45.0,
"phase": 0.0
"phase": 0.0,
"degrees_per_pixel": 1.0
}
}
Expand All @@ -79,6 +80,7 @@ Plays a drifting grating across the screen
* theta: orientation angle, in degrees (default: 45.0)
* phase: temporal phase, in degrees (default: 0.0)
* contrast: the maximum constrast, must be between 0 and 1.0 (default: 1.0)
* degrees_per_pixel: sampling pitch of the movie in degrees per pixel (default: 1 / (cpd * 10))


Full Field Flash
Expand Down

0 comments on commit 4a9c230

Please sign in to comment.