"""
.. _tut-visualize-raw:

=========================================
Built-in plotting methods for Raw objects
=========================================

This tutorial shows how to plot continuous data as a time series, how to plot the
spectral density of continuous data, and how to plot the sensor locations and projectors
stored in `~mne.io.Raw` objects.

As usual we'll start by importing the modules we need, loading some
:ref:`example data <sample-dataset>`, and cropping the `~mne.io.Raw` object to just 60
seconds before loading it into RAM to save memory:
"""
# Authors: The MNE-Python contributors.
# License: BSD-3-Clause
# Copyright the MNE-Python contributors.

# %%

import os

import mne

sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = os.path.join(
    sample_data_folder, "MEG", "sample", "sample_audvis_raw.fif"
)
raw = mne.io.read_raw_fif(sample_data_raw_file)
raw.crop(tmax=60).load_data()

# %%
# We've seen in :ref:`a previous tutorial <tut-raw-class>` how to plot data
# from a `~mne.io.Raw` object using :doc:`matplotlib <matplotlib:index>`,
# but `~mne.io.Raw` objects also have several built-in plotting methods:
#
# - `~mne.io.Raw.plot`
# - `~mne.io.Raw.plot_sensors`
# - `~mne.io.Raw.plot_projs_topomap`
#
# The first one is discussed here in detail; the last two are shown briefly
# and covered in-depth in other tutorials. This tutorial also covers a few
# ways of plotting the spectral content of :class:`~mne.io.Raw` data.
#
#
# Interactive data browsing with ``Raw.plot()``
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# The `~mne.io.Raw.plot` method of `~mne.io.Raw` objects provides
# a versatile interface for exploring continuous data. For interactive viewing
# and data quality checking, it can be called with no additional parameters:

raw.plot()

# %%
# It may not be obvious when viewing this tutorial online, but by default, the
# `~mne.io.Raw.plot` method generates an *interactive* plot window with
# several useful features:
#
# - It spaces the channels equally along the y-axis.
#
#   - 20 channels are shown by default; you can scroll through the channels
#     using the :kbd:`↑` and :kbd:`↓` arrow keys, or by clicking on the
#     colored scroll bar on the right edge of the plot.
#
#   - The number of visible channels can be adjusted by the ``n_channels``
#     parameter, or changed interactively using :kbd:`page up` and :kbd:`page
#     down` keys.
#
#   - You can toggle the display to "butterfly" mode (superimposing all
#     channels of the same type on top of one another) by pressing :kbd:`b`,
#     or start in butterfly mode by passing the ``butterfly=True`` parameter.
#
# - It shows the first 10 seconds of the `~mne.io.Raw` object.
#
#   - You can shorten or lengthen the window length using :kbd:`home` and
#     :kbd:`end` keys, or start with a specific window duration by passing the
#     ``duration`` parameter.
#
#   - You can scroll in the time domain using the :kbd:`←` and
#     :kbd:`→` arrow keys, or start at a specific point by passing the
#     ``start`` parameter. Scrolling using :kbd:`shift`:kbd:`→` or
#     :kbd:`shift`:kbd:`←` scrolls a full window width at a time.
#
# - It allows clicking on channels to mark/unmark as "bad".
#
#   - When the plot window is closed, the `~mne.io.Raw` object's
#     ``info`` attribute will be updated, adding or removing the newly
#     (un)marked channels to/from the `~mne.Info` object's ``bads``
#     field (A.K.A. ``raw.info['bads']``).
#
# - It allows interactive :term:`annotation <annotations>` of the raw data.
#
#   - This allows you to mark time spans that should be excluded from future
#     computations due to large movement artifacts, line noise, or other
#     distortions of the signal. Annotation mode is entered by pressing
#     :kbd:`a`. See :ref:`annotations-tutorial` for details.
#
# - It automatically applies any :term:`projectors <projector>` before plotting
#   the data.
#
#   - These can be enabled/disabled interactively by clicking the ``Proj``
#     button at the lower right corner of the plot window, or disabled by
#     default by passing the ``proj=False`` parameter. See
#     :ref:`tut-projectors-background` for more info on projectors.
#
# These and other keyboard shortcuts are listed in the Help window, accessed
# through the ``Help`` button at the lower left corner of the plot window.
# Other plot properties (such as color of the channel traces, channel order and
# grouping, simultaneous plotting of :term:`events`, scaling, clipping,
# filtering, etc.) can also be adjusted through parameters passed to the
# `~mne.io.Raw.plot` method; see the docstring for details.
#
#
# Plotting spectral density of continuous data
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# To visualize the frequency content of continuous data, the `~mne.io.Raw`
# object provides a :meth:`~mne.io.Raw.compute_psd` method to compute
# `spectral density`_ and the resulting :class:`~mne.time_frequency.Spectrum`
# object has a :meth:`~mne.time_frequency.Spectrum.plot` method:

