Skip to content

trial_decoding_pipeline

Description:

This script performs trial-level fMRI data decoding for neuroimaging analysis, specifically designed for real-time applications. It processes preprocessed neuroimaging volumes (e.g., fMRI) through multiple decoding approaches to classify or predict cognitive states, brain states, or any target conditions of interest. The script supports various machine learning algorithms and provides flexible processing options based on trial characteristics.

Key Features
  • Supports real-time trial-level fMRI data decoding
  • Implements dynamic decoding for immediate feedback in experimental setups
  • Allows for both single-trial and aggregated (HRF-peak) decoding approaches
  • Compatible with multiple machine learning algorithms (e.g., Logistic Regression, SVM)
  • Includes time-efficient processing to handle rapid data streams
  • Provides detailed timing information for each decoding step
Inputs
  • preproc_vols_data: List of masked and preprocessed fMRI volumes (NifTI format)
  • model_file: Path to a pretrained machine learning model (e.g., Logistic Regression, SVM)
  • ground_truth: Target class label corresponding to the ground truth condition

(integer value)

Outputs
  • decoding_prob: Probability of correct classification for the given volume/condition
  • decoding_time: List containing timing information for each decoding step
  • vols_decoding_probs: Optional output with individual probabilities for each HRF peak volume

Performance Considerations:

The script is optimized for efficient processing, ensuring minimal latency between data acquisition and model evaluation. It supports both single-trial dynamic decoding and aggregated decoding approaches, allowing flexibility in experimental design. The use of pre-trained models and efficient prediction algorithms ensures that even high-resolution neuroimaging data can be processed quickly.

average_hrf_peak_vols_decoding(preproc_vols_data, model_file, ground_truth)

Average volumes within a trial HRF peak before decoding a single averaged volume to increase signal-to-noise ratio

Steps:

1 - Load model
2 - Average volumes of interest (i.e., volumes within HRF peak) onto a single volume
3 - Predict class probabilities over this trial averaged volume
4 - Get probability of decoding ground truth class

Inputs:

preproc_vols: masked and preprocessed volumes (List of Numpy arrays. Each array has following dimensions: 1, n_voxels)
model_file: pretrained model (ex., a classifier) in a Region Of Interest (Have to match with mask_file)
ground_truth: as integer. Target class position in model probabilities predictions tuple.

Returns:

decoding_prob: probability of decoding ground truth of averaged HRF volume (Float)
decoding_time: processing time for each decoding pipeline step (List)
Source code in pyDecNef/1_server/2_neurofeedback/1_realtime_fMRI/modules/pipelines/trial_decoding_pipeline.py
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
def average_hrf_peak_vols_decoding(preproc_vols_data: list, model_file: str, ground_truth: int) -> Tuple[np.array, list]:

    """ 
    Average volumes within a trial HRF peak before decoding a single averaged volume to increase signal-to-noise ratio

    Steps:

        1 - Load model
        2 - Average volumes of interest (i.e., volumes within HRF peak) onto a single volume
        3 - Predict class probabilities over this trial averaged volume
        4 - Get probability of decoding ground truth class

    Inputs:

        preproc_vols: masked and preprocessed volumes (List of Numpy arrays. Each array has following dimensions: 1, n_voxels)
        model_file: pretrained model (ex., a classifier) in a Region Of Interest (Have to match with mask_file)
        ground_truth: as integer. Target class position in model probabilities predictions tuple.

    Returns:

        decoding_prob: probability of decoding ground truth of averaged HRF volume (Float)
        decoding_time: processing time for each decoding pipeline step (List)
    """

    # Decoding start time
    decoding_time = OrderedDict()
    # Load pretrained model
    clf_fit = load(model_file)

    start_decoding = time.time()

    # First, average vols within HRF peak
    start_average_vols = time.time()
    average_preproc = np.average(preproc_vols_data, axis = 0) # Average HRF peak vols
    average_preproc = average_preproc.reshape(1, -1) # Reshape so averaged array has (1, n_voxels) dimensions
    decoding_time['average_vols_time'] = time.time() - start_average_vols

    # Predict class probability
    start_prediction = time.time()
    class_probabilities = clf_fit.predict_proba(average_preproc) # Predict class probabilities over this trial averaged vol
    evaluation = clf_fit.evaluate(average_preproc,[ground_truth for i in len(average_preproc)])
    decoding_prob = class_probabilities[0][ground_truth] # Select the probability corresponding to the ground truth
    print("THE DECODING PROBABILITY:",decoding_prob)
    decoding_time['prediction_time'] = time.time() - start_prediction

    # Decoding end time
    decoding_time['total_decoding_time'] = time.time() - start_decoding
    decoding_time = [decoding_time] # Convert dict to a list to store all times in a pandas dataframe

    return decoding_prob, decoding_time

average_probs_decoding(preproc_vols_data, model_file, ground_truth)

Average decoding probabilities of volumes within a trial HRF peak

Steps:

1 - Load model
2 - Predict class probabilities for each HRF peak volume
3 - Get probability of decoding ground truth class for each HRF peak volume
4 - Average probabilities of decoding ground truth across volumes

Inputs:

preproc_vols: masked and preprocessed volumes (List of Numpy arrays. Each array has following dimensions: 1, n_voxels)
model_file: pretrained model (ex., a classifier) in a Region Of Interest (Have to match with mask_file)
ground_truth: as integer. Target class position in model probabilities predictions tuple.

