
.. DO NOT EDIT.
.. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY.
.. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE:
.. "examples\workflows\plot_amd_prima.py"
.. LINE NUMBERS ARE GIVEN BELOW.

.. only:: html

    .. note::
        :class: sphx-glr-download-link-note

        :ref:`Go to the end <sphx_glr_download_examples_workflows_plot_amd_prima.py>`
        to download the full example code.

.. rst-class:: sphx-glr-example-title

.. _sphx_glr_examples_workflows_plot_amd_prima.py:


===============================================================================
Simulating PRIMA in age-related macular degeneration
===============================================================================

In geographic atrophy, central vision is lost and peripheral vision remains.
The subretinal photovoltaic implant
:py:class:`~pulse2percept.implants.retina.PRIMAPivotal` is placed inside the
lesion and produces a coarse grayscale percept there.

This example covers scene, scotoma, prosthetic percept, gaze, device
preprocessing, and both eyes. The objects are documented under
:ref:`topics-vision`.

.. GENERATED FROM PYTHON SOURCE LINES 16-25

.. code-block:: Python


    import matplotlib.pyplot as plt

    from pulse2percept.implants.retina import PRIMAPivotal
    from pulse2percept.models.retina import ScoreboardModel
    from pulse2percept.stimuli import samples
    from pulse2percept.units import dva
    from pulse2percept.vision import BinocularScene, Scene, Scotoma








.. GENERATED FROM PYTHON SOURCE LINES 27-31

Residual vision
---------------

The lesion and the implant share an eccentric center (dva).

.. GENERATED FROM PYTHON SOURCE LINES 31-36

.. code-block:: Python


    center = (6, -2) * dva
    logo = samples.logo_bvl(resize=(240, 300))
    scotoma = Scotoma.ellipse(5 * dva, 4 * dva, center=center)








.. GENERATED FROM PYTHON SOURCE LINES 37-45

``scotoma_fill`` sets what is shown inside the loss. Simulations often use
black or gray, but people with AMD rarely report a black spot and are often
unaware of the loss. ``'inpaint'`` fills the scotoma from the surrounding
vision (:py:func:`skimage.restoration.inpaint_biharmonic`). This is a
frame-local image operation, not a model of perceptual filling-in.

``background=1`` shows the logo's transparent pixels as white.
``rings=True`` draws 5 dva eccentricity rings.

.. GENERATED FROM PYTHON SOURCE LINES 45-52

.. code-block:: Python


    filled_in = Scene(logo, fov=40 * dva, scotoma=scotoma,
                      scotoma_fill='inpaint', background=1)

    filled_in.plot(gaze=(0, 0) * dva, rings=True)
    plt.title('Native vision alone, with filling-in')




.. image-sg:: /examples/workflows/images/sphx_glr_plot_amd_prima_001.png
   :alt: Native vision alone, with filling-in
   :srcset: /examples/workflows/images/sphx_glr_plot_amd_prima_001.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 1.0, 'Native vision alone, with filling-in')



.. GENERATED FROM PYTHON SOURCE LINES 53-55

``'inpaint'`` is not combined with prosthetic percepts, so the rest of the
example uses a numeric fill.

.. GENERATED FROM PYTHON SOURCE LINES 55-59

.. code-block:: Python


    scene = Scene(logo, fov=40 * dva, scotoma=scotoma, scotoma_fill=0,
                  background=1)








.. GENERATED FROM PYTHON SOURCE LINES 60-67

Prosthetic vision inside the loss
---------------------------------

PRIMA is driven by pulsed 880 nm light. Its default
:py:class:`~pulse2percept.stimuli.PRIMAEncoder` converts gray levels to
projector ON durations. ``implant_position`` places the array at the lesion
center, and the model grid covers the field around it.

.. GENERATED FROM PYTHON SOURCE LINES 67-77

.. code-block:: Python


    implant = PRIMAPivotal()
    model = ScoreboardModel(implant=implant, implant_position=center, rho=50,
                            xrange=(0, 12), yrange=(-8, 4), step=0.05)

    percept = model.predict_percept(scene, gaze=(0, 0) * dva)

    scene.plot(percept=percept, gaze=(0, 0) * dva, vmax=2)
    plt.title('Native vision with a PRIMA percept in the scotoma')




.. image-sg:: /examples/workflows/images/sphx_glr_plot_amd_prima_002.png
   :alt: Native vision with a PRIMA percept in the scotoma
   :srcset: /examples/workflows/images/sphx_glr_plot_amd_prima_002.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 1.0, 'Native vision with a PRIMA percept in the scotoma')



.. GENERATED FROM PYTHON SOURCE LINES 78-86

The scene is drawn at its own 240 x 300 pixels and the percept on its
0.05 dva model grid; neither is resampled. ``scene.render(...)`` returns a
single RGB raster when one is needed.

Gaze
----

The lesion and the implant move with the eye; the scene does not:

.. GENERATED FROM PYTHON SOURCE LINES 86-92

