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

.. only:: html

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

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

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

.. _sphx_glr_examples_models_plot_beyeler2019_scoreboard.py:


============================================================================
Beyeler et al. (2019): Focal percepts with the scoreboard model
============================================================================

This example shows how to apply the
:py:class:`~pulse2percept.models.ScoreboardModel` to a
:py:class:`~pulse2percept.implants.PRIMA75` implant.

The scoreboard model is a standard baseline model of retinal prosthesis
stimulation, which assumes that electrical stimulation leads to the percept
of focal dots of light, centered over the visual field location associated with
the stimulated retinal field location :math:`(x_{stim}, y_{stim})`, whose
spatial intensity decays with a Gaussian profile [Hayes2003]_, [Thompson2003]_:

.. math::

    I_{score}(x,y; \rho) = \exp \Big(
    -\frac{(x-x_{stim})^2 + (y-y_{stim})^2}{2 \rho^2} \Big)

where :math:`\rho` is the spatial decay constant.

.. important::

    As pointed out by [Beyeler2019]_, the scoreboard model does not well
    account for percepts generated by **epiretinal** implants, where
    incidental stimulation of retinal nerve fiber bundles leads to elongated,
    'streaky' percepts.

    In that case, use :py:class:`~pulse2percept.models.AxonMapModel` instead.

The scoreboard model can be instantiated and run in three simple steps.

Creating the model
------------------

The first step is to instantiate the
:py:class:`~pulse2percept.models.ScoreboardModel` class by calling its
constructor method.

The model simulates a patch of the visual field specified by ``xrange`` and
``yrange`` (in degrees of visual angle), sampled at a step size of ``step``.
``step`` is a *target* spacing: both end points of the range are always
included, so the x axis of the grid is NumPy's
``linspace(*xrange, num=round(np.ptp(xrange) / step) + 1)``. When the range is
not a whole multiple of ``step``, the actual spacing differs slightly --
``xrange=(0, 1)`` with ``step=0.3`` gives four points spaced 0.333 apart.
Pass a tuple ``(x_step, y_step)`` to sample the two axes differently.

By default, this patch is quite large, spanning 30deg x 30deg.
Because PRIMA is rather small, we want to reduce the window size to 6deg x 6deg
and sample it at 0.05deg resolution:

.. GENERATED FROM PYTHON SOURCE LINES 56-60

.. code-block:: Python


    from pulse2percept.models import ScoreboardModel
    model = ScoreboardModel(xrange=(-3, 3), yrange=(-3, 3), step=0.05)








.. GENERATED FROM PYTHON SOURCE LINES 62-64

Parameters you don't specify will take on default values. You can inspect
all current model parameters as follows:

.. GENERATED FROM PYTHON SOURCE LINES 64-67

.. code-block:: Python


    print(model)





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

 .. code-block:: none

    ScoreboardModel(grid_type='rectangular', 
                    min_current_spread=1e-08, n_gray=None, 
                    n_jobs=14, n_threads=14, ndim=[2], 
                    noise=None, rho=100, 
                    spatial=ScoreboardSpatial, step=0.05, 
                    temporal=None, thresh_percept=0, 
                    verbose=True, vfmap=Watson2014Map(ndim=2), 
                    xrange=(-3, 3), yrange=(-3, 3))




.. GENERATED FROM PYTHON SOURCE LINES 68-84

This reveals a number of other parameters to set, such as:

* ``xrange``, ``yrange``: the extent of the visual field to be simulated,
  specified as a range of x and y coordinates (in degrees of visual angle,
  or dva). For example, we are currently sampling x values between -20 dva
  and +20dva, and y values between -15 dva and +15 dva.
* ``step``: The resolution (in dva) at which to sample the visual field.
  For example, we are currently sampling at 0.25 dva in both x and y
  direction.
* ``thresh_percept``: You can also define a brightness threshold, below which
  the predicted output brightness will be zero. It is currently set to
  ``1/sqrt(e)``, because that will make the radius of the predicted percept
  equal to ``rho``.

To change parameter values, either pass them directly to the constructor
above or set them by hand, like this:

.. GENERATED FROM PYTHON SOURCE LINES 84-87

.. code-block:: Python


    model.rho = 20








.. GENERATED FROM PYTHON SOURCE LINES 88-92

Then build the model. This is a necessary step before you can actually use
the model to predict a percept, as it performs a number of expensive setup
computations (e.g., building the spatial reference frame, calculating
electric potentials):

.. GENERATED FROM PYTHON SOURCE LINES 92-95

.. code-block:: Python


    model.build()





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

 .. code-block:: none


    ScoreboardModel(grid_type='rectangular', 
                    min_current_spread=1e-08, n_gray=None, 
                    n_jobs=14, n_threads=14, ndim=[2], 
                    noise=None, rho=20, 
                    spatial=ScoreboardSpatial, step=0.05, 
                    temporal=None, thresh_percept=0, 
                    verbose=True, vfmap=Watson2014Map(ndim=2), 
                    xrange=(-3, 3), yrange=(-3, 3))



.. GENERATED FROM PYTHON SOURCE LINES 96-111

.. note::

    You need to build a model only once. After that, you can apply any number
    of stimuli -- or even apply the model to different implants -- without
    having to rebuild (which takes time).

Assigning a stimulus
--------------------
The second step is to specify a visual prosthesis from the
:py:mod:`~pulse2percept.implants` module.

