Beispiel #1
0
	def __init__(self, sj_initial, base_directory, file_aliases, low_pass_pupil_f = 6, high_pass_pupil_f = 0.01):
		super(Pupil_SSVEP_Analyzer, self).__init__()

		self.sj_initial = sj_initial
		self.file_aliases = file_aliases
		self.base_directory = base_directory
		self.low_pass_pupil_f = low_pass_pupil_f
		self.high_pass_pupil_f = high_pass_pupil_f

		self.sj_dir = os.path.join(self.base_directory, self.sj_initial )
		self.fig_dir = os.path.join(self.base_directory, self.sj_initial, 'figs' )
		self.edf_files = [os.path.join(self.base_directory, 'raw', fa + '.edf') for fa in self.file_aliases]
		self.h5_file = os.path.join(self.base_directory, self.sj_initial, self.sj_initial + '.h5')


		try: 	os.mkdir(self.sj_dir)
		except OSError:		pass
		try: 	os.mkdir(self.fig_dir)
		except OSError:		pass

		os.chdir(self.base_directory)

		# initialize the hdfeyeoperator
		self.ho = HDFEyeOperator(self.h5_file)
		# insert the edf file contents only when the h5 is not present.
		if not os.path.isfile(self.h5_file):
			self.preprocess()
Beispiel #2
0
def convert_hdf_eye_to_tsv(hdf5_file,
                           tsv_file=None,
                           xy_intercepts=None,
                           xy_slopes=None):

    from hedfpy import HDFEyeOperator
    import tempfile
    import os
    import os.path as op
    import numpy as np

    tr_key = 116.0
    alias = op.splitext(op.split(hdf5_file)[-1])[0]

    ho = HDFEyeOperator(hdf5_file)
    ho.open_hdf_file('a')
    node = ho.h5f.get_node('/' + alias)
    trial_data = node.trials.read()
    events = node.events.read()

    if tsv_file == None:
        tempdir = tempfile.mkdtemp()
        temp_tsv = op.join(tempdir, alias + '.tsv')
    else:
        temp_tsv = tsv_file

    # find first TR, and use it to define:
    # the duration of the datastream and the tr
    tr_timestamps = events['EL_timestamp'][(events['key'] == tr_key)
                                           & (events['up_down'] == 'Down')]
    tr = np.round(np.mean(np.diff(tr_timestamps)))

    eye = ho.eye_during_trial(0, alias)
    sample_rate = ho.sample_rate_during_period(
        [tr_timestamps[0], tr_timestamps[-1] + tr], alias)

    raw_data = ho.data_from_time_period(
        [tr_timestamps[0], tr_timestamps[-1] + tr], alias)
    selected_data = np.array(
        raw_data[['time', eye + '_gaze_x', eye + '_gaze_y', eye + '_pupil']])

    # some post-processing:
    # time in seconds, from first TR
    selected_data[:, 0] -= selected_data[0, 0]
    selected_data[:, 0] /= 1000.0  # convert ms to s
    # linear gaze position scaling
    if (xy_intercepts != None) and (xy_slopes != None):
        for i in [1, 2]:
            selected_data[:, i] = (selected_data[:, i] *
                                   xy_slopes[i - 1]) + xy_intercepts[i - 1]

    np.savetxt(temp_tsv,
               selected_data,
               fmt='%3.3f',
               delimiter='\t',
               header="time   X   Y   pupil")
    os.system('gzip ' + temp_tsv)

    ho.h5f.close()
    return temp_tsv + '.gz'
Beispiel #3
0
def convert_edf_2_hdf5(edf_file, low_pass_pupil_f=6.0, high_pass_pupil_f=0.01):
    """converts the edf_file to hdf5 using hedfpy
    
    Requires hedfpy

    Parameters
    ----------
    edf_file : str
        absolute path to edf file.
    low_pass_pupil_f : float
        low pass cutoff frequency for band-pass filtering of the pupil signal
    high_pass_pupil_f : float
        high pass cutoff frequency for band-pass filtering of the pupil signal
    Returns
    -------
    hdf5_file : str
        absolute path to hdf5 file.
    """

    import os
    import os.path as op
    from hedfpy import HDFEyeOperator
    import tempfile

    tempdir = tempfile.mkdtemp()
    temp_edf = op.join(tempdir, op.split(edf_file)[-1])

    os.system('cp ' + edf_file + ' ' + temp_edf)

    hdf5_file = op.join(tempdir,
                        op.split(op.splitext(edf_file)[0] + '.h5')[-1])
    alias = op.splitext(op.split(edf_file)[-1])[0]

    ho = HDFEyeOperator(hdf5_file)
    ho.add_edf_file(temp_edf)
    ho.edf_message_data_to_hdf(alias=alias)
    ho.edf_gaze_data_to_hdf(alias=alias,
                            pupil_hp=high_pass_pupil_f,
                            pupil_lp=low_pass_pupil_f)

    return hdf5_file
