def load_data(filename): '''Get recordings from a single XDF file and order streams by device.''' # Load XDF file streams = load_xdf(filename) streameeg, streamacc, streamppg, streamgyr, device_name = [], [], [], [], [] # Get the individual names of every Muse device for stream in streams[0]: name = stream['info']['name'][0][:9] if name not in device_name: device_name.append(name) # Order the streams in a new list based on the name of the device streams_ordered = [] for item in device_name: if len(streams_ordered) < (len(device_name) * 4) + len(device_name): for stream in streams[0]: if item == stream['info']['name'][0][:9]: streams_ordered.append(stream) # Insert each stream inside a file into the corresponding list for stream in streams_ordered: if 'EEG' in stream['info']['type'][0]: streameeg.append(stream) if 'Accelerometer' in stream['info']['type'][0]: streamacc.append(stream) if 'Gyroscope' in stream['info']['type'][0]: streamgyr.append(stream) if 'PPG' in stream['info']['type'][0]: streamppg.append(stream) return streameeg, streamacc, streamppg, streamgyr
def load_eeg_data(folder_path): """ Load the raw EEG data from the xdf file. :param folder_path: path to the folder where the xdf file was located :return: ndarray, EEG data """ # Get the xdf file path = os.path.join(folder_path, 'EEG.xdf') data, header = pyxdf.load_xdf(path, [{'type': 'EEG'}]) # Get the EEG data & update sample rate param eeg_data = data[0]['time_series'] eeg_timestamp = data[0]['time_stamps'] params['data']['sample_freq'] = float(data[0]['info']['effective_srate']) # update the sample rate # Remove channels eeg_data = np.delete(eeg_data, obj=params['preprocess']['remove_channels'], axis=1) # Debug print print('EEG data loaded\nData shape: {}'.format(eeg_data.shape)) # Dump the info as JSON json.dump(data[0]['info'], open(os.path.join(folder_path, '.info'), 'w')) return eeg_data, eeg_timestamp
def __init__(self, path, verbose=None, freq=2048): logging.basicConfig( level=logging.INFO) # Use logging.INFO to reduce output. fname = os.path.abspath( os.path.join(os.path.dirname(__file__), '..', '..', path)) self.streams, self.fileheader = pyxdf.load_xdf(fname) self.freq = freq self.cut_EEG = None if verbose is True: print("Found {} streams:".format(len(self.streams))) for ix, stream in enumerate(self.streams): print( "Stream {}: {} - type {} - uid {} - shape {} at {} Hz (effective {} Hz)" .format(ix + 1, stream['info']['name'][0], stream['info']['type'][0], stream['info']['uid'][0], (int(stream['info']['channel_count'][0]), len(stream['time_stamps'])), stream['info']['nominal_srate'][0], stream['info']['effective_srate'])) if any(stream['time_stamps']): print("\tDuration: {} s".format(stream['time_stamps'][-1] - stream['time_stamps'][0])) print("Done.") else: print(type(self.streams), len(self.streams), type(self.streams[0]), len(self.streams[0])) print(self.streams[1]["time_series"].shape) self.data_EEG = np.array( self.streams[1]["time_series"]).transpose()[1:33]
def get_trials_times(subject_path): """ This function get subject path and return a list of the trials timestamps. contains the trial start & end timestamps. :param subject_path: str, path to the current subject folder :return: list with tuples correspond to the start & end of each trial """ # Load the markers from the xdf file path = os.path.join(subject_path, 'EEG.xdf') data, header = pyxdf.load_xdf(path, [{'type': 'Markers'}]) # Get the markers data and timestamps markers = [e[0] for e in data[0]['time_series']] markers_timestamps = data[0]['time_stamps'] start = params['lsl']['start_trial'] trial_times = [] for i in range(len(markers)): if markers[i] == start: trial_times.append( (markers_timestamps[i], markers_timestamps[i + 1])) return trial_times
def expand_files(file, dst_path): if not dst_path.exists(): dst_path.mkdir(parents=True) data, header = pyxdf.load_xdf(file) stream_names = [stream['info']['name'][0] for stream in data] # print(stream_names) markers, markers_time = get_experimental_marker(data) for stream in data: stream_name = stream['info']['name'][0] stream_info = stream['info'] time_series = np.array(stream['time_series']) #Recorded values time_stamps = np.array(stream['time_stamps']).reshape(-1, 1) #Timestamps #Trim signals with experimental markers idx = np.where((time_stamps > markers_time[0]) & (time_stamps < markers_time[1])) time_series = time_series[idx].reshape(-1, 1) time_stamps = time_stamps[idx].reshape(-1, 1) data = np.hstack((time_stamps, time_series)) df = pd.DataFrame(data) df.to_csv(dst_path / "{:}_data.csv".format(stream_name), index=False) with open(dst_path / "{:}_info.json".format(stream_name), 'w') as f1: json_data = json.dumps(stream_info, indent=3) f1.write(json_data)
def XDFFile(filename: Union[Path, str], verbose=False) -> Dict[str, XDFStream]: """load an :code:`xdf`-file and return a dictionary of its streams args ---- filename: the name of the xdffile returns ------- streams: Dict[str, XDFStream] a collection of all :class:`~.XDFStream` s in the file. These can be indexed by their respective name """ streams, _ = pyxdf.load_xdf(filename=str(filename)) collection: Dict[str, XDFStream] = dict() doublettes: Dict[str, int] = dict() for stream in streams: if not verbose: print("XDFFile: Parsing", stream["info"]["name"][0]) x = XDFStream(stream) x.origin = str(filename) doublettes[x.name] = doublettes.get(x.name, 0) + 1 if doublettes[x.name] == 1: collection[x.name] = x else: collection[x.name + str(doublettes[x.name])] = x return collection
def main(filename): streams, info = load_xdf(filename) hdr = "XDF Fileversion " + info["info"]["version"][0] print(f"\r\nLoading {filename:3}\n") print(f"{hdr:>80}\n") line = "{0:<25s}{1:^20s}{2:4s}{3:^5s}{4:>26s}" print(line.format("Name", "Type", "Ch", "Fs", "Source")) print("-" * 80) for s in streams: name = s["info"]["name"][0] typ = s["info"]["type"][0] cc = s["info"]["channel_count"][0] fs = s["info"]["nominal_srate"][0] name = shorten(name, 25) typ = shorten(typ, 20) try: sid = s["info"]["source_id"][0] sid = shorten(sid, 25) except IndexError: sid = '""' print(line.format(name, typ, cc, fs, sid)) print("\n") line = "{0:<30s}{1:>50s}" for s in streams: typ = s["info"]["type"][0] name = s["info"]["name"][0] if "marker" in typ.lower(): events = Counter([s[0] for s in s["time_series"]]) print(line.format(name, "Events")) print("-" * 80) for key, val in events.items(): if key == "": wrapped_key = '""' else: wrapped_key = textwrap.shorten(key, width=70, placeholder="...") alignment = 80 - len(wrapped_key) print("{0}{1:>{align}}".format(wrapped_key, val, align=alignment)) print() else: print(line.format(name, "Exemplary data")) print("-" * 80) sz = s["time_series"].shape if sz[1]: x = s["time_stamps"] y = s["time_series"][:, 0] plot(y, x) else: print("No data found, array has shape({0}, {1})".format(*sz)) print() print(f"Overview finished for {filename:3}\n")
def __init__(self, xdf_path: str, channels: List[str]): self.channels: List[str] = channels self.labels: List[int] = [] self.sample_freq: float = 125 self._xdf, _ = pyxdf.load_xdf(xdf_path) self.data: NDArray = self._xdf[1][ 'time_series'][:, 3:] # remove first 3 columns (time, noisy, noisy) self.duration: List[Tuple] = self.extract_durations()
def read_raw_xdf(fname, stream_id): """Read XDF file. Parameters ---------- fname : str Name of the XDF file. stream_id : int ID (number) of the stream to load. Returns ------- raw : mne.io.Raw XDF file data. """ from pyxdf import load_xdf streams, header = load_xdf(fname) for stream in streams: if stream["info"]["stream_id"] == stream_id: break # stream found n_chans = int(stream["info"]["channel_count"][0]) fs = float(stream["info"]["nominal_srate"][0]) labels, types, units = [], [], [] try: for ch in stream["info"]["desc"][0]["channels"][0]["channel"]: labels.append(str(ch["label"][0])) if ch["type"]: types.append(ch["type"][0]) if ch["unit"]: units.append(ch["unit"][0]) except (TypeError, IndexError): # no channel labels found pass if not labels: labels = [str(n) for n in range(n_chans)] if not units: units = ["NA" for _ in range(n_chans)] info = mne.create_info(ch_names=labels, sfreq=fs, ch_types="eeg") # convert from microvolts to volts if necessary scale = np.array([1e-6 if u == "microvolts" else 1 for u in units]) raw = mne.io.RawArray((stream["time_series"] * scale).T, info) first_samp = stream["time_stamps"][0] markers = match_streaminfos(resolve_streams(fname), [{"type": "Markers"}]) for stream_id in markers: for stream in streams: if stream["info"]["stream_id"] == stream_id: break onsets = stream["time_stamps"] - first_samp descriptions = [item for sub in stream["time_series"] for item in sub] raw.annotations.append(onsets, [0] * len(onsets), descriptions) return raw
def read_raw_xdf(fname, stream_id=None): """Read XDF file. Parameters ---------- fname : str Name of the XDF file. stream_id : int | str | None ID (number) or name of the stream to load (optional). If None, the first stream of type "EEG" will be read. Returns ------- raw : mne.io.Raw XDF file data. """ streams, header = load_xdf(fname) if stream_id is not None: if isinstance(stream_id, str): stream = _find_stream_by_name(streams, stream_id) elif isinstance(stream_id, int): stream = _find_stream_by_id(streams, stream_id) else: stream = _find_stream_by_type(streams, stream_type="EEG") if stream is not None: name = stream["info"]["name"][0] n_chans = int(stream["info"]["channel_count"][0]) fs = float(stream["info"]["nominal_srate"][0]) logger.info(f"Found EEG stream '{name}' ({n_chans} channels, " f"sampling rate {fs}Hz).") labels, types, units = _get_ch_info(stream) if not labels: labels = [str(n) for n in range(n_chans)] if not units: units = ["NA" for _ in range(n_chans)] info = mne.create_info(ch_names=labels, sfreq=fs, ch_types="eeg") # convert from microvolts to volts if necessary scale = np.array([1e-6 if u == "microvolts" else 1 for u in units]) raw = mne.io.RawArray((stream["time_series"] * scale).T, info) first_samp = stream["time_stamps"][0] else: logger.info("No EEG stream found.") return markers = _find_stream_by_type(streams, stream_type="Markers") if markers is not None: onsets = markers["time_stamps"] - first_samp logger.info(f"Adding {len(onsets)} annotations.") descriptions = markers["time_series"] annotations = mne.Annotations(onsets, [0] * len(onsets), descriptions) raw.set_annotations(annotations) return raw
def main(): for f in dataPath.glob('*.xdf'): # Load xdf files if len(re.findall(".xdf", f.name)) > 0: file = f # Rename files --> remove identifiers uid = re.findall('.+(?=_S[0-9][0-9]+_T[0-9][0-9]_)', file.name)[0] session = int( re.findall('(?<=_S)[0-9]+(?=_T[0-9][0-9]_)', file.name)[0]) trial = int( re.findall('(?<=_S[0-9]{2}_T)[0-9]{2}(?=_)', file.name)[0]) task = re.findall('(?<=_S[0-9]{2}_T[0-9]{2}_).+(?=_raw\.xdf)', file.name)[0] basePath = './eye_tracker_txt/' + "{:}_S{:02d}_T{:02d}_{:}_".format( uid, session, trial, task) print(uid, session, trial, task) print("srcPath", f) print("dstPath", basePath) data, header = pyxdf.load_xdf(file) stream_names = [stream['info']['name'][0] for stream in data] print(stream_names) eye_stream_dict = {} gaze_stream = None markers, markersTime = None, None # Get data and experiment markers for stream in data: if stream['info']['name'][0] == 'left_eye_data' or stream[ 'info']['name'][0] == 'right_eye_data': eye = 'left' if 'left' in stream['info']['name'][ 0] else 'right' eye_stream_dict[eye] = stream if stream['info']['name'][0] == 'gaze_position': gaze_stream = stream if stream['info']['name'][0] == 'ExperimentMarkers': if stream['time_series'][0][0] == '': continue markers = stream['time_series'] markersTime = stream['time_stamps'] extract_eye_data(eye_stream_dict, markers, markersTime, basePath) extract_gaze_position(gaze_stream, markers, markersTime, basePath)
def test_load_file(file): streams, header = load_xdf(file) if file.endswith("minimal.xdf"): assert header["info"]["version"][0] == "1.0" assert len(streams) == 2 assert streams[0]["info"]["name"][0] == "SendDataC" assert streams[0]["info"]["type"][0] == "EEG" assert streams[0]["info"]["channel_count"][0] == "3" assert streams[0]["info"]["nominal_srate"][0] == "10" assert streams[0]["info"]["channel_format"][0] == "int16" assert streams[0]["info"]["stream_id"] == 0 s = np.array([[192, 255, 238], [12, 22, 32], [13, 23, 33], [14, 24, 34], [15, 25, 35], [12, 22, 32], [13, 23, 33], [14, 24, 34], [15, 25, 35]], dtype=np.int16) t = np.array([5., 5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8]) np.testing.assert_array_equal(streams[0]["time_series"], s) np.testing.assert_array_almost_equal(streams[0]["time_stamps"], t) assert streams[1]["info"]["name"][0] == "SendDataString" assert streams[1]["info"]["type"][0] == "StringMarker" assert streams[1]["info"]["channel_count"][0] == "1" assert streams[1]["info"]["nominal_srate"][0] == "10" assert streams[1]["info"]["channel_format"][0] == "string" assert streams[1]["info"]["stream_id"] == 0x02C0FFEE s = [[ '<?xml version="1.0"?><info><writer>LabRecorder xdfwriter' '</writer><first_timestamp>5.1</first_timestamp><last_timestamp>' '5.9</last_timestamp><sample_count>9</sample_count>' '<clock_offsets><offset><time>50979.76</time><value>-.01</value>' '</offset><offset><time>50979.86</time><value>-.02</value>' '</offset></clock_offsets></info>' ], ['Hello'], ['World'], ['from'], ['LSL'], ['Hello'], ['World'], ['from'], ['LSL']] t = np.array([5.1, 5.2, 5.3, 5.4, 5.5, 5.6, 5.7, 5.8, 5.9]) assert streams[1]["time_series"] == s np.testing.assert_array_almost_equal(streams[1]["time_stamps"], t)
def Xdf_Load(path): logging.basicConfig( level=logging.DEBUG) # Use logging.INFO to reduce output. fname = path streams, fileheader = pyxdf.load_xdf(fname) print("Found {} streams:".format(len(streams))) for ix, stream in enumerate(streams): print( "Stream {}: {} - type {} - uid {} - shape {} at {} Hz (effective {} Hz)" .format(ix + 1, stream['info']['name'][0], stream['info']['type'][0], stream['info']['uid'][0], (int(stream['info']['channel_count'][0]), len(stream['time_stamps'])), stream['info']['nominal_srate'][0], stream['info']['effective_srate'])) if any(stream['time_stamps']): print("\tDuration: {} s".format(stream['time_stamps'][-1] - stream['time_stamps'][0])) print("Done.") return streams, fileheader
def XDFFile(filename: Union[Path, str]) -> Dict[str, XDFStream]: """load an :code:`xdf`-file and return a dictionary of its streams args ---- filename: the name of the xdffile returns ------- streams: Dict[str, XDFStream] a collection of all :class:`~.XDFStream` s in the file. These can be indexed by their respective name """ streams, _ = pyxdf.load_xdf(filename=str(filename)) collection: Dict[str, XDFStream] = dict() for stream in streams: print("Parsing ", stream["info"]["name"][0]) x = XDFStream(stream) collection[x.name] = x return collection
def replay(file_path, us_rate, repeat, verbose): """Replay .xdf file as LSL recording session Args: file_path: str path to .xdf file us_rate: int Sampling rate (Hz) to undersample original recording. If None it will keep the original sampling frequency repeat: int Number of times to repeat the recording verbose: bool Verbosity mode """ print("Attempting to load xdf data") streams, header = load_xdf(file_path, dejitter_timestamps=True, synchronize_clocks=True) first_timestamp = streams[0]["time_stamps"][0] threads = list() for stream in streams: if len(stream["time_stamps"]) < 1: continue if stream["time_stamps"][0] < first_timestamp: first_timestamp = stream["time_stamps"][0] for stream in streams: if len(stream["time_stamps"]) < 1: continue delay = stream["time_stamps"][0] - first_timestamp t = threading.Timer(0, lsl_stream, [stream, delay, us_rate, repeat, verbose]) t.daemon = True t.start() threads.append(t) while has_live_threads(threads): for t in threads: t.join(10)
Tester_age = 23 Tester_driverLicense = 0 Tester_sleepTime = 2407 Tester_testtime = 19 # 폴더 번호 설정 i = 0 # 데이터 저장 위치 Folder = r'C:\Users\ekdlw\Desktop\Bio Data Analysis\CSV_file' File_name = f'\\{Tester_sex}{Tester_age}{Tester_driverLicense}{Tester_sleepTime}{Tester_testtime}_{i}.csv' # 데이터 저장 시간 Cutting_time = Frame_rate * Data_Save_time data, header = pyxdf.load_xdf( r'C:\Users\ekdlw\Desktop\Bio Data Analysis\XDF_file\20101001.xdf') for stream in data: i = i + 1 y = stream['time_series'] x = stream['time_stamps'] df1 = pd.DataFrame(y) df2 = pd.DataFrame(x) df1 = pd.concat([df1, df2], axis=1) File_name = f'\\{Tester_sex}{Tester_age}{Tester_driverLicense}{Tester_sleepTime}{Tester_testtime}_{i}.csv' df1.to_csv(Folder + File_name, index=False, columns=False) if isinstance(y, list):
for f in dataPath.glob('*.xdf'): print(f) #Load xdf files if len(re.findall(".xdf", f.name)) > 0: file = f task = re.findall("(?<=T[0-9]{2}_).+(?=\.xdf)", file.name)[0] subject = re.findall(".+(?=_S[0-9]{1})", file.name)[0] session = int(re.findall("(?<=_S)[0-9]{1}(?=_T)", file.name)[0]) trial = int(re.findall("(?<=_T)[0-9]{2}(?=_)", file.name)[0]) dstPath1 = Path('./data-processed/' ) / "{:}_S{:d}_T{:d}_{:}_shimmer_ppg.txt".format( subject, session, trial, task) data, header = pyxdf.load_xdf(file) #Get data and experiment markers for stream in data: if stream['info']['name'][0] == 'ExperimentMarkers': markers = stream['time_series'] markersTime = stream['time_stamps'] elif stream['info']['name'][0] == 'Shimmer_ppg': if stream['footer']['info']['first_timestamp'][0] != '0': eegData = stream['time_series'] eegInfo = stream['info'] eegTime = stream['time_stamps'] # elif stream['info']['name'][0] == 'NB-2015.10.15': # if stream['footer']['info']['first_timestamp'][0] != '0': # eegData = stream['time_series'] # eegInfo = stream['info']
import os import matplotlib.pyplot as plt data_path = '../bci4als/data/noam/2' trial = 50 eeg_path = os.path.join(data_path, 'EEG.xdf') trials_path = os.path.join(data_path, 'EEG_trials.pickle') clean_path = os.path.join(data_path, 'EEG_clean.csv') ch_names = [ 'C03', 'C04', 'P07', 'P089', 'O01', 'O02', 'F07', 'F08', 'F03', 'F04', 'T07', 'T08', 'P03' ] s_rate = 125 trials = pickle.load(open(trials_path, 'rb')) trial_data = trials[trial].to_numpy() full_data = pyxdf.load_xdf(eeg_path, [{ 'type': 'EEG' }])[0][0]['time_series'][:, 3:] clean_data = np.genfromtxt(clean_path, delimiter=',', skip_header=1)[:, 1:] info = mne.create_info(ch_names, s_rate, verbose=False) raw_trial = mne.io.RawArray(trial_data.T, info, verbose=False) raw_full_data = mne.io.RawArray(full_data.T, info, verbose=False) raw_clean_data = mne.io.RawArray(clean_data.T, info, verbose=False) raw_trial.plot() # raw_trial.plot_psd(picks=ch_names) # fig_1 = raw_full_data.plot_psd(picks=ch_names) # fig_2 = raw_clean_data.plot_psd(picks=ch_names)
import numpy as np import pyxdf from matplotlib import pyplot as plt # File to test TEST_FILE = 'C:\\Recordings\\CurrentStudy\\exp4\\untitled.xdf' # Load it and get the channels data = pyxdf.load_xdf(TEST_FILE) channels = data[0][0]['info']['desc'][0]['channels'][0] # Get all the channel names channames = [] for channel in channels['channel']: print(channel) channames.append(channel['label'][0]) print(channames) # Get the channel for the Mindwave raw data in `rawEeg` raw_channel = "Fp1" chanind = [c for c, n in enumerate(channames) if n == raw_channel][0] print("rawEeg channel index: %s" % chanind) # Gather all the rawEeg data and plot it timeseries = data[0][0]['time_series'] raweeg = [] for row in timeseries: if np.isnan(row[chanind]): continue raweeg.append(row[chanind]) timestamps = data[0][0]['time_stamps']
'chans_excluded': [], 'segments_retained': [] } for d in dirs: print(f'subj {dirs.index(d)}') chdir(exdir + '/recordings') chdir(d) files = [f for f in listdir() if '.xdf' in f and not '.p' in f] #f = files[0] for f in files: print(f'file {files.index(f)}') dat = pyxdf.load_xdf(f, dejitter_timestamps=True, synchronize_clocks=True)[0] # """data structure e.g.: # 0 - marker # 1 - resp. belt # 2 - pupil 18-21 pupil size # 3 - EEG marker # 4 - EEG data # !!order is not consistent between datasets!!""" stream_indices = [dat[n]['info']['name'][0] for n in range(len(dat))] #% ECG # # extract ECG and R peaks try: pre_trial, stim_trial, post_trial, resp_times = segment_recording(
# Eric Larson <*****@*****.**> # # License: BSD-3-Clause # %% import os.path as op import pyxdf import mne from mne.datasets import misc fname = op.join(misc.data_path(), 'xdf', 'sub-P001_ses-S004_task-Default_run-001_eeg_a2.xdf') streams, header = pyxdf.load_xdf(fname) data = streams[0]["time_series"].T assert data.shape[0] == 5 # four raw EEG plus one stim channel data[:4:2] -= data[1:4:2] # subtract (rereference) to get two bipolar EEG data = data[::2] # subselect data[:2] *= (1e-6 / 50 / 2) # uV -> V and preamp gain sfreq = float(streams[0]["info"]["nominal_srate"][0]) info = mne.create_info(3, sfreq, ["eeg", "eeg", "stim"]) raw = mne.io.RawArray(data, info) raw.plot(scalings=dict(eeg=100e-6), duration=1, start=14) # %% # References # ---------- # .. footbibliography::
def read_raw_xdf(fname, stream_id, srate="effective", prefix_markers=False, *args, **kwargs): """Read XDF file. Parameters ---------- fname : str Name of the XDF file. stream_id : int ID (number) of the stream to load. srate : {"nominal", "effective"} Use either nominal or effective sampling rate. prefix_markers : bool Whether or not to prefix markers with their corresponding stream ID. Returns ------- raw : mne.io.Raw XDF file data. """ if srate not in ("nominal", "effective"): raise ValueError(f"The 'srate' parameter must be either 'nominal' or 'effective' " f"(got {srate}).") streams, _ = load_xdf(fname) for stream in streams: if stream["info"]["stream_id"] == stream_id: break # stream found else: # stream not found raise IOError(f"Stream ID {stream_id} not found.") if float(stream["info"]["nominal_srate"][0]) == 0: raise RuntimeError("Importing a marker stream is not supported, try importing a " "regularly sampled stream instead.") n_chans = int(stream["info"]["channel_count"][0]) fs = float(np.array(stream["info"][f"{srate}_srate"]).item()) labels, types, units = [], [], [] try: for ch in stream["info"]["desc"][0]["channels"][0]["channel"]: labels.append(str(ch["label"][0])) if ch["type"]: types.append(ch["type"][0]) units.append(ch["unit"][0] if ch["unit"] else "NA") except (TypeError, IndexError): # no channel labels found pass if not labels: labels = [str(n) for n in range(n_chans)] if not units: units = ["NA" for _ in range(n_chans)] info = mne.create_info(ch_names=labels, sfreq=fs, ch_types="eeg") # convert from microvolts to volts if necessary scale = np.array([1e-6 if u in ("microvolt", "microvolts") else 1 for u in units]) raw = mne.io.RawArray((stream["time_series"] * scale).T, info) raw._filenames = [fname] first_samp = stream["time_stamps"][0] markers = match_streaminfos(resolve_streams(fname), [{"type": "Markers"}]) for stream_id in markers: for stream in streams: if stream["info"]["stream_id"] == stream_id: break onsets = stream["time_stamps"] - first_samp prefix = f"{stream_id}-" if prefix_markers else "" descriptions = [f"{prefix}{item}" for sub in stream["time_series"] for item in sub] raw.annotations.append(onsets, [0] * len(onsets), descriptions) return raw
# -*- coding: utf-8 -*- import pyxdf # Open xdf files import matplotlib.pyplot as plt # used for plotting import numpy as np # Numeric library for python """## Open the singnals data The data recorded during the lab is in the xdf format. It is oppened with the pyxdf library, getting the data, and a header with metadata from the experiment. The data object contains one object for every stream recorded during the lab. In this case, threre are three streams: the biosignals, the markers for the biosignals (not used here) and the markers from psychopy. We visualize the signals and markers here: """ data, header = pyxdf.load_xdf('./analysis/raw/000.xdf') plt.figure(figsize=(30, 7)) # Read the biosignals from the first stream stream = data[0] y = stream['time_series'] fs = int(stream["info"]["nominal_srate"][0]) # Store sample frequency (fs) plt.plot(stream["time_stamps"], y) ecg, resp, gsr = np.split(y, [1, 2], axis=1) # Store three biosignals t = stream["time_stamps"] # Extract time array # Read the markers from the third stream stream = data[2] markers = {} # A variable to store the markers for marker, ts in zip(stream["time_series"], stream["time_stamps"]): plt.axvline(x=ts, c="red") markers[marker[0]] = ts plt.xlabel("Time (s)") plt.ylabel("Amplitude ($\mu$V)")
# Tristan Stenner # # License: BSD (2-clause) import os import logging import pyxdf import sys logging.basicConfig(level=logging.DEBUG) # Use logging.INFO to reduce output. if len(sys.argv) > 1: fname = sys.argv[1] else: fname = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', 'xdf_sample.xdf')) streams, fileheader = pyxdf.load_xdf(fname) print("Found {} streams:".format(len(streams))) for ix, stream in enumerate(streams): print("Stream {}: {} - type {} - uid {} - shape {} at {} Hz (effective {} Hz)".format( ix + 1, stream['info']['name'][0], stream['info']['type'][0], stream['info']['uid'][0], (int(stream['info']['channel_count'][0]), len(stream['time_stamps'])), stream['info']['nominal_srate'][0], stream['info']['effective_srate']) ) if any(stream['time_stamps']): print("\tDuration: {} s".format(stream['time_stamps'][-1] - stream['time_stamps'][0])) print("Done.")
import seaborn as sns sns.set(font_scale=1) import matplotlib.pyplot as plt from utils.utils import get_stream_names, extract_signal_stream from utils.utils import float_index_to_time_index, time_index_to_float_index from utils.utils import estimate_rate from utils.utils import pandas_to_mne print("Config LOADED") k_file = 0 raw_xdf_fname = Config.raw_files[k_file] streams, _ = load_xdf(raw_xdf_fname) stream_names = get_stream_names(streams) df_eeg_raw = extract_signal_stream(streams, 'Android_EEG_010026') df_presentation_events = extract_signal_stream(streams, 'Presentation_Markers') print("RAW EEG LOADED") eeg_columns = [ 'Fp1', 'Fp2', 'Fz', 'F7', 'F8', 'FC1', 'FC2', 'Cz', 'C3', 'C4', 'T7', 'T8', 'CPz', 'CP1', 'CP2', 'CP5', 'CP6', 'TP9', 'TP10', 'Pz', 'P3', 'P4', 'O1', 'O2' ] df_eeg_raw = float_index_to_time_index(df_eeg_raw) duration = (df_eeg_raw.index[-1] - df_eeg_raw.index[0]).total_seconds() / 60 rate = estimate_rate(df_eeg_raw)
def get_spec(fname): """ https://github.com/mne-tools/mne-python/blob/master/examples/time_frequency/plot_compute_raw_data_spectrum.py ================================================== Compute the power spectral density of raw data ================================================== This script shows how to compute the power spectral density (PSD) of measurements on a raw dataset. It also show the effect of applying SSP to the data to reduce ECG and EOG artifacts. """ # Authors: Alexandre Gramfort <*****@*****.**> # Martin Luessi <*****@*****.**> # Eric Larson <*****@*****.**> # License: BSD (3-clause) print(__doc__) ############################################################################### # Load data # --------- # # We'll load a sample MEG dataset, along with SSP projections that will # allow us to reduce EOG and ECG artifacts. For more information about # reducing artifacts, see the preprocessing section in :ref:`documentation`. ## follow https://mne.tools/mne-bids/stable/auto_examples/read_bids_datasets.html streams, fileheader = pyxdf.load_xdf(fname) for stream in streams: if stream['info']['name'] == ['Delsys']: emg = stream print('Delsys found') fmin, fmax = 1, 50 # look at frequencies between 1 and 50 Hz n_fft = 1024 # the FFT size (n_fft). Ideally a power of 2 tmin, tmax = 60 * 1, 60 * 3 # use the first 60s of data ############################################################################### # Plot a cleaned PSD # ------------------ # # Next we'll focus the visualization on a subset of channels. # This can be useful for identifying particularly noisy channels or # investigating how the power spectrum changes across channels. # # We'll visualize how this PSD changes after applying some standard # filtering techniques. We'll first apply the SSP projections, which is # accomplished with the ``proj=True`` kwarg. We'll then perform a notch filter # to remove particular frequency bands. # And now do the same with SSP + notch filtering # Pick all channels for notch since the SSP projection mixes channels together spectra, freqs = mne.time_frequency.psd_welch(emg['time_series'], fmin=fmin, fmax=fmax, tmin=tmin, tmax=tmax, n_overlap=150, n_fft=n_fft, average='mean') spectra = spectra.mean(axis=0) return spectra, freqs
Tester_driverLicense = 0 Tester_sleepTime = 2407 Tester_testtime = 19 # 폴더 번호 설정 i = 0 # 데이터 저장 위치 Folder = 'C:\\Users\\ekdlw\\Desktop\\TEST\\Bio' File_name = f'\\{Tester_sex}{Tester_age}{Tester_driverLicense}{Tester_sleepTime}{Tester_testtime}_{i}.csv' # 데이터 저장 시간 Cutting_time = Frame_rate * Data_Save_time data, header = pyxdf.load_xdf( 'C:\\Users\\ekdlw\\Desktop\\TEST\\Bio\\sub-P002\\ses-S001\\eeg\\sub-P002_ses-S001_task-Default_run-001_eeg.xdf' ) for stream in data: i = i + 1 y = stream['time_series'] x = stream['time_stamps'] df1 = pd.DataFrame(y) df2 = pd.DataFrame(x) df1 = pd.concat([df1, df2], axis=1) File_name = f'\\{Tester_sex}{Tester_age}{Tester_driverLicense}{Tester_sleepTime}{Tester_testtime}_{i}.csv' df1.to_csv(Folder + File_name)
def pupil_rebuild_video(xdf_file: str, draw_gaze: bool = True) -> None: """ Rebuilds the Pupil world video from the given XDF file (if the file contains data from the Pupil Capture LSL relay). @param xdf_file: Path to the XDF file. @param draw_gaze: Whether to draw marker for gaze data (if gaze data is available). Defaults to True. """ g = GAZE_CIRCLE_RADIUS xdf_dir = os.path.dirname(xdf_file) data, header = pyxdf.load_xdf(xdf_file) # Loading video stream for stream in data: if stream['info']['name'][0] == 'pupil_capture_video': frames = stream['time_series'] frames_ts = stream['time_stamps'] video_path = stream['info']['desc'][0]['video_path'][0] fps = ((frames[-1] - frames[0]) / (frames_ts[-1] - frames_ts[0])).flat[0] break else: raise Exception("No Pupil video found in XDF data file") if draw_gaze: # Loading gaze stream for stream in data: if stream['info']['name'][0] == 'pupil_capture' and stream['info']['type'][0] == 'Gaze': gazes = stream['time_series'] gazes_ts = stream['time_stamps'] break else: raise Exception("No Pupil Gaze data found in XDF data file to draw gaze overlay") input_fn = os.path.join(xdf_dir, "inputs.txt") output_fn = os.path.join(xdf_dir, "pupil_scene_video.mp4") # Writing concat file for FFmpeg with open(input_fn, "w+") as f: for frame, timestamp in zip(frames, frames_ts): base_fp = os.path.join(video_path, str(frame.flat[0])) fp = base_fp + ".jpg" if draw_gaze: # Finding closest gaze data to frame idx = (np.abs(gazes_ts - timestamp)).argmin() gaze = gazes[idx].flat # Get its gaze coords norm_x, norm_y = gaze[1], gaze[2] img = Image.open(fp) w, h = img.size # Scale coords to image x = norm_x * w y = (1 - norm_y) * h # Draw circle draw = ImageDraw.Draw(img) gaze_box = (x - g, y - g, x + g, y + g) draw.ellipse(gaze_box, outline='red', width=GAZE_CIRCLE_WIDTH) # Save new image fp = base_fp + "_gaze.jpg" img.save(fp) # FFmpeg wants forward slashes fp = fp.replace('\\', '/') f.write(f"file '{fp}'\n") ( ffmpeg .input(input_fn, format='concat', safe=0) .filter('fps', fps=fps, round='up') .output(output_fn, vcodec="mjpeg", **{'q:v': '2'}) .overwrite_output() .run() ) os.remove(input_fn)
import pandas as pd import numpy as np import pyxdf import cv2 if __name__ == '__main__': df = pd.read_csv('./UI08-T1-video_left_color_ts.txt', sep=',') df['ts'] = df['ts'] / 1e9 data, header = pyxdf.load_xdf('./EX1U08_S01_T01_pegNormal_raw.xdf') # Get data and experiment markers for stream in data: if stream['info']['name'][0] == 'ExperimentMarkers': markers = stream['time_series'] markersTime = stream['time_stamps'] elif stream['info']['name'][0] == 'NB-2015.10.15' or stream['info'][ 'name'][0] == 'NB-2015.10.16': if stream['footer']['info']['first_timestamp'][0] != '0': eegData = stream['time_series'] eegInfo = stream['info'] eegTime = stream['time_stamps'] start_time = float(markers[0][1]) end_time = float(markers[1][1]) df = df.loc[(df['ts'] > start_time) & (df['ts'] < end_time)] x = 0 start_frame = df['idx'].values[0] end_frame = df['idx'].values[-1]
def __init__(self, file, min_chunk_size=4): Node.__init__(self, None) filename, self._file_extension = os.path.splitext(file) self._events = [] if self._file_extension in ['.gdf', '.set', '.vhdr']: if self._file_extension == '.gdf': self._raw = read_raw_gdf(file) elif self._file_extension == '.set': self._raw = read_raw_eeglab(file) elif self._file_extension == '.vhdr': self._raw = read_raw_brainvision(file) self._sampling_frequency = self._raw.info['sfreq'] self._channels = self._raw.info.ch_names try: # to test events = find_events(self._raw) logging.debug('Get from find_events') except ValueError: events = events_from_annotations(self._raw) logging.debug('Get from events_from_annotations') nb_to_event = {events[1][key]: key for key in events[1]} for h in events[0]: try: value = float(nb_to_event[h[2]]) except ValueError: value = nb_to_event[h[2]] self._events.append((h[0] / 1000, value)) self._end_record = self._raw.times[-1] self._start_record = self._raw.times[0] elif self._file_extension == '.xdf': streams, header = pyxdf.load_xdf(file, synchronize_clocks=False, verbose=False) logging.info(f'Found {len(streams)} streams in xdf file') for ix, stream in enumerate(streams): sampling_frequency = float(stream['info']['nominal_srate'][0]) if sampling_frequency == 0: logging.debug(f'Get marker from stream {ix}') for timestamp, event in zip(stream['time_stamps'], stream['time_series']): self._events.append((timestamp, float(event))) else: logging.debug(f'Get data from stream {ix}') self._sampling_frequency = sampling_frequency nb_chan = int(stream['info']['channel_count'][0]) self._channels = [(stream['info']['desc'][0]['channels'][0] ['channel'][i]['label'][0]) for i in range(nb_chan)] self._df = pd.DataFrame(stream['time_series'], stream['time_stamps'], self._channels) self._start_record = stream['time_stamps'][0] self._end_record = stream['time_stamps'][-1] self.marker_output = Port() self.marker_output.set_parameters(data_type='marker', channels=['marker'], sampling_frequency=0, meta='') self.output.set_parameters(data_type='signal', channels=self._channels, sampling_frequency=self._sampling_frequency, meta='') Node.log_instance( self, { 'marquers output': self.marker_output.id, 'sampling frequency': self._sampling_frequency, 'channels': self._channels, 'min chunk size': min_chunk_size, 'from file': file }) self._last_t = None self._min_period = min_chunk_size / self._sampling_frequency self._start_time = None self._flag = True