import mne
import os.path as op
from matplotlib import pyplot as plt

"""
Explanation: The :class:Raw &lt;mne.io.Raw&gt; data structure: continuous data
Continuous data is stored in objects of type :class:Raw &lt;mne.io.Raw&gt;.
The core data structure is simply a 2D numpy array (channels × samples)
(in memory or loaded on demand) combined with an
:class:Info &lt;mne.Info&gt; object (.info attribute)
(see tut_info_objects).
The most common way to load continuous data is from a .fif file. For more
information on loading data from other formats &lt;ch_convert&gt;, or
creating it from scratch &lt;tut_creating_data_structures&gt;.
End of explanation
"""


data_path = op.join(mne.datasets.sample.data_path(), 'MEG',
                    'sample', 'sample_audvis_raw.fif')
raw = mne.io.read_raw_fif(data_path, preload=True)
raw.set_eeg_reference('average', projection=True)  # set EEG average reference

# Give the sample rate
print('sample rate:', raw.info['sfreq'], 'Hz')
# Give the size of the data matrix
print('%s channels x %s samples' % (len(raw), len(raw.times)))

"""
Explanation: Loading continuous data
Load an example dataset, the preload flag loads the data into memory now:
End of explanation
"""


# Extract data from the first 5 channels, from 1 s to 3 s.
sfreq = raw.info['sfreq']
data, times = raw[:5, int(sfreq * 1):int(sfreq * 3)]
_ = plt.plot(times, data.T)
_ = plt.title('Sample channels')

"""
Explanation: <div class="alert alert-info"><h4>Note</h4><p>This size can also be obtained by examining `raw._data.shape`.
          However this is a private attribute as its name starts
          with an `_`. This suggests that you should **not** access this
          variable directly but rely on indexing syntax detailed just below.</p></div>

Information about the channels contained in the :class:Raw &lt;mne.io.Raw&gt;
object is contained in the :class:Info &lt;mne.Info&gt; attribute.
This is essentially a dictionary with a number of relevant fields (see
tut_info_objects).
Indexing data
To access the data stored within :class:Raw &lt;mne.io.Raw&gt; objects,
it is possible to index the :class:Raw &lt;mne.io.Raw&gt; object.
Indexing a :class:Raw &lt;mne.io.Raw&gt; object will return two arrays: an array
of times, as well as the data representing those timepoints. This works
even if the data is not preloaded, in which case the data will be read from
disk when indexing. The syntax is as follows:
End of explanation
"""


# Pull all MEG gradiometer channels:
# Make sure to use .copy() or it will overwrite the data
meg_only = raw.copy().pick_types(meg=True)
eeg_only = raw.copy().pick_types(meg=False, eeg=True)

# The MEG flag in particular lets you specify a string for more specificity
grad_only = raw.copy().pick_types(meg='grad')

# Or you can use custom channel names
pick_chans = ['MEG 0112', 'MEG 0111', 'MEG 0122', 'MEG 0123']
specific_chans = raw.copy().pick_channels(pick_chans)
print(meg_only)
print(eeg_only)
print(grad_only)
print(specific_chans)

"""
Explanation: Selecting subsets of channels and samples
It is possible to use more intelligent indexing to extract data, using
channel names, types or time ranges.
End of explanation
"""


f, (a1, a2) = plt.subplots(2, 1)
eeg, times = eeg_only[0, :int(sfreq * 2)]
meg, times = meg_only[0, :int(sfreq * 2)]
a1.plot(times, meg[0])
a2.plot(times, eeg[0])
del eeg, meg, meg_only, grad_only, eeg_only, data, specific_chans

"""
Explanation: Notice the different scalings of these types
End of explanation
"""


raw = raw.crop(0, 50)  # in seconds
print('New time range from', raw.times.min(), 's to', raw.times.max(), 's')

"""
Explanation: You can restrict the data to a specific time range
End of explanation
"""


nchan = raw.info['nchan']
raw = raw.drop_channels(['MEG 0241', 'EEG 001'])
print('Number of channels reduced from', nchan, 'to', raw.info['nchan'])

"""
Explanation: And drop channels by name
End of explanation
"""


# Create multiple :class:`Raw <mne.io.RawFIF>` objects
raw1 = raw.copy().crop(0, 10)
raw2 = raw.copy().crop(10, 20)
raw3 = raw.copy().crop(20, 40)

# Concatenate in time (also works without preloading)
raw1.append([raw2, raw3])
print('Time extends from', raw1.times.min(), 's to', raw1.times.max(), 's')

"""
Explanation: Concatenating :class:Raw &lt;mne.io.Raw&gt; objects
:class:Raw &lt;mne.io.Raw&gt; objects can be concatenated in time by using the
:func:append &lt;mne.io.Raw.append&gt; function. For this to work, they must
have the same number of channels and their :class:Info
&lt;mne.Info&gt; structures should be compatible.
End of explanation
"""