Beispiel #4
0
def fit_FIR_pupil_files(experiment,
                        eye_h5_file_list='',
                        behavior_file_list='',
                        h5_file='',
                        in_files='',
                        fir_frequency=20,
                        fir_interval=[-2.0, 6.0],
                        data_type='_pupil_bp_zscore',
                        lost_signal_rate_threshold=0.05,
                        method='fir'):
    """Performs a per-slice FIR deconvolution on nifti-files in_files, 
    with per-slice regressors from slice_regressor_list of nifti files,
    and per-TR regressors from vol_regressors text file.
    Uses standard HRF and its time-derivative.
    Assumes slices to be the last spatial dimension of nifti files,
    and time to be the last.

    Parameters
    ----------
    in_file : str
        Absolute path to nifti-file.
    slice_regressor_list : list
        list of absolute paths to per-slice regressor nifti files
    vol_regressor_list : str
        absolute path to per-TR regressor text file

    Returns
    -------
    res_file : str
        Absolute path to nifti-file containing residuals after regression.
    rsq_file : str
        Absolute path to nifti-file containing rsq of regression.
    beta_file : str
        Absolute path to nifti-file containing betas from regression.

    """

    import nibabel as nib
    import numpy as np
    import numpy.linalg as LA
    import scipy as sp
    import os
    import os.path as op
    import pandas as pd
    from spynoza.nodes.utils import get_scaninfo
    from fir import FIRDeconvolution
    from hedfpy import HDFEyeOperator
    import tempfile
    import bottleneck as bn
    # from behavior import behavior_timing

    # constants
    tr_key = 116.0
    zero_interval = [-0.75, -0.25]

    if len(eye_h5_file_list) == 0:
        print 'pupil FIR of experiment {} not performed for lack of input files'.format(
            experiment)
        # return

    # the first file is longer in one or two subjects, so we take the scaninfo of the second file
    TR, dims, dyns, voxsize, affine = get_scaninfo(in_files[1])

    # behavior
    event_names, all_behav_event_times, rename_dict, which_event_name_rewarded = behavior_timing(
        experiment, behavior_file_list, dyns, TR)

    # pupil data
    aliases = [
        'eye/' + op.splitext(op.split(eye_h5_file)[-1])[0]
        for eye_h5_file in eye_h5_file_list
    ]

    ho = HDFEyeOperator(h5_file)

    pupil_data = []

    for x, alias in enumerate(aliases):
        ho.open_hdf_file('a')
        node = ho.h5f.get_node('/' + alias)
        trial_data = node.trials.read()
        events = node.events.read()
        ho.h5f.close()

        # find first TR, and use it to define:
        # the duration of the datastream and the tr
        tr_timestamps = events['EL_timestamp'][
            (events['key'] == tr_key) & (events['up_down'] == 'Down')][:dyns]

        eye = ho.eye_during_trial(0, alias)
        sample_rate = ho.sample_rate_during_period(
            [tr_timestamps[0], tr_timestamps[-1] + TR], alias)

        raw_data = ho.data_from_time_period(
            [tr_timestamps[0], tr_timestamps[0] + (1000.0 * dyns * TR)], alias)
        selected_data = np.array(raw_data[eye + data_type])

        # bad recordings are characterized, among other things, by a very high amount of lost samples.
        # if this lost sample rate crosses a threshold, we will throw the file out completely
        raw_pupil = np.array(raw_data[eye + '_pupil'])
        lost_signal_rate = (raw_pupil == 0).sum() / (dyns * TR * sample_rate)
        run_signal = np.zeros((sample_rate * dyns * TR))
        if lost_signal_rate > lost_signal_rate_threshold:
            print 'dropping this run, lost signal rate = %1.3f' % lost_signal_rate
        else:
            run_signal[:selected_data.shape[0]] = selected_data

        pupil_data.append(run_signal)
    pupil_data = np.concatenate(pupil_data)

    if method == 'fir':
        fd = FIRDeconvolution(
            signal=pupil_data[::(
                sample_rate /
                fir_frequency)],  # downsampled when used as argument
            events=[all_behav_event_times[en]
                    for en in event_names],  # dictate order
            event_names=event_names,
            sample_frequency=fir_frequency,
            deconvolution_frequency=fir_frequency,
            deconvolution_interval=fir_interval)

        # fd.resampled_signal = np.nan_to_num(fd.resampled_signal)
        fd.create_design_matrix()
        fd.regress(method='lstsq')
        fd.calculate_rsq()
        # convert to data that can be plotted
        fir_time_course_dict = {en: fd.betas_for_cov(en) for en in event_names}
        deconvolution_interval_timepoints = fd.deconvolution_interval_timepoints

    elif method == 'era':
        deconvolution_interval_timepoints = np.arange(fir_interval[0],
                                                      fir_interval[1],
                                                      1.0 / sample_rate)
        zero_interval_bools = (
            deconvolution_interval_timepoints > zero_interval[0]) & (
                deconvolution_interval_timepoints < zero_interval[1])
        sample_times = np.arange(0, pupil_data.shape[0] / sample_rate,
                                 1.0 / sample_rate)
        fir_time_course_dict = {}
        for en in event_names:
            event_times = all_behav_event_times[en]
            epoched_data = np.zeros(
                (len(event_times), len(deconvolution_interval_timepoints)))
            for i, et in enumerate(event_times):
                if (et + fir_interval[0]) < sample_times[-1]:
                    epoch_start_index = np.arange(
                        len(sample_times))[sample_times > (et +
                                                           fir_interval[0])][0]
                    epoch_end_index = np.min([
                        epoch_start_index +
                        len(deconvolution_interval_timepoints),
                        len(sample_times)
                    ])
                    epoched_data[i, 0:epoch_end_index -
                                 epoch_start_index] = pupil_data[
                                     epoch_start_index:epoch_end_index]

            epoched_data_zerod = (
                epoched_data.T -
                bn.nanmedian(epoched_data[:, zero_interval_bools], axis=1)).T
            fir_time_course_dict.update(
                {en: bn.nanmedian(epoched_data, axis=0)})

    if experiment == 'unpredictable':
        out_figures = [
            plot_fir_results_unpredictable(deconvolution_interval_timepoints,
                                           event_names,
                                           fir_time_course_dict,
                                           zero_interval=zero_interval,
                                           use_zero_interval=True,
                                           suffix='pupil'),
            plot_fir_results_unpredictable(deconvolution_interval_timepoints,
                                           event_names,
                                           fir_time_course_dict,
                                           zero_interval=zero_interval,
                                           use_zero_interval=False,
                                           suffix='pupil')
        ]
    elif experiment == 'predictable':
        out_figures = [
            plot_fir_results_predictable(deconvolution_interval_timepoints,
                                         rename_dict,
                                         event_names,
                                         fir_time_course_dict,
                                         zero_interval=zero_interval,
                                         use_zero_interval=True,
                                         suffix='pupil'),
            plot_fir_results_predictable(deconvolution_interval_timepoints,
                                         rename_dict,
                                         event_names,
                                         fir_time_course_dict,
                                         zero_interval=zero_interval,
                                         use_zero_interval=False,
                                         suffix='pupil')
        ]
    elif experiment == 'variable':
        out_figures = [
            plot_fir_results_variable(deconvolution_interval_timepoints,
                                      event_names,
                                      fir_time_course_dict,
                                      zero_interval=zero_interval,
                                      use_zero_interval=True,
                                      suffix='pupil'),
            plot_fir_results_variable(deconvolution_interval_timepoints,
                                      event_names,
                                      fir_time_course_dict,
                                      zero_interval=zero_interval,
                                      use_zero_interval=False,
                                      suffix='pupil')
        ]

    # the derived data types are added in the plot functions, and overwritten such that the no-zero'd data are saved
    out_values = np.array([
        np.squeeze(fir_time_course_dict[key])
        for key in fir_time_course_dict.iterkeys()
    ]).T
    out_columns = [key for key in fir_time_course_dict.iterkeys()]

    out_df = pd.DataFrame(out_values,
                          columns=out_columns,
                          index=deconvolution_interval_timepoints)

    store = pd.HDFStore(h5_file)
    store['/pupil/' + experiment] = out_df
    store.close()

    return out_figures