Returns:

averaged_decoding_prob: averaged decoding probability across HRF volumes (Float)
vols_decoding_probs: decoding probability for each independent volume within HRF peak (Float)
decoding_time: processing time for each decoding pipeline step (List)
Source code in pyDecNef/1_server/2_neurofeedback/1_realtime_fMRI/modules/pipelines/trial_decoding_pipeline.py
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
def average_probs_decoding(preproc_vols_data: list, model_file: str, ground_truth: int) -> Tuple[np.array, list, list]:

    """
    Average decoding probabilities of volumes within a trial HRF peak

    Steps:

        1 - Load model
        2 - Predict class probabilities for each HRF peak volume
        3 - Get probability of decoding ground truth class for each HRF peak volume
        4 - Average probabilities of decoding ground truth across volumes

    Inputs:

        preproc_vols: masked and preprocessed volumes (List of Numpy arrays. Each array has following dimensions: 1, n_voxels)
        model_file: pretrained model (ex., a classifier) in a Region Of Interest (Have to match with mask_file)
        ground_truth: as integer. Target class position in model probabilities predictions tuple.

    Returns:

        averaged_decoding_prob: averaged decoding probability across HRF volumes (Float)
        vols_decoding_probs: decoding probability for each independent volume within HRF peak (Float)
        decoding_time: processing time for each decoding pipeline step (List)
    """

    # Decoding start time
    decoding_time = OrderedDict()
    # Load pretrained model
    clf_fit = load(model_file)

    start_decoding = time.time()
    start_decoding_vols = time.time()
    vols_decoding_probs = [] # To store each HRF peak vol ground truth decoding probability

    # Iterate over all preprocessed volumes within HRF peak
    for vol in preproc_vols_data:
        # Predict class probability
        class_probabilities = clf_fit.predict_proba(vol) # Predict class probabilities over this trial averaged vol
        decoding_prob = class_probabilities[0][int(ground_truth)] # Select the probability corresponding to the ground truth
        vols_decoding_probs.append(decoding_prob) # Append decoding probability to list of decoding probabilities for each vol
    print("THE TOTAL DECODING PROBABILITIES FOR THE VOLUMES:",vols_decoding_probs)   
    averaged_decoding_prob = np.average(vols_decoding_probs) # Average probabilities of decoding ground truth across volumes
    decoding_time['decoding_vols_time'] = time.time() - start_decoding_vols

    # Decoding end time
    decoding_time['total_decoding_time'] = time.time() - start_decoding
    decoding_time = [decoding_time] # Convert dict to a list to store all times in a pandas dataframe

    return averaged_decoding_prob, vols_decoding_probs, decoding_time

dynamic_decoding(preproc_vol, model_file, ground_truth)

Decode a single volume. In dynamic decoding, all volumes within a trial HRF peak, will be decoded independently and sent individually to experimental software as feedback.

Steps:

1 - Load model
2 - Predict class probabilities of a preprocessed volume
3 - Get probability of decoding ground truth class for a preprocessed volume

Inputs:

preproc_vol: a single masked and preprocessed fMRI volume data (Array with following dimensions: 1, n_voxels)
model_file: pretrained model (ex., a classifier) in a Region Of Interest (Have to match with mask_file)
ground_truth: as integer. Target class position in model probabilities predictions tuple.

Returns:

decoding_prob: probability of decoding ground truth in preproc_vol
decoding_time: processing time for each decoding pipeline step (List)
Source code in pyDecNef/1_server/2_neurofeedback/1_realtime_fMRI/modules/pipelines/trial_decoding_pipeline.py
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
def dynamic_decoding(preproc_vol: np.array, model_file: str, ground_truth: int)  -> Tuple[np.array, list]:

    """
    Decode a single volume. In dynamic decoding, all volumes within a trial HRF peak, will be decoded independently and 
    sent individually to experimental software as feedback.

    Steps:

        1 - Load model
        2 - Predict class probabilities of a preprocessed volume
        3 - Get probability of decoding ground truth class for a preprocessed volume

    Inputs:

        preproc_vol: a single masked and preprocessed fMRI volume data (Array with following dimensions: 1, n_voxels)
        model_file: pretrained model (ex., a classifier) in a Region Of Interest (Have to match with mask_file)
        ground_truth: as integer. Target class position in model probabilities predictions tuple.

    Returns:

        decoding_prob: probability of decoding ground truth in preproc_vol
        decoding_time: processing time for each decoding pipeline step (List)
    """

    # Decoding start time
    decoding_time = OrderedDict()
    # Load pretrained model
    clf_fit = load(model_file)

    start_decoding = time.time()

    # Predict class probability
    start_prediction = time.time()

    class_probabilities = clf_fit.predict_proba(preproc_vol) # Predict class probabilities over this trial averaged vol
    decoding_prob = class_probabilities[0][ground_truth] # Select the probability corresponding to the ground truth
    print("THE DECODING PROBABILITY:",decoding_prob)   
    decoding_time['prediction_time'] = time.time() - start_prediction

    # Decoding end time
    decoding_time['total_decoding_time'] = time.time() - start_decoding
    decoding_time = [decoding_time] # Convert dict to a list to store all times in a pandas dataframe

    return decoding_prob, decoding_time