highspeed_glm_functions.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. #!/usr/bin/env python3
  2. # -*- coding: utf-8 -*-
  3. # ======================================================================
  4. # DEFINE FUNCTION: FUNCTION TO GET THE SUBJECT-SPECIFIC INFORMATION
  5. # ======================================================================
  6. def get_subject_info(events, confounds):
  7. """
  8. FUNCTION TO GET THE SUBJECT-SPECIFIC INFORMATION
  9. :param events: list with paths to events files
  10. :param confounds: list with paths to confounds files
  11. :return: Bunch object with event onsets, durations and regressors
  12. """
  13. # import libraries (needed to be done in the function):
  14. import pandas as pd
  15. from nipype.interfaces.base import Bunch
  16. # event types we consider:
  17. event_spec = {
  18. 'correct_rejection': {'target': 0, 'key_down': 0},
  19. 'hit': {'target': 1, 'key_down': 1},
  20. 'false_alarm': {'target': 0, 'key_down': 1},
  21. 'miss': {'target': 1, 'key_down': 0},
  22. }
  23. #event_names = ['correct_rejection']
  24. # read the events and confounds files of the current run:
  25. #events = selectfiles_results.outputs.events[0]
  26. #confounds = selectfiles_results.outputs.confounds[0]
  27. run_events = pd.read_csv(events, sep="\t")
  28. run_confounds = pd.read_csv(confounds, sep="\t")
  29. # define confounds to include as regressors:
  30. confounds = ['trans', 'rot', 'a_comp_cor', 'framewise_displacement']
  31. # search for confounds of interest in the confounds data frame:
  32. regressor_names = [col for col in run_confounds.columns if
  33. any([conf in col for conf in confounds])]
  34. def replace_nan(regressor_values):
  35. # calculate the mean value of the regressor:
  36. mean_value = regressor_values.mean(skipna=True)
  37. # replace all values containing nan with the mean value:
  38. regressor_values[regressor_values.isnull()] = mean_value
  39. # return list of the regressor values:
  40. return list(regressor_values)
  41. # create a nested list with regressor values
  42. regressors = [replace_nan(run_confounds[conf]) for conf in regressor_names]
  43. onsets = []
  44. durations = []
  45. event_names = []
  46. for event in event_spec:
  47. onset_list = list(
  48. run_events['onset']
  49. [(run_events['condition'] == 'oddball') &
  50. (run_events['target'] == event_spec[event]['target']) &
  51. (run_events['key_down'] == event_spec[event]['key_down'])])
  52. duration_list = list(
  53. run_events['duration']
  54. [(run_events['condition'] == 'oddball') &
  55. (run_events['target'] == event_spec[event]['target']) &
  56. (run_events['key_down'] == event_spec[event]['key_down'])])
  57. if (onset_list != []) & (duration_list != []):
  58. event_names.append(event)
  59. onsets.append(onset_list)
  60. durations.append(duration_list)
  61. # create a bunch for each run:
  62. subject_info = Bunch(
  63. conditions=event_names, onsets=onsets, durations=durations,
  64. regressor_names=regressor_names, regressors=regressors)
  65. return subject_info, sorted(event_names)
  66. # ======================================================================
  67. # DEFINE FUNCTION: FUNCTION TO PLOT THE CONTRASTS AGAINST ANATOMICAL
  68. # ======================================================================
  69. def plot_stat_maps(anat, stat_map, thresh):
  70. """
  71. :param anat:
  72. :param stat_map:
  73. :param thresh:
  74. :return:
  75. """
  76. # import libraries (needed to be done in the function):
  77. from nilearn.plotting import plot_stat_map
  78. from os import path as op
  79. out_path = op.join(op.dirname(stat_map), 'contrast_thresh_%s.png' % thresh)
  80. plot_stat_map(
  81. stat_map, title=('Threshold: %s' % thresh),
  82. bg_img=anat, threshold=thresh, dim=-1, display_mode='ortho',
  83. output_file=out_path)
  84. return out_path
  85. def leave_one_out(subject_info, event_names, data_func, run):
  86. """
  87. Select subsets of lists in leave-one-out fashion:
  88. :param subject_info: list of subject info bunch objects
  89. :param data_func: list of functional runs
  90. :param run: current run
  91. :return: return list of subject info and data excluding the current run
  92. """
  93. # create new list with event_names of all runs except current run:
  94. event_names = [info for i, info in enumerate(event_names) if i != run]
  95. num_events = [len(i) for i in event_names]
  96. max_events = event_names[num_events.index(max(num_events))]
  97. # create list of contrasts:
  98. stim = 'correct_rejection'
  99. contrast1 = (stim, 'T', max_events, [1 if stim in s else 0 for s in max_events])
  100. contrasts = [contrast1]
  101. # create new list with subject info of all runs except current run:
  102. subject_info = [info for i, info in enumerate(subject_info) if i != run]
  103. # create new list with functional data of all runs except current run:
  104. data_func = [info for i, info in enumerate(data_func) if i != run]
  105. # return the new lists
  106. return subject_info, data_func, contrasts