Beispiel #5
0
class Pupil_SSVEP_Analyzer(object):
	"""Pupil_SSVEP_Analyzer is a class that analyzes the results of a pupil size SSVEP experiment"""
	def __init__(self, sj_initial, base_directory, file_aliases, low_pass_pupil_f = 6, high_pass_pupil_f = 0.01):
		super(Pupil_SSVEP_Analyzer, self).__init__()

		self.sj_initial = sj_initial
		self.file_aliases = file_aliases
		self.base_directory = base_directory
		self.low_pass_pupil_f = low_pass_pupil_f
		self.high_pass_pupil_f = high_pass_pupil_f

		self.sj_dir = os.path.join(self.base_directory, self.sj_initial )
		self.fig_dir = os.path.join(self.base_directory, self.sj_initial, 'figs' )
		self.edf_files = [os.path.join(self.base_directory, 'raw', fa + '.edf') for fa in self.file_aliases]
		self.h5_file = os.path.join(self.base_directory, self.sj_initial, self.sj_initial + '.h5')


		try: 	os.mkdir(self.sj_dir)
		except OSError:		pass
		try: 	os.mkdir(self.fig_dir)
		except OSError:		pass

		os.chdir(self.base_directory)

		# initialize the hdfeyeoperator
		self.ho = HDFEyeOperator(self.h5_file)
		# insert the edf file contents only when the h5 is not present.
		if not os.path.isfile(self.h5_file):
			self.preprocess()

	def preprocess(self):
		# implicit preprocessing
		for i, ef in enumerate(self.edf_files):
			self.ho.add_edf_file(ef)
			self.ho.edf_message_data_to_hdf(alias = self.file_aliases[i])
			self.ho.edf_gaze_data_to_hdf(alias = self.file_aliases[i], pupil_hp = self.high_pass_pupil_f, pupil_lp = self.low_pass_pupil_f)

	def analyze(self, nr_cycles_tf = 12.0):
		for alias in self.file_aliases:
			pss = Pupil_SSVEP_Session(self, alias)
			# pss.raw_signal_plot()
			# pss.tf_analysis(nr_cycles = nr_cycles_tf)
			# pss.behavioral_analysis()
			pss.project_phases()
			pss.svm_classification()

	def analyze_tf(self, nr_cycles_tf = [40,20,12,8,4,2]):
		for alias in self.file_aliases:
			for nc_tf in nr_cycles_tf:
				pss = Pupil_SSVEP_Session(self, alias)
				pss.tf_analysis(nr_cycles = nc_tf)

	def get_experimental_phase(self, freqs_of_interest = [1.8, 2.2]):
		which_alias_reported_replay = [fa for fa in self.file_aliases if '_RP' in fa][0]

		with pd.get_store(self.h5_file) as h5_file: 
			replay_report_real = h5_file.get("/%s/tf/cycles_%s_%s"%(which_alias_reported_replay, 20, 'tf_complex_real'))
			replay_report_imag = h5_file.get("/%s/tf/cycles_%s_%s"%(which_alias_reported_replay, 20, 'tf_complex_imag'))

		frequencies = np.array(replay_report_real.major_axis)
		replay_report_real_m = np.array(replay_report_real, dtype = np.complex)[:,(frequencies>freqs_of_interest[0]) & (frequencies<freqs_of_interest[1]),:].mean(axis = 1)
		replay_report_imag_m = np.array(replay_report_imag)[:,(frequencies>freqs_of_interest[0]) & (frequencies<freqs_of_interest[1]),:].mean(axis = 1)

		replay_data = np.zeros(replay_report_real_m.shape, dtype = np.complex)
		replay_data.real = replay_report_real_m
		replay_data.imag = replay_report_imag_m

		angle_mean = np.angle(replay_data.mean(axis = 0).reshape([-1,100]).mean(axis = 0))
		real_mean = np.real(replay_data.mean(axis = 0).reshape([-1,100]).mean(axis = 0))
		imag_mean = np.imag(replay_data.mean(axis = 0).reshape([-1,100]).mean(axis = 0))

		distance_per_phase_real = np.array([(np.cos(np.linspace(0,4*np.pi,100, endpoint = False) + phase) - real_mean).max() for phase in np.linspace(0,2*np.pi,1000)])
		distance_per_phase_imag = np.array([(np.sin(np.linspace(0,4*np.pi,100, endpoint = False) + phase) - imag_mean).max() for phase in np.linspace(0,2*np.pi,1000)])
		phase_lag_real, phase_lag_imag = (np.linspace(0,2*np.pi,1000)[x] for x in (np.argmin(distance_per_phase_real), np.argmin(distance_per_phase_imag)))

		f = pl.figure()

		s = f.add_subplot(211)
		pl.plot(angle_mean, label = 'phase')
		pl.plot(real_mean, label = 'real')
		pl.plot(imag_mean, label = 'imag')

		pl.plot(np.arange(100),np.sin(np.linspace(0,4*np.pi,100, endpoint = False)), 'k--', label = 'sin')
		pl.plot(np.arange(100),np.cos(np.linspace(0,4*np.pi,100, endpoint = False)), 'k:', label = 'cos')
		pl.legend()

		s = f.add_subplot(212)

		pl.plot(np.linspace(0,2*np.pi,1000), distance_per_phase_real, 'k:', label = 'real')
		pl.plot(np.linspace(0,2*np.pi,1000), distance_per_phase_imag, 'k--', label = 'imag')
		s.axvline(phase_lag_real, color = 'r', lw = 2.0)
		s.axvline(phase_lag_imag, color = 'g', lw = 2.0)

		s.annotate('%0.3f'%phase_lag_imag, (0.5,0.3), textcoords = 'figure fraction')

		pl.legend()
		sn.despine(offset=10)
		pl.tight_layout()
		pl.savefig(os.path.join(self.fig_dir, 'phase_delay.pdf'))

		np.savetxt(os.path.join(self.sj_dir, 'phase_delay.txt'), np.array([phase_lag_real, np.degrees(phase_lag_real)]), delimiter = '\t', fmt = '%3.4f')

	def svm_decode(self, smoothing_widths = [0, 50, 100, 150, 200, 250, 300, 400, 500, 1000]):
		results = {}
		# train_alias = self.file_aliases[0]
		train_alias = [fa for fa in self.file_aliases if fa.split('_')[-1] == 'RP'][-1]

		# test_alias = [fa for fa in self.file_aliases if fa.split('_')[-1] == 'NR'][-1]
		test_alias = self.file_aliases[0]
		# shell()
		
		print 'train on ' + train_alias

		pss_train = Pupil_SSVEP_Session(self, train_alias)
		results.update({train_alias: pss_train.svm_classification()})

		print 'test on ' + test_alias

		pss_test = Pupil_SSVEP_Session(self, test_alias)
		pss_test.read_trans_counts()
		results.update({test_alias: pss_test.svm_classification()})

		replay_to_riv_prediction = results[train_alias][0].predict_proba(results[test_alias][1])

		rtr_ptr = replay_to_riv_prediction[:,0].reshape((8,-1))
		rtr_ptr_S = np.array([ndimage.gaussian_filter1d(rtr_ptr, sm, axis = -1, mode = 'constant', cval = 0.5) for sm in smoothing_widths])# 1 s smoothing width

		total_ratio_threshold = np.percentile(replay_to_riv_prediction, 100*pss_train.ratio_percept_red, interpolation = 'linear')
		total_duration_ratio_threshold = np.percentile(replay_to_riv_prediction, 100*pss_train.ratio_percept_red_durations[1], interpolation = 'linear')

		# plot these timecourses per trial
		f = pl.figure(figsize = (8,24))
		for x in range(len(rtr_ptr)):
			s = f.add_subplot(len(rtr_ptr), 1, x+1)
			pl.plot(np.linspace(0,pss_test.trial_duration,rtr_ptr.shape[-1]), rtr_ptr[x], 'k', lw = 2.0)
			for sm in range(rtr_ptr_S.shape[0]):
				pl.plot(np.linspace(0,pss_test.trial_duration,rtr_ptr.shape[-1]), rtr_ptr_S[sm,x], 'b--', lw = 2.0, alpha = 0.25 + 0.75 * (sm / rtr_ptr_S.shape[0]), label = '%i'%smoothing_widths[sm])
			s.axhline(total_ratio_threshold, color = 'g', ls = '--', lw = 2.0)
			s.axhline(total_duration_ratio_threshold, color = 'r', lw = 2.0, ls = '--', alpha = 0.6)
			if hasattr(pss_test, 'trans_counts'):
				s.annotate('%i'%pss_test.trans_counts[x], (0.05,0.1), textcoords = 'axes fraction', fontsize = 18)
			s.set_ylim([-0.2,1.1])
			pl.legend(fontsize = 8, ncol = len(rtr_ptr_S), loc = (0.0,-0.15))
			sn.despine(offset=10)
		pl.tight_layout()
		pl.savefig(os.path.join(self.fig_dir, self.sj_initial + '_svm_raw_%s_%s.pdf'%(train_alias, test_alias)))


		f = pl.figure(figsize = (8,24))
		for x in range(len(rtr_ptr)):
			s = f.add_subplot(len(rtr_ptr), 1, x+1)
			pl.imshow(rtr_ptr_S[:,x], cmap = 'seismic', extent = [0, pss_test.trial_duration, smoothing_widths[-1], smoothing_widths[0]], aspect='auto')
			if hasattr(pss_test, 'trans_counts'):
				s.annotate('%i'%pss_test.trans_counts[x], (0.05,0.1), textcoords = 'axes fraction', fontsize = 18)
			s.set_yticks([0, len(smoothing_widths)-1])
			s.set_yticklabels([smoothing_widths[0], smoothing_widths[0]])
			sn.despine(offset=10)
		pl.tight_layout()
		pl.savefig(os.path.join(self.fig_dir, self.sj_initial + '_svm_imshow_%s_%s.pdf'%(train_alias, test_alias)))
