pulse2percept.vision.binocular

BinocularScene

Classes

BinocularScene(left, right)

The left and right monocular views, side by side

class pulse2percept.vision.binocular.BinocularScene(left, right)[source]

The left and right monocular views, side by side

A Scene is one eye’s visual field. BinocularScene holds two of them, and says which eye each belongs to. The two sides are equal peers: neither is the implanted or the primary one, and they need not share a source, FOV, shape, scotoma or aperture.

It does not model how the visual system combines them. There is no fusion, suppression, rivalry, stereopsis or ocular dominance here: this is what the left eye sees, and this is what the right eye sees. Plotting them is therefore an HMD-style pair of monocular views rather than one binocularly fused image.

Models remain monocular in v0.11, so a prediction names the eye it is about:

percept = model.predict_percept(binocular.left)

Added in version 0.11.0.

Parameters:
  • left (Scene) – What each eye sees. Stored as given, not copied.

  • right (Scene) – What each eye sees. Stored as given, not copied.

Examples

A unilateral implant: a scotoma in the left eye, the fellow eye intact.

>>> import numpy as np
>>> from pulse2percept.units import dva
>>> from pulse2percept.vision import BinocularScene, Scene, Scotoma
>>> picture = np.zeros((8, 8))
>>> binocular = BinocularScene(
...     left=Scene(picture, fov=40 * dva, scotoma=Scotoma.circle(8 * dva)),
...     right=Scene(picture, fov=40 * dva))
>>> binocular.left.scotoma is None, binocular.right.scotoma is None
(False, True)

A bilateral loss that is symmetric about the vertical meridian, built with fellow_eye():

>>> left = Scene(picture, fov=40 * dva,
...              scotoma=Scotoma.circle(3 * dva, center=(6, 0) * dva))
>>> binocular = BinocularScene(left, left.fellow_eye())
>>> float(binocular.right.scotoma(-6, 0))
1.0

Imagery already packed left-right side by side, split with from_side_by_side():

>>> stereo = np.zeros((10, 40))
>>> stereo[:, 20:] = 1.0
>>> binocular = BinocularScene.from_side_by_side(stereo, fov=40 * dva)
>>> binocular.left.shape, binocular.right.shape
((10, 20), (10, 20))
>>> float(binocular.left.source.data.max())
0.0
classmethod from_side_by_side(source, fov, **scene_kwargs)[source]

Build a binocular scene from a side-by-side stereo image.

The left half of the image becomes the left-eye scene and the right half becomes the right-eye scene. The split is exact: neither view is flipped, resampled, or interpolated.

This method unpacks existing stereo imagery; it does not create disparity or infer depth.

Added in version 0.11.0.

Parameters:
  • source (ImageStimulus or image) – Side-by-side stereo image. Filenames, NumPy arrays, and other inputs accepted by ImageStimulus are converted to one first. Metadata is preserved in both eye images. Stereo video is not supported.

  • fov (float or (width, height)) – Per-eye field of view in degrees of visual angle. Unless extent is passed, each eye’s extent is inferred from one half of the image, not the packed stereo frame.

  • **scene_kwargs – Additional arguments passed unchanged to both Scene constructors. Use separate scenes when the two eyes need different scotomas or other settings.

Returns:

binocular – The left and right monocular scenes.

Return type:

BinocularScene

Examples

>>> import numpy as np
>>> from pulse2percept.units import dva
>>> from pulse2percept.vision import BinocularScene
>>> stereo = np.zeros((10, 40))
>>> binocular = BinocularScene.from_side_by_side(
...     stereo, fov=(60, 40) * dva)
>>> binocular.left.shape, binocular.left.fov
((10, 20), (60.0, 40.0))
property left

What the left eye sees, as a Scene

property right

What the right eye sees, as a Scene

plot(left_percept=None, right_percept=None, gaze=None, frame=0, rings=False, meridians=False, vmax=None, vmin=None, axes=None, view='scene', context_alpha=0.25, **kwargs)[source]

Plot the two eyes side by side

Each panel is its own plot(): an eye given no percept shows its native or residual scene, and an eye given one shows that percept in its own field. The two are drawn independently and never combined.

Parameters:
  • left_percept (Percept, optional) – A brightness percept for that eye, or None to draw its scene.

  • right_percept (Percept, optional) – A brightness percept for that eye, or None to draw its scene.

  • gaze ((x, y), optional) – Where both eyes are pointing, in dva. Defaults to the origin. One gaze is shared: vergence is not modeled.

  • frame (int, optional) – Which frame of a video scene to draw. Ignored for still scenes.

  • rings (bool, float, or sequence, optional) – Visual-field grid about each eye’s fovea, as in plot().

  • meridians (bool, float, or sequence, optional) – Visual-field grid about each eye’s fovea, as in plot().

  • vmax (float, optional) – The percept brightness that displays as white, shared by both eyes. Defaults to the maximum across both percepts.

  • vmin (float, optional) – The percept brightness that displays as black. Defaults to 0.

  • axes (sequence of two matplotlib.axes.Axes, optional) – Axes to draw the left and right eye on, in that order. If None, makes a new side-by-side pair.

  • view ({'scene', 'eye'}, optional) – As in plot(). Both panels share limits: the union of both extent values in the scene view (default), the largest FOV in the eye view.

  • context_alpha (float, optional) – Opacity of the source outside each FOV in the scene view, as in plot().

  • **kwargs – Passed on to plot().

Returns:

axes – The two axes, always in left-eye, right-eye order.

Return type:

(ax_left, ax_right)