def test_AxonMapSpatial_plot(): model = AxonMapSpatial() for use_dva, xlim in zip([True, False], [(-18, 18), (-5000, 5000)]): ax = model.plot(use_dva=use_dva) npt.assert_equal(isinstance(ax, Subplot), True) npt.assert_equal(ax.get_xlim(), xlim) # Simulated area might be larger than that: model = AxonMapSpatial(xrange=(-20.5, 20.5), yrange=(-16.1, 16.1)) ax = model.plot(use_dva=True) npt.assert_almost_equal(ax.get_xlim(), (-21, 21)) npt.assert_almost_equal(ax.get_ylim(), (-18, 18)) ax = model.plot(use_dva=False) npt.assert_almost_equal(ax.get_xlim(), (-6000, 6000)) npt.assert_almost_equal(ax.get_ylim(), (-5000, 5000)) # Figure size can be changed: ax = model.plot(figsize=(8, 7)) npt.assert_almost_equal(ax.figure.get_size_inches(), (8, 7)) # Quadrants can be annotated: for ann_q, n_q in [(True, 6), (False, 0)]: fig, ax = plt.subplots() model.plot(annotate=ann_q, ax=ax) npt.assert_equal(len(ax.child_axes), int(n_q > 0)) if len(ax.child_axes) > 0: npt.assert_equal(len(ax.child_axes[0].texts), n_q) plt.close(fig)
def test_AxonMapModel_predict_percept(engine): model = AxonMapModel(xystep=0.55, axlambda=100, rho=100, thresh_percept=0, engine=engine, xrange=(-20, 20), yrange=(-15, 15), n_axons=500) model.build() # Single-electrode stim: img_stim = np.zeros(60) img_stim[47] = 1 percept = model.predict_percept(ArgusII(stim=img_stim)) # Single bright pixel, rest of arc is less bright: npt.assert_equal(np.sum(percept.data > 0.8), 1) npt.assert_equal(np.sum(percept.data > 0.6), 2) npt.assert_equal(np.sum(percept.data > 0.1), 7) npt.assert_equal(np.sum(percept.data > 0.0001), 32) # Overall only a few bright pixels: npt.assert_almost_equal(np.sum(percept.data), 3.31321, decimal=3) # Brightest pixel is in lower right: npt.assert_almost_equal(percept.data[33, 46, 0], np.max(percept.data)) # Top half is empty: npt.assert_almost_equal(np.sum(percept.data[:27, :, 0]), 0) # Same for lower band: npt.assert_almost_equal(np.sum(percept.data[39:, :, 0]), 0) # Full Argus II with small lambda: 60 bright spots model = AxonMapModel(engine='serial', xystep=1, rho=100, axlambda=40, xrange=(-20, 20), yrange=(-15, 15), n_axons=500) model.build() percept = model.predict_percept(ArgusII(stim=np.ones(60))) # Most spots are pretty bright, but there are 2 dimmer ones (due to their # location on the retina): npt.assert_equal(np.sum(percept.data > 0.5), 28) npt.assert_equal(np.sum(percept.data > 0.275), 56) # Model gives same outcome as Spatial: spatial = AxonMapSpatial(engine='serial', xystep=1, rho=100, axlambda=40) spatial.build() spatial_percept = model.predict_percept(ArgusII(stim=np.ones(60))) npt.assert_almost_equal(percept.data, spatial_percept.data) npt.assert_equal(percept.time, None)
def test_AxonMapSpatial_plot(): model = AxonMapSpatial() for use_dva, xlim in zip([True, False], [(-18, 18), (-5000, 5000)]): ax = model.plot(use_dva=use_dva) npt.assert_equal(isinstance(ax, Subplot), True) npt.assert_equal(ax.get_xlim(), xlim) # Quadrants can be annotated: for ann_q, n_q in [(True, 6), (False, 0)]: fig, ax = plt.subplots() model.plot(annotate=ann_q, ax=ax) npt.assert_equal(len(ax.child_axes), int(n_q > 0)) if len(ax.child_axes) > 0: npt.assert_equal(len(ax.child_axes[0].texts), n_q) plt.close(fig)
def test_AxonMapSpatial_plot(): model = AxonMapSpatial() ax = model.plot() npt.assert_equal(isinstance(ax, Subplot), True) # Electrodes and quadrants can be annotated: for ann_q, n_q in [(True, 4), (False, 0)]: ax = model.plot(annotate=ann_q) npt.assert_equal(len(ax.texts), n_q) close(ax.figure) # Setting upside_down flips y axis: ax = model.plot(upside_down=True, autoscale=True) npt.assert_equal(ax.get_xlim(), (-5000, 5000)) npt.assert_equal(ax.get_ylim(), (4000, -4000))
def test_plot_implant_on_axon_map(): ax = plot_implant_on_axon_map(ArgusII()) npt.assert_equal(isinstance(ax, Subplot), True) # Check axis limits: for xlim, ylim in zip([None, (-2000, 1500)], [(-3000, 1300), None]): ax = plot_implant_on_axon_map(ArgusII(), xlim=xlim, ylim=ylim) if xlim is None: xlim = (-4000, 4500) if ylim is None: ylim = (-2500, 3000) npt.assert_almost_equal(ax.get_xlim(), xlim) npt.assert_almost_equal(ax.get_ylim(), ylim) # Check optic disc center in both eyes: model = AxonMapSpatial() for eye in ['RE', 'LE']: for loc_od in [(15.5, 1.5), (17.9, -0.01)]: od = (-loc_od[0], loc_od[1]) if eye == 'LE' else loc_od ax = plot_implant_on_axon_map(ArgusII(eye=eye), loc_od=od) npt.assert_equal(len(ax.patches), 1) npt.assert_almost_equal(ax.patches[0].center, model.dva2ret(od)) close(ax.figure) # Electrodes and quadrants can be annotated: for ann_el, n_el in [(True, 60), (False, 0)]: for ann_q, n_q in [(True, 4), (False, 0)]: ax = plot_implant_on_axon_map(ArgusII(), annotate_implant=ann_el, annotate_quadrants=ann_q) npt.assert_equal(len(ax.texts), n_el + n_q) npt.assert_equal(len(ax.collections[0]._paths), 60) close(ax.figure) # Stimulating electrodes are marked: ax = plot_implant_on_axon_map(ArgusII(stim=np.ones(60))) # Setting upside_down flips y axis: ax = plot_implant_on_axon_map(ArgusII(), upside_down=True) npt.assert_almost_equal(ax.get_xlim(), (-4000, 4500)) npt.assert_almost_equal(ax.get_ylim(), (3000, -2500)) with pytest.raises(TypeError): plot_implant_on_axon_map(DiskElectrode(0, 0, 0, 100)) with pytest.raises(ValueError): plot_implant_on_axon_map(ArgusII(), n_bundles=0)
def test_plot_axon_map(): ax = plot_axon_map() npt.assert_equal(isinstance(ax, Subplot), True) # Check axis limits: for xlim, ylim in zip([None, (-2000, 1500)], [(-3000, 1300), None]): ax = plot_axon_map(xlim=xlim, ylim=ylim) if xlim is None: xlim = (-5000, 5000) if ylim is None: ylim = (-4000, 4000) npt.assert_almost_equal(ax.get_xlim(), xlim) npt.assert_almost_equal(ax.get_ylim(), ylim) # Check optic disc center in both eyes: model = AxonMapSpatial() for eye in ['RE', 'LE']: for loc_od in [(15.5, 1.5), (-17.9, -0.01)]: ax = plot_axon_map(eye=eye, loc_od=loc_od) npt.assert_equal(len(ax.patches), 1) # Wrong sign for x-coord is automatically corrected: if eye == 'RE': od = (np.abs(loc_od[0]), loc_od[1]) else: od = (-np.abs(loc_od[0]), loc_od[1]) npt.assert_almost_equal(ax.patches[0].center, model.dva2ret(od)) close(ax.figure) # Electrodes and quadrants can be annotated: for ann_q, n_q in [(True, 4), (False, 0)]: ax = plot_axon_map(annotate_quadrants=ann_q) npt.assert_equal(len(ax.texts), n_q) # Setting upside_down flips y axis: ax = plot_axon_map(upside_down=True) npt.assert_equal(ax.get_xlim(), (-5000, 5000)) npt.assert_equal(ax.get_ylim(), (4000, -4000)) with pytest.raises(ValueError): plot_axon_map(loc_od=[3]) with pytest.raises(ValueError): plot_axon_map(eye='foo') with pytest.raises(ValueError): plot_axon_map(n_bundles=0)
def test_deepcopy_AxonMapSpatial(): original = AxonMapSpatial() copied = copy.deepcopy(original) # Assert these are two different objects npt.assert_equal(id(original) != id(copied), True) # Assert these objects are equivalent npt.assert_equal(original.__dict__ == copied.__dict__, True) npt.assert_equal(original == copied, True) # Assert building one object does not affect the copied original.build() npt.assert_equal(copied.is_built, False) npt.assert_equal(original.__dict__ != copied.__dict__, True) # Assert destroying the original doesn't affect the copied original = None npt.assert_equal(copied is not None, True)
def test_AxonMapSpatial(engine): # AxonMapSpatial automatically sets `rho`, `axlambda`: model = AxonMapSpatial(engine=engine, xystep=5) # User can set `rho`: model.rho = 123 npt.assert_equal(model.rho, 123) model.build(rho=987) npt.assert_equal(model.rho, 987) # Converting ret <=> dva npt.assert_almost_equal(model.ret2dva(0), 0) npt.assert_almost_equal(model.dva2ret(0), 0) # Nothing in, None out: npt.assert_equal(model.predict_percept(ArgusI()), None) # Zero in = zero out: implant = ArgusI(stim=np.zeros(16)) percept = model.predict_percept(implant) npt.assert_equal(isinstance(percept, Percept), True) npt.assert_equal(percept.shape, list(model.grid.x.shape) + [1]) npt.assert_almost_equal(percept.data, 0) # Multiple frames are processed independently: model = AxonMapSpatial(engine=engine, rho=200, axlambda=100, xystep=5) model.build() percept = model.predict_percept(ArgusI(stim={'A1': [1, 0], 'B3': [0, 2]})) npt.assert_equal(percept.shape, list(model.grid.x.shape) + [2]) pmax = percept.data.max(axis=(0, 1)) npt.assert_almost_equal(percept.data[2, 3, 0], pmax[0]) npt.assert_almost_equal(percept.data[2, 3, 1], 0) npt.assert_almost_equal(percept.data[3, 4, 0], 0) npt.assert_almost_equal(percept.data[3, 4, 1], pmax[1])
def test_biphasicAxonMapSpatial(engine): # Lambda cannot be too small: with pytest.raises(ValueError): BiphasicAxonMapSpatial(axlambda=9).build() model = BiphasicAxonMapModel(engine=engine, xystep=2).build() # Jax not implemented yet if engine == 'jax': with pytest.raises(NotImplementedError): implant = ArgusII() implant.stim = Stimulus({'A5': BiphasicPulseTrain(20, 1, 0.45)}) percept = model.predict_percept(implant) return # Only accepts biphasic pulse trains with no delay dur implant = ArgusI(stim=np.ones(16)) with pytest.raises(TypeError): model.predict_percept(implant) # Nothing in, None out: npt.assert_equal(model.predict_percept(ArgusI()), None) # Zero in = zero out: implant = ArgusI(stim=np.zeros(16)) percept = model.predict_percept(implant) npt.assert_equal(isinstance(percept, Percept), True) npt.assert_equal(percept.shape, list(model.grid.x.shape) + [1]) npt.assert_almost_equal(percept.data, 0) npt.assert_equal(percept.time, None) # Should be equal to axon map model if effects models return 1 model = BiphasicAxonMapSpatial(engine=engine, xystep=2) def bright_model(freq, amp, pdur): return 1 def size_model(freq, amp, pdur): return 1 def streak_model(freq, amp, pdur): return 1 model.bright_model = bright_model model.size_model = size_model model.streak_model = streak_model model.build() axon_map = AxonMapSpatial(xystep=2).build() implant = ArgusII() implant.stim = Stimulus({'A5': BiphasicPulseTrain(20, 1, 0.45)}) percept = model.predict_percept(implant) percept_axon = axon_map.predict_percept(implant) npt.assert_almost_equal(percept.data[:, :, 0], percept_axon.get_brightest_frame()) # Effect models must be callable model = BiphasicAxonMapSpatial(engine=engine, xystep=2) model.bright_model = 1.0 with pytest.raises(TypeError): model.build() # If t_percept is not specified, there should only be one frame model = BiphasicAxonMapSpatial(engine=engine, xystep=2) model.build() implant = ArgusII() implant.stim = Stimulus({'A5': BiphasicPulseTrain(20, 1, 0.45)}) percept = model.predict_percept(implant) npt.assert_equal(percept.time is None, True) # If t_percept is specified, only first frame should have data # and the rest should be empty percept = model.predict_percept(implant, t_percept=[0, 1, 2, 5, 10]) npt.assert_equal(len(percept.time), 5) npt.assert_equal(np.any(percept.data[:, :, 0]), True) npt.assert_equal(np.any(percept.data[:, :, 1:]), False) # Test that default models give expected values model = BiphasicAxonMapSpatial(engine=engine, rho=400, axlambda=600, xystep=1, xrange=(-20, 20), yrange=(-15, 15)) model.build() implant = ArgusII() implant.stim = Stimulus({'A4': BiphasicPulseTrain(20, 1, 1)}) percept = model.predict_percept(implant) npt.assert_equal(np.sum(percept.data > 0.0813), 81) npt.assert_equal(np.sum(percept.data > 0.1626), 59) npt.assert_equal(np.sum(percept.data > 0.2439), 44) npt.assert_equal(np.sum(percept.data > 0.4065), 26) npt.assert_equal(np.sum(percept.data > 0.5691), 14)
def test_AxonMapModel_predict_percept(engine): model = AxonMapModel(xystep=0.55, axlambda=100, rho=100, thresh_percept=0, engine=engine, xrange=(-20, 20), yrange=(-15, 15), n_axons=500) model.build() # Single-electrode stim: img_stim = np.zeros(60) img_stim[47] = 1 # Axon map jax predict_percept not implemented yet if engine == 'jax': with pytest.raises(NotImplementedError): percept = model.predict_percept(ArgusII(stim=img_stim)) return percept = model.predict_percept(ArgusII(stim=img_stim)) # Single bright pixel, rest of arc is less bright: npt.assert_equal(np.sum(percept.data > 0.8), 1) npt.assert_equal(np.sum(percept.data > 0.6), 2) npt.assert_equal(np.sum(percept.data > 0.1), 7) npt.assert_equal(np.sum(percept.data > 0.0001), 31) # Overall only a few bright pixels: npt.assert_almost_equal(np.sum(percept.data), 3.3087, decimal=3) # Brightest pixel is in lower right: npt.assert_almost_equal(percept.data[33, 46, 0], np.max(percept.data)) # Top half is empty: npt.assert_almost_equal(np.sum(percept.data[:27, :, 0]), 0) # Same for lower band: npt.assert_almost_equal(np.sum(percept.data[39:, :, 0]), 0) # Full Argus II with small lambda: 60 bright spots model = AxonMapModel(engine='serial', xystep=1, rho=100, axlambda=40, xrange=(-20, 20), yrange=(-15, 15), n_axons=500) model.build() percept = model.predict_percept(ArgusII(stim=np.ones(60))) # Most spots are pretty bright, but there are 2 dimmer ones (due to their # location on the retina): npt.assert_equal(np.sum(percept.data > 0.5), 28) npt.assert_equal(np.sum(percept.data > 0.275), 56) # Model gives same outcome as Spatial: spatial = AxonMapSpatial(engine='serial', xystep=1, rho=100, axlambda=40, xrange=(-20, 20), yrange=(-15, 15), n_axons=500) spatial.build() spatial_percept = spatial.predict_percept(ArgusII(stim=np.ones(60))) npt.assert_almost_equal(percept.data, spatial_percept.data) npt.assert_equal(percept.time, None) # Warning for nonzero electrode-retina distances implant = ArgusI(stim=np.ones(16), z=10) msg = ("Nonzero electrode-retina distances do not have any effect on the " "model output.") assert_warns_msg(UserWarning, model.predict_percept, msg, implant)
def test_AxonMapSpatial(engine): # AxonMapSpatial automatically sets `rho`, `axlambda`: model = AxonMapSpatial(engine=engine, xystep=5) # User can set `rho`: model.rho = 123 npt.assert_equal(model.rho, 123) model.build(rho=987) npt.assert_equal(model.rho, 987) # Converting ret <=> dva npt.assert_equal(isinstance(model.retinotopy, Watson2014Map), True) npt.assert_almost_equal(model.retinotopy.ret2dva(0, 0), (0, 0)) npt.assert_almost_equal(model.retinotopy.dva2ret(0, 0), (0, 0)) model2 = AxonMapSpatial(retinotopy=Watson2014DisplaceMap()) npt.assert_equal(isinstance(model2.retinotopy, Watson2014DisplaceMap), True) # Nothing in, None out: npt.assert_equal(model.predict_percept(ArgusI()), None) # Zero in = zero out: implant = ArgusI(stim=np.zeros(16)) percept = model.predict_percept(implant) npt.assert_equal(isinstance(percept, Percept), True) npt.assert_equal(percept.shape, list(model.grid.x.shape) + [1]) npt.assert_almost_equal(percept.data, 0) npt.assert_equal(percept.time, None) # Lambda cannot be too small: with pytest.raises(ValueError): AxonMapSpatial(axlambda=9).build() # Multiple frames are processed independently: model = AxonMapSpatial(engine=engine, rho=200, axlambda=100, xystep=5, xrange=(-20, 20), yrange=(-15, 15)) model.build() # Axon map jax predict_percept not implemented yet if engine == 'jax': with pytest.raises(NotImplementedError): percept = model.predict_percept( ArgusII(stim={ 'A1': [1, 0], 'B3': [0, 2] })) return percept = model.predict_percept(ArgusI(stim={'A1': [1, 0], 'B3': [0, 2]})) npt.assert_equal(percept.shape, list(model.grid.x.shape) + [2]) pmax = percept.data.max(axis=(0, 1)) npt.assert_almost_equal(percept.data[2, 3, 0], pmax[0]) npt.assert_almost_equal(percept.data[2, 3, 1], 0) npt.assert_almost_equal(percept.data[3, 4, 0], 0) npt.assert_almost_equal(percept.data[3, 4, 1], pmax[1]) npt.assert_almost_equal(percept.time, [0, 1])