Beispiel #6
0
def convert_streamup_trials_to_tsv(hdf5_file,
                                   tsv_file=None,
                                   reward_signal=1.0):

    from hedfpy import HDFEyeOperator
    import tempfile
    import os
    import os.path as op
    import numpy as np
    import pandas as pd

    tr_key = 116.0

    alias = op.splitext(op.split(hdf5_file)[-1])[0]

    ho = HDFEyeOperator(hdf5_file)
    ho.open_hdf_file('a')
    node = ho.h5f.get_node('/' + alias)
    trial_phase_data = node.trial_phases.read()
    events = node.events.read()
    parameters = node.parameters.read()

    if tsv_file == None:
        tempdir = tempfile.mkdtemp()
        temp_tsv = op.join(tempdir, alias.replace('eye', 'trials') + '.tsv')
    else:
        temp_tsv = tsv_file

    # find first TR, and use it to define:
    # the duration of the datastream and the tr
    tr_timestamps = events['EL_timestamp'][(events['key'] == tr_key)
                                           & (events['up_down'] == 'Down')]
    tr = np.round(np.mean(np.diff(tr_timestamps)))
    sample_rate = ho.sample_rate_during_period(
        [tr_timestamps[0], tr_timestamps[-1] + tr], alias)

    run_onset_EL_time = tr_timestamps[0]

    columns_df = [
        'sound', 'contrast', 'stim_eccentricity', 'orientation', 'mask_radius'
    ]
    tp_value = 2.0

    trial_phase_timestamps = np.array(
        trial_phase_data[trial_phase_data['trial_phase_index'] ==
                         tp_value]['trial_phase_EL_timestamp'])

    trial_parameters = pd.DataFrame(parameters[columns_df].T)

    # first, we re-code the parameters in terms of screen coordinates
    # convert stim position from proportion of screen (1920, 124 cm distance on BoldScreen32) to dva
    trial_parameters['stim_eccentricity'] = trial_parameters[
        'stim_eccentricity'] * 11  # 11 degrees from fix to edge of screen
    trial_parameters['mask_radius'] = trial_parameters[
        'mask_radius'] * 22 / 1920  # 11 degrees from fix to edge of screen

    # add the times at which stimuli and rewards were presented
    which_trials_reward = (np.array(trial_parameters['sound']) %
                           2).astype(bool)
    reward_times = np.zeros(len(trial_phase_timestamps))
    # the sound was 800 ms delayed wrt the stimulus onset
    reward_times[which_trials_reward] = \
                (800.0 + trial_phase_timestamps[which_trials_reward] - tr_timestamps[0] ) / 1000.0

    trial_parameters['reward_time'] = pd.Series(reward_times)
    trial_parameters['stim_onset_time'] = pd.Series(
        (trial_phase_timestamps - tr_timestamps[0]) / 1000.0)

    trial_parameters = trial_parameters.sort_values(by='stim_onset_time')

    trial_parameters.to_csv(temp_tsv,
                            sep='\t',
                            float_format='%3.2f',
                            header=True,
                            index=False)

    return temp_tsv
