Skip to content

Commit

Permalink
Merge pull request AllenInstitute#375 from shixnya/develop
Browse files Browse the repository at this point in the history
Fixing FilterNet behavior for frame_rate != 1000.0
  • Loading branch information
kaeldai authored Aug 29, 2024
2 parents 889c55d + 9775f66 commit b1ebdf1
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 13 deletions.
4 changes: 4 additions & 0 deletions bmtk/simulator/filternet/lgnmodel/cursor.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ def evaluate(self, t_min=None, t_max=None, downsample=1):

t_range = convert_tmin_tmax_framerate_to_trange(t_min, t_max, self.movie.frame_rate)[::int(downsample)]
y_vals = np.array([self(t) for t in t_range])
# normalize by the frame rate
y_vals = y_vals * 1000.0 / self.movie.frame_rate

return t_range, y_vals

Expand Down Expand Up @@ -246,6 +248,8 @@ def evaluate(self, threshold=0):
sig_tmp = np.zeros(len(full_temporal_kernel) + len(convolution_answer_sep_spatial) - 1)
sig_tmp[len(full_temporal_kernel)-1:] = convolution_answer_sep_spatial
convolution_answer_sep = spsig.convolve(sig_tmp, full_temporal_kernel[::-1], mode='valid')
# normalize by the frame rate
convolution_answer_sep = convolution_answer_sep * 1000.0 / self.movie.frame_rate
t = np.arange(len(convolution_answer_sep))/self.movie.frame_rate

