def sub2(raw, subject): # DEBUG-VARIABLES # subject = 204 # fname = '/net/store/nbp/projects/hyperscanning/hyperscanning-2.0/mne_data/sourcedata/sub-{}/eeg/sub-{}-task-hyper_eeg.fif'.format(subject, subject) # raw = mne.io.read_raw_fif(fname = fname, preload = False) # raw = add_info(raw) # CREATE temporary path to save file home = os.path.expanduser('~') hyper_dir = os.path.join( home, '/net/store/nbp/projects/hyperscanning/hyperscanning-2.0/') path_to_sub = hyper_dir + 'temp_saving_subsets/' # select first half of electrodes raw_data, _ = raw[0:72] # raw_data.shape eeg_indices = raw.info['ch_names'][0:72] # In 'mapping', specify which events get which ID mapping = map_events() # BrainVision file needs specific event-array structure: # Therefore delete second column in events-array. # 2nd argument selects the row or column (2nd col), # 3rd argument defines the axis (1=column) events, _ = mne.events_from_annotations(raw, event_id=mapping) events_formatted = np.delete(np.array(events), 1, 1) # Create and save the brainvision file pybv.write_brainvision(data=raw_data, sfreq=raw.info['sfreq'], ch_names=eeg_indices, fname_base='sub2', folder_out=path_to_sub, events=events_formatted, resolution=1e-6) # Load brainvision data # help(mne.events_from_annotations) # help(pybv.write_brainvision) # print(mne.io.read_raw_brainvision.__doc__) raw_bv = mne.io.read_raw_brainvision(vhdr_fname=path_to_sub + 'sub2.vhdr', preload=False) # annot = mne.read_annotations(path_to_sub+'sub2.vmrk') # # Delete first entry which is not of interest # mne.Annotations.delete(annot, 0) # raw_bv.set_annotations(annot) # add subject-specific information to the dict raw_bv.info['subject_info'] = subject_info(int(subject), 'Amp 1') return raw_bv
def write_BIDS(): # write Brainvision format l_session_path = get_used_sessions() for patient_idx, patient_l in enumerate(l_session_path): for sess_idx, sess_path in enumerate(patient_l): data, channel_names = read_raw_session( l_session_path[patient_idx][sess_idx]) pybv.write_brainvision(data, sfreq=1000, ch_names=channel_names, fname_base=str(sess_idx), folder_out='BrainVision', events=None, resolution=1e-7, scale_data=True, fmt='binary_float32', meas_date=None) # BIDS Filename if patient_idx < 10: subject_id = str('00') + str(patient_idx) else: subject_id = str('0') + str(patient_idx) raw = mne.io.read_raw_brainvision('BrainVision/' + str(sess_idx) + '.vhdr') run_ = sess_idx print(str(subject_id)) if 'LEFT' in channel_names[0]: laterality = 'left' else: laterality = 'right' bids_basename = make_bids_basename(subject=str(subject_id), session=laterality, task='force', run=str(run_)) # BIDS schreiben output_path = '/Users/hi/Documents/workshop_ML/thesis_plots/BIDS_new/' write_raw_bids(raw, bids_basename, output_path, event_id=0, overwrite=True)
def _export_bv(self, fname): """Export data to BrainVision EEG/VHDR/VMRK file (requires pybv).""" import pybv head, tail = split(fname) name, ext = splitext(tail) data = self.current["data"].get_data() fs = self.current["data"].info["sfreq"] ch_names = self.current["data"].info["ch_names"] events = None if not isinstance(self.current["events"], np.ndarray): if self.current["data"].annotations: events = mne.events_from_annotations(self.current["data"])[0] dur = self.current["data"].annotations.duration * fs events = np.column_stack([events[:, [0, 2]], dur.astype(int)]) else: events = self.current["events"][:, [0, 2]] pybv.write_brainvision(data, fs, ch_names, name, head, events=events)
def write_bv(fname, raw, events=None): """Export data to BrainVision EEG/VHDR/VMRK file (requires pybv).""" import pybv name, _ = Path(fname).stem, "".join(Path(fname).suffixes) parent = Path(fname).parent data = raw.get_data() fs = raw.info["sfreq"] ch_names = raw.info["ch_names"] if events is None: if raw.annotations: events = mne.events_from_annotations(raw)[0] dur = raw.annotations.duration * fs events = np.column_stack([events[:, [0, 2]], dur.astype(int)]) else: events = events[:, [0, 2]] pybv.write_brainvision(data, fs, ch_names, name, parent, events=events)
def fieldtrip_to_BIDS(filename, BIDS_path, subject_id, session, task, run): """ Write BIDS entry from a fieldtrip format The function has to temporarily save the output file as brainvision to set the filenames attribute in the mne RawArray Args: filename (string): .mat fieldtrip name BIDS_path (string): BIDS_path subject_id (string): BIDS subject id session (string): BIDS session task (string): BIDS session run (string): BIDS session """ raw = mne.io.read_raw_fieldtrip(filename, None) ieegdata = raw.get_data() info = mne.create_info(raw.ch_names, raw.info['sfreq'], ch_types='ecog') raw = mne.io.RawArray(ieegdata, info) bids_basename = mne_bids.make_bids_basename(subject=subject_id, session=session, task=task, run=run) pybv.write_brainvision(raw.get_data(), raw.info['sfreq'], raw.ch_names, 'dummy_write', os.getcwd()) bv_raw = mne.io.read_raw_brainvision('dummy_write.vhdr') # set all channel types to ECOG for iEEG - BIDS does not allow more than one channel type mapping = {} for ch in range(len(bv_raw.info['ch_names'])): mapping[bv_raw.info['ch_names'][ch]] = 'ecog' bv_raw.set_channel_types(mapping) mne_bids.write_raw_bids(bv_raw, bids_basename, BIDS_path, overwrite=True) # remove dummy file os.remove('dummy_write.vhdr') os.remove('dummy_write.eeg') os.remove('dummy_write.vmrk')
def write_raw_bids(raw, bids_basename, output_path, events_data=None, event_id=None, overwrite=False, verbose=True): """Walk over a folder of files and create BIDS compatible folder. .. warning:: The original files are simply copied over if the original file format is BIDS-supported for that modality. Otherwise, this function will convert to a BIDS-supported file format while warning the user. For EEG and iEEG data, conversion will be to BrainVision format, for MEG conversion will be to FIF. Parameters ---------- raw : instance of mne.io.Raw The raw data. It must be an instance of mne.Raw. The data should not be loaded on disk, i.e., raw.preload must be False. bids_basename : str The base filename of the BIDS compatible files. Typically, this can be generated using make_bids_basename. Example: `sub-01_ses-01_task-testing_acq-01_run-01`. This will write the following files in the correct subfolder of the output_path:: sub-01_ses-01_task-testing_acq-01_run-01_meg.fif sub-01_ses-01_task-testing_acq-01_run-01_meg.json sub-01_ses-01_task-testing_acq-01_run-01_channels.tsv sub-01_ses-01_task-testing_acq-01_run-01_coordsystem.json and the following one if events_data is not None:: sub-01_ses-01_task-testing_acq-01_run-01_events.tsv and add a line to the following files:: participants.tsv scans.tsv Note that the modality 'meg' is automatically inferred from the raw object and extension '.fif' is copied from raw.filenames. output_path : str The path of the root of the BIDS compatible folder. The session and subject specific folders will be populated automatically by parsing bids_basename. events_data : str | array | None The events file. If a string, a path to the events file. If an array, the MNE events array (shape n_events, 3). If None, events will be inferred from the stim channel using `mne.find_events`. event_id : dict | None The event id dict used to create a 'trial_type' column in events.tsv overwrite : bool Whether to overwrite existing files or data in files. Defaults to False. If overwrite is True, any existing files with the same BIDS parameters will be overwritten with the exception of the `participants.tsv` and `scans.tsv` files. For these files, parts of pre-existing data that match the current data will be replaced. If overwrite is False, no existing data will be overwritten or replaced. verbose : bool If verbose is True, this will print a snippet of the sidecar files. If False, no content will be printed. Returns ------- output_path : str The path of the root of the BIDS compatible folder. Notes ----- For the participants.tsv file, the raw.info['subjects_info'] should be updated and raw.info['meas_date'] should not be None to compute the age of the participant correctly. """ if not check_version('mne', '0.17'): raise ValueError('Your version of MNE is too old. ' 'Please update to 0.17 or newer.') if not isinstance(raw, BaseRaw): raise ValueError('raw_file must be an instance of BaseRaw, ' 'got %s' % type(raw)) if not hasattr(raw, 'filenames') or raw.filenames[0] is None: raise ValueError('raw.filenames is missing. Please set raw.filenames' 'as a list with the full path of original raw file.') if raw.preload is not False: raise ValueError('The data should not be preloaded.') raw = raw.copy() raw_fname = raw.filenames[0] if '.ds' in op.dirname(raw.filenames[0]): raw_fname = op.dirname(raw.filenames[0]) # point to file containing header info for multifile systems raw_fname = raw_fname.replace('.eeg', '.vhdr') raw_fname = raw_fname.replace('.fdt', '.set') _, ext = _parse_ext(raw_fname, verbose=verbose) raw_orig = reader[ext](**raw._init_kwargs) assert_array_equal(raw.times, raw_orig.times, "raw.times should not have changed since reading" " in from the file. It may have been cropped.") params = _parse_bids_filename(bids_basename, verbose) subject_id, session_id = params['sub'], params['ses'] acquisition, task, run = params['acq'], params['task'], params['run'] kind = _handle_kind(raw) bids_fname = bids_basename + '_%s%s' % (kind, ext) # check whether the info provided indicates that the data is emptyroom # data emptyroom = False if subject_id == 'emptyroom' and task == 'noise': emptyroom = True # check the session date provided is consistent with the value in raw meas_date = raw.info.get('meas_date', None) if meas_date is not None: er_date = datetime.fromtimestamp( raw.info['meas_date'][0]).strftime('%Y%m%d') if er_date != session_id: raise ValueError("Date provided for session doesn't match " "session date.") data_path = make_bids_folders(subject=subject_id, session=session_id, kind=kind, output_path=output_path, overwrite=False, verbose=verbose) if session_id is None: ses_path = os.sep.join(data_path.split(os.sep)[:-1]) else: ses_path = make_bids_folders(subject=subject_id, session=session_id, output_path=output_path, make_dir=False, overwrite=False, verbose=verbose) # create filenames scans_fname = make_bids_basename( subject=subject_id, session=session_id, suffix='scans.tsv', prefix=ses_path) participants_tsv_fname = make_bids_basename(prefix=output_path, suffix='participants.tsv') participants_json_fname = make_bids_basename(prefix=output_path, suffix='participants.json') coordsystem_fname = make_bids_basename( subject=subject_id, session=session_id, acquisition=acquisition, suffix='coordsystem.json', prefix=data_path) sidecar_fname = make_bids_basename( subject=subject_id, session=session_id, task=task, run=run, acquisition=acquisition, suffix='%s.json' % kind, prefix=data_path) events_fname = make_bids_basename( subject=subject_id, session=session_id, task=task, acquisition=acquisition, run=run, suffix='events.tsv', prefix=data_path) channels_fname = make_bids_basename( subject=subject_id, session=session_id, task=task, run=run, acquisition=acquisition, suffix='channels.tsv', prefix=data_path) if ext not in ['.fif', '.ds', '.vhdr', '.edf', '.bdf', '.set', '.con', '.sqd']: bids_raw_folder = bids_fname.split('.')[0] bids_fname = op.join(bids_raw_folder, bids_fname) # Read in Raw object and extract metadata from Raw object if needed orient = ORIENTATION.get(ext, 'n/a') unit = UNITS.get(ext, 'n/a') manufacturer = MANUFACTURERS.get(ext, 'n/a') # save all meta data _participants_tsv(raw, subject_id, participants_tsv_fname, overwrite, verbose) _participants_json(participants_json_fname, True, verbose) _scans_tsv(raw, op.join(kind, bids_fname), scans_fname, overwrite, verbose) # TODO: Implement coordystem.json and electrodes.tsv for EEG and iEEG if kind == 'meg' and not emptyroom: _coordsystem_json(raw, unit, orient, manufacturer, coordsystem_fname, overwrite, verbose) events, event_id = _read_events(events_data, event_id, raw, ext) if events is not None and len(events) > 0 and not emptyroom: _events_tsv(events, raw, events_fname, event_id, overwrite, verbose) make_dataset_description(output_path, name=" ", verbose=verbose) _sidecar_json(raw, task, manufacturer, sidecar_fname, kind, overwrite, verbose) _channels_tsv(raw, channels_fname, overwrite, verbose) # set the raw file name to now be the absolute path to ensure the files # are placed in the right location bids_fname = op.join(data_path, bids_fname) if os.path.exists(bids_fname) and not overwrite: raise FileExistsError('"%s" already exists. Please set ' # noqa: F821 'overwrite to True.' % bids_fname) _mkdir_p(os.path.dirname(bids_fname)) if verbose: print('Copying data files to %s' % op.splitext(bids_fname)[0]) convert = ext not in ALLOWED_EXTENSIONS[kind] # Copy the imaging data files if convert: if kind == 'meg': raise ValueError('Got file extension %s for MEG data, ' + 'expected one of %s' % ALLOWED_EXTENSIONS['meg']) if verbose: warn('Converting data files to BrainVision format') if not check_version('pybv', '0.2'): raise ImportError('pybv >=0.2.0 is required for converting ' + '%s files to Brainvision format' % ext) from pybv import write_brainvision events, event_id = events_from_annotations(raw) write_brainvision(raw.get_data(), raw.info['sfreq'], raw.ch_names, op.splitext(op.basename(bids_fname))[0], op.dirname(bids_fname), events[:, [0, 2]], resolution=1e-6) elif ext == '.fif': n_rawfiles = len(raw.filenames) if n_rawfiles > 1: split_naming = 'bids' raw.save(bids_fname, split_naming=split_naming, overwrite=True) else: # This ensures that single FIF files do not have the part param raw.save(bids_fname, split_naming='neuromag', overwrite=True) # CTF data is saved and renamed in a directory elif ext == '.ds': copyfile_ctf(raw_fname, bids_fname) # BrainVision is multifile, copy over all of them and fix pointers elif ext == '.vhdr': copyfile_brainvision(raw_fname, bids_fname) # EEGLAB .set might be accompanied by a .fdt - find out and copy it too elif ext == '.set': copyfile_eeglab(raw_fname, bids_fname) elif ext == '.pdf': copyfile_bti(raw_orig, op.join(data_path, bids_raw_folder)) else: sh.copyfile(raw_fname, bids_fname) # KIT data requires the marker file to be copied over too if 'mrk' in raw._init_kwargs: hpi = raw._init_kwargs['mrk'] acq_map = dict() if isinstance(hpi, list): if _get_mrk_meas_date(hpi[0]) > _get_mrk_meas_date(hpi[1]): raise ValueError('Markers provided in incorrect order.') _, marker_ext = _parse_ext(hpi[0]) acq_map = dict(zip(['pre', 'post'], hpi)) else: _, marker_ext = _parse_ext(hpi) acq_map[None] = hpi for key, value in acq_map.items(): marker_fname = make_bids_basename( subject=subject_id, session=session_id, task=task, run=run, acquisition=key, suffix='markers%s' % marker_ext, prefix=data_path) sh.copyfile(value, marker_fname) return output_path
def _export_mne_raw(*, raw, fname, events=None, overwrite=False): """Export raw data from MNE-Python. Parameters ---------- raw : mne.io.Raw The raw data to export. fname : str | pathlib.Path The name of the file where raw data will be exported to. Must end with ``".vhdr"``, and accompanying *.vmrk* and *.eeg* files will be written inside the same directory. events : np.ndarray | None Events to be written to the marker file (*.vmrk*). When array, must be in `MNE-Python format <https://mne.tools/stable/glossary.html#term-events>`_. When ``None`` (default), events will be written based on ``raw.annotations``. overwrite : bool Whether or not to overwrite existing data. Defaults to ``False``. """ # Prepare file location if not str(fname).endswith(".vhdr"): raise ValueError( "`fname` must have the '.vhdr' extension for BrainVision.") fname = Path(fname) folder_out = fname.parents[0] fname_base = fname.stem # Prepare data from raw data = raw.get_data() # gets data starting from raw.first_samp sfreq = raw.info["sfreq"] # in Hz meas_date = raw.info["meas_date"] # datetime.datetime ch_names = raw.ch_names # write voltage units as micro-volts and all other units without # scaling # We write units that we don't know as n/a unit = [] for ch in raw.info["chs"]: if ch["unit"] == FIFF.FIFF_UNIT_V: unit.append("µV") elif ch["unit"] == FIFF.FIFF_UNIT_CEL: unit.append("°C") else: unit.append(_unit2human.get(ch["unit"], "n/a")) unit = [u if u != "NA" else "n/a" for u in unit] # We enforce conversion to float32 format # XXX: Could add a feature that checks data and optimizes `unit`, `resolution`, # and `format` so that raw.orig_format could be retained if reasonable. if raw.orig_format != "single": warn( f"Encountered data in '{raw.orig_format}' format. " "Converting to float32.", RuntimeWarning, ) fmt = "binary_float32" resolution = 0.1 # Handle events # if we got an ndarray, this is in MNE-Python format msg = "`events` must be None or array in MNE-Python format." if events is not None: # Subtract raw.first_samp because brainvision marks events starting from # the first available data point and ignores the raw.first_samp assert isinstance(events, np.ndarray), msg assert events.ndim == 2, msg assert events.shape[-1] == 3, msg events[:, 0] -= raw.first_samp events = events[:, [0, 2]] # reorder for pybv required order # else, prepare pybv style events from raw.annotations else: events = _mne_annots2pybv_events(raw) # no information about reference channels in mne currently ref_ch_names = None # write to BrainVision write_brainvision( data=data, sfreq=sfreq, ch_names=ch_names, ref_ch_names=ref_ch_names, fname_base=fname_base, folder_out=folder_out, overwrite=overwrite, events=events, resolution=resolution, unit=unit, fmt=fmt, meas_date=meas_date, )
def run_vhdr_file(s): if s<10: subject_idx= 'sub-00' + str(s) else: subject_idx= 'sub-0' + str(s) subject_path=settings['BIDS_path'] + subject_idx subfolder=IO.get_subfolders(subject_path) vhdr_files=IO.get_files(subject_path, subfolder) vhdr_files.sort() for f in range(len(vhdr_files)): #%% get info and files for the specific subject/session/run vhdr_file=vhdr_files[f] #get info from vhdr_file subject, run, sess = IO.get_sess_run_subject(vhdr_file) print('RUNNIN SUBJECT_'+ subject+ '_SESS_'+ sess + '_RUN_' + run) #read sf sf=IO.read_run_sampling_frequency(vhdr_file) if len(sf.unique())==1: #all sf are equal sf=int(sf[0]) else: Warning('Different sampling freq.') #read data bv_raw, ch_names = IO.read_BIDS_file(vhdr_file) used_channels = IO.read_M1_channel_specs(vhdr_file[:-10]) # extract used channels/labels from brainvision file, split up in cortex/subcortex/labels #dat_ is a dict dat_ = IO.get_dat_cortex_subcortex(bv_raw, ch_names, used_channels) dat_MOV=dat_['dat_label'] label=np.empty(np.shape(dat_MOV), dtype=object) for m in range(len(dat_MOV)): label_name=ch_names[used_channels['labels'][m]] if subject == '016': target_channel_corrected, onoff, raw_target_channel=offline_analysis.baseline_correction(y=-dat_MOV[m], param=1, thr=2e-1, normalize=False) else: target_channel_corrected, onoff, raw_target_channel=offline_analysis.baseline_correction(y=dat_MOV[m], normalize=False) label[m]=target_channel_corrected #change channel info ch_names.append(label_name+'_CLEAN') data=np.vstack((bv_raw, label)) file_name=subject_idx+'_ses-'+sess+'_task-force_run-' +run +'_ieeg' out_path=settings['out_path'] + subject_idx+'/ses-'+sess+'/ieeg' pybv.write_brainvision(data, sfreq=1000, ch_names=ch_names, fname_base=file_name, folder_out=out_path, events=None, resolution=1e-7, scale_data=True, fmt='binary_float32', meas_date=None)