Beispiel #7
0
def convert_variable_trials_to_tsv(hdf5_file, tsv_file=None):

    from hedfpy import HDFEyeOperator
    import tempfile
    import os
    import os.path as op
    import numpy as np
    import pandas as pd
    import math

    tr_key = 116.0

    alias = op.splitext(op.split(hdf5_file)[-1])[0]

    ho = HDFEyeOperator(hdf5_file)
    ho.open_hdf_file('a')
    node = ho.h5f.get_node('/' + alias)
    trial_phase_data = node.trial_phases.read()
    events = node.events.read()
    parameters = node.parameters.read()

    if tsv_file == None:
        tempdir = tempfile.mkdtemp()
        temp_tsv = op.join(tempdir, alias.replace('eye', 'trials') + '.tsv')
    else:
        temp_tsv = tsv_file

    # find first TR, and use it to define:
    # the duration of the datastream and the tr
    tr_timestamps = events['EL_timestamp'][(events['key'] == tr_key)
                                           & (events['up_down'] == 'Down')]
    tr = np.round(np.mean(np.diff(tr_timestamps)))
    sample_rate = ho.sample_rate_during_period(
        [tr_timestamps[0], tr_timestamps[-1] + tr], alias)

    run_onset_EL_time = tr_timestamps[0]

    columns_df = [
        'sound', 'contrast', 'stim_eccentricity', 'stim_orientation',
        'mask_radius', 'reward_delay', 'which_stimulus_for_rgb_overlay'
    ]
    tp_value = 2.0

    trial_phase_timestamps = np.array(
        trial_phase_data[trial_phase_data['trial_phase_index'] ==
                         tp_value]['trial_phase_EL_timestamp'])

    trial_parameters = pd.DataFrame(parameters[columns_df].T)

    # first, we re-code the parameters in terms of screen coordinates
    # convert stim position from proportion of screen (1920, 124 cm distance on BoldScreen32) to dva
    trial_parameters['stim_eccentricity'] = trial_parameters[
        'stim_eccentricity'] * 11  # 11 degrees from fix to edge of screen
    trial_parameters['mask_radius'] = trial_parameters[
        'mask_radius'] * 22 / 1920  # 11 degrees from fix to edge of screen

    # the sound was 800 ms delayed wrt the stimulus onset
    reward_times = trial_parameters['reward_delay'] + (
        trial_phase_timestamps - tr_timestamps[0]) / 1000.0

    # now, we need to re-code the probabilities.
    # first, we detect which feedback sound was the high-reward one.
    # we do this by looking at the 0-orientation trials, because
    # these were always no-stim reward trials: there were no no-stim no-reward trials
    reward_signal = np.array(trial_parameters['sound'])[np.array(
        np.array(trial_parameters['stim_orientation'] == 0.0))].mean()
    which_trials_reward = np.array(trial_parameters['sound'] == reward_signal)

    # now, we can find which orientations had which reward probability, since
    # the reward probability is not theoretical, but practical, on every run
    orientations = np.sort(
        np.unique(np.array(trial_parameters['stim_orientation'])))
    reward_probabilities = [(np.array(trial_parameters['sound'])[np.array(
        trial_parameters['stim_orientation'] == ori)] == reward_signal).mean()
                            for ori in orientations]

    # and we use this to fill in the per-trial value for reward probability
    reward_probs_per_trial = np.zeros(len(trial_phase_timestamps))
    for ori, rp in zip(orientations, reward_probabilities):
        reward_probs_per_trial[np.array(
            trial_parameters['stim_orientation'] == ori)] = rp
    trial_parameters['reward_probability'] = pd.Series(reward_probs_per_trial)

    trial_parameters['feedback_time'] = pd.Series(reward_times)
    trial_parameters['feedback_was_reward'] = pd.Series(
        np.array(which_trials_reward, dtype=np.int))

    trial_parameters['stim_onset_time'] = pd.Series(
        (trial_phase_timestamps - tr_timestamps[0]) / 1000.0)

    trial_parameters = trial_parameters.sort_values(by='stim_onset_time')

    trial_parameters.to_csv(temp_tsv,
                            sep='\t',
                            float_format='%3.2f',
                            header=True,
                            index=False)

    return temp_tsv