return t, convolution_answer_sep
Expand Down
2 changes: 1 addition & 1 deletion bmtk/simulator/filternet/lgnmodel/movie.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ def create_movie(self, t_min=0, t_max=1, gray_screen_dur=0, cpd=0.05, temporal_f
:return: Movie object of grating with desired parameters
"""
assert contrast <= 1, "Contrast must be <= 1"
assert contrast > 0, "Contrast must be > 0"
assert contrast >= 0, "Contrast must be >= 0"

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
Expand Down
23 changes: 15 additions & 8 deletions bmtk/tests/simulator/filternet/lgnmodel/test_units.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,13 @@
from bmtk.simulator.filternet.lgnmodel.lgnmodel1 import LGNModel
from bmtk.simulator.filternet.lgnmodel import movie

# FilterNet now correctly normalize the rate other than 1000 Hz.
# The tests below were made before the change, so we correctionso on the
# firing rates.
norm_factor = 1000.0 / 24.0

def test_onunit():
ffm = movie.FullFieldFlashMovie(range(120), range(240), 0.3, 0.7)
ffm = movie.FullFieldFlashMovie(range(120), range(240), 0.3, 0.7, frame_rate=24.0)
mv = ffm.full(t_max=2.0)

spatial_filter = GaussianSpatialFilter(translate=(120.0, 60.0), sigma=(0.615, 0.615), origin=(0.0, 0.0))
Expand All @@ -29,11 +33,11 @@ def test_onunit():
rates = np.array(results[0][1], dtype=np.float64)

assert(np.allclose(times, [0.0, 0.41666, 0.83333, 1.250, 1.6666], atol=1.0e-4))
assert(np.allclose(rates, [1.05, 0.8635, 1.05, 1.05, 1.05], atol=1.0e-3))
assert(np.allclose(rates / norm_factor, [1.05, 0.8635, 1.05, 1.05, 1.05], atol=1.0e-3))


def test_offunit():
ffm = movie.FullFieldFlashMovie(range(120), range(240), 0.3, 0.7)
ffm = movie.FullFieldFlashMovie(range(120), range(240), 0.3, 0.7, frame_rate=24.0)
mv = ffm.full(t_max=2.0)

spatial_filter = GaussianSpatialFilter(translate=(120.0, 60.0), sigma=(0.615, 0.615), origin=(0.0, 0.0))
Expand All @@ -50,11 +54,11 @@ def test_offunit():
rates = np.array(results[0][1], dtype=np.float64)

assert(np.allclose(times, [0.0, 0.41666, 0.83333, 1.250, 1.6666], atol=1.0e-4))
assert(np.allclose(rates, [1.05, 1.2364, 1.05, 1.05, 1.05], atol=1.0e-3))
assert(np.allclose(rates / norm_factor, [1.05, 1.2364, 1.05, 1.05, 1.05], atol=1.0e-3))


def test_lgnonoffcell():
ffm = movie.FullFieldFlashMovie(range(120), range(240), 0.3, 0.7)
ffm = movie.FullFieldFlashMovie(range(120), range(240), 0.3, 0.7, frame_rate=24.0)
mv = ffm.full(t_max=2.0)

temporal_filter = TemporalFilterCosineBump(weights=[3.441, -2.115], kpeaks=[8.269, 19.991], delays=[0.0, 0.0])
Expand All @@ -74,11 +78,11 @@ def test_lgnonoffcell():
rates = np.array(results[0][1], dtype=np.float64)

assert(np.allclose(times, [0.0, 0.41666, 0.83333, 1.250, 1.6666], atol=1.0e-4))
assert(np.allclose(rates, [0.0, 3.7286, 0.0, 0.0, 0.0], atol=1.0e-3))
assert(np.allclose(rates / norm_factor, [0.0, 3.7286, 0.0, 0.0, 0.0], atol=1.0e-3))


def test_twosubfieldlinearcell():
ffm = movie.FullFieldFlashMovie(range(120), range(240), 0.3, 0.7)
ffm = movie.FullFieldFlashMovie(range(120), range(240), 0.3, 0.7, frame_rate=24.0)
mv = ffm.full(t_max=2.0)

spatial_filter = GaussianSpatialFilter(translate=(120.0, 60.0), sigma=(0.615, 0.615), origin=(0.0, 0.0))
Expand Down Expand Up @@ -107,7 +111,10 @@ def test_twosubfieldlinearcell():
rates = np.array(results[0][1], dtype=np.float64)

assert(np.allclose(times, [0.0, 0.41666, 0.83333, 1.250, 1.6666], atol=1.0e-4))
assert(np.allclose(rates, [4.0, 3.26931, 3.885, 4.0, 4.0], atol=1.0e-3))
# for this example, the offset (2.0) of the transfer function breaks the
# compatibility. It makes sense to update the values.
# assert(np.allclose(rates, [4.0, 3.26931, 3.885, 4.0, 4.0], atol=1.0e-3))
assert(np.allclose(rates, [4.0, 18.929, 11.894, 4.0, 4.0], atol=1.0e-3))


if __name__ == '__main__':
Expand Down
17 changes: 13 additions & 4 deletions bmtk/tests/simulator/filternet/test_default_setters.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ def __contains__(self, item):

np.set_printoptions(precision=4)

# FilterNet now correctly normalize the rate other than 1000 Hz.
# The tests below were made before the change, so we correctionso on the
# firing rates.
norm_factor = 1000.0 / 24.0

@pytest.mark.parametrize("cell_type,expected_val", [
('tON_TF8', [2.6, 2.5502, 2.7221, 2.7718, 2.6497]),
Expand All @@ -77,7 +81,7 @@ def test_onunit(cell_type, expected_val):
rates = np.array(results[0][1], dtype=np.float64)

assert(np.allclose(times, [0.0, 0.2083, 0.4167, 0.6250, 0.8333], atol=1.0e-3))
assert(np.allclose(rates, expected_val, atol=1.0e-3))
assert(np.allclose(rates / norm_factor, expected_val, atol=1.0e-3))


@pytest.mark.parametrize("cell_type,expected_val", [
Expand Down Expand Up @@ -105,12 +109,15 @@ def test_offunit(cell_type, expected_val):
rates = np.array(results[0][1], dtype=np.float64)

assert(np.allclose(times, [0.0, 0.2083, 0.4167, 0.6250, 0.8333], atol=1.0e-3))
assert(np.allclose(rates, expected_val, atol=1.0e-3))
assert(np.allclose(rates / norm_factor, expected_val, atol=1.0e-3))


@pytest.mark.parametrize("cell_type,expected_val", [
# ('sONsOFF_001', [4.0, 3.5654, 2.2956, 2.7437, 4.4480])
('sONsOFF_001', [4.0, 3.0136, 3.335, 4.3349, 4.9999]) # updated value after OS bug fix. (issue, #339)
# ('sONsOFF_001', [4.0, 3.0136, 3.335, 4.3349, 4.9999]) # updated value after OS bug fix. (issue, #339)
# Again, due to the offset in the transfer function, the expected values
# won't nicely convert, so updating the values.
('sONsOFF_001', [4.0, 20.1642, 0, 45.4373, 61.2649]) # updated value after OS bug fix. (issue, #339)
])
def test_sONsOFF(cell_type, expected_val):
gm = movie.GratingMovie(row_size=120, col_size=240, frame_rate=24.0)
Expand All @@ -130,7 +137,9 @@ def test_sONsOFF(cell_type, expected_val):

@pytest.mark.parametrize("cell_type,expected_val", [
# ('sONsOFF_001', [4.0, 3.5654, 2.2957, 2.7437, 4.4481])
('sONsOFF_001', [4.0, 3.0136, 3.335, 4.3349, 4.9999]) # updated value after OS bug fix. (issue, #339)
# ('sONsOFF_001', [4.0, 3.0136, 3.335, 4.3349, 4.9999]) # updated value after OS bug fix. (issue, #339)
('sONsOFF_001', [4.0, 20.1642, 0, 45.4373, 61.2649]) # updated value after OS bug fix. (issue, #339)
])
def test_sONtOFF(cell_type, expected_val):
gm = movie.GratingMovie(row_size=120, col_size=240, frame_rate=24.0)
Expand Down

0 comments on commit b1ebdf1

Please sign in to comment.