|
4 | 4 | ===================================== |
5 | 5 |
|
6 | 6 | This example demonstrates grouped radial/tangential topomap rendering for |
7 | | -colocated triaxial OPM sensors using a small segment of the UCL OPM auditory |
8 | | -dataset. The grouped rendering places radial maps alongside tangential maps |
9 | | -so orientation information is explicit. |
10 | | -
|
| 7 | +colocated triaxial OPM sensors. The grouped rendering places radial maps |
| 8 | +alongside tangential maps so orientation information is explicit. |
11 | 9 | """ |
12 | 10 | # Authors: MNE contributors |
13 | 11 | # License: BSD-3-Clause |
14 | 12 | # Copyright the MNE-Python contributors. |
15 | 13 |
|
16 | | -import matplotlib.pyplot as plt |
17 | 14 | import numpy as np |
18 | 15 |
|
19 | 16 | import mne |
20 | 17 |
|
21 | | -# Load a small segment of the UCL OPM dataset |
22 | | -subject = "sub-002" |
23 | | -data_path = mne.datasets.ucl_opm_auditory.data_path() |
24 | | -opm_file = ( |
25 | | - data_path / subject / "ses-001" / "meg" / "sub-002_ses-001_task-aef_run-001_meg.bin" |
| 18 | +# Create synthetic triaxial OPM data |
| 19 | +# Simulate three colocated OPM sensors with radial and tangential orientations |
| 20 | +n_channels = 6 # 3 locations × 2 orientations (radial + tangential) |
| 21 | +n_samples = 500 |
| 22 | +sfreq = 100.0 |
| 23 | + |
| 24 | +# Create synthetic channel info with triaxial OPM layout |
| 25 | +ch_names = [f"G{i // 2}-{['RAD', 'TAN'][i % 2]}" for i in range(n_channels)] |
| 26 | +ch_types = ["mag"] * n_channels |
| 27 | +info = mne.create_info(ch_names, sfreq, ch_types) |
| 28 | + |
| 29 | +# Set channel locations in a line to simulate colocated triplets |
| 30 | +locs = np.array([[0, i // 2 * 0.01, 0] for i in range(n_channels)]) |
| 31 | +info.set_montage( |
| 32 | + mne.channels.make_dig_montage( |
| 33 | + ch_pos={name: loc for name, loc in zip(ch_names, locs)} |
| 34 | + ) |
26 | 35 | ) |
27 | 36 |
|
28 | | -# Read and crop for speed |
29 | | -raw = mne.io.read_raw_fil(opm_file, verbose="error") |
30 | | -raw.crop(120, 210).load_data() |
| 37 | +# Create synthetic data |
| 38 | +data = np.random.randn(n_channels, n_samples) * 1e-12 # Tesla |
| 39 | +data[::2] += ( |
| 40 | + np.sin(2 * np.pi * 10 * np.arange(n_samples) / sfreq) * 1e-12 |
| 41 | +) # 10 Hz signal |
31 | 42 |
|
32 | | -# Create epochs and average to get evoked |
33 | | -events = mne.find_events(raw, min_duration=0.1) |
34 | | -epochs = mne.Epochs( |
35 | | - raw, events, tmin=-0.1, tmax=0.4, baseline=(None, 0), verbose="error" |
36 | | -) |
37 | | -evoked = epochs.average() |
| 43 | +# Create evoked object |
| 44 | +evoked = mne.EvokedArray(data, info, tmin=-0.5) |
38 | 45 |
|
39 | | -# Find a peak time and plot grouped topomap |
40 | | -t_peak = evoked.times[np.argmax(np.std(evoked.copy().pick("meg").data, axis=0))] |
41 | | -fig = evoked.plot_topomap(times=[float(t_peak)], ch_type="mag") |
42 | | -plt.show() |
| 46 | +# Plot grouped topomap showing radial and tangential maps side-by-side |
| 47 | +fig = evoked.plot_topomap(times=[0.0], ch_type="mag") |
0 commit comments