Beispiel #8
0
def fit_FIR_roi(experiment,
                h5_file,
                in_files,
                vol_regressor_list,
                behavior_file_list,
                eye_h5_file_list,
                mapper_file_list,
                mask_index,
                mask_threshold=2.0,
                mask_direction='pos',
                fmri_data_type='psc',
                pupil_data_type='_pupil_bp_zscore',
                fir_frequency=2,
                fir_interval=[-3.0, 15.0],
                roi_list=['V1', 'V2', 'V3']):

    import nibabel as nib
    import numpy as np
    import numpy.linalg as LA
    import scipy as sp
    from sklearn import decomposition
    import os
    import os.path as op
    import pandas as pd
    from spynoza.nodes.utils import get_scaninfo
    from fir import FIRDeconvolution
    from hedfpy import HDFEyeOperator
    import tempfile
    from lmfit import minimize, Minimizer, Parameters, Parameter, report_fit, report_errors, fit_report
    # from utils.behavior import behavior_timing
    # from utils.utils import roi_data_from_hdf

    tr_key = 116.0

    TR, dims, dyns, voxsize, affine = get_scaninfo(in_files[1])
    header = nib.load(in_files[1]).header

    ##################################################################################
    # behavior data generalizes across ROIs of course
    ##################################################################################
    event_names, all_behav_event_times, rename_dict, which_event_name_rewarded = behavior_timing(
        experiment, behavior_file_list, dyns, TR)

    mapper_alias = op.split(mapper_file_list[0])[-1][:-7] + '_T'

    ##################################################################################
    # eye-related data generalizes across ROIs of course
    ##################################################################################

    aliases = [
        'eye/' + op.splitext(op.split(eye_h5_file)[-1])[0]
        for eye_h5_file in eye_h5_file_list
    ]

    ho = HDFEyeOperator(h5_file)

    # blink_data, pupil_data = [], []

    # for x, alias in enumerate(aliases):
    #     ho.open_hdf_file('a')
    #     node = ho.h5f.get_node('/' + alias)
    #     trial_data = node.trials.read()
    #     blinks = pd.DataFrame(node.blinks_from_message_file.read())
    #     events = node.events.read()
    #     ho.h5f.close()

    #     # find first TR, and use it to define:
    #     # the duration of the datastream and the tr
    #     tr_timestamps = events['EL_timestamp'][(events['key'] == tr_key) & (events['up_down'] == 'Down')][:dyns]

    #     eye = ho.eye_during_trial(0, alias)
    #     sample_rate = ho.sample_rate_during_period([tr_timestamps[0], tr_timestamps[-1] + TR], alias)

    #     raw_data = ho.data_from_time_period([tr_timestamps[0], tr_timestamps[0] + (1000.0 * dyns * TR)], alias)
    #     selected_data = np.array(raw_data[eye + pupil_data_type])

    #     # take blinks
    #     run_blinks = blinks[(blinks.start_timestamp > tr_timestamps[0]) & (blinks.start_timestamp > (1000.0 * dyns * TR))]
    #     run_blinks.start_timestamp = (x * dyns * TR) + ((run_blinks.start_timestamp - tr_timestamps[0]) / 1000.0)
    #     run_blinks.end_timestamp = (x * dyns * TR) + ((run_blinks.end_timestamp - tr_timestamps[0]) / 1000.0)
    #     run_blinks.duration = run_blinks.duration / 1000.0
    #     blink_data.append(run_blinks)

    #     # bad recordings are characterized, among other things, by a very high amount of lost samples.
    #     # if this lost sample rate crosses a threshold, we will throw the file out completely
    #     raw_pupil = np.array(raw_data[eye + '_pupil'])
    #     lost_signal_rate = (raw_pupil == 0).sum() / (dyns * TR * sample_rate)
    #     run_signal = np.zeros((sample_rate * dyns * TR))
    #     if lost_signal_rate > lost_signal_rate_threshold:
    #         print 'dropping this run, lost signal rate = %1.3f'%lost_signal_rate
    #     else:
    #         run_signal[:selected_data.shape[0]] = selected_data

    #     pupil_data.append(run_signal)

    # pupil_data = np.concatenate(pupil_data)
    # blink_data = pd.concat(blink_data)

    ##################################################################################
    # whole-brain nuisance data generalizes across ROIs of course
    ##################################################################################

    if vol_regressor_list != []:
        all_vol_regs = []
        nr_vol_regressors = np.loadtxt(vol_regressor_list[0]).shape[-1]
        all_vol_reg = np.zeros((nr_vol_regressors, dyns * len(in_files)))
        for x in range(len(vol_regressor_list)):
            all_vol_reg[:, x * dyns:(x + 1) * dyns] = np.loadtxt(
                vol_regressor_list[x]).T[..., :dyns]

    ##################################################################################
    # per-roi data
    ##################################################################################

    out_figures = []
    for roi in roi_list:
        contrast_data = roi_data_from_hdf(data_types_wildcards=[mapper_alias],
                                          roi_name_wildcard=roi,
                                          hdf5_file=h5_file,
                                          folder_alias='GLM')
        time_course_data = [
            roi_data_from_hdf(
                data_types_wildcards=[os.path.split(in_f)[-1][:-7]],
                roi_name_wildcard=roi,
                hdf5_file=h5_file,
                folder_alias=fmri_data_type) for in_f in in_files
        ]

        time_course_data = np.hstack(time_course_data)

        if threshold < 0:
            threshold = -threshold
            contrast_data = -contrast_data

        over_threshold = (contrast_data[:, 1] > threshold)
        iceberg = contrast_data[over_threshold, 1]

        projected_time_course = np.dot(time_course_data[over_threshold].T,
                                       iceberg) / np.sum(iceberg)
        av_time_course = time_course_data[over_threshold].mean(axis=0)

        both_time_courses = np.vstack([projected_time_course, av_time_course])

        fir_timecourses = {
            en: np.zeros(
                [int((fir_interval[1] - fir_interval[0]) * fir_frequency)])
            for en in event_names
        }

        nuisance_regressors = np.nan_to_num(all_vol_reg)

        if num_components != 0:
            if method == 'PCA':
                pca = decomposition.PCA(n_components=num_components,
                                        whiten=True)
                nuisance_regressors = pca.fit_transform(
                    nuisance_regressors.T).T
            elif method == 'ICA':
                ica = decomposition.FastICA(n_components=num_components,
                                            whiten=True)
                nuisance_regressors = ica.fit_transform(
                    nuisance_regressors.T).T

        fd = FIRDeconvolution(
            signal=projected_time_course,
            events=[all_behav_event_times[en]
                    for en in event_names],  # dictate order
            event_names=event_names,
            sample_frequency=1.0 / TR,
            deconvolution_frequency=fir_frequency,
            deconvolution_interval=fir_interval)

        fd.resampled_signal = np.nan_to_num(fd.resampled_signal)
        # we then tell it to create its design matrix
        fd.create_design_matrix()

        # resample mocos and so forth
        all_nuisances = sp.signal.resample(nuisance_regressors,
                                           fd.resampled_signal_size,
                                           axis=-1)
        fd.add_continuous_regressors_to_design_matrix(all_nuisances)

        # fit
        fd.regress(method='lstsq')
        fd.calculate_rsq()

        for en in event_names:
            fir_timecourses[en] = np.squeeze(
                np.nan_to_num(fd.betas_for_cov(en).T))

        plot_fir_results_unpredictable(fd.deconvolution_interval_timepoints,
                                       event_names,
                                       fir_time_course_dict=fir_timecourses,
                                       zero_interval=[-0.75, -0.25],
                                       use_zero_interval=False,
                                       suffix=roi + '_roi')

        irf_timepoints = np.arange(0, 30, 1.0 / fir_frequency)
        shape, loc, scale, gain = (6.91318195e+03, -1.85261652e+02,
                                   2.78354064e-02, -2.24467302e+00)
        rew_irf = sp.stats.gamma.pdf(
            irf_timepoints, shape, loc=loc, scale=scale) * gain
        stim_irf = hrf.spmt(irf_timepoints)

        stim_events = np.concatenate([
            all_behav_event_times[en] for en in event_names if 'visual' in en
        ])
        stim_regressor = np.zeros(fd.resampled_signal_size)
        stim_regressor[np.round(stim_events * fir_frequency).astype(int)] = 1.0
        stim_regressor_c = sp.signal.fftconvolve(
            stim_regressor, stim_irf)[:fd.resampled_signal_size]
        stim_regressor_c -= stim_regressor_c.mean()

        rew_events = np.concatenate(
            [all_behav_event_times[en] for en in event_names])
        rew_events.sort()
        rew_regressor = np.zeros(
            (rew_events.shape[0], fd.resampled_signal_size))
        rew_regressor_c = np.zeros(
            (rew_events.shape[0], fd.resampled_signal_size))
        for i, re in enumerate(rew_events):
            rew_regressor[i, np.round(re * fir_frequency).astype(int)] = 1.0
            rew_regressor_c[i] = sp.signal.fftconvolve(
                rew_regressor[i], rew_irf, 'full')[:fd.resampled_signal_size]
        rew_regressor_c = (rew_regressor_c.T - rew_regressor_c.mean(axis=1)).T

        # create actual design matrix
        all_regressors = np.vstack(
            (stim_regressor_c, all_nuisances, np.ones(stim_regressor_c.shape)))

        # fit
        betas, sse, rank, svs = LA.lstsq(all_regressors.T,
                                         fd.resampled_signal.T)

        # predicted data, rsq and residuals
        prediction = np.dot(betas.T, all_regressors)
        rsq = 1.0 - np.sum(
            (prediction - fd.resampled_signal)**2, axis=-1) / np.sum(
                fd.resampled_signal.squeeze()**2, axis=-1)
        residuals = np.squeeze(fd.resampled_signal - prediction)

        figure()
        plot(fd.resampled_signal.T)
        plot(residuals)
        plot(stim_regressor_c)
        plot(stim_regressor)

        # reward design matrix
        all_regressors = np.vstack(
            (rew_regressor_c, np.ones(stim_regressor_c.shape)))

        # fit
        betas, sse, rank, svs = LA.lstsq(all_regressors.T, residuals)

        # predicted data, rsq and residuals
        prediction = np.dot(betas.T, all_regressors)
        rsq = 1.0 - np.sum(
            (prediction - fd.resampled_signal)**2, axis=-1) / np.sum(
                fd.resampled_signal.squeeze()**2, axis=-1)
        residuals_2 = np.squeeze(residuals - prediction)
        figure()
        plot(residuals)
        plot(residuals_2)
        plot(rew_regressor.sum(axis=0))
        plot(rew_regressor_c.sum(axis=0))

        reward_betas = betas[:-1]
        rew_mins = np.argmin(rew_regressor_c, axis=-1).astype(int)
        reward_values = np.array([fd.resampled_signal[0, x] for x in rew_mins])

        timing = np.argsort(
            np.concatenate([
                all_behav_event_times[name] for symbol in [
                    'visual_reward', 'visual_no_reward', 'fixation_reward',
                    'fixation_no_reward'
                ]
            ]))
        trial_array = np.concatenate(
            [[symbol for x in range(len(all_behav_event_times[name]))]
             for symbol in ['SR', 'SN', 'FR', 'FN']])[timing]

        phm = Model(PHmodel)

        figure()
        result = phm.fit(reward_betas,
                         trial_array=trial_array,
                         alpha=2,
                         kappa=0.2,
                         pos=0.75,
                         which='V',
                         fit_kws={'nan_policy': 'omit'})
        print result.fit_report()
        plot(reward_betas)
        plot(np.array(result.best_fit).T)

        figure()
        result = phm.fit(reward_betas,
                         trial_array=trial_array,
                         alpha=2,
                         kappa=0.2,
                         pos=0.75,
                         which='PE',
                         fit_kws={'nan_policy': 'omit'})
        print result.fit_report()
        plot(reward_betas)
        plot(np.array(result.best_fit).T)

        figure()
        result = phm.fit(reward_betas,
                         trial_array=trial_array,
                         alpha=2,
                         kappa=0.2,
                         pos=0.75,
                         which='alphas',
                         fit_kws={'nan_policy': 'omit'})
        print result.fit_report()
        plot(reward_betas)
        plot(np.array(result.best_fit).T)