spectrum = raw.compute_psd()
spectrum.plot(average=True, picks="data", exclude="bads", amplitude=False)

# %%
# If the data have been filtered, vertical dashed lines will automatically
# indicate filter boundaries. The spectrum for each channel type is drawn in
# its own subplot; here we've passed the ``average=True`` parameter to get a
# summary for each channel type, but it is also possible to plot each channel
# individually, with options for how the spectrum should be computed,
# color-coding the channels by location, and more. For example, here is a plot
# of just a few sensors (specified with the ``picks`` parameter), color-coded
# by spatial location (via the ``spatial_colors`` parameter, see the
# documentation of `~mne.time_frequency.Spectrum.plot` for full details):

midline = ["EEG 002", "EEG 012", "EEG 030", "EEG 048", "EEG 058", "EEG 060"]
spectrum.plot(picks=midline, exclude="bads", amplitude=False)

# %%
# It is also possible to plot spectral power estimates across sensors as a
# scalp topography, using the :class:`~mne.time_frequency.Spectrum`'s
# :meth:`~mne.time_frequency.Spectrum.plot_topomap` method. The default
# parameters will plot five frequency bands (δ, θ, α, β, γ), will compute power
# based on magnetometer channels (if present), and will plot the power
# estimates on a dB-like log-scale:

spectrum.plot_topomap()

# %%
# Alternatively, you can plot the PSD for every sensor on its own axes, with
# the axes arranged spatially to correspond to sensor locations in space, using
# `~mne.time_frequency.Spectrum.plot_topo`:

spectrum.plot_topo()

# %%
# This plot is also interactive; hovering over each "thumbnail" plot will
# display the channel name in the bottom left of the plot window, and clicking
# on a thumbnail plot will create a second figure showing a larger version of
# the selected channel's spectral density (as if you had called
# `~mne.time_frequency.Spectrum.plot` with that channel passed as ``picks``).
#
# By default, `~mne.time_frequency.Spectrum.plot_topo` will show only the MEG
# channels if MEG channels are present; if only EEG channels are found, they
# will be plotted instead:

spectrum.pick("eeg").plot_topo()

# %%
# .. note::
#
#    Prior to the addition of the :class:`~mne.time_frequency.Spectrum` class,
#    the above plots were possible via::
#
#        raw.plot_psd(average=True)
#        raw.plot_psd_topo()
#        raw.pick('eeg').plot_psd_topo()
#
#    (there was no ``plot_topomap`` method for :class:`~mne.io.Raw`). The
#    :meth:`~mne.io.Raw.plot_psd` and :meth:`~mne.io.Raw.plot_psd_topo` methods
#    of :class:`~mne.io.Raw` objects are still provided to support legacy
#    analysis scripts, but new code should instead use the
#    :class:`~mne.time_frequency.Spectrum` object API.
#
#
# Plotting sensor locations from ``Raw`` objects
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# The channel locations in a `~mne.io.Raw` object can be easily plotted
# with the `~mne.io.Raw.plot_sensors` method. A brief example is shown
# here; notice that channels in ``raw.info['bads']`` are plotted in red. More
# details and additional examples are given in the tutorial
# :ref:`tut-sensor-locations`.

raw.plot_sensors(ch_type="eeg")

# %%
# .. _`tut-section-raw-plot-proj`:
#
# Plotting projectors from ``Raw`` objects
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#
# As seen in the output of `mne.io.read_raw_fif` above, there are
# :term:`projectors <projector>` included in the example `~mne.io.Raw`
# file (representing environmental noise in the signal, so it can later be
# "projected out" during preprocessing). You can visualize these projectors
# using the `~mne.io.Raw.plot_projs_topomap` method. By default it will
# show one figure per channel type for which projectors are present, and each
# figure will have one subplot per projector. The three projectors in this file
# were only computed for magnetometers, so one figure with three subplots is
# generated. More details on working with and plotting projectors are given in
# :ref:`tut-projectors-background` and :ref:`tut-artifact-ssp`.

raw.plot_projs_topomap(colorbar=True)

# %%
# .. LINKS
#
# .. _spectral density: https://en.wikipedia.org/wiki/Spectral_density
