.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/plot_find_pd_on_and_off.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note Click :ref:`here ` to download the full example code .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_plot_find_pd_on_and_off.py: ================================= Find Photodiode On and Off Events ================================= In this example, we use ``pd-parser`` to find photodiode events and align both the onset of the deflection and the cessation to to behavior. .. GENERATED FROM PYTHON SOURCE LINES 9-14 .. code-block:: default # Authors: Alex Rockhill # # License: BSD (3-clause) .. GENERATED FROM PYTHON SOURCE LINES 15-20 Simulate data and use it to make a raw object We'll make an `mne.io.Raw` object so that we can save out some random data with a photodiode event channel in it in fif format (a commonly used electrophysiology data format). .. GENERATED FROM PYTHON SOURCE LINES 20-59 .. code-block:: default import os.path as op import numpy as np import mne from mne.utils import _TempDir import pd_parser from pd_parser.parse_pd import _load_data import matplotlib.pyplot as plt import matplotlib.cm as cm out_dir = _TempDir() # simulate photodiode data np.random.seed(29) n_events = 300 # let's make our photodiode events on random uniform from 0.5 to 1 second n_secs_on = np.random.random(n_events) * 0.5 + 0.5 prop_corrupted = 0.01 raw, beh, events, corrupted_indices = \ pd_parser.simulate_pd_data(n_events=n_events, n_secs_on=n_secs_on, prop_corrupted=prop_corrupted) # make fake electrophysiology data info = mne.create_info(['ch1', 'ch2', 'ch3'], raw.info['sfreq'], ['seeg'] * 3) raw2 = mne.io.RawArray(np.random.random((3, raw.times.size)) * 1e-6, info) raw.add_channels([raw2]) raw.info['line_freq'] = 60 # for bids # add some offsets to the behavior so it's a bit more realistic offsets = np.random.randn(n_events) * 0.01 beh['time'] = np.array(beh['time']) + offsets # save to disk as required by ``pd-parser`` fname = op.join(out_dir, 'sub-1_task-mytask_raw.fif') raw.save(fname) .. rst-class:: sphx-glr-script-out .. code-block:: none Creating RawArray with float64 data, n_channels=1, n_times=2042100 Range : 0 ... 2042099 = 0.000 ... 2042.099 secs Ready. Creating RawArray with float64 data, n_channels=3, n_times=2042100 Range : 0 ... 2042099 = 0.000 ... 2042.099 secs Ready. Writing /tmp/tmp_mne_tempdir_xzf6z3xo/sub-1_task-mytask_raw.fif Closing /tmp/tmp_mne_tempdir_xzf6z3xo/sub-1_task-mytask_raw.fif [done] .. GENERATED FROM PYTHON SOURCE LINES 60-66 Find the photodiode events relative to the behavioral timing of interest This function will use the default parameters to find and align the photodiode events, excluding events that were off. One percent of the 300 events (3) were corrupted as shown in the plots and some were too far off from large offsets that we're going to exclude them. .. GENERATED FROM PYTHON SOURCE LINES 66-71 .. code-block:: default pd_parser.parse_pd(fname, pd_event_name='Stim On', beh=beh, pd_ch_names=['pd'], beh_key='time', max_len=1.5) # none are on longer than 1.5 seconds .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_plot_find_pd_on_and_off_001.png :alt: Alignment (First 10), Event Differences :srcset: /auto_examples/images/sphx_glr_plot_find_pd_on_and_off_001.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_plot_find_pd_on_and_off_002.png :alt: Excluded Events, 1 off by -35 ms, 19 none found, 29 off by -39 ms, 31 off by -31 ms, 63 none found, 78 off by 33 ms, 108 off by -32 ms, 141 off by -31 ms, 154 off by 30 ms, 180 none found, 224 off by -31 ms :srcset: /auto_examples/images/sphx_glr_plot_find_pd_on_and_off_002.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none Reading in /tmp/tmp_mne_tempdir_xzf6z3xo/sub-1_task-mytask_raw.fif Opening raw data file /tmp/tmp_mne_tempdir_xzf6z3xo/sub-1_task-mytask_raw.fif... Range : 0 ... 2042099 = 0.000 ... 2042.099 secs Ready. Reading 0 ... 2042099 = 0.000 ... 2042.099 secs... Finding photodiode events 0%| | 0/722 [00:00, [12270, 'n/a', 24994, 32081, 38711, 45439, 51458, 58189, 65602, 72878, 79973, 86136, 93477, 100763, 107011, 113960, 119991, 126166, 132641, 'n/a', 146016, 153243, 159760, 166238, 172405, 178531, 185600, 192499, 198583, 'n/a', 211906, 'n/a', 226255, 233158, 239987, 247411, 254891, 261398, 267758, 274953, 281049, 287596, 293701, 300180, 306286, 312721, 319906, 327264, 334453, 341296, 348220, 354762, 361015, 367669, 374768, 380862, 386893, 394049, 400499, 407551, 414653, 422052, 428652, 'n/a', 442400, 449547, 456526, 463742, 470705, 478141, 484642, 491749, 499174, 505676, 512593, 519142, 525834, 531947, 'n/a', 545115, 551794, 558728, 565838, 572466, 579017, 585271, 592462, 599712, 606813, 614126, 621098, 628142, 634432, 641583, 648084, 654741, 661219, 668071, 675059, 681922, 688399, 694726, 701993, 708446, 715103, 721240, 727691, 733820, 'n/a', 747400, 754861, 761799, 768203, 775188, 782128, 789366, 796167, 803534, 810157, 816586, 823365, 830749, 837835, 844576, 851322, 858295, 864967, 871793, 879250, 886649, 893910, 900101, 906936, 913486, 920854, 927325, 934721, 941079, 947710, 955150, 962043, 'n/a', 976249, 982591, 989660, 996442, 1003200, 1009405, 1015622, 1023016, 1030450, 1037899, 1044436, 1050505, 'n/a', 1064440, 1071412, 1077491, 1083840, 1090899, 1096982, 1104252, 1111736, 1118108, 1124189, 1131659, 1138810, 1145491, 1152208, 1159581, 1166115, 1172195, 1179116, 1185585, 1192607, 1200029, 1206570, 1212940, 1219019, 1226266, 'n/a', 1239812, 1246871, 1254238, 1261460, 1267746, 1274010, 1281452, 1287889, 1295075, 1301331, 1307780, 1314790, 1321163, 1328291, 1335610, 1342091, 1348539, 1354581, 1361215, 1367313, 1374175, 1381207, 1388059, 1394965, 1401864, 1409218, 1416015, 1423307, 1429835, 1436046, 1442379, 1449569, 1455914, 1463073, 1470427, 1477244, 1483459, 1490394, 1496963, 1504326, 1510661, 1517012, 1523736, 'n/a', 1536758, 1543320, 1550322, 1557028, 1563118, 1569741, 1576365, 1583036, 1589072, 1595483, 1602909, 1610234, 1617645, 1624783, 1631434, 1638840, 1645291, 1652181, 1659062, 1665723, 1672099, 1678595, 1685559, 1691985, 1698504, 1705035, 1711522, 1718765, 1725584, 1731612, 1738724, 1745477, 1752645, 1759387, 1765853, 1773112, 1779372, 1785789, 1792515, 1799805, 1805978, 1812486, 1819284, 1826302, 1832460, 1839593, 1846428, 1853204, 1859775, 1866247, 1873583, 1881074, 1887337, 1893654, 1900655, 1907802, 1915036, 1921490, 1927804, 1933913, 1940477, 1947321, 1954630, 1960680, 1966814, 1973794, 1980801, 1986987, 1993132, 1999174, 2006147, 2012567, 2018928, 2025925, 2032107]) .. GENERATED FROM PYTHON SOURCE LINES 72-76 Find cessations of the photodiode deflections Another piece of information in the photodiode channel is the cessation of the events. Let's find those and add them to the events. .. GENERATED FROM PYTHON SOURCE LINES 76-79 .. code-block:: default pd_parser.add_pd_off_events(fname, off_event_name='Stim Off', max_len=1.5) .. rst-class:: sphx-glr-script-out .. code-block:: none Reading in /tmp/tmp_mne_tempdir_xzf6z3xo/sub-1_task-mytask_raw.fif Opening raw data file /tmp/tmp_mne_tempdir_xzf6z3xo/sub-1_task-mytask_raw.fif... Range : 0 ... 2042099 = 0.000 ... 2042.099 secs Ready. Reading 0 ... 2042099 = 0.000 ... 2042.099 secs... Finding photodiode events 0%| | 0/722 [00:00 .. GENERATED FROM PYTHON SOURCE LINES 80-90 Check recovered event lengths and compare to the simulation ground truth Let's load in the on and off events and plot their difference compared to the ``n_secs_on`` event lengths we used to simulate. The plot below show the differences between the simulated deflection event lengths on the x axis scattered against the recovered event lengths on the y axis. The identity line (the line with 1:1 correspondance) is not shown as it would occlude the plotted data; the the lengths are recovered within 1 millisecond. Note that the colors are arbitrary and are only used to increase contrast and ease of visualization. .. GENERATED FROM PYTHON SOURCE LINES 90-111 .. code-block:: default annot, pd_ch_names, beh = _load_data(fname) raw.set_annotations(annot) events, event_id = mne.events_from_annotations(raw) on_events = events[events[:, 2] == event_id['Stim On']] off_events = events[events[:, 2] == event_id['Stim Off']] recovered = (off_events[:, 0] - on_events[:, 0]) / raw.info['sfreq'] not_corrupted = [s != 'n/a' for s in beh['pd_parser_sample']] ground_truth_not_corrupted = n_secs_on[not_corrupted] fig, ax = plt.subplots() ax.scatter(ground_truth_not_corrupted, recovered, s=1, color=cm.rainbow(np.linspace(0, 1, len(recovered)))) ax.set_title('Photodiode offset eventfidelity of recovery') ax.set_xlabel('ground truth duration (s)') ax.set_ylabel('recovered duration (s)') print('Mean difference in the recovered from simulated length is {:.3f} ' 'milliseconds'.format( 1000 * abs(ground_truth_not_corrupted - recovered).mean())) .. image-sg:: /auto_examples/images/sphx_glr_plot_find_pd_on_and_off_003.png :alt: Photodiode offset eventfidelity of recovery :srcset: /auto_examples/images/sphx_glr_plot_find_pd_on_and_off_003.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Reading in /tmp/tmp_mne_tempdir_xzf6z3xo/sub-1_task-mytask_raw.fif Opening raw data file /tmp/tmp_mne_tempdir_xzf6z3xo/sub-1_task-mytask_raw.fif... Range : 0 ... 2042099 = 0.000 ... 2042.099 secs Ready. Used Annotations descriptions: ['Stim Off', 'Stim On'] Mean difference in the recovered from simulated length is 0.253 milliseconds .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 20.497 seconds) .. _sphx_glr_download_auto_examples_plot_find_pd_on_and_off.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_find_pd_on_and_off.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_find_pd_on_and_off.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_