In the following, we will create an
:py:class:`~pulse2percept.implants.PRIMA75` implant. By default, the implant
will be centered over the fovea (at x=0, y=0) and aligned with the horizontal
meridian (rot=0):

.. GENERATED FROM PYTHON SOURCE LINES 111-115

.. code-block:: Python


    from pulse2percept.implants import PRIMA75
    implant = PRIMA75()








.. GENERATED FROM PYTHON SOURCE LINES 116-118

We can visualize the implant and verify that we are simulating the correct
patch of retina as follows:

.. GENERATED FROM PYTHON SOURCE LINES 118-122

.. code-block:: Python


    model.plot()
    implant.plot()




.. image-sg:: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_001.png
   :alt: plot beyeler2019 scoreboard
   :srcset: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_001.png
   :class: sphx-glr-single-img


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

 .. code-block:: none


    <Axes: xlabel='x (microns)', ylabel='y (microns)'>



.. GENERATED FROM PYTHON SOURCE LINES 123-134

The gray window indicates the extent of the grid that was created during
``model.build()`` using the values specified by ``xrange``, ``yrange``, and
``step``. As we can see, the window well-covers the implant that we want
to simulate.

The easiest way to assign a stimulus to the implant is to pass a NumPy array
that specifies the current amplitude to be applied to every electrode in the
implant.

For example, the following sends 10 microamps to all 142 electrodes of the
implant:

.. GENERATED FROM PYTHON SOURCE LINES 134-138

.. code-block:: Python


    import numpy as np
    implant.stim = 10 * np.ones(142)








.. GENERATED FROM PYTHON SOURCE LINES 139-149

.. note::

    Some models can handle stimuli that have both a spatial and a temporal
    component. The scoreboard model cannot.

Predicting the percept
----------------------

The third step is to apply the model to predict the percept resulting from
the specified stimulus. Note that this may take some time on your machine:

.. GENERATED FROM PYTHON SOURCE LINES 149-152

.. code-block:: Python


    percept = model.predict_percept(implant)








.. GENERATED FROM PYTHON SOURCE LINES 153-160

The resulting percept is stored in a
:py:class:`~pulse2percept.percepts.Percept` object, which is similar in
organization to the :py:class:`~pulse2percept.stimuli.Stimulus` object:
the ``data`` container is a 3D NumPy array (Y, X, T) with labeled axes
``xdva``, ``ydva``, and ``time``.

The percept can be plotted as follows:

.. GENERATED FROM PYTHON SOURCE LINES 160-164

.. code-block:: Python


    ax = percept.plot()
    ax.set_title('Predicted percept')




.. image-sg:: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_002.png
   :alt: Predicted percept
   :srcset: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_002.png
   :class: sphx-glr-single-img


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

 .. code-block:: none


    Text(0.5, 1.0, 'Predicted percept')



.. GENERATED FROM PYTHON SOURCE LINES 165-178

.. note::

    Stimulation of the inferior retina leads to percepts appearing in the
    upper visual field. This is why the percept (with axes showing the visual
    field in degrees of visual angle) appears upside down with respect to
    the earlier figure of the implant (with axes showing retinal coordinates
    in microns).

By default, the :py:meth:`~pulse2percept.percepts.Percept.plot` method uses
Matplotlib's ``pcolor`` function.
However, it can also be configured to use a hex grid (using Matplotlib's
``hexbin`` function). Additional parameters can be passed to ``hexbin`` as
keyword arguments of :py:meth:`~pulse2percept.percepts.Percept.plot`:

.. GENERATED FROM PYTHON SOURCE LINES 178-183

.. code-block:: Python


    percept = model.predict_percept(implant)
    percept.plot(kind='hex', cmap='inferno')





.. image-sg:: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_003.png
   :alt: plot beyeler2019 scoreboard
   :srcset: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_003.png
   :class: sphx-glr-single-img


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

 .. code-block:: none


    <Axes: xlabel='x (degrees of visual angle)', ylabel='y (degrees of visual angle)'>



.. GENERATED FROM PYTHON SOURCE LINES 184-189

Addressing individual electrodes
--------------------------------

Alternatively, we can address an individual electrode. To show the electrode
names, the implant can be plotted with ``annotate=True``:

.. GENERATED FROM PYTHON SOURCE LINES 189-192

.. code-block:: Python


    implant.plot(annotate=True)




.. image-sg:: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_004.png
   :alt: plot beyeler2019 scoreboard
   :srcset: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_004.png
   :class: sphx-glr-single-img


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

 .. code-block:: none


    <Axes: xlabel='x (microns)', ylabel='y (microns)'>



.. GENERATED FROM PYTHON SOURCE LINES 193-194

This makes it easier to pick an electrode; e.g., F7:

.. GENERATED FROM PYTHON SOURCE LINES 194-200

.. code-block:: Python


    implant.stim = {'F7': 10}

    percept = model.predict_percept(implant)

    percept.plot()



.. image-sg:: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_005.png
   :alt: plot beyeler2019 scoreboard
   :srcset: /examples/models/images/sphx_glr_plot_beyeler2019_scoreboard_005.png
   :class: sphx-glr-single-img


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

 .. code-block:: none


    <Axes: xlabel='x (degrees of visual angle)', ylabel='y (degrees of visual angle)'>




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

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


.. _sphx_glr_download_examples_models_plot_beyeler2019_scoreboard.py:

.. only:: html

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

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

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

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

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

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

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


.. only:: html

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

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