.. code-block:: Python


    percept = model.predict_percept(scene, gaze=(8, -4) * dva)

    scene.plot(percept=percept, gaze=(8, -4) * dva, vmax=2)
    plt.title('Looking 8 degrees right and 4 degrees down')




.. image-sg:: /examples/workflows/images/sphx_glr_plot_amd_prima_003.png
   :alt: Looking 8 degrees right and 4 degrees down
   :srcset: /examples/workflows/images/sphx_glr_plot_amd_prima_003.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 1.0, 'Looking 8 degrees right and 4 degrees down')



.. GENERATED FROM PYTHON SOURCE LINES 93-99

Device preprocessing
--------------------

``implant.preprocess`` applies to the prosthetic input only. An edge filter
changes the percept; native vision is unchanged. Edges light fewer pixels,
so ``vmax`` is lowered:

.. GENERATED FROM PYTHON SOURCE LINES 99-107

.. code-block:: Python


    implant.preprocess = lambda stim: stim.filter('sobel')

    percept = model.predict_percept(scene, gaze=(0, 0) * dva)

    scene.plot(percept=percept, gaze=(0, 0) * dva, vmax=0.3)
    plt.title('Edge-filtered device input, intact vision around it')




.. image-sg:: /examples/workflows/images/sphx_glr_plot_amd_prima_004.png
   :alt: Edge-filtered device input, intact vision around it
   :srcset: /examples/workflows/images/sphx_glr_plot_amd_prima_004.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    Text(0.5, 1.0, 'Edge-filtered device input, intact vision around it')



.. GENERATED FROM PYTHON SOURCE LINES 108-115

Both eyes
---------

A :py:class:`~pulse2percept.vision.Scene` is one eye, so the fellow eye
gets its own scene, here with a smaller, partial loss. A
:py:class:`~pulse2percept.vision.BinocularScene` holds the pair.
``aperture='round'`` draws each field as an ellipse (display only).

.. GENERATED FROM PYTHON SOURCE LINES 115-126

.. code-block:: Python


    implant.preprocess = False

    worse_eye = Scene(logo, fov=40 * dva, scotoma=scotoma, scotoma_fill=0,
                      background=1, aperture='round')
    fellow_eye = Scene(logo, fov=40 * dva, background=1, aperture='round',
                       scotoma=Scotoma.circle(3 * dva, center=center),
                       scotoma_fill=0.4)

    binocular = BinocularScene(left=worse_eye, right=fellow_eye)








.. GENERATED FROM PYTHON SOURCE LINES 127-129

Models are monocular: the percept is predicted for the implanted eye and
drawn on that side. The fellow eye shows only its own scene.

.. GENERATED FROM PYTHON SOURCE LINES 129-135

.. code-block:: Python


    prosthetic_input = Scene(logo, fov=40 * dva, background=1)
    percept = model.predict_percept(prosthetic_input, gaze=(0, 0) * dva)

    binocular.plot(left_percept=percept, vmax=2, rings=True)




.. image-sg:: /examples/workflows/images/sphx_glr_plot_amd_prima_005.png
   :alt: left eye, right eye
   :srcset: /examples/workflows/images/sphx_glr_plot_amd_prima_005.png
   :class: sphx-glr-single-img


.. rst-class:: sphx-glr-script-out

 .. code-block:: none


    (<Axes: title={'center': 'left eye'}, xlabel='x (degrees of visual angle)', ylabel='y (degrees of visual angle)'>, <Axes: title={'center': 'right eye'}, xlabel='x (degrees of visual angle)', ylabel='y (degrees of visual angle)'>)



.. GENERATED FROM PYTHON SOURCE LINES 136-149

What this does not establish
----------------------------

* :py:class:`~pulse2percept.models.retina.ScoreboardModel` shows where the
  light lands, normalized to a fully lit pixel. It does not model
  photovoltaic transduction or retinal activation
  (:py:class:`~pulse2percept.models.retina.Ho2018Model` does).
* ``rho = 50`` um is an illustrative spread, not a measured PRIMA
  point-spread function.
* Combining prosthetic and residual vision inside the scotoma is a display
  convention; their perceptual interaction is not modeled.
* Residual acuity, binocular combination, disparity, and depth are not
  modeled.


.. rst-class:: sphx-glr-timing

   **Total running time of the script:** (0 minutes 3.134 seconds)


.. _sphx_glr_download_examples_workflows_plot_amd_prima.py:

.. only:: html

  .. container:: sphx-glr-footer sphx-glr-footer-example

    .. container:: sphx-glr-download sphx-glr-download-jupyter

      :download:`Download Jupyter notebook: plot_amd_prima.ipynb <plot_amd_prima.ipynb>`

    .. container:: sphx-glr-download sphx-glr-download-python

      :download:`Download Python source code: plot_amd_prima.py <plot_amd_prima.py>`

    .. container:: sphx-glr-download sphx-glr-download-zip

      :download:`Download zipped: plot_amd_prima.zip <plot_amd_prima.zip>`


.. only:: html

 .. rst-class:: sphx-glr-signature

    `Gallery generated by Sphinx-Gallery <https://sphinx-gallery.github.io>`_
