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

.. only:: html

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

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

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

.. _sphx_glr_examples_implants_plot_custom_electrode_array.py:


============================================================================
Creating your own electrode array
============================================================================

This example shows how to create a new
:py:class:`~pulse2percept.implants.ElectrodeArray` object.

As the base class for all electrode arrays in pulse2percept, the
:py:class:`~pulse2percept.implants.ElectrodeArray` class provides a blue print
for the functionality that every electrode array should have.

First and foremost, an :py:class:`~pulse2percept.implants.ElectrodeArray`
contains a collection of :py:class:`~pulse2percept.implants.Electrode` objects,
and new electrodes can be added via the
:py:func:`~pulse2percept.implants.ElectrodeArray.add_electrodes` method.

In addition, individual electrodes in the array can be accessed by indexing
using either their pre-assigned names (a string) or their place in the array
(integer).

Arranging electrodes in a circle
--------------------------------

In this example, we want to build a new type of electrode array that arranges
all of its electrodes in a circle.

To do this, we need to create a new class ``CircleElectrodeArray`` that is
a child of :py:class:`~pulse2percept.implants.ElectrodeArray`:

.. GENERATED FROM PYTHON SOURCE LINES 33-56

.. code-block:: python

    class CircleElectrodeArray(ElectrodeArray):
        """Electrodes arranged in a circle"""
        ...

This way, the ``CircleElectrodeArray`` class can access all public methods
of :py:class:`~pulse2percept.implants.ElectrodeArray`.

The constructor then has the job of creating all electrodes in the array
and placing them at the appropriate location; for example, by using the
:py:func:`~pulse2percept.implants.ElectrodeArray.add_electrodes` method.

The constructor of the class should accept a number of arguments:

- ``n_electrodes``: how many electrodes to arrange in a circle
- ``radius``: the radius of the circle
- ``x_center``: the x-coordinate of the center of the circle
- ``y_center``: the y-coordinate of the center of the circle

For simplicity, we will use :py:class:`~pulse2percept.implants.DiskElectrode`
objects of a given radius (100um), although it would be relatively straightforward
to allow the user to choose the electrode type.

.. GENERATED FROM PYTHON SOURCE LINES 56-93

.. code-block:: Python


    from pulse2percept.implants import ElectrodeArray, DiskElectrode
    import collections as coll
    import numpy as np


    class CircleElectrodeArray(ElectrodeArray):

        def __init__(self, n_electrodes, radius, x_center, y_center):
            """Electrodes arranged in a circle

            Electrodes will be named 'A0', 'A1', ...

            Parameters
            ----------
            n_electrodes : int
                how many electrodes to arrange in a circle
            radius : float
                the radius of the circle (microns)
            x_center, y_center : float
                the x,y coordinates of the center of the circle (microns),
                where (0,0) is the center of the fovea
            """
            # The job of the constructor is to create the electrodes. We start
            # with an empty collection:
            self._electrodes = coll.OrderedDict()
            # We then generate a number `n_electrodes` of electrodes, arranged on
            # the circumference of a circle:
            for n in range(n_electrodes):
                # Angular position of the electrode:
                ang = 2.0 * np.pi / n_electrodes * n
                # Create the disk electrode:
                electrode = DiskElectrode(x_center + np.cos(ang) * radius,
                                          y_center + np.sin(ang) * radius, 0, 100)
                # Add the electrode to the collection:
                self.add_electrode('A' + str(n), electrode)








.. GENERATED FROM PYTHON SOURCE LINES 94-99

Using the CircleElectrodeArray class
------------------------------------

To use the new class, we need to specify all input arguments and pass them
to the constructor:

.. GENERATED FROM PYTHON SOURCE LINES 99-110

.. code-block:: Python



    n_electrodes = 10
    radius = 1000  # radius in microns
    x_center = 0  # x-coordinate of circle center (microns)
    y_center = 0  # y-coordinate of circle center (microns)

    # Create a new instance of type CircleElectrodeArray:
    earray = CircleElectrodeArray(n_electrodes, radius, x_center, y_center)
    print(earray)





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

 .. code-block:: none

    CircleElectrodeArray(electrodes=OrderedDict, 
                         n_electrodes=10)




.. GENERATED FROM PYTHON SOURCE LINES 111-112

Individual electrodes can be accessed by their name or integer index:

.. GENERATED FROM PYTHON SOURCE LINES 112-119

.. code-block:: Python


    earray[0]

    earray['A0']

    earray[0] == earray['A0']





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

 .. code-block:: none


    True



.. GENERATED FROM PYTHON SOURCE LINES 120-124

Visualizing the electrode array
-------------------------------

Electrode arrays come with their own plotting method:

.. GENERATED FROM PYTHON SOURCE LINES 124-127

.. code-block:: Python


    earray.plot()




.. image-sg:: /examples/implants/images/sphx_glr_plot_custom_electrode_array_001.png
   :alt: plot custom electrode array
   :srcset: /examples/implants/images/sphx_glr_plot_custom_electrode_array_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 128-142

By default, the method will use the current Axes object or create a new one
if none exists. Alternatively, you can specify ``ax=`` yourself.

Extending the CircleElectrodeArray class
----------------------------------------

Similar to extending :py:class:`~pulse2percept.implants.ElectrodeArray` for
our purposes, we can extend ``CircleElectrodeArray``.

To add new functionality, we could simply edit the above constructor.
However, nobody stops us from creating our own hierarchy of classes.

For example, we could build a ``FlexibleCircleElectrodeArray`` that allows us
to remove individual electrodes from the array:

.. GENERATED FROM PYTHON SOURCE LINES 142-156

.. code-block:: Python



    class FlexibleCircleElectrodeArray(CircleElectrodeArray):

        def remove(self, name):
            """Deletean electrode from the array

            Parameters
            ----------
            name : int, string
                the name of the electrode to be removed
            """
            del self.electrodes[name]








.. GENERATED FROM PYTHON SOURCE LINES 157-161

Note how we didn't even specify a constructor.
By default, the class inherits all (public) functionality from its parent,
including its constructor. So the following line will create the same
electrode array as above:

.. GENERATED FROM PYTHON SOURCE LINES 161-167

.. code-block:: Python



    flex_earray = FlexibleCircleElectrodeArray(
        n_electrodes, radius, x_center, y_center)
    print(flex_earray)





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

 .. code-block:: none

    FlexibleCircleElectrodeArray(electrodes=OrderedDict, 
                                 n_electrodes=10)




.. GENERATED FROM PYTHON SOURCE LINES 168-170

A single electrode can be removed by passing its name to the ``remove``
method:

.. GENERATED FROM PYTHON SOURCE LINES 170-176

.. code-block:: Python


    # Remove electrode 'A1'
    flex_earray.remove('A1')

    # Replot the implant:
    flex_earray.plot()



.. image-sg:: /examples/implants/images/sphx_glr_plot_custom_electrode_array_002.png
   :alt: plot custom electrode array
   :srcset: /examples/implants/images/sphx_glr_plot_custom_electrode_array_002.png
   :class: sphx-glr-single-img


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

 .. code-block:: none


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




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

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


.. _sphx_glr_download_examples_implants_plot_custom_electrode_array.py:

.. only:: html

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

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

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

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

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

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

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


.. only:: html

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

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