def test_AxonMapModel(): set_params = {'xystep': 2, 'engine': 'serial', 'rho': 432, 'axlambda': 2, 'n_axons': 9, 'n_ax_segments': 50, 'xrange': (-30, 30), 'yrange': (-20, 20), 'loc_od_x': 5, 'loc_od_y': 6} model = models.AxonMapModel() for param in set_params: npt.assert_equal(hasattr(model, param), True) # User can override default values for key, value in set_params.items(): setattr(model, key, value) npt.assert_equal(getattr(model, key), value) model = models.AxonMapModel(**set_params) model.build(**set_params) for key, value in set_params.items(): npt.assert_equal(getattr(model, key), value) # Zeros in, zeros out: implant = implants.ArgusII(stim=np.zeros(60)) npt.assert_almost_equal(model.predict_percept(implant), 0) implant.stim = np.zeros(60) npt.assert_almost_equal(model.predict_percept(implant), 0) # Implant and model must be built for same eye: with pytest.raises(ValueError): implant = implants.ArgusII(eye='LE', stim=np.zeros(60)) model.predict_percept(implant)
def test_AxonMapModel_predict_percept(): model = models.AxonMapModel(xystep=1, axlambda=100, thresh_percept=0) model.build() # Single-electrode stim: img_stim = np.zeros(60) img_stim[47] = 1 percept = model.predict_percept(implants.ArgusII(stim=img_stim)) # Single bright pixel, rest of arc is less bright: npt.assert_equal(np.sum(percept > 0.9), 1) npt.assert_equal(np.sum(percept > 0.5), 2) npt.assert_equal(np.sum(percept > 0.1), 8) npt.assert_equal(np.sum(percept > 0.0001), 28) # Overall only a few bright pixels: npt.assert_almost_equal(np.sum(percept), 3.207, decimal=3) # Brightest pixel is in lower right: npt.assert_almost_equal(percept[18, 25], np.max(percept)) # Top half is empty: npt.assert_almost_equal(np.sum(percept[:15, :]), 0) # Same for lower band: npt.assert_almost_equal(np.sum(percept[21:, :]), 0) # Full Argus II with small lambda: 60 bright spots model = models.AxonMapModel(engine='serial', xystep=1, rho=100, axlambda=40) model.build() percept = model.predict_percept(implants.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 > 0.5), 58) npt.assert_equal(np.sum(percept > 0.275), 60)
def test_BaseModel_predict_percept(): img_stim = np.zeros(60) model = ValidBaseModel(engine='serial', xystep=5, xrange=(-30, 30), yrange=(-20, 20)) # Model must be built first: with pytest.raises(models.NotBuiltError): model.predict_percept(implants.ArgusII()) # But then must pass through ``predict_percept`` just fine model.build() percept = model.predict_percept(implants.ArgusII(stim=img_stim)) npt.assert_equal(percept.shape, (9, 13)) npt.assert_almost_equal(percept, 0) # Requires ProsthesisSystem object: with pytest.raises(TypeError): model.predict_percept(img_stim) # None in, None out: npt.assert_equal(model.predict_percept(implants.ArgusII(stim=None)), None) # `img_stim` must have right size: for shape in [(2, 60), (59, ), (2, 3, 4)]: with pytest.raises(ValueError): model.predict_percept(implants.ArgusII(stim=np.zeros(shape))) # Single-pixel percept: model = ValidBaseModel(engine='serial', xrange=(0.45, 0.45), yrange=(0, 0)) model.build() percept = model.predict_percept(implants.ArgusII(stim=np.zeros(60))) npt.assert_equal(percept.shape, (1, 1)) npt.assert_almost_equal(percept, 0)
def test_BaseModel_fit(): # Create a valid DataFrame X = get_dummy_data(nrows=3) # Model must be fitted first thing model = ValidBaseModel(engine='serial') npt.assert_equal(model._is_fitted, False) model.fit(X) npt.assert_equal(model._is_fitted, True) npt.assert_equal(hasattr(model, 'implant'), True) npt.assert_equal(hasattr(model, 'implant_type'), True) npt.assert_equal(isinstance(model.implant, model.implant_type), True) # `fit` only accepts DataFrame for XX in [42, [3.3, 1.1], np.array([[0]]), {'img': [[2]]}]: with pytest.raises(TypeError): model.fit(XX) yy = pd.DataFrame([{'img': [[2]]}, {'img': [[4]]}], index=[0, 1]) for XX in [42, [3.3, 1.1], {'img': [[2]]}]: with pytest.raises(TypeError): model.fit(XX, y=yy) for yy in [42, [3.3, 1.1], {'img': [[2]]}]: with pytest.raises(TypeError): model.fit(X, y=yy) # We must pass an implant type, not an implant instance with pytest.raises(TypeError): model = ValidBaseModel(engine='serial', implant_type=p2pi.ArgusII()) model.fit(X) with pytest.raises(TypeError): model = ValidBaseModel(engine='serial') model.set_params(implant_type=p2pi.ArgusII()) model.fit(X) with pytest.raises(TypeError): model = ValidBaseModel(engine='serial') model.fit(X, implant_type=p2pi.ArgusII()) # Implant rotation must be in radians: with pytest.raises(ValueError): model = ValidBaseModel(implant_rot=180) model.fit(X) # `fit_params` must take effect model = ValidBaseModel(engine='serial') model_params = model.get_params() for key, value in six.iteritems(model_params): npt.assert_equal(getattr(model, key), value) if isinstance(value, (int, float)): set_param = {key: 0.1234} elif isinstance(value, (list, set, tuple, np.ndarray)): set_param = {key: np.array([0, 0])} else: continue model.fit(X, **set_param) npt.assert_equal(getattr(model, key), set_param[key])
def test_ScoreboardModel_predict_percept(): model = models.ScoreboardModel(xystep=1, rho=100, thresh_percept=0) model.build() # Single-electrode stim: img_stim = np.zeros(60) img_stim[47] = 1 percept = model.predict_percept(implants.ArgusII(stim=img_stim)) # Single bright pixel, very small Gaussian kernel: npt.assert_equal(np.sum(percept > 0.9), 1) npt.assert_equal(np.sum(percept > 0.5), 1) npt.assert_equal(np.sum(percept > 0.1), 1) npt.assert_equal(np.sum(percept > 0.00001), 9) # Brightest pixel is in lower right: npt.assert_almost_equal(percept[18, 25], np.max(percept)) # Full Argus II: 60 bright spots model = models.ScoreboardModel(engine='serial', xystep=1, rho=100) model.build() percept = model.predict_percept(implants.ArgusII(stim=np.ones(60))) npt.assert_equal(np.sum(np.isclose(percept, 0.9, rtol=0.1, atol=0.1)), 60)
def test_ArgusII(ztype, x, y, rot): # Create an ArgusII and make sure location is correct # Height `h` can either be a float or a list z = 100 if ztype == 'float' else np.ones(60) * 20 argus = implants.ArgusII(x=x, y=y, z=z, rot=rot) # Slots: npt.assert_equal(hasattr(argus, '__slots__'), True) npt.assert_equal(hasattr(argus, '__dict__'), False) # Coordinates of first electrode xy = np.array([-2587.5, -1437.5]).T # Rotate rot_rad = np.deg2rad(rot) R = np.array( [np.cos(rot_rad), -np.sin(rot_rad), np.sin(rot_rad), np.cos(rot_rad)]).reshape((2, 2)) xy = np.matmul(R, xy) # Then off-set: Make sure first electrode is placed # correctly npt.assert_almost_equal(argus['A1'].x, xy[0] + x) npt.assert_almost_equal(argus['A1'].y, xy[1] + y) # Make sure array center is still (x,y) y_center = argus['F1'].y + (argus['A10'].y - argus['F1'].y) / 2 npt.assert_almost_equal(y_center, y) x_center = argus['A1'].x + (argus['F10'].x - argus['A1'].x) / 2 npt.assert_almost_equal(x_center, x) # Make sure radius is correct for e in ['A1', 'B3', 'C5', 'D7', 'E9', 'F10']: npt.assert_almost_equal(argus[e].r, 112.5) # `h` must have the right dimensions with pytest.raises(ValueError): implants.ArgusII(x=-100, y=10, z=np.zeros(5)) with pytest.raises(ValueError): implants.ArgusII(x=-100, y=100, z=[1, 2, 3]) # Indexing must work for both integers and electrode names argus = implants.ArgusII() for idx, (name, electrode) in enumerate(argus.electrodes.items()): npt.assert_equal(electrode, argus[idx]) npt.assert_equal(electrode, argus[name]) npt.assert_equal(argus["unlikely name for an electrode"], None) # Right-eye implant: xc, yc = 500, -500 argus_re = implants.ArgusII(eye='RE', x=xc, y=yc) npt.assert_equal(argus_re['A10'].x > argus_re['A1'].x, True) npt.assert_almost_equal(argus_re['A10'].y, argus_re['A1'].y) # Left-eye implant: argus_le = implants.ArgusII(eye='LE', x=xc, y=yc) npt.assert_equal(argus_le['A1'].x > argus_le['A10'].x, True) npt.assert_almost_equal(argus_le['A10'].y, argus_le['A1'].y) # In both left and right eyes, rotation with positive angle should be # counter-clock-wise (CCW): for (x>0,y>0), decreasing x and increasing y for eye, el in zip(['LE', 'RE'], ['F2', 'F10']): # By default, electrode 'F1' in a left eye has the same coordinates as # 'F10' in a right eye (because the columns are reversed). Thus both # cases are testing an electrode with x>0, y>0: before = implants.ArgusII(eye=eye) after = implants.ArgusII(eye=eye, rot=20) npt.assert_equal(after[el].x < before[el].x, True) npt.assert_equal(after[el].y > before[el].y, True) # Set a stimulus via dict: argus = implants.ArgusII(stim={'B7': 13}) npt.assert_equal(argus.stim.shape, (1, 1)) npt.assert_equal(argus.stim.electrodes, ['B7']) # Set a stimulus via array: argus = implants.ArgusII(stim=np.ones(60)) npt.assert_equal(argus.stim.shape, (60, 1)) npt.assert_almost_equal(argus.stim.data, 1)