|
| 1 | +Customize a plot |
| 2 | +================ |
| 3 | + |
| 4 | +The ``SpikeInterface`` widgets are designed to have reasonable default |
| 5 | +plotting options, but sometimes you’ll want to make adjustments to the |
| 6 | +plots. The plotting functions all return a ``Widget`` object. These |
| 7 | +contain and give you access to the underlying matplotlib figure and |
| 8 | +axis, which you can apply any matplotlib machinery to. Let’s see how to |
| 9 | +do this in an example, by first making some synthetic data and computing |
| 10 | +extensions which can be used for plotting. |
| 11 | + |
| 12 | +.. code:: |
| 13 | +
|
| 14 | + import spikeinterface.full as si |
| 15 | + import matplotlib.pyplot as plt |
| 16 | +
|
| 17 | + recording, sorting = si.generate_ground_truth_recording(seed=1205) |
| 18 | + sorting_analyzer = si.create_sorting_analyzer(sorting=sorting, recording=recording) |
| 19 | + sorting_analyzer.compute({"random_spikes": {'seed': 1205}, "templates": {}, "unit_locations": {}}) |
| 20 | +
|
| 21 | + unit_locations = sorting_analyzer.get_extension("unit_locations").get_data() |
| 22 | +
|
| 23 | +
|
| 24 | +
|
| 25 | +.. parsed-literal:: |
| 26 | +
|
| 27 | + estimate_sparsity (no parallelization): 0%| | 0/10 [00:00<?, ?it/s] |
| 28 | +
|
| 29 | +
|
| 30 | +
|
| 31 | +.. parsed-literal:: |
| 32 | +
|
| 33 | + estimate_templates_with_accumulator (no parallelization): 0%| | 0/10 [00:00<?, ?it/s] |
| 34 | +
|
| 35 | +
|
| 36 | +Now we can plot the ``unit_locations`` and ``unit_templates`` using the |
| 37 | +appropriate widgets (see the `full list of |
| 38 | +widgets <https://spikeinterface.readthedocs.io/en/stable/modules/widgets.html#available-plotting-functions>`__ |
| 39 | +for more!). These functions output a ``Widget object``. We’ll assign the |
| 40 | +unit locations widget to ``fig_units``. |
| 41 | + |
| 42 | +.. code:: |
| 43 | +
|
| 44 | + fig_units = si.plot_unit_locations(sorting_analyzer) |
| 45 | +
|
| 46 | + # Each widget contains a `matplotlib` figure and axis: |
| 47 | + print(type(fig_units.figure)) |
| 48 | + print(type(fig_units.ax)) |
| 49 | +
|
| 50 | +
|
| 51 | +.. parsed-literal:: |
| 52 | +
|
| 53 | + <class 'matplotlib.figure.Figure'> |
| 54 | + <class 'matplotlib.axes._axes.Axes'> |
| 55 | +
|
| 56 | +
|
| 57 | +
|
| 58 | +.. image:: customize_a_plot_files/customize_a_plot_4_1.png |
| 59 | + |
| 60 | + |
| 61 | +By gaining access to the matplotlib objects, we are able to utilize the |
| 62 | +full ``matplotlib`` machinery: adding custom titles, axis labels, ticks, |
| 63 | +more plots etc. Let’s customize our unit locations plot. (Note: the |
| 64 | +``SpikeInterface`` Team does not endorse the following style |
| 65 | +conventions): |
| 66 | + |
| 67 | +.. code:: |
| 68 | +
|
| 69 | + # Get the widget |
| 70 | + fig_units = si.plot_unit_locations(sorting_analyzer) |
| 71 | +
|
| 72 | + # Modify the widget's `axis`` to set the title and axes labels |
| 73 | + fig_units.ax.set_title("My favorite units", fontname = "Comic Sans MS") |
| 74 | + fig_units.ax.set_xlabel("x probe location (um)") |
| 75 | + fig_units.ax.set_ylabel("y probe location (um)") |
| 76 | +
|
| 77 | + # You can also set custom ticks |
| 78 | + fig_units.ax.set_xticks([-60,-30,unit_locations[0,0],30,60]) |
| 79 | + fig_units.ax.set_xticklabels([-60,-30,"unit_0_x",30,60]) |
| 80 | + fig_units.ax.set_yticks([-40,-20,0,unit_locations[0,1],40]) |
| 81 | + fig_units.ax.set_yticklabels([-40,-20,0,"unit_0_y",40]) |
| 82 | +
|
| 83 | + # Change the limits of the plot |
| 84 | + fig_units.ax.set_xlim((-30,50)) |
| 85 | + fig_units.ax.set_ylim((-50,50)) |
| 86 | +
|
| 87 | + # And add extra information on the plot |
| 88 | + fig_units.ax.text(unit_locations[6,0], unit_locations[6,1]+5, s="UNIT 6!!!", fontname="Courier") |
| 89 | +
|
| 90 | + fig_units |
| 91 | +
|
| 92 | +
|
| 93 | +
|
| 94 | +
|
| 95 | +.. parsed-literal:: |
| 96 | +
|
| 97 | + <spikeinterface.widgets.unit_locations.UnitLocationsWidget at 0x147a81520> |
| 98 | +
|
| 99 | +
|
| 100 | +
|
| 101 | +
|
| 102 | +.. image:: customize_a_plot_files/customize_a_plot_6_1.png |
| 103 | + |
| 104 | + |
| 105 | +Beautiful!!! |
| 106 | + |
| 107 | +You can also combine figures into a multi-figure plot. The easiest way |
| 108 | +to do this is to set up your figure and axes first, then tell |
| 109 | +``SpikeInterface`` which axes it should attach the widget plot to. |
| 110 | +Here’s an example of making a unit summary plot. |
| 111 | + |
| 112 | +.. code:: |
| 113 | +
|
| 114 | + import matplotlib.pyplot as plt |
| 115 | + fig, axs = plt.subplots(ncols=2, nrows=1) |
| 116 | +
|
| 117 | + unit_id=8 |
| 118 | + si.plot_unit_locations(sorting_analyzer=sorting_analyzer, ax=axs[0]) |
| 119 | + si.plot_unit_templates(sorting_analyzer, axes=[axs[1]], unit_ids=[f'{unit_id}']) |
| 120 | +
|
| 121 | + axs[0].plot([unit_locations[8,0], unit_locations[8,0]+50], [unit_locations[8,1], unit_locations[8,1]+50]) |
| 122 | + axs[0].text(unit_locations[8,0]+52, unit_locations[8,1]+52, s=f"Unit {unit_id}") |
| 123 | + axs[0].set_title("Unit location", fontsize=10) |
| 124 | +
|
| 125 | + fig.suptitle(f"Unit {unit_id} summary", fontfamily="Comic Sans MS", fontsize=20) |
| 126 | +
|
| 127 | + fig.tight_layout() |
| 128 | +
|
| 129 | +
|
| 130 | +
|
| 131 | +
|
| 132 | +.. image:: customize_a_plot_files/customize_a_plot_8_1.png |
| 133 | + |
| 134 | + |
| 135 | +For more details on what you can do using matplotlib, check out their |
| 136 | +`extensive documentation <https://matplotlib.org/stable/>`__ |
0 commit comments