.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/plot_find_pd_events.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_events.py: ====================== Find Photodiode Events ====================== In this example, we use ``pd-parser`` to find photodiode events and align them to behavior. Then, we save the data to BIDS format. .. GENERATED FROM PYTHON SOURCE LINES 8-13 .. code-block:: default # Authors: Alex Rockhill # # License: BSD (3-clause) .. GENERATED FROM PYTHON SOURCE LINES 14-19 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 19-51 .. 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 _read_raw, _to_tsv out_dir = _TempDir() print(f'After running this example, you can find the data here: {out_dir}') # simulate photodiode data n_events = 300 prop_corrupted = 0.01 raw, beh, events, corrupted_indices = \ pd_parser.simulate_pd_data(n_events=n_events, 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 fname = op.join(out_dir, 'sub-1_task-mytask_raw.fif') raw.save(fname) # roundtrip so that raw is properly loaded from disk and has a filename raw = _read_raw(fname) .. rst-class:: sphx-glr-script-out .. code-block:: none After running this example, you can find the data here: /tmp/tmp_mne_tempdir_2_ee581j Creating RawArray with float64 data, n_channels=1, n_times=2042106 Range : 0 ... 2042105 = 0.000 ... 2042.105 secs Ready. Creating RawArray with float64 data, n_channels=3, n_times=2042106 Range : 0 ... 2042105 = 0.000 ... 2042.105 secs Ready. Writing /tmp/tmp_mne_tempdir_2_ee581j/sub-1_task-mytask_raw.fif Closing /tmp/tmp_mne_tempdir_2_ee581j/sub-1_task-mytask_raw.fif [done] Reading in /tmp/tmp_mne_tempdir_2_ee581j/sub-1_task-mytask_raw.fif Opening raw data file /tmp/tmp_mne_tempdir_2_ee581j/sub-1_task-mytask_raw.fif... Range : 0 ... 2042105 = 0.000 ... 2042.105 secs Ready. .. GENERATED FROM PYTHON SOURCE LINES 52-60 Make behavior data We'll make a dictionary with lists for the events that are time-stamped when the photodiode was turned on and other events relative to those events. We'll add some noise to the time-stamps so that we can see how behavior might look in an experimental setting. Let's make a task where there is a fixation stimulus, then a go cue, and a then response as an example. .. GENERATED FROM PYTHON SOURCE LINES 60-82 .. code-block:: default np.random.seed(12) # add some noise to make it harder to align, use just over # the exclusion of 0.03 to make some events excluded offsets = np.random.random(n_events) * 0.035 - 0.0125 # in this example, the fixation would always be 700 ms # after which point a cue would appear which is the "go time" go_time = np.repeat(0.7, n_events) # let's make the response time between 0.5 and 1.5 seconds uniform random response_time = list(go_time + np.random.random(n_events) + 1.5) for i in [10, 129, 232, 288]: response_time[i] = 'n/a' # make some no responses # put in dictionary to be converted to tsv file beh['fix_onset_time'] = beh['time'] + offsets beh['go_time'] = go_time beh['response_time'] = response_time behf = op.join(out_dir, 'sub-1_task-mytask_beh.tsv') # save behavior file out _to_tsv(behf, beh) .. GENERATED FROM PYTHON SOURCE LINES 83-90 Use the interactive graphical user interface (GUI) to find parameters On the documentation webpage, this is example is not interactive, but if you download it as a jupyter notebook and run it or copy the code into a console running python (ipython recommended), you can see how to interact with the photodiode data to pick reasonable parameters by following the instructions. .. GENERATED FROM PYTHON SOURCE LINES 90-93 .. code-block:: default pd_parser.find_pd_params(raw, pd_ch_names=['pd']) .. image-sg:: /auto_examples/images/sphx_glr_plot_find_pd_events_001.png :alt: Align Use the left/right keys to find an uncorrupted photodiode event and align the onset to the center of the window use +/- to zoom the yaxis in and out (up/down to translate) press enter when finished :srcset: /auto_examples/images/sphx_glr_plot_find_pd_events_001.png :class: sphx-glr-single-img .. rst-class:: sphx-glr-script-out .. code-block:: none Reading 0 ... 2042105 = 0.000 ... 2042.105 secs... .. GENERATED FROM PYTHON SOURCE LINES 94-104 Find the photodiode events relative to the behavioral timing of interest This function will use the default parameters or the parameters you found from :func:`pd_parser.find_pd_parameters` to find and align the photodiode events, excluding events that were off because the computer hung up on computation, for instance. That data is saved in the same folder as the raw file (in this case, a temperary directory generated by :func:`_TempDir`). The data can be used directly, or it can be accessed via :func:`pd_parser.pd_parser_save_to_bids` to store it in the brain imagine data structure (BIDS) standardized format before using it. .. GENERATED FROM PYTHON SOURCE LINES 104-107 .. code-block:: default pd_parser.parse_pd(raw, beh=beh, pd_ch_names=['pd'], max_len=1.5) .. rst-class:: sphx-glr-horizontal * .. image-sg:: /auto_examples/images/sphx_glr_plot_find_pd_events_002.png :alt: Alignment (First 10), Event Differences :srcset: /auto_examples/images/sphx_glr_plot_find_pd_events_002.png :class: sphx-glr-multi-img * .. image-sg:: /auto_examples/images/sphx_glr_plot_find_pd_events_003.png :alt: Excluded Events, 1 off by 34 ms, 57 none found, 76 off by -30 ms, 96 none found, 97 off by 32 ms, 98 off by -31 ms, 172 none found :srcset: /auto_examples/images/sphx_glr_plot_find_pd_events_003.png :class: sphx-glr-multi-img .. rst-class:: sphx-glr-script-out .. code-block:: none Reading 0 ... 2042105 = 0.000 ... 2042.105 secs... Finding photodiode events 0%| | 0/793 [00:00, [12270, 'n/a', 24994, 32081, 38711, 45439, 51458, 58189, 65602, 72878, 79973, 86136, 93477, 100763, 107011, 113960, 119991, 126166, 132641, 138878, 146016, 153243, 159760, 166238, 172405, 178531, 185600, 192499, 198583, 205303, 211906, 219178, 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, 'n/a', 400499, 407551, 414653, 422052, 428652, 435190, 442400, 449547, 456526, 463742, 470705, 478141, 484642, 491749, 499174, 505676, 512593, 519142, 'n/a', 531947, 537976, 545115, 551794, 558728, 565838, 572466, 579017, 585271, 592462, 599712, 606813, 614126, 621098, 628142, 634432, 641583, 648084, 654741, 'n/a', 'n/a', 'n/a', 681922, 688399, 694726, 701993, 708446, 715103, 721240, 727691, 733820, 740336, 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, 969441, 976249, 982591, 989660, 996442, 1003200, 1009405, 1015622, 1023016, 1030450, 1037899, 1044436, 1050505, 1057336, 1064440, 1071412, 1077491, 1083840, 1090899, 1096982, 1104252, 1111736, 1118108, 1124189, 1131659, 1138810, 1145491, 1152208, 1159581, 1166115, 1172195, 'n/a', 1185585, 1192607, 1200029, 1206570, 1212940, 1219019, 1226266, 1232384, 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, 1530476, 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 108-120 Add events relative to the photodiode events The photodiode is usually sychronized to one event (e.g. the fixation so that if the deflections caused by the photodiode are large enough to influence other channels through amplifier interactions it doesn't cause issues with the analysis) so often the events of interest are relative to the photodiode event. In the task a timer can be started at the photodiode event and checked each time a subsequent event occurs. These events should then be recorded in tsv file, which can be passed to ``pd-parser`` in order to add the events. Note: if more than one photodiode event is used, the parser can be used for each event separately using the keyword `add_event=True`. .. GENERATED FROM PYTHON SOURCE LINES 120-127 .. code-block:: default pd_parser.add_relative_events( raw, beh, relative_event_keys=['go_time', 'response_time'], relative_event_names=['Go Cue', 'Response']) .. rst-class:: sphx-glr-script-out .. code-block:: none Overwriting existing file. .. GENERATED FROM PYTHON SOURCE LINES 128-135 Save data to BIDS format This saves our data to BIDS format so that it's ready to be analyzed in a reproducible way; BIDS requires all the files the BIDS community has deemed necessary for analysis, so you should have everything you need to continue on with an analysis at this point. See https://bids.neuroimaging.io/ and https://mne.tools/mne-bids/ for more information about BIDS. .. GENERATED FROM PYTHON SOURCE LINES 135-138 .. code-block:: default pd_parser.save_to_bids(op.join(out_dir, 'bids_dir'), fname, sub='1', task='mytask') .. rst-class:: sphx-glr-script-out .. code-block:: none Reading in /tmp/tmp_mne_tempdir_2_ee581j/sub-1_task-mytask_raw.fif Opening raw data file /tmp/tmp_mne_tempdir_2_ee581j/sub-1_task-mytask_raw.fif... Range : 0 ... 2042105 = 0.000 ... 2042.105 secs Ready. Used Annotations descriptions: ['Fixation', 'Go Cue', 'Response'] Opening raw data file /tmp/tmp_mne_tempdir_2_ee581j/sub-1_task-mytask_raw.fif... Range : 0 ... 2042105 = 0.000 ... 2042.105 secs Ready. Writing '/tmp/tmp_mne_tempdir_2_ee581j/bids_dir/README'... Writing '/tmp/tmp_mne_tempdir_2_ee581j/bids_dir/participants.tsv'... Writing '/tmp/tmp_mne_tempdir_2_ee581j/bids_dir/participants.json'... Used Annotations descriptions: ['Fixation', 'Go Cue', 'Response'] Writing '/tmp/tmp_mne_tempdir_2_ee581j/bids_dir/sub-1/ieeg/sub-1_task-mytask_events.tsv'... Writing '/tmp/tmp_mne_tempdir_2_ee581j/bids_dir/dataset_description.json'... Writing '/tmp/tmp_mne_tempdir_2_ee581j/bids_dir/sub-1/ieeg/sub-1_task-mytask_ieeg.json'... Writing '/tmp/tmp_mne_tempdir_2_ee581j/bids_dir/sub-1/ieeg/sub-1_task-mytask_channels.tsv'... /home/alexrockhill/software/anaconda3/envs/mne/lib/python3.10/site-packages/mne_bids/write.py:1848: RuntimeWarning: Converting data files to BrainVision format warn('Converting data files to BrainVision format') Writing '/tmp/tmp_mne_tempdir_2_ee581j/bids_dir/sub-1/sub-1_scans.tsv'... Wrote /tmp/tmp_mne_tempdir_2_ee581j/bids_dir/sub-1/sub-1_scans.tsv entry with ieeg/sub-1_task-mytask_ieeg.vhdr. .. rst-class:: sphx-glr-timing **Total running time of the script:** ( 0 minutes 16.826 seconds) .. _sphx_glr_download_auto_examples_plot_find_pd_events.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_events.py ` .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_find_pd_events.ipynb ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_