|
1 | 1 | """
|
2 |
| -The **events** and :class:`~mne.Annotations` data structures |
| 2 | +The :term:`Events <events>` and :class:`~mne.Annotations` data structures |
3 | 3 | =========================================================================
|
4 | 4 |
|
5 |
| -Events and :class:`~mne.Annotations` are quite similar. |
| 5 | +:term:`Events <events>` and :term:`annotations` are quite similar. |
6 | 6 | This tutorial highlights their differences and similarities, and tries to shed
|
7 | 7 | some light on which one is preferred to use in different situations when using
|
8 | 8 | MNE.
|
9 | 9 |
|
10 |
| -Here are the definitions from the :ref:`glossary`. |
11 |
| -
|
12 |
| - events |
13 |
| - Events correspond to specific time points in raw data; e.g., triggers, |
14 |
| - experimental condition events, etc. MNE represents events with integers |
15 |
| - that are stored in numpy arrays of shape (n_events, 3). Such arrays are |
16 |
| - classically obtained from a trigger channel, also referred to as stim |
17 |
| - channel. |
18 |
| -
|
19 |
| - annotations |
20 |
| - An annotation is defined by an onset, a duration, and a string |
21 |
| - description. It can contain information about the experiment, but |
22 |
| - also details on signals marked by a human: bad data segments, |
23 |
| - sleep scores, sleep events (spindles, K-complex) etc. |
24 |
| -
|
25 | 10 | Both events and :class:`~mne.Annotations` can be seen as triplets
|
26 | 11 | where the first element answers to **when** something happens and the last
|
27 | 12 | element refers to **what** it is.
|
|
101 | 86 |
|
102 | 87 |
|
103 | 88 | ###############################################################################
|
104 |
| -# Working with Annotations |
105 |
| -# ------------------------ |
| 89 | +# Add :term:`annotations` to :term:`raw` objects |
| 90 | +# ---------------------------------------------- |
106 | 91 | #
|
107 | 92 | # An important element of :class:`~mne.Annotations` is
|
108 | 93 | # ``orig_time`` which is the time reference for the ``onset``.
|
|
179 | 164 | print('raw_a.annotations.onset[0] is {}'.format(raw_a.annotations.onset[0]))
|
180 | 165 |
|
181 | 166 | ###############################################################################
|
| 167 | +# Valid operations in :class:`mne.Annotations` |
| 168 | +# -------------------------------------------- |
| 169 | +# |
| 170 | +# Concatenate |
| 171 | +# ~~~~~~~~~~~ |
| 172 | +# |
182 | 173 | # It is possible to concatenate two annotations with the + operator (just like
|
183 | 174 | # lists) if both share the same ``orig_time``
|
184 | 175 |
|
|
189 | 180 | print(annot)
|
190 | 181 |
|
191 | 182 | ###############################################################################
|
| 183 | +# Iterating, Indexing and Slicing :class:`mne.Annotations` |
| 184 | +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
| 185 | +# |
| 186 | +# :class:`~mne.Annotations` supports iterating, indexing and slicing. |
| 187 | +# Iterating over :class:`~mne.Annotations` and indexing with an integer returns |
| 188 | +# a dictionary. While slicing returns a new :class:`~mne.Annotations` instance. |
| 189 | +# |
| 190 | +# See the following examples and usages: |
| 191 | + |
| 192 | +# difference between indexing and slicing a single element |
| 193 | +print(annot[0]) # indexing |
| 194 | +print(annot[:1]) # slicing |
| 195 | + |
| 196 | +############################################################################### |
| 197 | +# How about iterations? |
| 198 | + |
| 199 | +for key, val in annot[0].items(): # iterate on one element which is dictionary |
| 200 | + print(key, val) |
| 201 | + |
| 202 | +############################################################################### |
| 203 | + |
| 204 | +for idx, my_annot in enumerate(annot): # iterate on the Annotations object |
| 205 | + print('annot #{0}: onset={1}'.format(idx, my_annot['onset'])) |
| 206 | + print('annot #{0}: duration={1}'.format(idx, my_annot['duration'])) |
| 207 | + print('annot #{0}: description={1}'.format(idx, my_annot['description'])) |
| 208 | + |
| 209 | +############################################################################### |
| 210 | + |
| 211 | +for idx, my_annot in enumerate(annot[:1]): |
| 212 | + for key, val in my_annot.items(): |
| 213 | + print('annot #{0}: {1} = {2}'.format(idx, key, val)) |
| 214 | + |
| 215 | +############################################################################### |
| 216 | +# Iterating, indexing and slicing return a copy. This has implications like the |
| 217 | +# fact that changes are not kept. |
| 218 | + |
| 219 | +# this change is not kept |
| 220 | +annot[0]['onset'] = 42 |
| 221 | +print(annot[0]) |
| 222 | + |
| 223 | +# this change is kept |
| 224 | +annot.onset[0] = 42 |
| 225 | +print(annot[0]) |
| 226 | + |
| 227 | + |
| 228 | +############################################################################### |
| 229 | +# Save |
| 230 | +# ~~~~ |
| 231 | +# |
192 | 232 | # Note that you can also save annotations to disk in FIF format::
|
193 | 233 | #
|
194 | 234 | # >>> annot.save('my-annot.fif')
|
|
0 commit comments