A question in "Generate simulated source data"

If you have a question or issue with MNE-Python, please include the following info:

  • MNE-Python version: 0.22.0
  • operating system: win10

I have an error when I try to simulate the mixed source space:

raw = mne.simulation.simulate_raw(info, source_simulator, forward=fwd)
Setting up raw simulation: 1 position, "cos2" interpolation
Traceback (most recent call last):

  File "<ipython-input-6-b77397278474>", line 1, in <module>
    raw = mne.simulation.simulate_raw(info, source_simulator, forward=fwd)

  File "<decorator-gen-465>", line 24, in simulate_raw

  File "F:\anzhuangfreesurfer\envs\mne\lib\site-packages\mne\simulation\raw.py", line 279, in simulate_raw
    forward = restrict_forward_to_stc(forward, verts)

  File "F:\anzhuangfreesurfer\envs\mne\lib\site-packages\mne\forward\forward.py", line 1524, in restrict_forward_to_stc
    src_sel, _, vertices = _stc_src_sel(fwd['src'], stc, on_missing=on_missing)

  File "F:\anzhuangfreesurfer\envs\mne\lib\site-packages\mne\forward\forward.py", line 1273, in _stc_src_sel
    raise RuntimeError('Mismatch between number of source spaces (%s) and '

RuntimeError: Mismatch between number of source spaces (9) and STC vertices (2)"

there is my code:

import os.path as op

import numpy as np

import mne
from mne.datasets import sample
from mne import setup_volume_source_space, setup_source_space
from mne import make_forward_solution
from mne.io import read_raw_fif
from mne.minimum_norm import make_inverse_operator, apply_inverse_epochs
from mne.connectivity import spectral_connectivity
from mne.viz import circular_layout, plot_connectivity_circle
print(__doc__)

# For this example, we will be using the information of the sample subject.
# This will download the data if it not already on your machine. We also set
# the subjects directory so we don't need to give it to functions.
data_path = sample.data_path()
subject = 'sample'
data_dir = op.join(data_path, 'MEG', subject)
subjects_dir = op.join(data_path, 'subjects')
bem_dir = op.join(subjects_dir, subject, 'bem')
subjects_dir = op.join(data_path, 'subjects')
subject = 'sample'
fname_trans = data_dir + '/sample_audvis_raw-trans.fif'
meg_path = op.join(data_path, 'MEG', subject)
fname_aseg = op.join(subjects_dir, subject, 'mri', 'aseg.mgz')
fname_raw = data_dir + '/sample_audvis_filt-0-40_raw.fif'
fname_trans = data_dir + '/sample_audvis_raw-trans.fif'
fname_cov = data_dir + '/ernoise-cov.fif'
fname_model = op.join(bem_dir, '%s-5120-bem.fif' % subject)
# First, we get an info structure from the test subject.
evoked_fname = op.join(data_path, 'MEG', subject, 'sample_audvis-ave.fif')
info = mne.io.read_info(evoked_fname)
fname_bem = op.join(bem_dir, '%s-5120-bem-sol.fif' % subject)
tstep = 1. / info['sfreq']
fname_cov = op.join(meg_path, 'sample_audvis-cov.fif')
# To simulate sources, we also need a source space. It can be obtained from the
# forward solution of the sample subject.

noise_cov = mne.read_cov(fname_cov)
# To select a region to activate, we use the caudal middle frontal to grow
# a region of interest.
parc = 'aparc'  
selected_label = mne.read_labels_from_annot(
    subject, parc=parc, subjects_dir=subjects_dir)[0]
location = 'center'  # Use the center of the region as a seed.
extent = 10.  # Extent in mm of the region.
labels_vol = ['Left-Amygdala',
              'Left-Thalamus-Proper',
              'Left-Cerebellum-Cortex',
              'Brain-Stem',
              'Right-Amygdala',
              'Right-Thalamus-Proper',
              'Right-Cerebellum-Cortex']
src = setup_source_space(subject, subjects_dir=subjects_dir,
                         spacing='oct5', add_dist=False)
vol_src = setup_volume_source_space(
    subject, mri=fname_aseg, pos=10.0, bem=fname_model,
    add_interpolator=False,  # just for speed, usually use True
    volume_label=labels_vol, subjects_dir=subjects_dir)
# Generate the mixed source space
src += vol_src
raw = read_raw_fif(fname_raw)
raw.pick_types(meg=True, eeg=False, eog=True, stim=True).load_data()
events = mne.find_events(raw)
noise_cov = mne.read_cov(fname_cov)

# compute the fwd matrix
fwd = make_forward_solution(raw.info, fname_trans, src, fname_bem,
                            mindist=5.0)  # ignore sources<=5mm from innerskull
label = mne.label.select_sources(
    subject, selected_label, location=location, extent=extent,
    subjects_dir=subjects_dir)

# Define the time course of the activity for each source of the region to
# activate. Here we use a sine wave at 18 Hz with a peak amplitude
# of 10 nAm.
source_time_series = np.sin(2. * np.pi * 18. * np.arange(100) * tstep) * 10e-9

# Define when the activity occurs using events. The first column is the sample
# of the event, the second is not used, and the third is the event id. Here the
# events occur every 200 samples.
n_events = 50
events = np.zeros((n_events, 3))
events[:, 0] = 100 + 200 * np.arange(n_events)  # Events sample.
events[:, 2] = 1  # All events have the sample id.

# Create simulated source activity. Here we use a SourceSimulator whose
# add_data method is key. It specified where (label), what
# (source_time_series), and when (events) an event type will occur.
source_simulator = mne.simulation.SourceSimulator(src, tstep=tstep)
source_simulator.add_data(label, source_time_series, events)
#!!!

# Project the source time series to sensor space and add some noise. The source
# simulator can be given directly to the simulate_raw function.
raw = mne.simulation.simulate_raw(info, source_simulator, forward=fwd)
cov = mne.make_ad_hoc_cov(raw.info)
mne.simulation.add_noise(raw, cov, iir_filter=[0.2, -0.2, 0.04])
raw.plot()

# Plot evoked data to get another view of the simulated raw data.
events = mne.find_events(raw)
epochs = mne.Epochs(raw, events, 1, tmin=-0.05, tmax=0.2)
evoked = epochs.average()
evoked.plot()

I’m dying to know the answer, please help me!

looking for your reply, thank you

Hello and welcome to the forum. Please note that you won’t get a response faster if you post 3 times within two hours. You have to be a bit more patient until someone has had the time to look at your question. If you need immediate responses, you can probably pay someone to give you personalized support.

1 Like

Thank you, and sorry.where can I pay for it?

I wondered the comand " mne.simulation.SourceSimulator" can’t create the mix source space.

The error happens when you call simulate_raw(). The docstring of simulate_raw() says that its stc parameter must be a SourceEstimate, an iterable of SourceEstimate, or an iterable of (SourceEstimate, ndarray) tuples. It does not mention MixedSourceEstimate as being supported.

Can I simulate a MixedSource in MNE-python?

Not currently because we don’t allow free orientation sources (SourceEstimate sources are assumed to be oriented normally to the gray/white matter cortical boundary). In theory we could add support for it but it’s probably not trivial

I am a bit confused… This thread seems to say that we cannot simulate mixed sources models (because the volume sources will have free orientation) while this thread Simulate activity in subcortical structures using MNE python? seems to say it is possible, although it is a bit short in details.

So, just to be clear, is it possible to simulate a mixed source model and if so what combination of loose, fixed, and pick_ori allows to estimate mixed sources that are compatible with the simulation routines?

If it is not possible as @larsoner seems to say, I guess I would just like to put a thumb up for this feature request :slight_smile:

You should find that if you use a volumetric source space you hit an error.

The problem is that you need to define the direction of the volumetric sources. For surfaces it’s easy, we just use the cortical surface normals. For volumes, it’s not clear what you should use.

One hack around this would be to use discrete source spaces where you setup_volume_source_space(pos=(rr=vol_src[0]['rr'][vol_src[0]['vertno'], nn=...) and you set the nn of the volume source space RR to whatever you want. You could even duplicate the vertex positions three times and have X/Y/Z normals. Then you could substitute this into the mixed source space in place of the volumetric one.

@christian-oreilly feel free to open an issue about how to add native support for this. I think first we want to improve the simulation code to allow support for volumetric source spaces, probably by making it work with VectorVolSourceEstimate objects. Then make it work with VectorSourceEstimate objects for surfaces. Then the mixed-source-space case with MixedVectorSourceEstimate objects is trivial.

How you actually construct a meaningful MixedVectorSourceEstimate to use is going to be a challenge, as will be enhancing SourceSimulator to support this. But you’re going to run into this issue whether you go the hack route or the proper-implementation route…

Thanks for your thoughts on that @larsoner I might have a closer look at this issue, as time will allow and as it aligns with ongoing projects. I will take your comments into consideration and see how it goes. I’ll keep you posted (maybe in the context of an issue report as you proposed) if I come up with something that might be useful for the general MNE-Python community.

I specified a dipole source with an assumed position (containing only one specified direction) and used make_forward_solution generates the corresponding source space in order to obtain a 4 * 1 conduction matrix. But in the case of four analog sensors, the lead field matrix is a conduction matrix with a dimension of 4 * 3. It seems that it’s because of make_forward_solution. Is there any way to solve the problem where space defaults to “free orientations”?

make_forward_solution always computes free orientations. If you want to convert to the single (normal) orientation you’re interested in, convert_forward_solution(..., force_fixed=True) is probably what you want

https://mne.tools/stable/generated/mne.convert_forward_solution.html

1 Like

Thank you very much for your help!