From 2b8116a194de087518f0308f2128e7479d09b75d Mon Sep 17 00:00:00 2001 From: Mingbo Cai Date: Sun, 9 Sep 2018 23:45:38 -0400 Subject: [PATCH 1/7] add a check in utils.gen_design so that when there is no event, an all-zero time series is directly generated --- brainiak/utils/utils.py | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/brainiak/utils/utils.py b/brainiak/utils/utils.py index 1e7084266..a19cd7772 100644 --- a/brainiak/utils/utils.py +++ b/brainiak/utils/utils.py @@ -445,21 +445,24 @@ def gen_design(stimtime_files, scan_duration, TR, style='FSL', # generate design matrix for i_s in range(n_S): for i_c in range(n_C): - stimfunction = generate_stimfunction( - onsets=design_info[i_s][i_c]['onset'], - event_durations=design_info[i_s][i_c]['duration'], - total_time=scan_duration[i_s], - weights=design_info[i_s][i_c]['weight'], - temporal_resolution=1.0/temp_res) - hrf = _double_gamma_hrf(response_delay=response_delay, - undershoot_delay=undershoot_delay, - response_dispersion=response_disp, - undershoot_dispersion=undershoot_disp, - undershoot_scale=undershoot_scale, - temporal_resolution=1.0/temp_res) - design[i_s][:, i_c] = convolve_hrf( - stimfunction, TR, hrf_type=hrf, scale_function=0, - temporal_resolution=1.0 / temp_res).transpose() * temp_res + if len(design_info[i_s][i_c]['onset']) > 0: + stimfunction = generate_stimfunction( + onsets=design_info[i_s][i_c]['onset'], + event_durations=design_info[i_s][i_c]['duration'], + total_time=scan_duration[i_s], + weights=design_info[i_s][i_c]['weight'], + temporal_resolution=1.0/temp_res) + hrf = _double_gamma_hrf(response_delay=response_delay, + undershoot_delay=undershoot_delay, + response_dispersion=response_disp, + undershoot_dispersion=undershoot_disp, + undershoot_scale=undershoot_scale, + temporal_resolution=1.0/temp_res) + design[i_s][:, i_c] = convolve_hrf( + stimfunction, TR, hrf_type=hrf, scale_function=False, + temporal_resolution=1.0 / temp_res).transpose() * temp_res + else: + design[i_s][:, i_c] = 0.0 # We multiply the resulting design matrix with # the temporal resolution to normalize it. # We do not use the internal normalization From d944873dc51f6682d55daa7cb3a0bf7f4b4c6734 Mon Sep 17 00:00:00 2001 From: Mingbo Cai Date: Mon, 10 Sep 2018 00:06:01 -0400 Subject: [PATCH 2/7] add test for the changes --- tests/utils/test_utils.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/tests/utils/test_utils.py b/tests/utils/test_utils.py index 820b648e8..1348790db 100644 --- a/tests/utils/test_utils.py +++ b/tests/utils/test_utils.py @@ -101,7 +101,8 @@ def test_gen_design(): import os.path files = {'FSL1': 'example_stimtime_1_FSL.txt', 'FSL2': 'example_stimtime_2_FSL.txt', - 'AFNI1': 'example_stimtime_1_AFNI.txt'} + 'AFNI1': 'example_stimtime_1_AFNI.txt', + 'AFNI2': 'example_stimtime_2_AFNI.txt'} for key in files.keys(): files[key] = os.path.join(os.path.dirname(__file__), files[key]) design1 = gen_design(stimtime_files=files['FSL1'], scan_duration=[48, 20], @@ -130,6 +131,11 @@ def test_gen_design(): scan_duration=[48, 20], TR=2, style='AFNI') assert np.all(np.isclose(design1, design6)), ( 'design matrices generated from AFNI style and FSL style do not match') + design7 = gen_design(stimtime_files=[files['AFNI2']], + scan_duration=[48], TR=2, style='AFNI') + assert np.all(design7 == 0.0), ( + 'A negative stimulus onset of AFNI style should result in an all-zero' + + ' design matrix') def test_center_mass_exp(): From 71cc6df5a719ce2371ef2603c8fad8b7e65f6a18 Mon Sep 17 00:00:00 2001 From: Mingbo Cai Date: Mon, 10 Sep 2018 17:35:43 -0400 Subject: [PATCH 3/7] add the example stimulus timing file of AFNI style --- brainiak/utils/fmrisim.py | 1 + tests/utils/example_stimtime_2_AFNI.txt | 1 + 2 files changed, 2 insertions(+) create mode 100644 tests/utils/example_stimtime_2_AFNI.txt diff --git a/brainiak/utils/fmrisim.py b/brainiak/utils/fmrisim.py index 41c5d73dd..cb2fdcf73 100644 --- a/brainiak/utils/fmrisim.py +++ b/brainiak/utils/fmrisim.py @@ -852,6 +852,7 @@ def convolve_hrf(stimfunction, """ # Check if it is timepoint by feature + print(stimfunction.shape) if stimfunction.shape[0] < stimfunction.shape[1]: logger.warning('Stimfunction may be the wrong shape') diff --git a/tests/utils/example_stimtime_2_AFNI.txt b/tests/utils/example_stimtime_2_AFNI.txt new file mode 100644 index 000000000..39d03d9ee --- /dev/null +++ b/tests/utils/example_stimtime_2_AFNI.txt @@ -0,0 +1 @@ +-10.0 From 32dc6c33e0e97aa53607404719faea23dfc19fd1 Mon Sep 17 00:00:00 2001 From: Mingbo Cai Date: Mon, 10 Sep 2018 17:38:06 -0400 Subject: [PATCH 4/7] remove the printing test line --- brainiak/utils/fmrisim.py | 1 - 1 file changed, 1 deletion(-) diff --git a/brainiak/utils/fmrisim.py b/brainiak/utils/fmrisim.py index cb2fdcf73..41c5d73dd 100644 --- a/brainiak/utils/fmrisim.py +++ b/brainiak/utils/fmrisim.py @@ -852,7 +852,6 @@ def convolve_hrf(stimfunction, """ # Check if it is timepoint by feature - print(stimfunction.shape) if stimfunction.shape[0] < stimfunction.shape[1]: logger.warning('Stimfunction may be the wrong shape') From b24cc4dcf1e165e6e73f21763b93174e11ce063b Mon Sep 17 00:00:00 2001 From: Mingbo Cai Date: Mon, 10 Sep 2018 21:38:18 -0400 Subject: [PATCH 5/7] removed the conditional clause in generate_stimfunction of fmrisim.py, which shortens stim_function if its length is smaller than the product of total_time and temporal_resolution --- brainiak/utils/fmrisim.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/brainiak/utils/fmrisim.py b/brainiak/utils/fmrisim.py index 41c5d73dd..6e19fdf4e 100644 --- a/brainiak/utils/fmrisim.py +++ b/brainiak/utils/fmrisim.py @@ -522,11 +522,7 @@ def generate_stimfunction(onsets, # Store the weights stimfunction[onset_idx:offset_idx, 0] = [weights[onset_counter]] - - # Shorten the data if it's too long - if stimfunction.shape[0] > total_time * temporal_resolution: - stimfunction = stimfunction[0:int(total_time * temporal_resolution), 0] - + return stimfunction From 4daa70a1bb98533d37362e9b68f1db75aeed5815 Mon Sep 17 00:00:00 2001 From: lcnature Date: Mon, 10 Sep 2018 21:52:52 -0400 Subject: [PATCH 6/7] fix whitespace --- brainiak/utils/fmrisim.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/brainiak/utils/fmrisim.py b/brainiak/utils/fmrisim.py index 6e19fdf4e..05838abf1 100644 --- a/brainiak/utils/fmrisim.py +++ b/brainiak/utils/fmrisim.py @@ -522,7 +522,7 @@ def generate_stimfunction(onsets, # Store the weights stimfunction[onset_idx:offset_idx, 0] = [weights[onset_counter]] - + return stimfunction From 1c5d20b63bf082df09cbcb6ec304a6181a11630c Mon Sep 17 00:00:00 2001 From: lcnature Date: Mon, 10 Sep 2018 22:17:37 -0400 Subject: [PATCH 7/7] changed two `floor` to `round` in utils.gen_design, because in principle there is no reason to use floor. And in practice, due to precision of float number computation, this can sometime result in a smaller count of number of TRs. As long as the user provide the correct total_duration --- brainiak/utils/utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/brainiak/utils/utils.py b/brainiak/utils/utils.py index a19cd7772..56119e02a 100644 --- a/brainiak/utils/utils.py +++ b/brainiak/utils/utils.py @@ -427,10 +427,10 @@ def gen_design(stimtime_files, scan_duration, TR, style='FSL', n_C = len(stimtime_files) # number of conditions n_S = np.size(scan_duration) # number of scans if n_S > 1: - design = [np.empty([int(np.floor(duration / TR)), n_C]) + design = [np.empty([int(np.round(duration / TR)), n_C]) for duration in scan_duration] else: - design = [np.empty([int(np.floor(scan_duration / TR)), n_C])] + design = [np.empty([int(np.round(scan_duration / TR)), n_C])] scan_onoff = np.insert(np.cumsum(scan_duration), 0, 0) if style == 'FSL': design_info = _read_stimtime_FSL(stimtime_files, n_C, n_S, scan_onoff)